diff --git a/.github/actions/build-onedir-deps/action.yml b/.github/actions/build-onedir-deps/action.yml index b0ff43b4033..fceb79f0eb7 100644 --- a/.github/actions/build-onedir-deps/action.yml +++ b/.github/actions/build-onedir-deps/action.yml @@ -29,6 +29,7 @@ env: COLUMNS: 190 PIP_INDEX_URL: https://pypi-proxy.saltstack.net/root/local/+simple/ PIP_EXTRA_INDEX_URL: https://pypi.org/simple + RELENV_BUILDENV: 1 runs: @@ -41,13 +42,20 @@ runs: uses: actions/cache@v3 with: path: artifacts/${{ inputs.package-name }} - key: ${{ inputs.cache-prefix }}|${{ inputs.python-version }}|deps|${{ inputs.platform }}|${{ inputs.arch }}|${{ inputs.package-name }}|${{ hashFiles(format('{0}/.relenv/**/*.xz', github.workspace), 'requirements/static/pkg/*/*.txt', '.github/actions/build-onedir-deps/action.yml') }} + key: > + ${{ inputs.cache-prefix }}|${{ inputs.python-version }}|deps|${{ inputs.platform }}|${{ inputs.arch }}|${{ inputs.package-name }}| + ${{ hashFiles( + format('{0}/.relenv/**/*.xz', github.workspace), + 'requirements/static/pkg/*/*.txt', + '.github/actions/build-onedir-deps/action.yml', + 'cicd/shared-gh-workflows-context.yml' + ) }} - name: Install Salt Onedir Package Dependencies shell: bash if: steps.onedir-pkg-cache.outputs.cache-hit != 'true' run: | - tools pkg build onedir-dependencies --arch ${{ inputs.arch }} --python-version ${{ inputs.python-version }} --package-name ${{ inputs.package-name }} --platform ${{ inputs.platform }} + tools pkg build onedir-dependencies --arch ${{ inputs.arch }} --python-version ${{ inputs.python-version }} --package-name artifacts/${{ inputs.package-name }} --platform ${{ inputs.platform }} - name: Cleanup Salt Onedir Directory shell: bash diff --git a/.github/actions/build-onedir-salt/action.yml b/.github/actions/build-onedir-salt/action.yml index e15f03c2a63..1f115607e81 100644 --- a/.github/actions/build-onedir-salt/action.yml +++ b/.github/actions/build-onedir-salt/action.yml @@ -33,6 +33,7 @@ env: COLUMNS: 190 PIP_INDEX_URL: https://pypi-proxy.saltstack.net/root/local/+simple/ PIP_EXTRA_INDEX_URL: https://pypi.org/simple + RELENV_BUILDENV: 1 runs: @@ -45,7 +46,14 @@ runs: uses: actions/cache@v3 with: path: artifacts/${{ inputs.package-name }} - key: ${{ inputs.cache-prefix }}|${{ inputs.python-version }}|deps|${{ inputs.platform }}|${{ inputs.arch }}|${{ inputs.package-name }}|${{ hashFiles(format('{0}/.relenv/**/*.xz', github.workspace), 'requirements/static/pkg/*/*.txt', '.github/actions/build-onedir-deps/action.yml') }} + key: > + ${{ inputs.cache-prefix }}|${{ inputs.python-version }}|deps|${{ inputs.platform }}|${{ inputs.arch }}|${{ inputs.package-name }}| + ${{ hashFiles( + format('{0}/.relenv/**/*.xz', github.workspace), + 'requirements/static/pkg/*/*.txt', + '.github/actions/build-onedir-deps/action.yml', + 'cicd/shared-gh-workflows-context.yml' + ) }} - name: Download Source Tarball uses: actions/download-artifact@v3 @@ -55,7 +63,7 @@ runs: - name: Install Salt Into Onedir shell: bash run: | - tools pkg build salt-onedir salt-${{ inputs.salt-version }}.tar.gz --platform ${{ inputs.platform }} --package-name ${{ inputs.package-name }} + tools pkg build salt-onedir salt-${{ inputs.salt-version }}.tar.gz --platform ${{ inputs.platform }} --package-name artifacts/${{ inputs.package-name }} - name: Cleanup Salt Onedir Directory shell: bash diff --git a/.github/actions/get-pull-labels/action.yml b/.github/actions/get-pull-labels/action.yml new file mode 100644 index 00000000000..2da0a2c9dae --- /dev/null +++ b/.github/actions/get-pull-labels/action.yml @@ -0,0 +1,23 @@ +--- +name: get-pull-labels +description: Get Pull Labels +inputs: + pull-request: + type: string + +outputs: + labels: + value: ${{ steps.get-pull-labels.outputs.labels }} + +runs: + using: composite + steps: + - name: Get Pull Labels + id: get-pull-labels + shell: bash + env: + PULL_REQUEST: ${{ inputs.pull-request }} + run: | + labels=$(jq -c '[.labels[].name]' <<< $PULL_REQUEST) + echo $labels + echo "labels=$labels" >> "$GITHUB_OUTPUT" diff --git a/.github/actions/get-pull-number/action.yml b/.github/actions/get-pull-number/action.yml new file mode 100644 index 00000000000..00fd0425aff --- /dev/null +++ b/.github/actions/get-pull-number/action.yml @@ -0,0 +1,46 @@ + +--- +name: get-pull-number +description: Get Pull Number +inputs: + owner: + type: string + repo: + type: string + sha: + type: string + pull-number: + default: null + +outputs: + number: + value: ${{ steps.get-pull-number.outputs.number }} + +runs: + using: composite + steps: + - name: Get Pull Number + id: get-pull-number + shell: bash + env: + GITHUB_OWNER: ${{ inputs.owner }} + GITHUB_REPO: ${{ inputs.repo }} + GITHUB_SHA: ${{ inputs.sha }} + GITHUB_PULL_NUMBER: ${{ inputs.pull-number }} + run: | + if [ -z "$GITHUB_PULL_NUMBER" ] + then + echo "Searching For Pull Number" + echo $GITHUB_OWNER + echo $GITHUB_REPO + echo $GITHUB_SHA + pulls=$(gh api repos/$GITHUB_OWNER/$GITHUB_REPO/commits/$GITHUB_SHA/pulls) + echo $pulls + full_name=$GITHUB_OWNER/$GITHUB_REPO + number=$(jq -c --arg r "$full_name" '[.[] | select(.url | contains($r))][0].number' <<< $pulls ) + else + echo "Given Pull Number" + number=$GITHUB_PULL_NUMBER + fi + echo $number + echo "number=$number" >> "$GITHUB_OUTPUT" diff --git a/.github/actions/get-pull-request/action.yml b/.github/actions/get-pull-request/action.yml new file mode 100644 index 00000000000..781aa24fe98 --- /dev/null +++ b/.github/actions/get-pull-request/action.yml @@ -0,0 +1,30 @@ + +--- +name: get-pull-request +description: Get Pull Request +inputs: + owner: + type: string + repo: + type: string + pull-number: + type: number + +outputs: + pull-request: + value: ${{ steps.get-pull-request.outputs.request }} + +runs: + using: composite + steps: + - name: Get Pull Request + id: get-pull-request + shell: bash + env: + GITHUB_OWNER: ${{ inputs.owner }} + GITHUB_REPO: ${{ inputs.repo }} + GITHUB_PULL_NUMBER: ${{ inputs.pull-number }} + run: | + pull=$(gh api repos/$GITHUB_OWNER/$GITHUB_REPO/pulls/$GITHUB_PULL_NUMBER) + echo $pull + echo "request=$pull" >> "$GITHUB_OUTPUT" diff --git a/.github/actions/setup-relenv/action.yml b/.github/actions/setup-relenv/action.yml index aaa83245178..745eb293932 100644 --- a/.github/actions/setup-relenv/action.yml +++ b/.github/actions/setup-relenv/action.yml @@ -22,7 +22,7 @@ inputs: required: false type: string description: The version of relenv to use - default: 0.10.1 + default: 0.10.2 outputs: version: diff --git a/.github/workflows/build-deb-packages.yml b/.github/workflows/build-deb-packages.yml index d77f512f0ab..f9aa6af3ae3 100644 --- a/.github/workflows/build-deb-packages.yml +++ b/.github/workflows/build-deb-packages.yml @@ -22,6 +22,9 @@ jobs: arch: - x86_64 - aarch64 + src: + - true + - false container: image: ghcr.io/saltstack/salt-ci-containers/packaging:debian-11 @@ -76,17 +79,34 @@ jobs: - name: Build Deb working-directory: pkgs/checkout/ + if: ${{ matrix.src != true}} run: | tools pkg build deb --onedir salt-${{ inputs.salt-version }}-onedir-linux-${{ matrix.arch }}.tar.xz + - name: Build Deb + working-directory: pkgs/checkout/ + if: ${{ matrix.src == true}} + run: | + tools pkg build deb --arch ${{ matrix.arch }} + - name: Cleanup run: | rm -rf pkgs/checkout/ - name: Upload DEBs uses: actions/upload-artifact@v3 + if: ${{ matrix.src == false}} with: name: salt-${{ inputs.salt-version }}-${{ matrix.arch }}-deb path: ${{ github.workspace }}/pkgs/* retention-days: 7 if-no-files-found: error + + - name: Upload DEBs + uses: actions/upload-artifact@v3 + if: ${{ matrix.src == true}} + with: + name: salt-${{ inputs.salt-version }}-${{ matrix.arch }}-deb-from-src + path: ${{ github.workspace }}/pkgs/* + retention-days: 7 + if-no-files-found: error diff --git a/.github/workflows/build-deps-onedir.yml b/.github/workflows/build-deps-onedir.yml index a52bd12ccdc..8a703373f8f 100644 --- a/.github/workflows/build-deps-onedir.yml +++ b/.github/workflows/build-deps-onedir.yml @@ -21,7 +21,7 @@ on: relenv-version: required: false type: string - default: 0.10.0 + default: 0.10.2 description: The version of relenv to use python-version-linux: required: false diff --git a/.github/workflows/build-macos-packages.yml b/.github/workflows/build-macos-packages.yml index 24c45a6c7e2..54a5af28bb8 100644 --- a/.github/workflows/build-macos-packages.yml +++ b/.github/workflows/build-macos-packages.yml @@ -8,11 +8,16 @@ on: type: string required: true description: The Salt version to set prior to building packages. + environment: + type: string + description: The GitHub Environment where this workflow should run + default: ci jobs: build-pkgs: name: macOS + environment: ${{ inputs.environment }} strategy: fail-fast: false matrix: @@ -21,6 +26,19 @@ jobs: runs-on: - macos-12 steps: + + - name: Check Package Signing Enabled + shell: bash + id: check-pkg-sign + run: | + if [ "${{ (secrets.MAC_SIGN_APPLE_ACCT != '' && contains(fromJSON('["nightly", "staging"]'), inputs.environment)) && 'true' || 'false' }}" != "true" ]; then + echo "The packages created will NOT be signed" + echo "sign-pkgs=false" >> "$GITHUB_OUTPUT" + else + echo "The packages created WILL be signed" + echo "sign-pkgs=true" >> "$GITHUB_OUTPUT" + fi + - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: @@ -41,14 +59,41 @@ jobs: name: salt-${{ inputs.salt-version }}-onedir-darwin-${{ matrix.arch }}.tar.xz path: artifacts/ - - name: Build MacOS Package + - name: Prepare Package Signing + if: ${{ steps.check-pkg-sign.outputs.sign-pkgs == 'true' }} run: | - tools pkg build macos --onedir salt-${{ inputs.salt-version }}-onedir-darwin-${{ matrix.arch }}.tar.xz --salt-version ${{ inputs.salt-version }} + echo ${{ secrets.MAC_SIGN_DEV_APP_CERT_B64 }} | base64 --decode > app-cert.p12 + echo ${{ secrets.MAC_SIGN_DEV_INSTALL_CERT_B64 }} | base64 --decode > install-cert.p12 + # Create SaltSigning keychain. This will contain the certificates for signing + security create-keychain -p "${{ secrets.MAC_SIGN_DEV_PASSWORD }}" "${{ secrets.MAC_SIGN_DEV_KEYCHAIN }}" + # Append SaltSigning keychain to the search list + security list-keychains -d user -s "${{ secrets.MAC_SIGN_DEV_KEYCHAIN }}" "$(security list-keychains -d user | sed s/\"//g)" + # Unlock the keychain so we can import certs + security unlock-keychain -p "${{ secrets.MAC_SIGN_DEV_PASSWORD }}" "${{ secrets.MAC_SIGN_DEV_KEYCHAIN }}" + # Developer Application Certificate + security import "app-cert.p12" -t agg -k "${{ secrets.MAC_SIGN_DEV_KEYCHAIN }}" -P "${{ secrets.MAC_SIGN_DEV_PASSWORD }}" -A + rm app-cert.p12 + # Developer Installer Certificate + security import "install-cert.p12" -t agg -k "${{ secrets.MAC_SIGN_DEV_KEYCHAIN }}" -P "${{ secrets.MAC_SIGN_DEV_PASSWORD }}" -A + rm install-cert.p12 + security set-key-partition-list -S apple-tool:,apple: -k "${{ secrets.MAC_SIGN_DEV_PASSWORD }}" "${{ secrets.MAC_SIGN_DEV_KEYCHAIN }}" &> /dev/null + + - name: Build MacOS Package + env: + 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 }}" + APP_SPEC_PWD: "${{ secrets.MAC_SIGN_APP_SPEC_PWD }}" + run: | + tools pkg build macos --onedir salt-${{ inputs.salt-version }}-onedir-darwin-${{ matrix.arch }}.tar.xz \ + --salt-version ${{ inputs.salt-version }} ${{ + steps.check-pkg-sign.outputs.sign-pkgs == 'true' && '--sign' || '' + }} - name: Upload ${{ matrix.arch }} Package uses: actions/upload-artifact@v3 with: name: salt-${{ inputs.salt-version }}-${{ matrix.arch }}-macos - path: pkg/macos/*unsigned.pkg + path: pkg/macos/salt-${{ inputs.salt-version }}-py3-*.pkg retention-days: 7 if-no-files-found: error diff --git a/.github/workflows/build-rpm-packages.yml b/.github/workflows/build-rpm-packages.yml index 3e4e30a913c..ef032568063 100644 --- a/.github/workflows/build-rpm-packages.yml +++ b/.github/workflows/build-rpm-packages.yml @@ -25,6 +25,9 @@ jobs: arch: - x86_64 - aarch64 + src: + - true + - false container: image: ghcr.io/saltstack/salt-ci-containers/packaging:centosstream-9 @@ -64,13 +67,29 @@ jobs: tools pkg apply-release-patch salt-${{ inputs.salt-version }}.patch --delete - name: Build RPM + if: ${{ matrix.src != true}} run: | tools pkg build rpm --onedir salt-${{ inputs.salt-version }}-onedir-linux-${{ matrix.arch }}.tar.xz + - name: Build RPM + if: ${{ matrix.src == true}} + run: | + tools pkg build rpm --arch ${{ matrix.arch }} + - name: Upload RPMs uses: actions/upload-artifact@v3 + if: ${{ matrix.src != true}} with: name: salt-${{ inputs.salt-version }}-${{ matrix.arch }}-rpm path: ~/rpmbuild/RPMS/${{ matrix.arch }}/*.rpm retention-days: 7 if-no-files-found: error + + - name: Upload RPMs + uses: actions/upload-artifact@v3 + if: ${{ matrix.src == true}} + with: + name: salt-${{ inputs.salt-version }}-${{ matrix.arch }}-rpm-from-src + path: ~/rpmbuild/RPMS/${{ matrix.arch }}/*.rpm + retention-days: 7 + if-no-files-found: error diff --git a/.github/workflows/build-salt-onedir.yml b/.github/workflows/build-salt-onedir.yml index 91a5b20b29d..837c6cf30b8 100644 --- a/.github/workflows/build-salt-onedir.yml +++ b/.github/workflows/build-salt-onedir.yml @@ -21,7 +21,7 @@ on: relenv-version: required: false type: string - default: 0.10.0 + default: 0.10.2 description: The version of relenv to use python-version-linux: required: false diff --git a/.github/workflows/build-windows-packages.yml b/.github/workflows/build-windows-packages.yml index b30150a575f..4831a59e718 100644 --- a/.github/workflows/build-windows-packages.yml +++ b/.github/workflows/build-windows-packages.yml @@ -7,12 +7,17 @@ on: salt-version: type: string required: true - description: The Salt version to set prior to building packages. + description: The Salt version to set prior to building packages + environment: + type: string + description: The GitHub Environment where this workflow should run + default: ci jobs: build-pkgs: name: Windows + environment: ${{ inputs.environment }} strategy: fail-fast: false max-parallel: 2 @@ -22,7 +27,27 @@ jobs: - amd64 runs-on: - windows-latest + env: + SM_HOST: "${{ secrets.WIN_SIGN_HOST_PROD }}" + SM_API_KEY: "${{ secrets.WIN_SIGN_API_KEY }}" + SM_CLIENT_CERT_FILE: "D:\\Certificate_pkcs12.p12" + SM_CLIENT_CERT_PASSWORD: "${{ secrets.WIN_SIGN_CERT_PASSWORD }}" + SM_CLIENT_CERT_FILE_B64: "${{ secrets.WIN_SIGN_CERT_FILE_B64 }}" + WIN_SIGN_CERT_SHA1_HASH: "${{ secrets.WIN_SIGN_CERT_SHA1_HASH }}" + steps: + - name: Check Package Signing Enabled + shell: bash + id: check-pkg-sign + run: | + if [ "${{ (secrets.WIN_SIGN_API_KEY != '' && env.SM_HOST != '' && inputs.environment == 'staging') && 'true' || 'false' }}" != "true" ]; then + echo "The packages created will NOT be signed" + echo "sign-pkgs=false" >> "$GITHUB_OUTPUT" + else + echo "The packages created WILL be signed" + echo "sign-pkgs=true" >> "$GITHUB_OUTPUT" + fi + - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: @@ -43,9 +68,22 @@ jobs: name: salt-${{ inputs.salt-version }}-onedir-windows-${{ matrix.arch }}.zip path: artifacts/ + - name: Code signing with Software Trust Manager + if: ${{ steps.check-pkg-sign.outputs.sign-pkgs == 'true' }} + uses: digicert/ssm-code-signing@v0.0.2 + + - name: Setup Certificate + if: ${{ steps.check-pkg-sign.outputs.sign-pkgs == 'true' }} + shell: bash + run: | + echo "${{ secrets.WIN_SIGN_CERT_FILE_B64 }}" | base64 --decode > /d/Certificate_pkcs12.p12 + - name: Build Windows Packages run: | - tools pkg build windows --onedir salt-${{ inputs.salt-version }}-onedir-windows-${{ matrix.arch }}.zip --salt-version ${{ inputs.salt-version }} --arch ${{ matrix.arch }} + tools pkg build windows --onedir salt-${{ inputs.salt-version }}-onedir-windows-${{ matrix.arch }}.zip ` + --salt-version ${{ inputs.salt-version }} --arch ${{ matrix.arch }} ${{ + steps.check-pkg-sign.outputs.sign-pkgs == 'true' && '--sign' || '' + }} - name: Upload ${{ matrix.arch }} Packages uses: actions/upload-artifact@v3 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d9e4965b09f..49f7240dcc5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ on: env: COLUMNS: 190 - CACHE_SEED: SEED-1 # Bump the number to invalidate all caches + CACHE_SEED: SEED-3 # Bump the number to invalidate all caches RELENV_DATA: "${{ github.workspace }}/.relenv" permissions: @@ -33,6 +33,7 @@ jobs: jobs: ${{ steps.define-jobs.outputs.jobs }} runners: ${{ steps.runner-types.outputs.runners }} changed-files: ${{ steps.process-changed-files.outputs.changed-files }} + pull-labels: ${{ steps.get-pull-labels.outputs.labels }} testrun: ${{ steps.define-testrun.outputs.testrun }} salt-version: ${{ steps.setup-salt-version.outputs.salt-version }} cache-seed: ${{ steps.set-cache-seed.outputs.cache-seed }} @@ -83,6 +84,7 @@ jobs: - *doc_requirements workflows: - added|modified: + - cicd/shared-gh-workflows-context.yml - .github/actions/**/action.yml - .github/workflows/*.yml - .github/workflows/templates/*.yml.jinja2 @@ -135,6 +137,36 @@ jobs: salt-version: "" validate-version: true + - name: Get Pull Number + if: ${{ github.event_name == 'pull_request' }} + id: get-pull-number + uses: ./.github/actions/get-pull-number + with: + owner: ${{ github.repository_owner }} + repo: ${{ github.event.repository.name }} + sha: ${{ github.sha }} + pull-number: ${{ github.event.pull_request.number }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get Pull Request + if: ${{ github.event_name == 'pull_request' }} + id: get-pull-request + uses: ./.github/actions/get-pull-request + with: + owner: ${{ github.repository_owner }} + repo: ${{ github.event.repository.name }} + pull-number: ${{ steps.get-pull-number.outputs.number }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get Pull Labels + if: ${{ github.event_name == 'pull_request' }} + id: get-pull-labels + uses: ./.github/actions/get-pull-labels + with: + pull-request: ${{ steps.get-pull-request.outputs.pull-request }} + - name: Write Changed Files To A Local File run: echo '${{ toJSON(steps.changed-files.outputs) }}' > changed-files.json @@ -402,10 +434,10 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" self-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }} github-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['github-hosted'] }} - relenv-version: "0.10.1" - python-version-linux: "3.10.10" - python-version-macos: "3.10.10" - python-version-windows: "3.10.10" + relenv-version: "0.11.2" + python-version-linux: "3.10.11" + python-version-macos: "3.10.11" + python-version-windows: "3.10.11" build-salt-onedir: name: Build Salt Onedir @@ -420,10 +452,10 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" self-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }} github-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['github-hosted'] }} - relenv-version: "0.10.1" - python-version-linux: "3.10.10" - python-version-macos: "3.10.10" - python-version-windows: "3.10.10" + relenv-version: "0.11.2" + python-version-linux: "3.10.11" + python-version-macos: "3.10.11" + python-version-windows: "3.10.11" build-rpm-pkgs: name: Build RPM Packages @@ -478,7 +510,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -495,7 +527,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -512,7 +544,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -529,7 +561,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -546,7 +578,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -563,7 +595,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -580,7 +612,41 @@ jobs: arch: aarch64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + skip-code-coverage: ${{ github.event_name == 'pull_request' }} + skip-junit-reports: ${{ github.event_name == 'pull_request' }} + + photonos-3-pkg-tests: + name: Photon OS 3 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-3 + platform: linux + arch: x86_64 + salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" + pkg-type: rpm + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + skip-code-coverage: ${{ github.event_name == 'pull_request' }} + skip-junit-reports: ${{ github.event_name == 'pull_request' }} + + photonos-4-pkg-tests: + name: Photon OS 4 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 + platform: linux + arch: x86_64 + salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" + pkg-type: rpm + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -597,7 +663,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -614,7 +680,7 @@ jobs: arch: aarch64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -631,7 +697,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -648,7 +714,7 @@ jobs: arch: aarch64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -665,7 +731,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: macos - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -682,7 +748,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: NSIS - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -699,7 +765,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: MSI - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -716,7 +782,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: NSIS - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -733,7 +799,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: MSI - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -750,7 +816,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: NSIS - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -767,7 +833,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: MSI - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -785,7 +851,8 @@ jobs: arch: amd64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -803,7 +870,8 @@ jobs: arch: amd64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -821,7 +889,8 @@ jobs: arch: amd64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -839,7 +908,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -857,7 +927,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -875,7 +946,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -893,7 +965,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -911,7 +984,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -929,7 +1003,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -947,7 +1022,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -965,7 +1041,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -983,7 +1060,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -1001,7 +1079,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -1019,7 +1098,8 @@ jobs: arch: aarch64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -1037,7 +1117,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -1055,7 +1136,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -1073,7 +1155,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -1091,7 +1174,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -1109,7 +1193,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -1127,7 +1212,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -1145,7 +1231,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -1163,7 +1250,8 @@ jobs: arch: aarch64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -1181,7 +1269,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -1199,7 +1288,8 @@ jobs: arch: aarch64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: ${{ github.event_name == 'pull_request' }} skip-junit-reports: ${{ github.event_name == 'pull_request' }} @@ -1247,6 +1337,8 @@ jobs: - debian-10-pkg-tests - debian-11-pkg-tests - debian-11-arm64-pkg-tests + - photonos-3-pkg-tests + - photonos-4-pkg-tests - ubuntu-2004-pkg-tests - ubuntu-2004-arm64-pkg-tests - ubuntu-2204-pkg-tests diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index e3a5fb86b8c..1cc7062c94d 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -13,7 +13,7 @@ on: env: COLUMNS: 190 - CACHE_SEED: SEED-1 # Bump the number to invalidate all caches + CACHE_SEED: SEED-3 # Bump the number to invalidate all caches RELENV_DATA: "${{ github.workspace }}/.relenv" permissions: @@ -36,7 +36,7 @@ jobs: - name: Check Requirements id: check-requirements run: | - if [ "${RUN_SCHEDULED_BUILDS}" = "1" ]; then + if [ "${{ vars.RUN_SCHEDULED_BUILDS }}" = "1" ]; then MSG="Running workflow because RUN_SCHEDULED_BUILDS=1" echo "${MSG}" echo "${MSG}" >> "${GITHUB_STEP_SUMMARY}" @@ -77,6 +77,7 @@ jobs: jobs: ${{ steps.define-jobs.outputs.jobs }} runners: ${{ steps.runner-types.outputs.runners }} changed-files: ${{ steps.process-changed-files.outputs.changed-files }} + pull-labels: ${{ steps.get-pull-labels.outputs.labels }} testrun: ${{ steps.define-testrun.outputs.testrun }} salt-version: ${{ steps.setup-salt-version.outputs.salt-version }} cache-seed: ${{ steps.set-cache-seed.outputs.cache-seed }} @@ -127,6 +128,7 @@ jobs: - *doc_requirements workflows: - added|modified: + - cicd/shared-gh-workflows-context.yml - .github/actions/**/action.yml - .github/workflows/*.yml - .github/workflows/templates/*.yml.jinja2 @@ -179,6 +181,36 @@ jobs: salt-version: "" validate-version: true + - name: Get Pull Number + if: ${{ github.event_name == 'pull_request' }} + id: get-pull-number + uses: ./.github/actions/get-pull-number + with: + owner: ${{ github.repository_owner }} + repo: ${{ github.event.repository.name }} + sha: ${{ github.sha }} + pull-number: ${{ github.event.pull_request.number }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get Pull Request + if: ${{ github.event_name == 'pull_request' }} + id: get-pull-request + uses: ./.github/actions/get-pull-request + with: + owner: ${{ github.repository_owner }} + repo: ${{ github.event.repository.name }} + pull-number: ${{ steps.get-pull-number.outputs.number }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get Pull Labels + if: ${{ github.event_name == 'pull_request' }} + id: get-pull-labels + uses: ./.github/actions/get-pull-labels + with: + pull-request: ${{ steps.get-pull-request.outputs.pull-request }} + - name: Write Changed Files To A Local File run: echo '${{ toJSON(steps.changed-files.outputs) }}' > changed-files.json @@ -318,8 +350,13 @@ jobs: shell: bash if: ${{ startsWith(github.event.ref, 'refs/tags') == false }} run: | - tools changelog update-release-notes --draft - tools changelog update-release-notes + if [ "${{ contains(fromJSON('["master"]'), github.ref_name) }}" == "true" ]; then + tools changelog update-release-notes --draft --next-release + tools changelog update-release-notes --next-release + else + tools changelog update-release-notes --draft + tools changelog update-release-notes + fi - name: Generate MAN Pages shell: bash @@ -446,10 +483,10 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" self-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }} github-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['github-hosted'] }} - relenv-version: "0.10.1" - python-version-linux: "3.10.10" - python-version-macos: "3.10.10" - python-version-windows: "3.10.10" + relenv-version: "0.11.2" + python-version-linux: "3.10.11" + python-version-macos: "3.10.11" + python-version-windows: "3.10.11" build-salt-onedir: name: Build Salt Onedir @@ -464,10 +501,10 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" self-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }} github-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['github-hosted'] }} - relenv-version: "0.10.1" - python-version-linux: "3.10.10" - python-version-macos: "3.10.10" - python-version-windows: "3.10.10" + relenv-version: "0.11.2" + python-version-linux: "3.10.11" + python-version-macos: "3.10.11" + python-version-windows: "3.10.11" build-rpm-pkgs: name: Build RPM Packages @@ -498,6 +535,8 @@ jobs: uses: ./.github/workflows/build-windows-packages.yml with: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" + environment: nightly + secrets: inherit build-macos-pkgs: name: Build macOS Packages @@ -508,6 +547,8 @@ jobs: uses: ./.github/workflows/build-macos-packages.yml with: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" + environment: nightly + secrets: inherit amazonlinux-2-pkg-tests: name: Amazon Linux 2 Package Tests @@ -522,7 +563,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -539,7 +580,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -556,7 +597,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -573,7 +614,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -590,7 +631,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -607,7 +648,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -624,7 +665,41 @@ jobs: arch: aarch64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + skip-code-coverage: false + skip-junit-reports: false + + photonos-3-pkg-tests: + name: Photon OS 3 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-3 + platform: linux + arch: x86_64 + salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" + pkg-type: rpm + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + skip-code-coverage: false + skip-junit-reports: false + + photonos-4-pkg-tests: + name: Photon OS 4 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 + platform: linux + arch: x86_64 + salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" + pkg-type: rpm + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -641,7 +716,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -658,7 +733,7 @@ jobs: arch: aarch64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -675,7 +750,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -692,7 +767,7 @@ jobs: arch: aarch64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -709,7 +784,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: macos - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -726,7 +801,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: NSIS - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -743,7 +818,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: MSI - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -760,7 +835,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: NSIS - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -777,7 +852,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: MSI - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -794,7 +869,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: NSIS - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -811,7 +886,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: MSI - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -829,7 +904,8 @@ jobs: arch: amd64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -847,7 +923,8 @@ jobs: arch: amd64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -865,7 +942,8 @@ jobs: arch: amd64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -883,7 +961,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -901,7 +980,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -919,7 +999,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -937,7 +1018,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -955,7 +1037,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -973,7 +1056,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -991,7 +1075,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1009,7 +1094,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1027,7 +1113,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1045,7 +1132,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1063,7 +1151,8 @@ jobs: arch: aarch64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1081,7 +1170,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1099,7 +1189,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1117,7 +1208,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1135,7 +1227,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1153,7 +1246,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1171,7 +1265,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1189,7 +1284,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1207,7 +1303,8 @@ jobs: arch: aarch64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1225,7 +1322,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1243,7 +1341,8 @@ jobs: arch: aarch64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1501,6 +1600,18 @@ jobs: - distro: fedora version: "38" arch: aarch64 + - distro: photon + version: "3" + arch: x86_64 + - distro: photon + version: "3" + arch: aarch64 + - distro: photon + version: "4" + arch: x86_64 + - distro: photon + version: "4" + arch: aarch64 steps: - uses: actions/checkout@v3 @@ -1956,6 +2067,8 @@ jobs: - debian-10-pkg-tests - debian-11-pkg-tests - debian-11-arm64-pkg-tests + - photonos-3-pkg-tests + - photonos-4-pkg-tests - ubuntu-2004-pkg-tests - ubuntu-2004-arm64-pkg-tests - ubuntu-2204-pkg-tests diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bae0f6fb0db..3c44a807a99 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,10 +14,14 @@ on: description: > The Salt version to get from staging to publish the release. (DO NOT prefix the version with a v, ie, 3006.0 NOT v3006.0). + skip-salt-pkg-download-test-suite: + type: boolean + default: false + description: Skip running the Salt packages download test suite. env: COLUMNS: 190 - CACHE_SEED: SEED-1 # Bump the number to invalidate all caches + CACHE_SEED: SEED-3 # Bump the number to invalidate all caches RELENV_DATA: "${{ github.workspace }}/.relenv" permissions: @@ -151,54 +155,6 @@ jobs: run: | tools pkg repo publish release ${{ needs.prepare-workflow.outputs.salt-version }} - test-linux-pkg-downloads: - name: Test Linux Package Downloads - needs: - - prepare-workflow - - publish-repositories - uses: ./.github/workflows/test-package-downloads-action-linux.yml - with: - distro-slug: ubuntu-latest - platform: linux - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 - salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - environment: release - skip-code-coverage: true - artifacts-from-workflow: staging.yml - secrets: inherit - - test-macos-pkg-downloads: - name: Test macOS Package Downloads - needs: - - prepare-workflow - - publish-repositories - uses: ./.github/workflows/test-package-downloads-action-macos.yml - with: - distro-slug: macos-12 - platform: darwin - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 - salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - environment: release - skip-code-coverage: true - artifacts-from-workflow: staging.yml - secrets: inherit - - test-windows-pkg-downloads: - name: Test Windows Package Downloads - needs: - - prepare-workflow - - publish-repositories - uses: ./.github/workflows/test-package-downloads-action-windows.yml - with: - distro-slug: windows-2022 - platform: windows - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 - salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - environment: release - skip-code-coverage: true - artifacts-from-workflow: staging.yml - secrets: inherit - release: name: Release v${{ needs.prepare-workflow.outputs.salt-version }} runs-on: @@ -209,9 +165,6 @@ jobs: - prepare-workflow - backup - publish-repositories - - test-linux-pkg-downloads - - test-macos-pkg-downloads - - test-windows-pkg-downloads environment: release steps: - name: Clone The Salt Repository @@ -310,7 +263,7 @@ jobs: restore: name: Restore Release Bucket From Backup - if: ${{ failure() || cancelled() }} + if: ${{ always() }} runs-on: - self-hosted - linux @@ -320,24 +273,28 @@ jobs: environment: release steps: - name: Clone The Salt Repository + if: ${{ failure() || cancelled() }} uses: actions/checkout@v3 with: ssh-key: ${{ secrets.GHA_SSH_KEY }} - name: Setup Rclone + if: ${{ failure() || cancelled() }} uses: AnimMouse/setup-rclone@v1 with: version: v1.61.1 - name: Setup Python Tools Scripts + if: ${{ failure() || cancelled() }} uses: ./.github/actions/setup-python-tools-scripts - name: Restore Release Bucket + if: ${{ failure() || cancelled() }} run: | tools pkg repo restore-previous-releases publish-pypi: - name: Publish to PyPi(test) + name: Publish to PyPi if: ${{ github.event.repository.fork != true }} needs: - prepare-workflow @@ -384,7 +341,7 @@ jobs: name: pypi-artifacts path: artifacts/release - - name: Publish to Test PyPi + - name: Publish to PyPi env: TWINE_PASSWORD: "${{ steps.get-secrets.outputs.twine-password }}" run: | diff --git a/.github/workflows/scheduled.yml b/.github/workflows/scheduled.yml index 638ee727b63..b00b7e8d1e6 100644 --- a/.github/workflows/scheduled.yml +++ b/.github/workflows/scheduled.yml @@ -12,7 +12,7 @@ on: env: COLUMNS: 190 - CACHE_SEED: SEED-1 # Bump the number to invalidate all caches + CACHE_SEED: SEED-3 # Bump the number to invalidate all caches RELENV_DATA: "${{ github.workspace }}/.relenv" permissions: @@ -35,7 +35,7 @@ jobs: - name: Check Requirements id: check-requirements run: | - if [ "${RUN_SCHEDULED_BUILDS}" = "1" ]; then + if [ "${{ vars.RUN_SCHEDULED_BUILDS }}" = "1" ]; then MSG="Running workflow because RUN_SCHEDULED_BUILDS=1" echo "${MSG}" echo "${MSG}" >> "${GITHUB_STEP_SUMMARY}" @@ -76,6 +76,7 @@ jobs: jobs: ${{ steps.define-jobs.outputs.jobs }} runners: ${{ steps.runner-types.outputs.runners }} changed-files: ${{ steps.process-changed-files.outputs.changed-files }} + pull-labels: ${{ steps.get-pull-labels.outputs.labels }} testrun: ${{ steps.define-testrun.outputs.testrun }} salt-version: ${{ steps.setup-salt-version.outputs.salt-version }} cache-seed: ${{ steps.set-cache-seed.outputs.cache-seed }} @@ -126,6 +127,7 @@ jobs: - *doc_requirements workflows: - added|modified: + - cicd/shared-gh-workflows-context.yml - .github/actions/**/action.yml - .github/workflows/*.yml - .github/workflows/templates/*.yml.jinja2 @@ -178,6 +180,36 @@ jobs: salt-version: "" validate-version: true + - name: Get Pull Number + if: ${{ github.event_name == 'pull_request' }} + id: get-pull-number + uses: ./.github/actions/get-pull-number + with: + owner: ${{ github.repository_owner }} + repo: ${{ github.event.repository.name }} + sha: ${{ github.sha }} + pull-number: ${{ github.event.pull_request.number }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get Pull Request + if: ${{ github.event_name == 'pull_request' }} + id: get-pull-request + uses: ./.github/actions/get-pull-request + with: + owner: ${{ github.repository_owner }} + repo: ${{ github.event.repository.name }} + pull-number: ${{ steps.get-pull-number.outputs.number }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get Pull Labels + if: ${{ github.event_name == 'pull_request' }} + id: get-pull-labels + uses: ./.github/actions/get-pull-labels + with: + pull-request: ${{ steps.get-pull-request.outputs.pull-request }} + - name: Write Changed Files To A Local File run: echo '${{ toJSON(steps.changed-files.outputs) }}' > changed-files.json @@ -445,10 +477,10 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" self-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }} github-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['github-hosted'] }} - relenv-version: "0.10.1" - python-version-linux: "3.10.10" - python-version-macos: "3.10.10" - python-version-windows: "3.10.10" + relenv-version: "0.11.2" + python-version-linux: "3.10.11" + python-version-macos: "3.10.11" + python-version-windows: "3.10.11" build-salt-onedir: name: Build Salt Onedir @@ -463,10 +495,10 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" self-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }} github-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['github-hosted'] }} - relenv-version: "0.10.1" - python-version-linux: "3.10.10" - python-version-macos: "3.10.10" - python-version-windows: "3.10.10" + relenv-version: "0.11.2" + python-version-linux: "3.10.11" + python-version-macos: "3.10.11" + python-version-windows: "3.10.11" build-rpm-pkgs: name: Build RPM Packages @@ -521,7 +553,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -538,7 +570,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -555,7 +587,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -572,7 +604,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -589,7 +621,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -606,7 +638,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -623,7 +655,41 @@ jobs: arch: aarch64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + skip-code-coverage: false + skip-junit-reports: false + + photonos-3-pkg-tests: + name: Photon OS 3 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-3 + platform: linux + arch: x86_64 + salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" + pkg-type: rpm + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + skip-code-coverage: false + skip-junit-reports: false + + photonos-4-pkg-tests: + name: Photon OS 4 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 + platform: linux + arch: x86_64 + salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" + pkg-type: rpm + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -640,7 +706,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -657,7 +723,7 @@ jobs: arch: aarch64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -674,7 +740,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -691,7 +757,7 @@ jobs: arch: aarch64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -708,7 +774,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: macos - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -725,7 +791,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: NSIS - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -742,7 +808,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: MSI - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -759,7 +825,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: NSIS - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -776,7 +842,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: MSI - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -793,7 +859,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: NSIS - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -810,7 +876,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: MSI - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: false skip-junit-reports: false @@ -828,7 +894,8 @@ jobs: arch: amd64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -846,7 +913,8 @@ jobs: arch: amd64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -864,7 +932,8 @@ jobs: arch: amd64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -882,7 +951,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -900,7 +970,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -918,7 +989,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -936,7 +1008,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -954,7 +1027,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -972,7 +1046,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -990,7 +1065,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1008,7 +1084,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1026,7 +1103,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1044,7 +1122,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1062,7 +1141,8 @@ jobs: arch: aarch64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1080,7 +1160,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1098,7 +1179,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1116,7 +1198,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1134,7 +1217,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1152,7 +1236,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1170,7 +1255,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1188,7 +1274,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1206,7 +1293,8 @@ jobs: arch: aarch64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1224,7 +1312,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1242,7 +1331,8 @@ jobs: arch: aarch64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: false skip-junit-reports: false @@ -1292,6 +1382,8 @@ jobs: - debian-10-pkg-tests - debian-11-pkg-tests - debian-11-arm64-pkg-tests + - photonos-3-pkg-tests + - photonos-4-pkg-tests - ubuntu-2004-pkg-tests - ubuntu-2004-arm64-pkg-tests - ubuntu-2204-pkg-tests diff --git a/.github/workflows/scripts/update_winrepo.py b/.github/workflows/scripts/update_winrepo.py new file mode 100644 index 00000000000..b12d6558a4d --- /dev/null +++ b/.github/workflows/scripts/update_winrepo.py @@ -0,0 +1,31 @@ +import argparse +import os + +# Where are we +print(os.getcwd()) + +arg_parser = argparse.ArgumentParser() +arg_parser.add_argument("-f", "--file", help="the winrepo file to edit") +arg_parser.add_argument("-v", "--version", help="The version to add") + +args = arg_parser.parse_args() +file = args.file +version = args.version + +if version.startswith("v"): + version = version[1:] + +with open(file) as f: + current_contents = f.readlines() + +new_contents = [] + +added = False +for line in current_contents: + new_contents.append(line) + if "for version in [" in line and not added: + new_contents.append(f" '{version}',\n") + added = True + +with open(file, "w") as f: + f.writelines(new_contents) diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml index 2149dd712fb..0c0f5c5f88a 100644 --- a/.github/workflows/staging.yml +++ b/.github/workflows/staging.yml @@ -22,10 +22,14 @@ on: type: boolean default: false description: Skip running the Salt packages test suite. + skip-salt-pkg-download-test-suite: + type: boolean + default: false + description: Skip running the Salt packages download test suite. env: COLUMNS: 190 - CACHE_SEED: SEED-1 # Bump the number to invalidate all caches + CACHE_SEED: SEED-3 # Bump the number to invalidate all caches RELENV_DATA: "${{ github.workspace }}/.relenv" permissions: @@ -69,6 +73,7 @@ jobs: jobs: ${{ steps.define-jobs.outputs.jobs }} runners: ${{ steps.runner-types.outputs.runners }} changed-files: ${{ steps.process-changed-files.outputs.changed-files }} + pull-labels: ${{ steps.get-pull-labels.outputs.labels }} testrun: ${{ steps.define-testrun.outputs.testrun }} salt-version: ${{ steps.setup-salt-version.outputs.salt-version }} cache-seed: ${{ steps.set-cache-seed.outputs.cache-seed }} @@ -119,6 +124,7 @@ jobs: - *doc_requirements workflows: - added|modified: + - cicd/shared-gh-workflows-context.yml - .github/actions/**/action.yml - .github/workflows/*.yml - .github/workflows/templates/*.yml.jinja2 @@ -171,6 +177,36 @@ jobs: salt-version: "${{ inputs.salt-version }}" validate-version: true + - name: Get Pull Number + if: ${{ github.event_name == 'pull_request' }} + id: get-pull-number + uses: ./.github/actions/get-pull-number + with: + owner: ${{ github.repository_owner }} + repo: ${{ github.event.repository.name }} + sha: ${{ github.sha }} + pull-number: ${{ github.event.pull_request.number }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get Pull Request + if: ${{ github.event_name == 'pull_request' }} + id: get-pull-request + uses: ./.github/actions/get-pull-request + with: + owner: ${{ github.repository_owner }} + repo: ${{ github.event.repository.name }} + pull-number: ${{ steps.get-pull-number.outputs.number }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get Pull Labels + if: ${{ github.event_name == 'pull_request' }} + id: get-pull-labels + uses: ./.github/actions/get-pull-labels + with: + pull-request: ${{ steps.get-pull-request.outputs.pull-request }} + - name: Check Existing Releases env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -208,7 +244,7 @@ jobs: - name: Define Jobs id: define-jobs run: | - tools ci define-jobs${{ inputs.skip-salt-test-suite && ' --skip-tests' || '' }}${{ inputs.skip-salt-pkg-test-suite && ' --skip-pkg-tests' || '' }} ${{ github.event_name }} changed-files.json + tools ci define-jobs${{ inputs.skip-salt-test-suite && ' --skip-tests' || '' }}${{ inputs.skip-salt-pkg-test-suite && ' --skip-pkg-tests' || '' }}${{ inputs.skip-salt-pkg-download-test-suite && ' --skip-pkg-download-tests' || '' }} ${{ github.event_name }} changed-files.json - name: Check Defined Jobs run: | @@ -448,10 +484,10 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" self-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }} github-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['github-hosted'] }} - relenv-version: "0.10.1" - python-version-linux: "3.10.10" - python-version-macos: "3.10.10" - python-version-windows: "3.10.10" + relenv-version: "0.11.2" + python-version-linux: "3.10.11" + python-version-macos: "3.10.11" + python-version-windows: "3.10.11" build-salt-onedir: name: Build Salt Onedir @@ -466,10 +502,10 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" self-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }} github-hosted-runners: ${{ fromJSON(needs.prepare-workflow.outputs.runners)['github-hosted'] }} - relenv-version: "0.10.1" - python-version-linux: "3.10.10" - python-version-macos: "3.10.10" - python-version-windows: "3.10.10" + relenv-version: "0.11.2" + python-version-linux: "3.10.11" + python-version-macos: "3.10.11" + python-version-windows: "3.10.11" build-rpm-pkgs: name: Build RPM Packages @@ -500,6 +536,8 @@ jobs: uses: ./.github/workflows/build-windows-packages.yml with: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" + environment: staging + secrets: inherit build-macos-pkgs: name: Build macOS Packages @@ -510,6 +548,8 @@ jobs: uses: ./.github/workflows/build-macos-packages.yml with: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" + environment: staging + secrets: inherit amazonlinux-2-pkg-tests: name: Amazon Linux 2 Package Tests @@ -524,7 +564,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -541,7 +581,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -558,7 +598,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -575,7 +615,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: rpm - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -592,7 +632,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -609,7 +649,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -626,7 +666,41 @@ jobs: arch: aarch64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + skip-code-coverage: true + skip-junit-reports: true + + photonos-3-pkg-tests: + name: Photon OS 3 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-3 + platform: linux + arch: x86_64 + salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" + pkg-type: rpm + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + skip-code-coverage: true + skip-junit-reports: true + + photonos-4-pkg-tests: + name: Photon OS 4 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 + platform: linux + arch: x86_64 + salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" + pkg-type: rpm + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -643,7 +717,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -660,7 +734,7 @@ jobs: arch: aarch64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -677,7 +751,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -694,7 +768,7 @@ jobs: arch: aarch64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: deb - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -711,7 +785,7 @@ jobs: arch: x86_64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: macos - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -728,7 +802,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: NSIS - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -745,7 +819,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: MSI - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -762,7 +836,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: NSIS - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -779,7 +853,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: MSI - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -796,7 +870,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: NSIS - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -813,7 +887,7 @@ jobs: arch: amd64 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" pkg-type: MSI - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 skip-code-coverage: true skip-junit-reports: true @@ -831,7 +905,8 @@ jobs: arch: amd64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -849,7 +924,8 @@ jobs: arch: amd64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -867,7 +943,8 @@ jobs: arch: amd64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -885,7 +962,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -903,7 +981,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -921,7 +1000,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -939,7 +1019,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -957,7 +1038,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -975,7 +1057,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -993,7 +1076,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -1011,7 +1095,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -1029,7 +1114,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -1047,7 +1133,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -1065,7 +1152,8 @@ jobs: arch: aarch64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -1083,7 +1171,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -1101,7 +1190,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -1119,7 +1209,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -1137,7 +1228,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -1155,7 +1247,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -1173,7 +1266,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -1191,7 +1285,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -1209,7 +1304,8 @@ jobs: arch: aarch64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -1227,7 +1323,8 @@ jobs: arch: x86_64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -1245,7 +1342,8 @@ jobs: arch: aarch64 testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: true skip-junit-reports: true @@ -1503,6 +1601,18 @@ jobs: - distro: fedora version: "38" arch: aarch64 + - distro: photon + version: "3" + arch: x86_64 + - distro: photon + version: "3" + arch: aarch64 + - distro: photon + version: "4" + arch: x86_64 + - distro: photon + version: "4" + arch: aarch64 steps: - uses: actions/checkout@v3 @@ -1976,6 +2086,7 @@ jobs: test-linux-pkg-downloads: name: Test Linux 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 @@ -1983,7 +2094,7 @@ jobs: with: distro-slug: ubuntu-latest platform: linux - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" environment: staging skip-code-coverage: true @@ -1991,6 +2102,7 @@ jobs: test-macos-pkg-downloads: name: Test macOS 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 @@ -1998,13 +2110,14 @@ jobs: with: distro-slug: macos-12 platform: darwin - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" environment: staging skip-code-coverage: true secrets: inherit test-windows-pkg-downloads: + if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test-pkg-download'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }} name: Test Windows Package Downloads needs: - prepare-workflow @@ -2013,7 +2126,7 @@ jobs: with: distro-slug: windows-2022 platform: windows - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.10 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.11 salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" environment: staging skip-code-coverage: true @@ -2056,6 +2169,8 @@ jobs: - debian-10-pkg-tests - debian-11-pkg-tests - debian-11-arm64-pkg-tests + - photonos-3-pkg-tests + - photonos-4-pkg-tests - ubuntu-2004-pkg-tests - ubuntu-2004-arm64-pkg-tests - ubuntu-2204-pkg-tests diff --git a/.github/workflows/templates/build-packages.yml.jinja b/.github/workflows/templates/build-packages.yml.jinja index a9cb4fad39a..87a87d69b28 100644 --- a/.github/workflows/templates/build-packages.yml.jinja +++ b/.github/workflows/templates/build-packages.yml.jinja @@ -16,5 +16,9 @@ uses: ./.github/workflows/build-<{ pkg_type }>-packages.yml with: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" + <%- if pkg_type in ("macos", "windows") and gh_environment %> + environment: <{ gh_environment }> + secrets: inherit + <%- endif %> <%- endfor %> diff --git a/.github/workflows/templates/build-rpm-repo.yml.jinja b/.github/workflows/templates/build-rpm-repo.yml.jinja index 87af16d6e3c..49316861d47 100644 --- a/.github/workflows/templates/build-rpm-repo.yml.jinja +++ b/.github/workflows/templates/build-rpm-repo.yml.jinja @@ -18,6 +18,10 @@ ("fedora", "37", "aarch64"), ("fedora", "38", "x86_64"), ("fedora", "38", "aarch64"), + ("photon", "3", "x86_64"), + ("photon", "3", "aarch64"), + ("photon", "4", "x86_64"), + ("photon", "4", "aarch64"), ) %> - distro: <{ distro }> version: "<{ version }>" diff --git a/.github/workflows/templates/ci.yml.jinja b/.github/workflows/templates/ci.yml.jinja index ef410c20c28..538c0f91a33 100644 --- a/.github/workflows/templates/ci.yml.jinja +++ b/.github/workflows/templates/ci.yml.jinja @@ -116,8 +116,18 @@ on: shell: bash if: ${{ startsWith(github.event.ref, 'refs/tags') == false }} run: | + <%- if gh_environment == 'nightly' %> + if [ "${{ contains(fromJSON('["master"]'), github.ref_name) }}" == "true" ]; then + tools changelog update-release-notes --draft <%- if prepare_actual_release %> --release <%- endif %> --next-release + tools changelog update-release-notes <%- if prepare_actual_release %> --release <%- endif %> --next-release + else + tools changelog update-release-notes --draft <%- if prepare_actual_release %> --release <%- endif %> + tools changelog update-release-notes <%- if prepare_actual_release %> --release <%- endif %> + fi + <%- else %> tools changelog update-release-notes --draft <%- if prepare_actual_release %> --release <%- endif %> tools changelog update-release-notes <%- if prepare_actual_release %> --release <%- endif %> + <%- endif %> - name: Generate MAN Pages shell: bash diff --git a/.github/workflows/templates/layout.yml.jinja b/.github/workflows/templates/layout.yml.jinja index 9caa046796b..bbbae394ff3 100644 --- a/.github/workflows/templates/layout.yml.jinja +++ b/.github/workflows/templates/layout.yml.jinja @@ -3,13 +3,10 @@ <%- set prepare_workflow_if_check = prepare_workflow_if_check|default(False) %> <%- set prepare_workflow_skip_test_suite = prepare_workflow_skip_test_suite|default("") %> <%- set prepare_workflow_skip_pkg_test_suite = prepare_workflow_skip_pkg_test_suite|default("") %> +<%- set prepare_workflow_skip_pkg_download_test_suite = prepare_workflow_skip_pkg_download_test_suite|default("") %> <%- set prepare_workflow_salt_version_input = prepare_workflow_salt_version_input|default("") %> <%- set skip_test_coverage_check = skip_test_coverage_check|default("${{ github.event_name == 'pull_request' }}") %> <%- set skip_junit_reports_check = skip_junit_reports_check|default("${{ github.event_name == 'pull_request' }}") %> -<%- set python_version_linux = "3.10.10" %> -<%- set python_version_macos = "3.10.10" %> -<%- set python_version_windows = "3.10.10" %> -<%- set relenv_version = "0.10.1" %> <%- set gpg_key_id = "64CBBC8173D76B3F" %> <%- set prepare_actual_release = prepare_actual_release | default(False) %> <%- set release_branches = ["master", "3006.x"] %> @@ -23,7 +20,13 @@ run-name: "<{ workflow_name }> (${{ github.event_name == 'pull_request' && forma on: push: {} - pull_request: {} + pull_request: + types: + - labeled + - unlabeled + - opened + - reopened + - synchronize <%- endblock on %> @@ -31,7 +34,7 @@ on: env: COLUMNS: 190 - CACHE_SEED: SEED-1 # Bump the number to invalidate all caches + CACHE_SEED: SEED-3 # Bump the number to invalidate all caches RELENV_DATA: "${{ github.workspace }}/.relenv" <%- endblock env %> @@ -83,6 +86,7 @@ jobs: jobs: ${{ steps.define-jobs.outputs.jobs }} runners: ${{ steps.runner-types.outputs.runners }} changed-files: ${{ steps.process-changed-files.outputs.changed-files }} + pull-labels: ${{ steps.get-pull-labels.outputs.labels }} testrun: ${{ steps.define-testrun.outputs.testrun }} salt-version: ${{ steps.setup-salt-version.outputs.salt-version }} cache-seed: ${{ steps.set-cache-seed.outputs.cache-seed }} @@ -133,6 +137,7 @@ jobs: - *doc_requirements workflows: - added|modified: + - cicd/shared-gh-workflows-context.yml - .github/actions/**/action.yml - .github/workflows/*.yml - .github/workflows/templates/*.yml.jinja2 @@ -185,6 +190,36 @@ jobs: salt-version: "<{ prepare_workflow_salt_version_input }>" validate-version: true + - name: Get Pull Number + if: ${{ github.event_name == 'pull_request' }} + id: get-pull-number + uses: ./.github/actions/get-pull-number + with: + owner: ${{ github.repository_owner }} + repo: ${{ github.event.repository.name }} + sha: ${{ github.sha }} + pull-number: ${{ github.event.pull_request.number }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get Pull Request + if: ${{ github.event_name == 'pull_request' }} + id: get-pull-request + uses: ./.github/actions/get-pull-request + with: + owner: ${{ github.repository_owner }} + repo: ${{ github.event.repository.name }} + pull-number: ${{ steps.get-pull-number.outputs.number }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get Pull Labels + if: ${{ github.event_name == 'pull_request' }} + id: get-pull-labels + uses: ./.github/actions/get-pull-labels + with: + pull-request: ${{ steps.get-pull-request.outputs.pull-request }} + <%- if prepare_actual_release %> - name: Check Existing Releases @@ -226,7 +261,7 @@ jobs: - name: Define Jobs id: define-jobs run: | - tools ci define-jobs<{ prepare_workflow_skip_test_suite }><{ prepare_workflow_skip_pkg_test_suite }> ${{ github.event_name }} changed-files.json + tools ci define-jobs<{ prepare_workflow_skip_test_suite }><{ prepare_workflow_skip_pkg_test_suite }><{ prepare_workflow_skip_pkg_download_test_suite }> ${{ github.event_name }} changed-files.json - name: Check Defined Jobs run: | diff --git a/.github/workflows/templates/release.yml.jinja b/.github/workflows/templates/release.yml.jinja index 39dc7b54def..73852ffefba 100644 --- a/.github/workflows/templates/release.yml.jinja +++ b/.github/workflows/templates/release.yml.jinja @@ -1,4 +1,5 @@ <%- set prepare_workflow_salt_version_input = "${{ inputs.salt-version }}" %> +<%- set prepare_workflow_skip_pkg_download_test_suite = "${{ inputs.skip-salt-pkg-download-test-suite && ' --skip-pkg-download-tests' || '' }}" %> <%- set gh_environment = "release" %> <%- extends 'layout.yml.jinja' %> @@ -22,6 +23,10 @@ on: description: > The Salt version to get from staging to publish the release. (DO NOT prefix the version with a v, ie, 3006.0 NOT v3006.0). + skip-salt-pkg-download-test-suite: + type: boolean + default: false + description: Skip running the Salt packages download test suite. <%- endblock on %> @@ -302,7 +307,7 @@ permissions: restore: <%- do conclusion_needs.append('restore') %> name: Restore Release Bucket From Backup - if: ${{ failure() || cancelled() }} + if: ${{ always() }} runs-on: - self-hosted - linux @@ -315,25 +320,29 @@ permissions: environment: <{ gh_environment }> steps: - name: Clone The Salt Repository + if: ${{ failure() || cancelled() }} uses: actions/checkout@v3 with: ssh-key: ${{ secrets.GHA_SSH_KEY }} - name: Setup Rclone + if: ${{ failure() || cancelled() }} uses: AnimMouse/setup-rclone@v1 with: version: v1.61.1 - name: Setup Python Tools Scripts + if: ${{ failure() || cancelled() }} uses: ./.github/actions/setup-python-tools-scripts - name: Restore Release Bucket + if: ${{ failure() || cancelled() }} run: | tools pkg repo restore-previous-releases publish-pypi: <%- do conclusion_needs.append('publish-pypi') %> - name: Publish to PyPi(test) + name: Publish to PyPi if: ${{ github.event.repository.fork != true }} needs: - prepare-workflow @@ -380,7 +389,7 @@ permissions: name: pypi-artifacts path: artifacts/release - - name: Publish to Test PyPi + - name: Publish to PyPi env: TWINE_PASSWORD: "${{ steps.get-secrets.outputs.twine-password }}" run: | diff --git a/.github/workflows/templates/staging.yml.jinja b/.github/workflows/templates/staging.yml.jinja index c56344e34ab..c34607eeeca 100644 --- a/.github/workflows/templates/staging.yml.jinja +++ b/.github/workflows/templates/staging.yml.jinja @@ -2,6 +2,7 @@ <%- set prepare_workflow_salt_version_input = "${{ inputs.salt-version }}" %> <%- set prepare_workflow_skip_test_suite = "${{ inputs.skip-salt-test-suite && ' --skip-tests' || '' }}" %> <%- set prepare_workflow_skip_pkg_test_suite = "${{ inputs.skip-salt-pkg-test-suite && ' --skip-pkg-tests' || '' }}" %> +<%- set prepare_workflow_skip_pkg_download_test_suite = "${{ inputs.skip-salt-pkg-download-test-suite && ' --skip-pkg-download-tests' || '' }}" %> <%- set gh_environment = "staging" %> <%- set prepare_actual_release = True %> <%- set skip_test_coverage_check = "true" %> @@ -34,6 +35,10 @@ on: type: boolean default: false description: Skip running the Salt packages test suite. + skip-salt-pkg-download-test-suite: + type: boolean + default: false + description: Skip running the Salt packages download test suite. <%- endblock on %> diff --git a/.github/workflows/templates/test-pkg-repo-downloads.yml.jinja b/.github/workflows/templates/test-pkg-repo-downloads.yml.jinja index 788d686fd7b..6c2c956c9b1 100644 --- a/.github/workflows/templates/test-pkg-repo-downloads.yml.jinja +++ b/.github/workflows/templates/test-pkg-repo-downloads.yml.jinja @@ -3,6 +3,11 @@ <{ job_name }>: <%- do test_repo_needs.append(job_name) %> name: Test Linux Package Downloads + <%- if gh_environment == "staging" %> + if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test-pkg-download'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }} + <%- else %> + if: ${{ inputs.skip-salt-pkg-download-test-suite == false }} + <%- endif %> needs: - prepare-workflow - publish-repositories @@ -25,6 +30,11 @@ <{ job_name }>: <%- do test_repo_needs.append(job_name) %> name: Test macOS Package Downloads + <%- if gh_environment == "staging" %> + if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test-pkg-download'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }} + <%- else %> + if: ${{ inputs.skip-salt-pkg-download-test-suite == false }} + <%- endif %> needs: - prepare-workflow - publish-repositories @@ -46,6 +56,11 @@ <{ job_name }>: <%- do test_repo_needs.append(job_name) %> + <%- if gh_environment == "staging" %> + if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test-pkg-download'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }} + <%- else %> + if: ${{ inputs.skip-salt-pkg-download-test-suite == false }} + <%- endif %> name: Test Windows Package Downloads needs: - prepare-workflow diff --git a/.github/workflows/templates/test-salt-pkg.yml.jinja b/.github/workflows/templates/test-salt-pkg.yml.jinja index 3cc2b1d6c61..99fc85db4fb 100644 --- a/.github/workflows/templates/test-salt-pkg.yml.jinja +++ b/.github/workflows/templates/test-salt-pkg.yml.jinja @@ -26,6 +26,8 @@ ("debian-10", "Debian 10", "x86_64", "deb"), ("debian-11", "Debian 11", "x86_64", "deb"), ("debian-11-arm64", "Debian 11 Arm64", "aarch64", "deb"), + ("photonos-3", "Photon OS 3", "x86_64", "rpm"), + ("photonos-4", "Photon OS 4", "x86_64", "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"), diff --git a/.github/workflows/templates/test-salt.yml.jinja b/.github/workflows/templates/test-salt.yml.jinja index f79c4124640..2eb0fb5e50e 100644 --- a/.github/workflows/templates/test-salt.yml.jinja +++ b/.github/workflows/templates/test-salt.yml.jinja @@ -19,6 +19,7 @@ testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|<{ python_version_windows }> + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: <{ skip_test_coverage_check }> skip-junit-reports: <{ skip_junit_reports_check }> @@ -42,6 +43,7 @@ testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|<{ python_version_macos }> + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: <{ skip_test_coverage_check }> skip-junit-reports: <{ skip_junit_reports_check }> @@ -84,6 +86,7 @@ testrun: ${{ needs.prepare-workflow.outputs.testrun }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|<{ python_version_linux }> + pull-labels: ${{ needs.prepare-workflow.outputs.pull-labels }} skip-code-coverage: <{ skip_test_coverage_check }> skip-junit-reports: <{ skip_junit_reports_check }> diff --git a/.github/workflows/templates/workflow-requirements-check.yml.jinja b/.github/workflows/templates/workflow-requirements-check.yml.jinja index 8fe06e6d6bb..419ee3f6f52 100644 --- a/.github/workflows/templates/workflow-requirements-check.yml.jinja +++ b/.github/workflows/templates/workflow-requirements-check.yml.jinja @@ -11,7 +11,7 @@ - name: Check Requirements id: check-requirements run: | - if [ "${RUN_SCHEDULED_BUILDS}" = "1" ]; then + if [ "${{ vars.RUN_SCHEDULED_BUILDS }}" = "1" ]; then MSG="Running workflow because RUN_SCHEDULED_BUILDS=1" echo "${MSG}" echo "${MSG}" >> "${GITHUB_STEP_SUMMARY}" diff --git a/.github/workflows/test-action-macos.yml b/.github/workflows/test-action-macos.yml index 601f25bdfad..971238966d1 100644 --- a/.github/workflows/test-action-macos.yml +++ b/.github/workflows/test-action-macos.yml @@ -42,6 +42,11 @@ on: type: string description: The onedir package name to use default: salt + pull-labels: + required: false + type: string + description: List of all the pull labels + default: '["test:slow", "test:core"]' skip-code-coverage: required: false type: boolean @@ -262,9 +267,36 @@ jobs: run: | sudo -E nox -e ${{ env.NOX_SESSION }} -- ${{ matrix.tests-chunk }} -- -k "mac or darwin" - - name: Run Slow/Changed Tests - id: run-slow-changed-tests - if: ${{ fromJSON(inputs.testrun)['type'] != 'full' }} + - name: Get Test Flags + id: get-test-flags + shell: bash + env: + PULL_LABELS: ${{ inputs.pull-labels }} + run: | + echo "$PULL_LABELS" + # shellcheck disable=SC2086 + no_fast_tests="$(jq -c '. | any(index("test:no-fast"))' <<< $PULL_LABELS)" + # shellcheck disable=SC2086 + slow_tests="$(jq -c '. | any(index("test:slow"))' <<< $PULL_LABELS)" + # shellcheck disable=SC2086 + core_tests="$(jq -c '. | any(index("test:core"))' <<< $PULL_LABELS)" + # shellcheck disable=SC2086 + flaky_jail_tests="$(jq -c '. | any(index("test:flaky-jail"))' <<< $PULL_LABELS)" + echo "$no_fast_tests" + echo "$slow_tests" + echo "$core_tests" + echo "$flaky_jail_tests" + # shellcheck disable=SC2086 + { + echo "no_fast_tests=$no_fast_tests"; + echo "slow_tests=$slow_tests"; + echo "core_tests=$core_tests"; + echo "flaky_jail_tests=$flaky_jail_tests"; + } >> "$GITHUB_OUTPUT" + + - name: Run Fast/Changed Tests + id: run-fast-changed-tests + if: ${{ fromJSON(inputs.testrun)['type'] != 'full' && steps.get-test-flags.outputs.no_fast_tests == 'true' }} env: SKIP_REQUIREMENTS_INSTALL: "1" PRINT_TEST_SELECTION: "0" @@ -276,11 +308,46 @@ jobs: SKIP_CODE_COVERAGE: "${{ inputs.skip-code-coverage && '1' || '0' }}" run: | sudo -E nox -e ${{ env.NOX_SESSION }} -- ${{ matrix.tests-chunk }} -- \ - -k "mac or darwin" --suppress-no-test-exit-code --run-slow --from-filenames=testrun-changed-files.txt + -k "mac or darwin" --suppress-no-test-exit-code \ + --from-filenames=testrun-changed-files.txt + + - name: Run Slow/Changed Tests + id: run-slow-changed-tests + if: ${{ fromJSON(inputs.testrun)['type'] != 'full' && steps.get-test-flags.outputs.slow_tests == 'false' }} + env: + SKIP_REQUIREMENTS_INSTALL: "1" + PRINT_TEST_SELECTION: "0" + PRINT_TEST_PLAN_ONLY: "0" + PRINT_SYSTEM_INFO: "0" + RERUN_FAILURES: "1" + GITHUB_ACTIONS_PIPELINE: "1" + SKIP_INITIAL_GH_ACTIONS_FAILURES: "1" + SKIP_CODE_COVERAGE: "${{ inputs.skip-code-coverage && '1' || '0' }}" + run: | + sudo -E nox -e ${{ env.NOX_SESSION }} -- ${{ matrix.tests-chunk }} -- \ + -k "mac or darwin" --suppress-no-test-exit-code --no-fast-tests --slow-tests \ + --from-filenames=testrun-changed-files.txt + + - name: Run Core/Changed Tests + id: run-core-changed-tests + if: ${{ fromJSON(inputs.testrun)['type'] != 'full' && steps.get-test-flags.outputs.core_tests == 'false' }} + env: + SKIP_REQUIREMENTS_INSTALL: "1" + PRINT_TEST_SELECTION: "0" + PRINT_TEST_PLAN_ONLY: "0" + PRINT_SYSTEM_INFO: "0" + RERUN_FAILURES: "1" + GITHUB_ACTIONS_PIPELINE: "1" + SKIP_INITIAL_GH_ACTIONS_FAILURES: "1" + SKIP_CODE_COVERAGE: "${{ inputs.skip-code-coverage && '1' || '0' }}" + run: | + sudo -E nox -e ${{ env.NOX_SESSION }} -- ${{ matrix.tests-chunk }} -- \ + -k "mac or darwin" --suppress-no-test-exit-code --no-fast-tests --core-tests \ + --from-filenames=testrun-changed-files.txt - name: Run Fast Tests id: run-fast-tests - if: ${{ fromJSON(inputs.testrun)['type'] != 'full' }} + if: ${{ fromJSON(inputs.testrun)['type'] != 'full' && steps.get-test-flags.outputs.no_fast_tests == 'false' }} env: SKIP_REQUIREMENTS_INSTALL: "1" PRINT_TEST_SELECTION: "0" @@ -292,7 +359,55 @@ jobs: SKIP_CODE_COVERAGE: "${{ inputs.skip-code-coverage && '1' || '0' }}" run: | sudo -E nox -e ${{ env.NOX_SESSION }} -- ${{ matrix.tests-chunk }} -- \ - -k "mac or darwin" + -k "mac or darwin" --suppress-no-test-exit-code + + - name: Run Slow Tests + id: run-slow-tests + if: ${{ fromJSON(inputs.testrun)['type'] != 'full' && steps.get-test-flags.outputs.slow_tests == 'true' }} + env: + SKIP_REQUIREMENTS_INSTALL: "1" + PRINT_TEST_SELECTION: "0" + PRINT_TEST_PLAN_ONLY: "0" + PRINT_SYSTEM_INFO: "0" + RERUN_FAILURES: "1" + GITHUB_ACTIONS_PIPELINE: "1" + SKIP_INITIAL_GH_ACTIONS_FAILURES: "1" + SKIP_CODE_COVERAGE: "${{ inputs.skip-code-coverage && '1' || '0' }}" + run: | + sudo -E nox -e ${{ env.NOX_SESSION }} -- ${{ matrix.tests-chunk }} -- \ + -k "mac or darwin" --suppress-no-test-exit-code --no-fast-tests --slow-tests + + - name: Run Core Tests + id: run-core-tests + if: ${{ fromJSON(inputs.testrun)['type'] != 'full' && steps.get-test-flags.outputs.core_tests == 'true' }} + env: + SKIP_REQUIREMENTS_INSTALL: "1" + PRINT_TEST_SELECTION: "0" + PRINT_TEST_PLAN_ONLY: "0" + PRINT_SYSTEM_INFO: "0" + RERUN_FAILURES: "1" + GITHUB_ACTIONS_PIPELINE: "1" + SKIP_INITIAL_GH_ACTIONS_FAILURES: "1" + SKIP_CODE_COVERAGE: "${{ inputs.skip-code-coverage && '1' || '0' }}" + run: | + sudo -E nox -e ${{ env.NOX_SESSION }} -- ${{ matrix.tests-chunk }} -- \ + -k "mac or darwin" --suppress-no-test-exit-code --no-fast-tests --core-tests + + - name: Run Flaky Tests + id: run-flaky-tests + if: ${{ fromJSON(inputs.testrun)['type'] != 'full' && steps.get-test-flags.outputs.flaky_jail_tests == 'false' }} + env: + SKIP_REQUIREMENTS_INSTALL: "1" + PRINT_TEST_SELECTION: "0" + PRINT_TEST_PLAN_ONLY: "0" + PRINT_SYSTEM_INFO: "0" + RERUN_FAILURES: "1" + GITHUB_ACTIONS_PIPELINE: "1" + SKIP_INITIAL_GH_ACTIONS_FAILURES: "1" + SKIP_CODE_COVERAGE: "${{ inputs.skip-code-coverage && '1' || '0' }}" + run: | + sudo -E nox -e ${{ env.NOX_SESSION }} -- ${{ matrix.tests-chunk }} -- \ + -k "mac or darwin" --suppress-no-test-exit-code --no-fast-tests --flaky-jail - name: Run Full Tests id: run-full-tests @@ -308,7 +423,7 @@ jobs: SKIP_CODE_COVERAGE: "${{ inputs.skip-code-coverage && '1' || '0' }}" run: | sudo -E nox -e ${{ env.NOX_SESSION }} -- ${{ matrix.tests-chunk }} -- \ - --run-slow -k "mac or darwin" + --slow-tests --core-tests -k "mac or darwin" - name: Fix file ownership run: | diff --git a/.github/workflows/test-action.yml b/.github/workflows/test-action.yml index 7553d710c23..b9ff40b3e3f 100644 --- a/.github/workflows/test-action.yml +++ b/.github/workflows/test-action.yml @@ -37,6 +37,11 @@ on: type: string description: The onedir package name to use default: salt + pull-labels: + required: false + type: string + description: List of all the pull labels + default: '["test:slow", "test:core"]' skip-code-coverage: required: false type: boolean @@ -194,7 +199,7 @@ jobs: - name: Destroy VM if: always() && steps.nox-dependencies-cache.outputs.cache-hit != 'true' run: | - tools --timestamps vm destroy ${{ inputs.distro-slug }} + tools --timestamps vm destroy --no-wait ${{ inputs.distro-slug }} - name: Upload Nox Requirements Tarball uses: actions/upload-artifact@v3 @@ -296,30 +301,99 @@ jobs: --nox-session=${{ env.NOX_SESSION }} ${{ inputs.distro-slug }} \ ${{ matrix.tests-chunk }} - - name: Run Slow/Changed Tests - id: run-slow-changed-tests - if: ${{ fromJSON(inputs.testrun)['type'] != 'full' }} + - name: Get Test Flags + id: get-test-flags + shell: bash + env: + PULL_LABELS: ${{ inputs.pull-labels }} + run: | + echo "$PULL_LABELS" + # shellcheck disable=SC2086 + no_fast_tests="$(jq -c '. | any(index("test:no-fast"))' <<< $PULL_LABELS)" + # shellcheck disable=SC2086 + slow_tests="$(jq -c '. | any(index("test:slow"))' <<< $PULL_LABELS)" + # shellcheck disable=SC2086 + core_tests="$(jq -c '. | any(index("test:core"))' <<< $PULL_LABELS)" + # shellcheck disable=SC2086 + flaky_jail_tests="$(jq -c '. | any(index("test:flaky-jail"))' <<< $PULL_LABELS)" + echo "$no_fast_tests" + echo "$slow_tests" + echo "$core_tests" + echo "$flaky_jail_tests" + # shellcheck disable=SC2086 + { + echo "no_fast_tests=$no_fast_tests"; + echo "slow_tests=$slow_tests"; + echo "core_tests=$core_tests"; + echo "flaky_jail_tests=$flaky_jail_tests"; + } >> "$GITHUB_OUTPUT" + + - name: Run Fast/Changed Tests + id: run-fast-changed-tests + if: ${{ fromJSON(inputs.testrun)['type'] != 'full' && steps.get-test-flags.outputs.no_fast_tests == 'true' }} run: | tools --timestamps --no-output-timeout-secs=1800 --timeout-secs=14400 vm test --skip-requirements-install \ - --nox-session=${{ env.NOX_SESSION }} --rerun-failures ${{ (inputs.skip-code-coverage && matrix.tests-chunk != 'unit') && '--skip-code-coverage' || '' }} \ - ${{ inputs.distro-slug }} ${{ matrix.tests-chunk }} -- \ - --run-slow --suppress-no-test-exit-code --from-filenames=testrun-changed-files.txt + --nox-session=${{ env.NOX_SESSION }} --rerun-failures ${{ inputs.distro-slug }} \ + ${{ matrix.tests-chunk }} -- --suppress-no-test-exit-code \ + --from-filenames=testrun-changed-files.txt + + - name: Run Slow/Changed Tests + id: run-slow-changed-tests + if: ${{ fromJSON(inputs.testrun)['type'] != 'full' && steps.get-test-flags.outputs.slow_tests == 'false' }} + run: | + tools --timestamps --no-output-timeout-secs=1800 --timeout-secs=14400 vm test --skip-requirements-install \ + --nox-session=${{ env.NOX_SESSION }} --rerun-failures ${{ inputs.distro-slug }} \ + ${{ matrix.tests-chunk }} -- --no-fast-tests --slow-tests --suppress-no-test-exit-code \ + --from-filenames=testrun-changed-files.txt + + - name: Run Core/Changed Tests + id: run-core-changed-tests + if: ${{ fromJSON(inputs.testrun)['type'] != 'full' && steps.get-test-flags.outputs.core_tests == 'false' }} + run: | + tools --timestamps --no-output-timeout-secs=1800 --timeout-secs=14400 vm test --skip-requirements-install \ + --nox-session=${{ env.NOX_SESSION }} --rerun-failures ${{ inputs.distro-slug }} \ + ${{ matrix.tests-chunk }} -- --no-fast-tests --core-tests --suppress-no-test-exit-code \ + --from-filenames=testrun-changed-files.txt - name: Run Fast Tests id: run-fast-tests - if: ${{ fromJSON(inputs.testrun)['type'] != 'full' }} + if: ${{ fromJSON(inputs.testrun)['type'] != 'full' && steps.get-test-flags.outputs.no_fast_tests == 'false' }} run: | tools --timestamps --no-output-timeout-secs=1800 --timeout-secs=14400 vm test --skip-requirements-install \ --nox-session=${{ env.NOX_SESSION }} --rerun-failures ${{ (inputs.skip-code-coverage && matrix.tests-chunk != 'unit') && '--skip-code-coverage' || '' }} \ ${{ inputs.distro-slug }} ${{ matrix.tests-chunk }} + - name: Run Slow Tests + id: run-slow-tests + if: ${{ fromJSON(inputs.testrun)['type'] != 'full' && steps.get-test-flags.outputs.slow_tests == 'true' }} + run: | + tools --timestamps --no-output-timeout-secs=1800 --timeout-secs=14400 vm test --skip-requirements-install \ + --nox-session=${{ env.NOX_SESSION }} --rerun-failures ${{ inputs.distro-slug }} \ + ${{ matrix.tests-chunk }} -- --no-fast-tests --slow-tests + + - name: Run Core Tests + id: run-core-tests + if: ${{ fromJSON(inputs.testrun)['type'] != 'full' && steps.get-test-flags.outputs.core_tests == 'true' }} + run: | + tools --timestamps --no-output-timeout-secs=1800 --timeout-secs=14400 vm test --skip-requirements-install \ + --nox-session=${{ env.NOX_SESSION }} --rerun-failures ${{ inputs.distro-slug }} \ + ${{ matrix.tests-chunk }} -- --no-fast-tests --core-tests + + - name: Run Flaky Tests + id: run-flaky-tests + if: ${{ fromJSON(inputs.testrun)['type'] != 'full' && steps.get-test-flags.outputs.flaky_jail_tests == 'false' }} + run: | + tools --timestamps --no-output-timeout-secs=1800 --timeout-secs=14400 vm test --skip-requirements-install \ + --nox-session=${{ env.NOX_SESSION }} --rerun-failures ${{ inputs.distro-slug }} \ + ${{ matrix.tests-chunk }} -- --no-fast-tests --flaky-jail + - name: Run Full Tests id: run-full-tests if: ${{ fromJSON(inputs.testrun)['type'] == 'full' }} run: | tools --timestamps --no-output-timeout-secs=1800 --timeout-secs=14400 vm test --skip-requirements-install \ --nox-session=${{ env.NOX_SESSION }} --rerun-failures ${{ (inputs.skip-code-coverage && matrix.tests-chunk != 'unit') && '--skip-code-coverage' || '' }} \ - ${{ inputs.distro-slug }} ${{ matrix.tests-chunk }} -- --run-slow + ${{ inputs.distro-slug }} ${{ matrix.tests-chunk }} -- --slow-tests --core-tests - name: Combine Coverage Reports if: always() && inputs.skip-code-coverage == false && steps.spin-up-vm.outcome == 'success' && job.status != 'cancelled' @@ -343,7 +417,7 @@ jobs: - name: Destroy VM if: always() run: | - tools --timestamps vm destroy ${{ inputs.distro-slug }} || true + tools --timestamps vm destroy --no-wait ${{ inputs.distro-slug }} || true - name: Upload Code Coverage Test Run Artifacts if: always() && inputs.skip-code-coverage == false && steps.download-artifacts-from-vm.outcome == 'success' && job.status != 'cancelled' diff --git a/.github/workflows/test-package-downloads-action-windows.yml b/.github/workflows/test-package-downloads-action-windows.yml index 0a2d67e0aea..c13ef47d62c 100644 --- a/.github/workflows/test-package-downloads-action-windows.yml +++ b/.github/workflows/test-package-downloads-action-windows.yml @@ -188,7 +188,7 @@ jobs: - name: Destroy VM if: always() && steps.nox-dependencies-cache.outputs.cache-hit != 'true' run: | - tools --timestamps vm destroy ${{ inputs.distro-slug }} + tools --timestamps vm destroy --no-wait ${{ inputs.distro-slug }} - name: Upload Onedir Tarball as an Artifact uses: actions/upload-artifact@v3 @@ -321,7 +321,7 @@ jobs: - name: Destroy VM if: always() run: | - tools --timestamps vm destroy ${{ inputs.distro-slug }} || true + tools --timestamps vm destroy --no-wait ${{ inputs.distro-slug }} || true - name: Fix file ownership run: | diff --git a/.github/workflows/test-packages-action.yml b/.github/workflows/test-packages-action.yml index a06e157bc2d..d167eda634e 100644 --- a/.github/workflows/test-packages-action.yml +++ b/.github/workflows/test-packages-action.yml @@ -164,7 +164,7 @@ jobs: - name: Destroy VM if: always() && steps.nox-dependencies-cache.outputs.cache-hit != 'true' run: | - tools --timestamps vm destroy ${{ inputs.distro-slug }} + tools --timestamps vm destroy --no-wait ${{ inputs.distro-slug }} - name: Upload Nox Requirements Tarball uses: actions/upload-artifact@v3 @@ -269,7 +269,7 @@ jobs: - name: Destroy VM if: always() run: | - tools --timestamps vm destroy ${{ inputs.distro-slug }} || true + tools --timestamps vm destroy --no-wait ${{ inputs.distro-slug }} || true - name: Upload Test Run Artifacts if: always() && steps.download-artifacts-from-vm.outcome == 'success' diff --git a/.github/workflows/update_winrepo.yml b/.github/workflows/update_winrepo.yml new file mode 100644 index 00000000000..91ce9df6f73 --- /dev/null +++ b/.github/workflows/update_winrepo.yml @@ -0,0 +1,71 @@ +--- +name: Update Winrepo + +on: + release: + types: [released] + workflow_dispatch: + inputs: + salt-version: + type: string + required: true + description: > + The Salt version to set prior to building packages and staging the release. + (DO NOT prefix the version with a v, ie, 3006.0 NOT v3006.0). + +permissions: + contents: read + +jobs: + update-winrepo: + name: Update Winrepo + runs-on: ubuntu-latest + steps: + + - name: Checkout Salt + uses: actions/checkout@v3 + with: + path: salt + + - name: Checkout WinRepo + uses: actions/checkout@v3 + with: + path: winrepo + repository: twangboy/salt-winrepo-ng + + - name: Set Up Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Add Version to Minion Definition File + working-directory: salt + run: | + python .github/workflows/scripts/update_winrepo.py \ + --file ../winrepo/salt-minion.sls \ + --version ${{ inputs.salt-version || github.ref_name }} + + - name: Commit Changes + working-directory: winrepo + run: | + git status + git add . + git config user.name 'saltbot-open' + git config user.email 'saltbot-open@users.noreply.github.com' + git commit -m "Adding salt minion ${{ inputs.salt-version && format('v{0}', inputs.salt-version) || github.ref_name }}" + + - name: Create Pull Request + id: cpr + uses: peter-evans/create-pull-request@v4 + with: + path: winrepo + push-to-fork: saltbot-open/salt-winrepo-ng + token: ${{ secrets.SALTBOT_OPEN_SALT_WINREPO_NG }} + +# - name: Enable Pull Request Automerge +# if: steps.cpr.outputs.pull-request-operation == 'created' +# uses: peter-evans/enable-pull-request-automerge@v2 +# with: +# token: ${{ secrets.SALTBOT_OPEN_SALT_WINREPO_NG }} +# pull-request-number: ${{ steps.cpr.outputs.pull-request-number }} +# merge-method: squash diff --git a/.github/workflows/upload-virustotal.yml b/.github/workflows/upload-virustotal.yml new file mode 100644 index 00000000000..71594ac244e --- /dev/null +++ b/.github/workflows/upload-virustotal.yml @@ -0,0 +1,44 @@ +--- +name: Upload VirusTotal + +on: + release: + types: [released] + workflow_dispatch: + inputs: + salt-version: + type: string + required: true + description: > + The Salt version to get from staging to upload to VirusTotal. + (DO NOT prefix the version with a v, ie, 3006.0 NOT v3006.0). + +permissions: + contents: read + +jobs: + upload-virustotal: + name: Upload VirusTotal + environment: release + runs-on: + - self-hosted + - linux + - repo-release + steps: + + - name: Checkout Salt + uses: actions/checkout@v3 + + - name: Set Up Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Setup Python Tools Scripts + uses: ./.github/actions/setup-python-tools-scripts + + - name: Upload to VirusTotal + env: + VIRUSTOTAL_API_KEY: ${{ secrets.VIRUSTOTAL_API_KEY }} + run: | + tools release upload-virustotal ${{ inputs.salt-version || github.ref_name }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7590e920db0..2ccd0bd7d2b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -59,6 +59,7 @@ repos: - pyyaml==6.0 - jinja2==3.1.2 - packaging==23.0 + - virustotal3==1.0.8 - id: tools alias: generate-workflows name: Generate GitHub Workflow Templates @@ -72,6 +73,7 @@ repos: - pyyaml==6.0 - jinja2==3.1.2 - packaging==23.0 + - virustotal3==1.0.8 - id: tools alias: actionlint name: Lint GitHub Actions Workflows diff --git a/CHANGELOG.md b/CHANGELOG.md index ec71450f23e..834323eec49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,374 @@ Versions are `MAJOR.PATCH`. # Changelog +## 3006.0 (2023-04-18) + + +### Removed + +- Remove and deprecate the __orchestration__ key from salt.runner and salt.wheel return data. To get it back, set features.enable_deprecated_orchestration_flag master configuration option to True. The flag will be completely removed in Salt 3008 Argon. [#59917](https://github.com/saltstack/salt/issues/59917) +- Removed distutils and replaced with setuptools, given distutils is deprecated and removed in Python 3.12 [#60476](https://github.com/saltstack/salt/issues/60476) +- Removed ``runtests`` targets from ``noxfile.py`` [#62239](https://github.com/saltstack/salt/issues/62239) +- Removed the PyObjC dependency. + + This addresses problems with building a one dir build for macOS. + It became problematic because depending on the macOS version, it pulls different dependencies, and we would either have to build a macos onedir for each macOS supported release, or ship a crippled onedir(because it would be tied to the macOS version where the onedir was built). + Since it's currently not being used, it's removed. [#62432](https://github.com/saltstack/salt/issues/62432) +- Removed `SixRedirectImporter` from Salt. Salt hasn't shipped `six` since Salt 3004. [#63874](https://github.com/saltstack/salt/issues/63874) + + +### Deprecated + +- renamed `keep_jobs`, specifying job cache TTL in hours, to `keep_jobs_seconds`, specifying TTL in seconds. + `keep_jobs` will be removed in the Argon release [#55295](https://github.com/saltstack/salt/issues/55295) +- Removing all references to napalm-base which is no longer supported. [#61542](https://github.com/saltstack/salt/issues/61542) +- The 'ip_bracket' function has been moved from salt/utils/zeromq.py in salt/utils/network.py [#62009](https://github.com/saltstack/salt/issues/62009) +- The `expand_repo_def` function in `salt.modules.aptpkg` is now deprecated. It's only used in `salt.states.pkgrepo` and it has no use of being exposed to the CLI. [#62485](https://github.com/saltstack/salt/issues/62485) +- Deprecated defunct Django returner [#62644](https://github.com/saltstack/salt/issues/62644) +- Deprecate core ESXi and associated states and modules, vcenter and vsphere support in favor of Salt VMware Extensions [#62754](https://github.com/saltstack/salt/issues/62754) +- Removing manufacture grain which has been deprecated. [#62914](https://github.com/saltstack/salt/issues/62914) +- Removing deprecated utils/boto3_elasticsearch.py [#62915](https://github.com/saltstack/salt/issues/62915) +- Removing support for the now deprecated _ext_nodes from salt/master.py. [#62917](https://github.com/saltstack/salt/issues/62917) +- Deprecating the Salt Slack engine in favor of the Salt Slack Bolt Engine. [#63095](https://github.com/saltstack/salt/issues/63095) +- `salt.utils.version.StrictVersion` is now deprecated and it's use should be replaced with `salt.utils.version.Version`. [#63383](https://github.com/saltstack/salt/issues/63383) + + +### Changed + +- More intelligent diffing in changes of file.serialize state. [#48609](https://github.com/saltstack/salt/issues/48609) +- Move deprecation of the neutron module to Argon. Please migrate to the neutronng module instead. [#49430](https://github.com/saltstack/salt/issues/49430) +- ``umask`` is now a global state argument, instead of only applying to ``cmd`` + states. [#57803](https://github.com/saltstack/salt/issues/57803) +- Update pillar.obfuscate to accept kwargs in addition to args. This is useful when passing in keyword arguments like saltenv that are then passed along to pillar.items. [#58971](https://github.com/saltstack/salt/issues/58971) +- Improve support for listing macOS brew casks [#59439](https://github.com/saltstack/salt/issues/59439) +- Add missing MariaDB Grants to mysql module. + MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. + Also improved exception handling in `grant_add` which did not log the original error message and replaced it with a generic error. [#61409](https://github.com/saltstack/salt/issues/61409) +- Use VENV_PIP_TARGET environment variable as a default target for pip if present. [#62089](https://github.com/saltstack/salt/issues/62089) +- Disabled FQDNs grains on macOS by default [#62168](https://github.com/saltstack/salt/issues/62168) +- Replaced pyroute2.IPDB with pyroute2.NDB, as the former is deprecated [#62218](https://github.com/saltstack/salt/issues/62218) +- Enhance capture of error messages for Zypper calls in zypperpkg module. [#62346](https://github.com/saltstack/salt/issues/62346) +- Removed GPG_1_3_1 check [#62895](https://github.com/saltstack/salt/issues/62895) +- Requisite state chunks now all consistently contain `__id__`, `__sls__` and `name`. [#63012](https://github.com/saltstack/salt/issues/63012) +- netapi_enable_clients option to allow enabling/disabling of clients in salt-api. + By default all clients will now be disabled. Users of salt-api will need + to update their master config to enable the clients that they use. Not adding + the netapi_enable_clients option with required clients to the master config will + disable salt-api. [#63050](https://github.com/saltstack/salt/issues/63050) +- Stop relying on `salt/_version.py` to write Salt's version. Instead use `salt/_version.txt` which only contains the version string. [#63383](https://github.com/saltstack/salt/issues/63383) +- Set enable_fqdns_grains to be False by default. [#63595](https://github.com/saltstack/salt/issues/63595) +- Changelog snippet files must now have a `.md` file extension to be more explicit on what type of rendering is done when they are included in the main `CHANGELOG.md` file. [#63710](https://github.com/saltstack/salt/issues/63710) +- Upgraded to `relenv==0.9.0` [#63883](https://github.com/saltstack/salt/issues/63883) + + +### Fixed + +- Add kwargs to handle extra parameters for http.query [#36138](https://github.com/saltstack/salt/issues/36138) +- Fix mounted bind mounts getting active mount options added [#39292](https://github.com/saltstack/salt/issues/39292) +- Fix `sysctl.present` converts spaces to tabs. [#40054](https://github.com/saltstack/salt/issues/40054) +- Fixes state pkg.purged to purge removed packages on Debian family systems [#42306](https://github.com/saltstack/salt/issues/42306) +- Fix fun_args missing from syndic returns [#45823](https://github.com/saltstack/salt/issues/45823) +- Fix mount.mounted with 'mount: False' reports unmounted file system as unchanged when running with test=True [#47201](https://github.com/saltstack/salt/issues/47201) +- Issue #49310: Allow users to touch a file with Unix date of birth [#49310](https://github.com/saltstack/salt/issues/49310) +- Do not raise an exception in pkg.info_installed on nonzero return code [#51620](https://github.com/saltstack/salt/issues/51620) +- Passes the value of the force parameter from file.copy to its call to file.remove so that files with the read-only attribute are handled. [#51739](https://github.com/saltstack/salt/issues/51739) +- Fixed x509.certificate_managed creates new certificate every run in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#52167](https://github.com/saltstack/salt/issues/52167) +- Don't check for cached pillar errors on state.apply [#52354](https://github.com/saltstack/salt/issues/52354), [#57180](https://github.com/saltstack/salt/issues/57180), [#59339](https://github.com/saltstack/salt/issues/59339) +- Swapping out args and kwargs for arg and kwarg respectively in the Slack engine when the command passed is a runner. [#52400](https://github.com/saltstack/salt/issues/52400) +- Ensure when we're adding chunks to the rules when running aggregation with the iptables state module we use a copy of the chunk otherwise we end up with a recursive mess. [#53353](https://github.com/saltstack/salt/issues/53353) +- When user_create or user_remove fail, return False instead of returning the error. [#53377](https://github.com/saltstack/salt/issues/53377) +- Include sync_roster when sync_all is called. [#53914](https://github.com/saltstack/salt/issues/53914) +- Avoid warning noise in lograte.get [#53988](https://github.com/saltstack/salt/issues/53988) +- Fixed listing revoked keys with gpg.list_keys [#54347](https://github.com/saltstack/salt/issues/54347) +- Fix mount.mounted does not handle blanks properly [#54508](https://github.com/saltstack/salt/issues/54508) +- Fixed grain num_cpus get wrong CPUs count in case of inconsistent CPU numbering. [#54682](https://github.com/saltstack/salt/issues/54682) +- Fix spelling error for python_shell argument in dpkg_lower module [#54907](https://github.com/saltstack/salt/issues/54907) +- Cleaned up bytes response data before sending to non-bytes compatible returners (postgres, mysql) [#55226](https://github.com/saltstack/salt/issues/55226) +- Fixed malformed state return when testing file.managed with unavailable source file [#55269](https://github.com/saltstack/salt/issues/55269) +- Included stdout in error message for Zypper calls in zypperpkg module. [#56016](https://github.com/saltstack/salt/issues/56016) +- Fixed pillar.filter_by with salt-ssh [#56093](https://github.com/saltstack/salt/issues/56093) +- Fix boto_route53 issue with (multiple) VPCs. [#57139](https://github.com/saltstack/salt/issues/57139) +- Remove log from mine runner which was not used. [#57463](https://github.com/saltstack/salt/issues/57463) +- Fixed x509.read_certificate error when reading a Microsoft CA issued certificate in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#57535](https://github.com/saltstack/salt/issues/57535) +- Updating Slack engine to use slack_bolt library. [#57842](https://github.com/saltstack/salt/issues/57842) +- Fixed warning about replace=True with x509.certificate_managed in the new cryptography x509 module. [#58165](https://github.com/saltstack/salt/issues/58165) +- Fix salt.modules.pip:is_installed doesn't handle locally installed packages [#58202](https://github.com/saltstack/salt/issues/58202) +- Add missing MariaDB Grants to mysql module. MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. [#58297](https://github.com/saltstack/salt/issues/58297) +- linux_shadow: Fix cases where malformed shadow entries cause `user.present` + states to fail. [#58423](https://github.com/saltstack/salt/issues/58423) +- Fixed salt.utils.compat.cmp to work with dictionaries [#58729](https://github.com/saltstack/salt/issues/58729) +- Fixed formatting for terse output mode [#58953](https://github.com/saltstack/salt/issues/58953) +- Fixed RecursiveDictDiffer with added nested dicts [#59017](https://github.com/saltstack/salt/issues/59017) +- Fixed x509.certificate_managed has DoS effect on master in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#59169](https://github.com/saltstack/salt/issues/59169) +- Fixed saltnado websockets disconnecting immediately [#59183](https://github.com/saltstack/salt/issues/59183) +- Fixed x509.certificate_managed rolls certificates every now and then in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#59315](https://github.com/saltstack/salt/issues/59315) +- Fix postgres_privileges.present not idempotent for functions [#59585](https://github.com/saltstack/salt/issues/59585) +- Fixed influxdb_continuous_query.present state to provide the client args to the underlying module on create. [#59766](https://github.com/saltstack/salt/issues/59766) +- Warn when using insecure (http:// based) key_urls for apt-based systems in pkgrepo.managed, and add a kwarg that determines the validity of such a url. [#59786](https://github.com/saltstack/salt/issues/59786) +- add load balancing policy default option and ensure the module can be executed with arguments from CLI [#59909](https://github.com/saltstack/salt/issues/59909) +- Fix salt-ssh when using imports with extra-filerefs. [#60003](https://github.com/saltstack/salt/issues/60003) +- Fixed cache directory corruption startup error [#60170](https://github.com/saltstack/salt/issues/60170) +- Update docs remove dry_run in docstring of file.blockreplace state. [#60227](https://github.com/saltstack/salt/issues/60227) +- Adds Parrot to OS_Family_Map in grains. [#60249](https://github.com/saltstack/salt/issues/60249) +- Fixed stdout and stderr being empty sometimes when use_vt=True for the cmd.run[*] functions [#60365](https://github.com/saltstack/salt/issues/60365) +- Use return code in iptables --check to verify rule exists. [#60467](https://github.com/saltstack/salt/issues/60467) +- Fix regression pip.installed does not pass env_vars when calling pip.list [#60557](https://github.com/saltstack/salt/issues/60557) +- Fix xfs module when additional output included in mkfs.xfs command. [#60853](https://github.com/saltstack/salt/issues/60853) +- Fixed parsing new format of terraform states in roster.terraform [#60915](https://github.com/saltstack/salt/issues/60915) +- Fixed recognizing installed ARMv7 rpm packages in compatible architectures. [#60994](https://github.com/saltstack/salt/issues/60994) +- Fixing changes dict in pkg state to be consistent when installing and test=True. [#60995](https://github.com/saltstack/salt/issues/60995) +- Fix cron.present duplicating entries when changing timespec to special. [#60997](https://github.com/saltstack/salt/issues/60997) +- Made salt-ssh respect --wipe again [#61083](https://github.com/saltstack/salt/issues/61083) +- state.orchestrate_single only passes a pillar if it is set to the state + function. This allows it to be used with state functions that don't accept a + pillar keyword argument. [#61092](https://github.com/saltstack/salt/issues/61092) +- Fix ipset state when the comment kwarg is set. [#61122](https://github.com/saltstack/salt/issues/61122) +- Fix issue with archive.unzip where the password was not being encoded for the extract function [#61422](https://github.com/saltstack/salt/issues/61422) +- Some Linux distributions (like AlmaLinux, Astra Linux, Debian, Mendel, Linux + Mint, Pop!_OS, Rocky Linux) report different `oscodename`, `osfullname`, + `osfinger` grains if lsb-release is installed or not. They have been changed to + only derive these OS grains from `/etc/os-release`. [#61618](https://github.com/saltstack/salt/issues/61618) +- Pop!_OS uses the full version (YY.MM) in the osfinger grain now, not just the year. This allows differentiating for example between 20.04 and 20.10. [#61619](https://github.com/saltstack/salt/issues/61619) +- Fix ssh config roster to correctly parse the ssh config files that contain spaces. [#61650](https://github.com/saltstack/salt/issues/61650) +- Fix SoftLayer configuration not raising an exception when a domain is missing [#61727](https://github.com/saltstack/salt/issues/61727) +- Allow the minion to start or salt-call to run even if the user doesn't have permissions to read the root_dir value from the registry [#61789](https://github.com/saltstack/salt/issues/61789) +- Need to move the creation of the proxy object for the ProxyMinion further down in the initialization for sub proxies to ensure that all modules, especially any custom proxy modules, are available before attempting to run the init function. [#61805](https://github.com/saltstack/salt/issues/61805) +- Fixed malformed state return when merge-serializing to an improperly formatted file [#61814](https://github.com/saltstack/salt/issues/61814) +- Made cmdmod._run[_all]_quiet work during minion startup on MacOS with runas specified (which fixed mac_service) [#61816](https://github.com/saltstack/salt/issues/61816) +- When deleting the vault cache, also delete from the session cache [#61821](https://github.com/saltstack/salt/issues/61821) +- Ignore errors on reading license info with dpkg_lowpkg to prevent tracebacks on getting package information. [#61827](https://github.com/saltstack/salt/issues/61827) +- win_lgpo: Display conflicting policy names when more than one policy is found [#61859](https://github.com/saltstack/salt/issues/61859) +- win_lgpo: Fixed intermittent KeyError when getting policy setting using lgpo.get_policy [#61860](https://github.com/saltstack/salt/issues/61860) +- Fixed listing minions on OpenBSD [#61966](https://github.com/saltstack/salt/issues/61966) +- Make Salt to return an error on "pkg" modules and states when targeting duplicated package names [#62019](https://github.com/saltstack/salt/issues/62019) +- Fix return of REST-returned permissions when auth_list is set [#62022](https://github.com/saltstack/salt/issues/62022) +- Normalize package names once on using pkg.installed/removed with yum to make it possible to install packages with the name containing a part similar to a name of architecture. [#62029](https://github.com/saltstack/salt/issues/62029) +- Fix inconsitency regarding name and pkgs parameters between zypperpkg.upgrade() and yumpkg.upgrade() [#62030](https://github.com/saltstack/salt/issues/62030) +- Fix attr=all handling in pkg.list_pkgs() (yum/zypper). [#62032](https://github.com/saltstack/salt/issues/62032) +- Fixed the humanname being ignored in pkgrepo.managed on openSUSE Leap [#62053](https://github.com/saltstack/salt/issues/62053) +- Fixed issue with some LGPO policies having whitespace at the beginning or end of the element alias [#62058](https://github.com/saltstack/salt/issues/62058) +- Fix ordering of args to libcloud_storage.download_object module [#62074](https://github.com/saltstack/salt/issues/62074) +- Ignore extend declarations in sls files that are excluded. [#62082](https://github.com/saltstack/salt/issues/62082) +- Remove leftover usage of impacket [#62101](https://github.com/saltstack/salt/issues/62101) +- Pass executable path from _get_path_exec() is used when calling the program. + The $HOME env is no longer modified globally. + Only trailing newlines are stripped from the fetched secret. + Pass process arguments are handled in a secure way. [#62120](https://github.com/saltstack/salt/issues/62120) +- Ignore some command return codes in openbsdrcctl_service to prevent spurious errors [#62131](https://github.com/saltstack/salt/issues/62131) +- Fixed extra period in filename output in tls module. Instead of "server.crt." it will now be "server.crt". [#62139](https://github.com/saltstack/salt/issues/62139) +- Make sure lingering PAexec-*.exe files in the Windows directory are cleaned up [#62152](https://github.com/saltstack/salt/issues/62152) +- Restored Salt's DeprecationWarnings [#62185](https://github.com/saltstack/salt/issues/62185) +- Fixed issue with forward slashes on Windows with file.recurse and clean=True [#62197](https://github.com/saltstack/salt/issues/62197) +- Recognize OSMC as Debian-based [#62198](https://github.com/saltstack/salt/issues/62198) +- Fixed Zypper module failing on RPM lock file being temporarily unavailable. [#62204](https://github.com/saltstack/salt/issues/62204) +- Improved error handling and diagnostics in the proxmox salt-cloud driver [#62211](https://github.com/saltstack/salt/issues/62211) +- Added EndeavourOS to the Arch os_family. [#62220](https://github.com/saltstack/salt/issues/62220) +- Fix salt-ssh not detecting `platform-python` as a valid interpreter on EL8 [#62235](https://github.com/saltstack/salt/issues/62235) +- Fix pkg.version_cmp on openEuler and a few other os flavors. [#62248](https://github.com/saltstack/salt/issues/62248) +- Fix localhost detection in glusterfs.peers [#62273](https://github.com/saltstack/salt/issues/62273) +- Fix Salt Package Manager (SPM) exception when calling spm create_repo . [#62281](https://github.com/saltstack/salt/issues/62281) +- Fix matcher slowness due to loader invocation [#62283](https://github.com/saltstack/salt/issues/62283) +- Fixes the Puppet module for non-aio Puppet packages for example running the Puppet module on FreeBSD. [#62323](https://github.com/saltstack/salt/issues/62323) +- Issue 62334: Displays a debug log message instead of an error log message when the publisher fails to connect [#62334](https://github.com/saltstack/salt/issues/62334) +- Fix pyobjects renderer access to opts and sls [#62336](https://github.com/saltstack/salt/issues/62336) +- Fix use of random shuffle and sample functions as Jinja filters [#62372](https://github.com/saltstack/salt/issues/62372) +- Fix groups with duplicate GIDs are not returned by get_group_list [#62377](https://github.com/saltstack/salt/issues/62377) +- Fix the "zpool.present" state when enabling zpool features that are already active. [#62390](https://github.com/saltstack/salt/issues/62390) +- Fix ability to execute remote file client methods in saltcheck [#62398](https://github.com/saltstack/salt/issues/62398) +- Update all platforms to use pycparser 2.21 or greater for Py 3.9 or higher, fixes fips fault with openssl v3.x [#62400](https://github.com/saltstack/salt/issues/62400) +- Due to changes in the Netmiko library for the exception paths, need to check the version of Netmiko python library and then import the exceptions from different locations depending on the result. [#62405](https://github.com/saltstack/salt/issues/62405) +- When using preq on a state, then prereq state will first be run with test=True to determine if there are changes. When there are changes, the state with the prereq option will be run prior to the prereq state. If this state fails then the prereq state will not run and the state output uses the test=True run. However, the proposed changes are included for the prereq state are included from the test=True run. We should pull those out as there weren't actually changes since the prereq state did not run. [#62408](https://github.com/saltstack/salt/issues/62408) +- Added directory mode for file.copy with makedirs [#62426](https://github.com/saltstack/salt/issues/62426) +- Provide better error handling in the various napalm proxy minion functions when the device is not accessible. [#62435](https://github.com/saltstack/salt/issues/62435) +- When handling aggregation, change the order to ensure that the requisites are aggregated first and then the state functions are aggregated. Caching whether aggregate functions are available for particular states so we don't need to attempt to load them everytime. [#62439](https://github.com/saltstack/salt/issues/62439) +- The patch allows to boostrap kubernetes clusters in the version above 1.13 via salt module [#62451](https://github.com/saltstack/salt/issues/62451) +- sysctl.persist now updates the in-memory value on FreeBSD even if the on-disk value was already correct. [#62461](https://github.com/saltstack/salt/issues/62461) +- Fixed parsing CDROM apt sources [#62474](https://github.com/saltstack/salt/issues/62474) +- Update sanitizing masking for Salt SSH to include additional password like strings. [#62483](https://github.com/saltstack/salt/issues/62483) +- Fix user/group checking on file state functions in the test mode. [#62499](https://github.com/saltstack/salt/issues/62499) +- Fix user.present to allow removing groups using optional_groups parameter and enforcing idempotent group membership. [#62502](https://github.com/saltstack/salt/issues/62502) +- Fix possible tracebacks if there is a package with '------' or '======' in the description is installed on the Debian based minion. [#62519](https://github.com/saltstack/salt/issues/62519) +- Fixed the omitted "pool" parameter when cloning a VM with the proxmox salt-cloud driver [#62521](https://github.com/saltstack/salt/issues/62521) +- Fix rendering of pyobjects states in saltcheck [#62523](https://github.com/saltstack/salt/issues/62523) +- Fixes pillar where a corrupted CacheDisk file forces the pillar to be rebuilt [#62527](https://github.com/saltstack/salt/issues/62527) +- Use str() method instead of repo_line for when python3-apt is installed or not in aptpkg.py. [#62546](https://github.com/saltstack/salt/issues/62546) +- Remove the connection_timeout from netmiko_connection_args before netmiko_connection_args is added to __context__["netmiko_device"]["args"] which is passed along to the Netmiko library. [#62547](https://github.com/saltstack/salt/issues/62547) +- Fix order specific mount.mounted options for persist [#62556](https://github.com/saltstack/salt/issues/62556) +- Fixed salt-cloud cloning a proxmox VM with a specified new vmid. [#62558](https://github.com/saltstack/salt/issues/62558) +- Fix runas with cmd module when using the onedir bundled packages [#62565](https://github.com/saltstack/salt/issues/62565) +- Update setproctitle version for all platforms [#62576](https://github.com/saltstack/salt/issues/62576) +- Fixed missing parameters when cloning a VM with the proxmox salt-cloud driver [#62580](https://github.com/saltstack/salt/issues/62580) +- Handle PermissionError when importing crypt when FIPS is enabled. [#62587](https://github.com/saltstack/salt/issues/62587) +- Correctly reraise exceptions in states.http [#62595](https://github.com/saltstack/salt/issues/62595) +- Fixed syndic eauth. Now jobs will be published when a valid eauth user is targeting allowed minions/functions. [#62618](https://github.com/saltstack/salt/issues/62618) +- updated rest_cherry/app to properly detect arg sent as a string as curl will do when only one arg is supplied. [#62624](https://github.com/saltstack/salt/issues/62624) +- Prevent possible tracebacks in core grains module by ignoring non utf8 characters in /proc/1/environ, /proc/1/cmdline, /proc/cmdline [#62633](https://github.com/saltstack/salt/issues/62633) +- Fixed vault ext pillar return data for KV v2 [#62651](https://github.com/saltstack/salt/issues/62651) +- Fix saltcheck _get_top_states doesn't pass saltenv to state.show_top [#62654](https://github.com/saltstack/salt/issues/62654) +- Fix groupadd.* functions hard code relative command name [#62657](https://github.com/saltstack/salt/issues/62657) +- Fixed pdbedit.create trying to use a bytes-like hash as string. [#62670](https://github.com/saltstack/salt/issues/62670) +- Fix depenency on legacy boto module in boto3 modules [#62672](https://github.com/saltstack/salt/issues/62672) +- Modified "_get_flags" function so that it returns regex flags instead of integers [#62676](https://github.com/saltstack/salt/issues/62676) +- Change startup ReqServer log messages from error to info level. [#62728](https://github.com/saltstack/salt/issues/62728) +- Fix kmod.* functions hard code relative command name [#62772](https://github.com/saltstack/salt/issues/62772) +- Remove mako as a dependency in Windows and macOS. [#62785](https://github.com/saltstack/salt/issues/62785) +- Fix mac_brew_pkg to work with null taps [#62793](https://github.com/saltstack/salt/issues/62793) +- Fixing a bug when listing the running schedule if "schedule.enable" and/or "schedule.disable" has been run, where the "enabled" items is being treated as a schedule item. [#62795](https://github.com/saltstack/salt/issues/62795) +- Prevent annoying RuntimeWarning message about line buffering (buffering=1) not being supported in binary mode [#62817](https://github.com/saltstack/salt/issues/62817) +- Include UID and GID checks in modules.file.check_perms as well as comparing + ownership by username and group name. [#62818](https://github.com/saltstack/salt/issues/62818) +- Fix presence events on TCP transport by removing a client's presence when minion disconnects from publish channel correctly [#62826](https://github.com/saltstack/salt/issues/62826) +- Remove Azure deprecation messages from functions that always run w/ salt-cloud [#62845](https://github.com/saltstack/salt/issues/62845) +- Use select instead of iterating over entrypoints as a dictionary for importlib_metadata>=5.0.0 [#62854](https://github.com/saltstack/salt/issues/62854) +- Fixed master job scheduler using when [#62858](https://github.com/saltstack/salt/issues/62858) +- LGPO: Added support for missing domain controller policies: VulnerableChannelAllowList and LdapEnforceChannelBinding [#62873](https://github.com/saltstack/salt/issues/62873) +- Fix unnecessarily complex gce metadata grains code to use googles metadata service more effectively. [#62878](https://github.com/saltstack/salt/issues/62878) +- Fixed dockermod version_info function for docker-py 6.0.0+ [#62882](https://github.com/saltstack/salt/issues/62882) +- Moving setting the LOAD_BALANCING_POLICY_MAP dictionary into the try except block that determines if the cassandra_cql module should be made available. [#62886](https://github.com/saltstack/salt/issues/62886) +- Updating various MongoDB module functions to work with latest version of pymongo. [#62900](https://github.com/saltstack/salt/issues/62900) +- Restored channel for Syndic minions to send job returns to the Salt master. [#62933](https://github.com/saltstack/salt/issues/62933) +- removed _resolve_deps as it required a library that is not generally avalible. and switched to apt-get for everything as that can auto resolve dependencies. [#62934](https://github.com/saltstack/salt/issues/62934) +- Updated pyzmq to version 22.0.3 on Windows builds because the old version was causing salt-minion/salt-call to hang [#62937](https://github.com/saltstack/salt/issues/62937) +- Allow root user to modify crontab lines for non-root users (except AIX and Solaris). Align crontab line changes with the file ones and also with listing crontab. [#62940](https://github.com/saltstack/salt/issues/62940) +- Fix systemd_service.* functions hard code relative command name [#62942](https://github.com/saltstack/salt/issues/62942) +- Fix file.symlink backupname operation can copy remote contents to local disk [#62953](https://github.com/saltstack/salt/issues/62953) +- Issue #62968: Fix issue where cloud deployments were putting the keys in the wrong location on Windows hosts [#62968](https://github.com/saltstack/salt/issues/62968) +- Fixed gpg_passphrase issue with gpg decrypt/encrypt functions [#62977](https://github.com/saltstack/salt/issues/62977) +- Fix file.tidied FileNotFoundError [#62986](https://github.com/saltstack/salt/issues/62986) +- Fixed bug where module.wait states were detected as running legacy module.run syntax [#62988](https://github.com/saltstack/salt/issues/62988) +- Fixed issue with win_wua module where it wouldn't load if the CryptSvc was set to Manual start [#62993](https://github.com/saltstack/salt/issues/62993) +- The `__opts__` dunder dictionary is now added to the loader's `pack` if not + already present, which makes it accessible via the + `salt.loader.context.NamedLoaderContext` class. [#63013](https://github.com/saltstack/salt/issues/63013) +- Issue #63024: Fix issue where grains and config data were being place in the wrong location on Windows hosts [#63024](https://github.com/saltstack/salt/issues/63024) +- Fix btrfs.subvolume_snapshot command failing [#63025](https://github.com/saltstack/salt/issues/63025) +- Fix file.retention_schedule always reports changes [#63033](https://github.com/saltstack/salt/issues/63033) +- Fix mongo authentication for mongo ext_pillar and mongo returner + + This fix also include the ability to use the mongo connection string for mongo ext_pillar [#63058](https://github.com/saltstack/salt/issues/63058) +- Fixed x509.create_csr creates invalid CSR by default in the new cryptography x509 module. [#63103](https://github.com/saltstack/salt/issues/63103) +- TCP transport documentation now contains proper master/minion-side filtering information [#63120](https://github.com/saltstack/salt/issues/63120) +- Fixed gpg.verify does not respect gnupghome [#63145](https://github.com/saltstack/salt/issues/63145) +- User responsible for the runner is now correctly reported in the events on the event bus for the runner. [#63148](https://github.com/saltstack/salt/issues/63148) +- Made pillar cache pass extra minion data as well [#63208](https://github.com/saltstack/salt/issues/63208) +- Fix serious performance issues with the file.tidied module [#63231](https://github.com/saltstack/salt/issues/63231) +- Fix rpm_lowpkg version comparison logic when using rpm-vercmp and only one version has a release number. [#63317](https://github.com/saltstack/salt/issues/63317) +- Import StrictVersion and LooseVersion from setuptools.distutils.verison or setuptools._distutils.version, if first not available [#63350](https://github.com/saltstack/salt/issues/63350) +- ``service.status`` on Windows does no longer throws a CommandExecutionError if + the service is not found on the system. It now returns "Not Found" instead. [#63577](https://github.com/saltstack/salt/issues/63577) +- When the shell is passed as powershell or pwsh, only wrapper the shell in quotes if cmd.run is running on Windows. When quoted on Linux hosts, this results in an error when the keyword arguments are appended. [#63590](https://github.com/saltstack/salt/issues/63590) +- LGPO: Added support for "Relax minimum password length limits" [#63596](https://github.com/saltstack/salt/issues/63596) +- Fixed the ability to set a scheduled task to auto delete if not scheduled to run again (``delete_after``) [#63650](https://github.com/saltstack/salt/issues/63650) +- When a job is disabled only increase it's _next_fire_time value if the job would have run at the current time, eg. the current _next_fire_time == now. [#63699](https://github.com/saltstack/salt/issues/63699) +- have salt.template.compile_template_str cleanup its temp files. [#63724](https://github.com/saltstack/salt/issues/63724) +- Check file is not empty before attempting to read pillar disk cache file [#63729](https://github.com/saltstack/salt/issues/63729) +- Fixed an issue with generating fingerprints for public keys with different line endings [#63742](https://github.com/saltstack/salt/issues/63742) +- Add `fileserver_interval` and `maintenance_interval` master configuration options. These options control how often to restart the FileServerUpdate and Maintenance processes. Some file server and pillar configurations are known to cause memory leaks over time. A notable example of this are configurations that use pygit2. Salt can not guarantee dependency libraries like pygit2 won't leak memory. Restarting any long running processes that use pygit2 guarantees we can keep the master's memory usage in check. [#63747](https://github.com/saltstack/salt/issues/63747) +- mac_xattr.list and mac_xattr.read will replace undecode-able bytes to avoid raising CommandExecutionError. [#63779](https://github.com/saltstack/salt/issues/63779) [#63779](https://github.com/saltstack/salt/issues/63779) +- Change default GPG keyserver from pgp.mit.edu to keys.openpgp.org. [#63806](https://github.com/saltstack/salt/issues/63806) +- fix cherrypy 400 error output to be less generic. [#63835](https://github.com/saltstack/salt/issues/63835) +- Ensure kwargs is passed along to _call_apt when passed into install function. [#63847](https://github.com/saltstack/salt/issues/63847) +- remove eval and update logging to be more informative on bad config [#63879](https://github.com/saltstack/salt/issues/63879) +- add linux_distribution to util to stop dep warning [#63904](https://github.com/saltstack/salt/issues/63904) +- Fix valuerror when trying to close fileclient. Remove usage of __del__ and close the filclient properly. [#63920](https://github.com/saltstack/salt/issues/63920) +- Handle the situation when a sub proxy minion does not init properly, eg. an exception happens, and the sub proxy object is not available. [#63923](https://github.com/saltstack/salt/issues/63923) +- Clarifying documentation for extension_modules configuration option. [#63929](https://github.com/saltstack/salt/issues/63929) +- Windows pkg module now properly handles versions containing strings [#63935](https://github.com/saltstack/salt/issues/63935) +- Handle the scenario when the check_cmd requisite is used with a state function when the state has a local check_cmd function but that function isn't used by that function. [#63948](https://github.com/saltstack/salt/issues/63948) +- Issue #63981: Allow users to pass verify_ssl to pkg.install/pkg.installed on Windows [#63981](https://github.com/saltstack/salt/issues/63981) +- Hardened permissions on workers.ipc and master_event_pub.ipc. [#64063](https://github.com/saltstack/salt/issues/64063) + + +### Added + +- Introduce a `LIB_STATE_DIR` syspaths variable which defaults to `CONFIG_DIR`, + but can be individually customized during installation by specifying + `--salt-lib-state-dir` during installation. Change the default `pki_dir` to + `/pki/master` (for the master) and `/pki/minion` + (for the minion). [#3396](https://github.com/saltstack/salt/issues/3396) +- Allow users to enable 'queue=True' for all state runs via config file [#31468](https://github.com/saltstack/salt/issues/31468) +- Added pillar templating to vault policies [#43287](https://github.com/saltstack/salt/issues/43287) +- Add support for NVMeF as a transport protocol for hosts in a Pure Storage FlashArray [#51088](https://github.com/saltstack/salt/issues/51088) +- A new salt-ssh roster that generates a roster by parses a known_hosts file. [#54679](https://github.com/saltstack/salt/issues/54679) +- Added Windows Event Viewer support [#54713](https://github.com/saltstack/salt/issues/54713) +- Added the win_lgpo_reg state and execution modules which will allow registry based group policy to be set directly in the Registry.pol file [#56013](https://github.com/saltstack/salt/issues/56013) +- Added resource tagging functions to boto_dynamodb execution module [#57500](https://github.com/saltstack/salt/issues/57500) +- Added `openvswitch_db` state module and functions `bridge_to_parent`, + `bridge_to_vlan`, `db_get`, and `db_set` to the `openvswitch` execution module. + Also added optional `parent` and `vlan` parameters to the + `openvswitch_bridge.present` state module function and the + `openvswitch.bridge_create` execution module function. [#58986](https://github.com/saltstack/salt/issues/58986) +- State module to manage SysFS attributes [#60154](https://github.com/saltstack/salt/issues/60154) +- Added ability for `salt.wait_for_event` to handle `event_id`s that have a list value. [#60430](https://github.com/saltstack/salt/issues/60430) +- Added suport for Linux ppc64le core grains (cpu_model, virtual, productname, manufacturer, serialnumber) and arm core grains (serialnumber, productname) [#60518](https://github.com/saltstack/salt/issues/60518) +- Added autostart option to virt.defined and virt.running states, along with virt.update execution modules. [#60700](https://github.com/saltstack/salt/issues/60700) +- Added .0 back to our versioning scheme for future versions (e.g. 3006.0) [#60722](https://github.com/saltstack/salt/issues/60722) +- Initial work to allow parallel startup of proxy minions when used as sub proxies with Deltaproxy. [#61153](https://github.com/saltstack/salt/issues/61153) +- Added node label support for GCE [#61245](https://github.com/saltstack/salt/issues/61245) +- Support the --priority flag when adding sources to Chocolatey. [#61319](https://github.com/saltstack/salt/issues/61319) +- Add namespace option to ext_pillar.http_json [#61335](https://github.com/saltstack/salt/issues/61335) +- Added a filter function to ps module to get a list of processes on a minion according to their state. [#61420](https://github.com/saltstack/salt/issues/61420) +- Add postgres.timeout option to postgres module for limiting postgres query times [#61433](https://github.com/saltstack/salt/issues/61433) +- Added new optional vault option, ``config_location``. This can be either ``master`` or ``local`` and defines where vault will look for connection details, either requesting them from the master or using the local config. [#61857](https://github.com/saltstack/salt/issues/61857) +- Add ipwrap() jinja filter to wrap IPv6 addresses with brackets. [#61931](https://github.com/saltstack/salt/issues/61931) +- 'tcp' transport is now available in ipv6-only network [#62009](https://github.com/saltstack/salt/issues/62009) +- Add `diff_attr` parameter to pkg.upgrade() (zypper/yum). [#62031](https://github.com/saltstack/salt/issues/62031) +- Config option pass_variable_prefix allows to distinguish variables that contain paths to pass secrets. + Config option pass_strict_fetch allows to error out when a secret cannot be fetched from pass. + Config option pass_dir allows setting the PASSWORD_STORE_DIR env for pass. + Config option pass_gnupghome allows setting the $GNUPGHOME env for pass. [#62120](https://github.com/saltstack/salt/issues/62120) +- Add file.pruned state and expanded file.rmdir exec module functionality [#62178](https://github.com/saltstack/salt/issues/62178) +- Added "dig.PTR" function to resolve PTR records for IPs, as well as tests and documentation [#62275](https://github.com/saltstack/salt/issues/62275) +- Added the ability to remove a KB using the DISM state/execution modules [#62366](https://github.com/saltstack/salt/issues/62366) +- Add " python" subcommand to allow execution or arbitrary scripts via bundled Python runtime [#62381](https://github.com/saltstack/salt/issues/62381) +- Add ability to provide conditions which convert normal state actions to no-op when true [#62446](https://github.com/saltstack/salt/issues/62446) +- Added debug log messages displaying the command being run when installing packages on Windows [#62480](https://github.com/saltstack/salt/issues/62480) +- Add biosvendor grain [#62496](https://github.com/saltstack/salt/issues/62496) +- Add ifelse Jinja function as found in CFEngine [#62508](https://github.com/saltstack/salt/issues/62508) +- Implementation of Amazon EC2 instance detection and setting `virtual_subtype` grain accordingly including the product if possible to identify. [#62539](https://github.com/saltstack/salt/issues/62539) +- Adds __env__substitution to ext_pillar.stack; followup of #61531, improved exception handling for stacked template (jinja) template rendering and yaml parsing in ext_pillar.stack [#62578](https://github.com/saltstack/salt/issues/62578) +- Increase file.tidied flexibility with regard to age and size [#62678](https://github.com/saltstack/salt/issues/62678) +- Added "connected_devices" feature to netbox pillar module. It contains extra information about devices connected to the minion [#62761](https://github.com/saltstack/salt/issues/62761) +- Add atomic file operation for symlink changes [#62768](https://github.com/saltstack/salt/issues/62768) +- Add password/account locking/unlocking in user.present state on supported operating systems [#62856](https://github.com/saltstack/salt/issues/62856) +- Added onchange configuration for script engine [#62867](https://github.com/saltstack/salt/issues/62867) +- Added output and bare functionality to export_key gpg module function [#62978](https://github.com/saltstack/salt/issues/62978) +- Add keyvalue serializer for environment files [#62983](https://github.com/saltstack/salt/issues/62983) +- Add ability to ignore symlinks in file.tidied [#63042](https://github.com/saltstack/salt/issues/63042) +- salt-cloud support IMDSv2 tokens when using 'use-instance-role-credentials' [#63067](https://github.com/saltstack/salt/issues/63067) +- Fix running fast tests twice and add git labels to suite. [#63081](https://github.com/saltstack/salt/issues/63081) +- Add ability for file.symlink to not set ownership on existing links [#63093](https://github.com/saltstack/salt/issues/63093) +- Restore the previous slack engine and deprecate it, rename replace the slack engine to slack_bolt until deprecation [#63095](https://github.com/saltstack/salt/issues/63095) +- Add functions that will return the underlying block device, mount point, and filesystem type for a given path [#63098](https://github.com/saltstack/salt/issues/63098) +- Add ethtool execution and state module functions for pause [#63128](https://github.com/saltstack/salt/issues/63128) +- Add boardname grain [#63131](https://github.com/saltstack/salt/issues/63131) +- Added management of ECDSA/EdDSA private keys with x509 modules in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#63248](https://github.com/saltstack/salt/issues/63248) +- Added x509 modules support for different output formats in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#63249](https://github.com/saltstack/salt/issues/63249) +- Added deprecation_warning test state for ensuring that deprecation warnings are correctly emitted. [#63315](https://github.com/saltstack/salt/issues/63315) +- Adds a state_events option to state.highstate, state.apply, state.sls, state.sls_id. + This allows users to enable state_events on a per use basis rather than having to + enable them globally for all state runs. [#63316](https://github.com/saltstack/salt/issues/63316) +- Allow max queue size setting for state runs to prevent performance problems from queue growth [#63356](https://github.com/saltstack/salt/issues/63356) +- Add support of exposing meta_server_grains for Azure VMs [#63606](https://github.com/saltstack/salt/issues/63606) +- Include the version of `relenv` in the versions report. [#63827](https://github.com/saltstack/salt/issues/63827) +- Added debug log messages displaying the command being run when removing packages on Windows [#63866](https://github.com/saltstack/salt/issues/63866) +- Adding the ability to exclude arguments from a state that end up passed to cmd.retcode when requisites such as onlyif or unless are used. [#63956](https://github.com/saltstack/salt/issues/63956) +- Add --next-release argument to salt/version.py, which prints the next upcoming release. [#64023](https://github.com/saltstack/salt/issues/64023) + + +### Security + +- Upgrade Requirements Due to Security Issues. + + * Upgrade to `cryptography>=39.0.1` due to: + * https://github.com/advisories/GHSA-x4qr-2fvf-3mr5 + * https://github.com/advisories/GHSA-w7pp-m8wf-vj6r + * Upgrade to `pyopenssl==23.0.0` due to the cryptography upgrade. + * Update to `markdown-it-py==2.2.0` due to: + * https://github.com/advisories/GHSA-jrwr-5x3p-hvc3 + * https://github.com/advisories/GHSA-vrjv-mxr7-vjf8 [#63882](https://github.com/saltstack/salt/issues/63882) + + ## 3006.0rc3 (2023-03-29) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 91b09c73752..cd24612df49 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -513,7 +513,7 @@ Now you can run your tests: :: - python -m nox -e "pytest-3.7(coverage=False)" -- tests/unit/cli/test_batch.py + python -m nox -e "test-3(coverage=False)" -- tests/unit/cli/test_batch.py It's a good idea to install `espeak `__ or use ``say`` on @@ -522,11 +522,31 @@ this: :: - python -m nox -e "pytest-3.7(coverage=False)" -- tests/unit/cli/test_batch.py; espeak "Tests done, woohoo!" + python -m nox -e "test-3(coverage=False)" -- tests/unit/cli/test_batch.py; espeak "Tests done, woohoo!" That way you don't have to keep monitoring the actual test run. +:: + + python -m nox -e "test-3(coverage=False)" -- --core-tests + +You can enable or disable test groups locally by passing their respected flag: + +* --no-fast-tests - Tests that are ~10s or faster. Fast tests make up ~75% of tests and can run in 10 to 20 minutes. +* --slow-tests - Tests that are ~10s or slower. +* --core-tests - Tests of any speed that test the root parts of salt. +* --flaky-jail - Test that need to be temporarily skipped. + +In Your PR, you can enable or disable test groups by setting a label. +All fast, slow, and core tests specified in the change file will always run. + +* test:no-fast +* test:core +* test:slow +* test:flaky-jail + + Changelog and commit! --------------------- When you write your commit message you should use imperative style. Do diff --git a/changelog/31468.added.md b/changelog/31468.added.md deleted file mode 100644 index f1b2b802ba9..00000000000 --- a/changelog/31468.added.md +++ /dev/null @@ -1 +0,0 @@ -Allow users to enable 'queue=True' for all state runs via config file diff --git a/changelog/3396.added.md b/changelog/3396.added.md deleted file mode 100644 index 8a6987bb4a5..00000000000 --- a/changelog/3396.added.md +++ /dev/null @@ -1,5 +0,0 @@ -Introduce a `LIB_STATE_DIR` syspaths variable which defaults to `CONFIG_DIR`, -but can be individually customized during installation by specifying -`--salt-lib-state-dir` during installation. Change the default `pki_dir` to -`/pki/master` (for the master) and `/pki/minion` -(for the minion). diff --git a/changelog/36138.fixed.md b/changelog/36138.fixed.md deleted file mode 100644 index 78b2e97cc44..00000000000 --- a/changelog/36138.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Add kwargs to handle extra parameters for http.query diff --git a/changelog/39292.fixed.md b/changelog/39292.fixed.md deleted file mode 100644 index cbb472423aa..00000000000 --- a/changelog/39292.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix mounted bind mounts getting active mount options added diff --git a/changelog/40054.fixed.md b/changelog/40054.fixed.md deleted file mode 100644 index 57641e5c186..00000000000 --- a/changelog/40054.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix `sysctl.present` converts spaces to tabs. diff --git a/changelog/42306.fixed.md b/changelog/42306.fixed.md deleted file mode 100644 index d6392749171..00000000000 --- a/changelog/42306.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixes state pkg.purged to purge removed packages on Debian family systems diff --git a/changelog/43287.added.md b/changelog/43287.added.md deleted file mode 100644 index 90b47e65d44..00000000000 --- a/changelog/43287.added.md +++ /dev/null @@ -1 +0,0 @@ -Added pillar templating to vault policies diff --git a/changelog/45823.fixed.md b/changelog/45823.fixed.md deleted file mode 100644 index e419ad4f7e9..00000000000 --- a/changelog/45823.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix fun_args missing from syndic returns diff --git a/changelog/47201.fixed.md b/changelog/47201.fixed.md deleted file mode 100644 index 0dbb18186a9..00000000000 --- a/changelog/47201.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix mount.mounted with 'mount: False' reports unmounted file system as unchanged when running with test=True diff --git a/changelog/48609.changed.md b/changelog/48609.changed.md deleted file mode 100644 index 92f1dc00f8e..00000000000 --- a/changelog/48609.changed.md +++ /dev/null @@ -1 +0,0 @@ -More intelligent diffing in changes of file.serialize state. diff --git a/changelog/49310.fixed.md b/changelog/49310.fixed.md deleted file mode 100644 index ce6c5536b30..00000000000 --- a/changelog/49310.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Issue #49310: Allow users to touch a file with Unix date of birth diff --git a/changelog/49430.changed.md b/changelog/49430.changed.md deleted file mode 100644 index 4e94ec3f596..00000000000 --- a/changelog/49430.changed.md +++ /dev/null @@ -1 +0,0 @@ -Move deprecation of the neutron module to Argon. Please migrate to the neutronng module instead. diff --git a/changelog/51088.added.md b/changelog/51088.added.md deleted file mode 100644 index a87c8890668..00000000000 --- a/changelog/51088.added.md +++ /dev/null @@ -1 +0,0 @@ -Add support for NVMeF as a transport protocol for hosts in a Pure Storage FlashArray diff --git a/changelog/51620.fixed.md b/changelog/51620.fixed.md deleted file mode 100644 index 79deac1397f..00000000000 --- a/changelog/51620.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Do not raise an exception in pkg.info_installed on nonzero return code diff --git a/changelog/51739.fixed.md b/changelog/51739.fixed.md deleted file mode 100644 index 97ee15c0019..00000000000 --- a/changelog/51739.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Passes the value of the force parameter from file.copy to its call to file.remove so that files with the read-only attribute are handled. diff --git a/changelog/52167.fixed.md b/changelog/52167.fixed.md deleted file mode 100644 index 4a13253aaaa..00000000000 --- a/changelog/52167.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed x509.certificate_managed creates new certificate every run in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. diff --git a/changelog/52354.fixed.md b/changelog/52354.fixed.md deleted file mode 100644 index af885d77fa4..00000000000 --- a/changelog/52354.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Don't check for cached pillar errors on state.apply diff --git a/changelog/52400.fixed.md b/changelog/52400.fixed.md deleted file mode 100644 index 1d806f80cbc..00000000000 --- a/changelog/52400.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Swapping out args and kwargs for arg and kwarg respectively in the Slack engine when the command passed is a runner. diff --git a/changelog/53353.fixed.md b/changelog/53353.fixed.md deleted file mode 100644 index cadda5448cc..00000000000 --- a/changelog/53353.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Ensure when we're adding chunks to the rules when running aggregation with the iptables state module we use a copy of the chunk otherwise we end up with a recursive mess. diff --git a/changelog/53377.fixed.md b/changelog/53377.fixed.md deleted file mode 100644 index d1eac3cfff3..00000000000 --- a/changelog/53377.fixed.md +++ /dev/null @@ -1 +0,0 @@ -When user_create or user_remove fail, return False instead of returning the error. diff --git a/changelog/53914.fixed.md b/changelog/53914.fixed.md deleted file mode 100644 index 5b08af66647..00000000000 --- a/changelog/53914.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Include sync_roster when sync_all is called. diff --git a/changelog/53988.fixed.md b/changelog/53988.fixed.md deleted file mode 100644 index 8220d4acddd..00000000000 --- a/changelog/53988.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Avoid warning noise in lograte.get diff --git a/changelog/54347.fixed.md b/changelog/54347.fixed.md deleted file mode 100644 index 307e630eccf..00000000000 --- a/changelog/54347.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed listing revoked keys with gpg.list_keys diff --git a/changelog/54508.fixed.md b/changelog/54508.fixed.md deleted file mode 100644 index 0292039705a..00000000000 --- a/changelog/54508.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix mount.mounted does not handle blanks properly diff --git a/changelog/54679.added.md b/changelog/54679.added.md deleted file mode 100644 index c0d663f8926..00000000000 --- a/changelog/54679.added.md +++ /dev/null @@ -1 +0,0 @@ -A new salt-ssh roster that generates a roster by parses a known_hosts file. diff --git a/changelog/54682.fixed.md b/changelog/54682.fixed.md deleted file mode 100644 index 87a958c2a79..00000000000 --- a/changelog/54682.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed grain num_cpus get wrong CPUs count in case of inconsistent CPU numbering. diff --git a/changelog/54713.added.md b/changelog/54713.added.md deleted file mode 100644 index 174564b4162..00000000000 --- a/changelog/54713.added.md +++ /dev/null @@ -1 +0,0 @@ -Added Windows Event Viewer support diff --git a/changelog/54907.fixed.md b/changelog/54907.fixed.md deleted file mode 100644 index 1f29c53b1ad..00000000000 --- a/changelog/54907.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix spelling error for python_shell argument in dpkg_lower module diff --git a/changelog/55226.fixed.md b/changelog/55226.fixed.md deleted file mode 100644 index 6947dc684aa..00000000000 --- a/changelog/55226.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Cleaned up bytes response data before sending to non-bytes compatible returners (postgres, mysql) diff --git a/changelog/55269.fixed.md b/changelog/55269.fixed.md deleted file mode 100644 index 42543738580..00000000000 --- a/changelog/55269.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed malformed state return when testing file.managed with unavailable source file diff --git a/changelog/55295.deprecated.md b/changelog/55295.deprecated.md deleted file mode 100644 index 71c9da60baa..00000000000 --- a/changelog/55295.deprecated.md +++ /dev/null @@ -1,2 +0,0 @@ -renamed `keep_jobs`, specifying job cache TTL in hours, to `keep_jobs_seconds`, specifying TTL in seconds. -`keep_jobs` will be removed in the Argon release diff --git a/changelog/56013.added.md b/changelog/56013.added.md deleted file mode 100644 index a249f407a45..00000000000 --- a/changelog/56013.added.md +++ /dev/null @@ -1 +0,0 @@ -Added the win_lgpo_reg state and execution modules which will allow registry based group policy to be set directly in the Registry.pol file diff --git a/changelog/56016.fixed.md b/changelog/56016.fixed.md deleted file mode 100644 index de186daa9d0..00000000000 --- a/changelog/56016.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Included stdout in error message for Zypper calls in zypperpkg module. diff --git a/changelog/56093.fixed.md b/changelog/56093.fixed.md deleted file mode 100644 index 2b898dd72f3..00000000000 --- a/changelog/56093.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed pillar.filter_by with salt-ssh diff --git a/changelog/57139.fixed.md b/changelog/57139.fixed.md deleted file mode 100644 index af460e9b2a7..00000000000 --- a/changelog/57139.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix boto_route53 issue with (multiple) VPCs. diff --git a/changelog/57180.fixed.md b/changelog/57180.fixed.md deleted file mode 100644 index af885d77fa4..00000000000 --- a/changelog/57180.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Don't check for cached pillar errors on state.apply diff --git a/changelog/57463.fixed.md b/changelog/57463.fixed.md deleted file mode 100644 index d0678bf0e28..00000000000 --- a/changelog/57463.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Remove log from mine runner which was not used. diff --git a/changelog/57500.added.md b/changelog/57500.added.md deleted file mode 100644 index 91af2f8bae2..00000000000 --- a/changelog/57500.added.md +++ /dev/null @@ -1 +0,0 @@ -Added resource tagging functions to boto_dynamodb execution module diff --git a/changelog/57535.fixed.md b/changelog/57535.fixed.md deleted file mode 100644 index 23e8ceaff93..00000000000 --- a/changelog/57535.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed x509.read_certificate error when reading a Microsoft CA issued certificate in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. diff --git a/changelog/57803.changed.md b/changelog/57803.changed.md deleted file mode 100644 index f278bd479a7..00000000000 --- a/changelog/57803.changed.md +++ /dev/null @@ -1,2 +0,0 @@ -``umask`` is now a global state argument, instead of only applying to ``cmd`` -states. diff --git a/changelog/57842.fixed.md b/changelog/57842.fixed.md deleted file mode 100644 index c708020bd1a..00000000000 --- a/changelog/57842.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Updating Slack engine to use slack_bolt library. diff --git a/changelog/58165.fixed.md b/changelog/58165.fixed.md deleted file mode 100644 index 31a76928f7a..00000000000 --- a/changelog/58165.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed warning about replace=True with x509.certificate_managed in the new cryptography x509 module. diff --git a/changelog/58202.fixed.md b/changelog/58202.fixed.md deleted file mode 100644 index b4cf0c0add7..00000000000 --- a/changelog/58202.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix salt.modules.pip:is_installed doesn't handle locally installed packages diff --git a/changelog/58297.fixed.md b/changelog/58297.fixed.md deleted file mode 100644 index 4aaa8803413..00000000000 --- a/changelog/58297.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Add missing MariaDB Grants to mysql module. MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. diff --git a/changelog/58423.fixed.md b/changelog/58423.fixed.md deleted file mode 100644 index ea678fb6985..00000000000 --- a/changelog/58423.fixed.md +++ /dev/null @@ -1,2 +0,0 @@ -linux_shadow: Fix cases where malformed shadow entries cause `user.present` -states to fail. diff --git a/changelog/58729.fixed.md b/changelog/58729.fixed.md deleted file mode 100644 index 6e806784a36..00000000000 --- a/changelog/58729.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed salt.utils.compat.cmp to work with dictionaries diff --git a/changelog/58953.fixed.md b/changelog/58953.fixed.md deleted file mode 100644 index fd8b01baec6..00000000000 --- a/changelog/58953.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed formatting for terse output mode diff --git a/changelog/58971.changed.md b/changelog/58971.changed.md deleted file mode 100644 index d0d54ec84a1..00000000000 --- a/changelog/58971.changed.md +++ /dev/null @@ -1 +0,0 @@ -Update pillar.obfuscate to accept kwargs in addition to args. This is useful when passing in keyword arguments like saltenv that are then passed along to pillar.items. diff --git a/changelog/58986.added.md b/changelog/58986.added.md deleted file mode 100644 index ba03c9324b7..00000000000 --- a/changelog/58986.added.md +++ /dev/null @@ -1,5 +0,0 @@ -Added `openvswitch_db` state module and functions `bridge_to_parent`, -`bridge_to_vlan`, `db_get`, and `db_set` to the `openvswitch` execution module. -Also added optional `parent` and `vlan` parameters to the -`openvswitch_bridge.present` state module function and the -`openvswitch.bridge_create` execution module function. diff --git a/changelog/59017.fixed.md b/changelog/59017.fixed.md deleted file mode 100644 index a34acd3429d..00000000000 --- a/changelog/59017.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed RecursiveDictDiffer with added nested dicts diff --git a/changelog/59169.fixed.md b/changelog/59169.fixed.md deleted file mode 100644 index 718be2a22e3..00000000000 --- a/changelog/59169.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed x509.certificate_managed has DoS effect on master in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. diff --git a/changelog/59183.fixed.md b/changelog/59183.fixed.md deleted file mode 100644 index 953c94b2b5d..00000000000 --- a/changelog/59183.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed saltnado websockets disconnecting immediately diff --git a/changelog/59315.fixed.md b/changelog/59315.fixed.md deleted file mode 100644 index 67fa822f678..00000000000 --- a/changelog/59315.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed x509.certificate_managed rolls certificates every now and then in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. diff --git a/changelog/59339.fixed.md b/changelog/59339.fixed.md deleted file mode 100644 index af885d77fa4..00000000000 --- a/changelog/59339.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Don't check for cached pillar errors on state.apply diff --git a/changelog/59439.changed.md b/changelog/59439.changed.md deleted file mode 100644 index 282c55a658f..00000000000 --- a/changelog/59439.changed.md +++ /dev/null @@ -1 +0,0 @@ -Improve support for listing macOS brew casks diff --git a/changelog/59585.fixed.md b/changelog/59585.fixed.md deleted file mode 100644 index c73593f7dec..00000000000 --- a/changelog/59585.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix postgres_privileges.present not idempotent for functions diff --git a/changelog/59766.fixed.md b/changelog/59766.fixed.md deleted file mode 100644 index 24feb19ddf5..00000000000 --- a/changelog/59766.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed influxdb_continuous_query.present state to provide the client args to the underlying module on create. diff --git a/changelog/59786.fixed.md b/changelog/59786.fixed.md deleted file mode 100644 index 00612d70fbf..00000000000 --- a/changelog/59786.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Warn when using insecure (http:// based) key_urls for apt-based systems in pkgrepo.managed, and add a kwarg that determines the validity of such a url. diff --git a/changelog/59909.fixed.md b/changelog/59909.fixed.md deleted file mode 100644 index b16c524c7a9..00000000000 --- a/changelog/59909.fixed.md +++ /dev/null @@ -1 +0,0 @@ -add load balancing policy default option and ensure the module can be executed with arguments from CLI diff --git a/changelog/59917.removed.md b/changelog/59917.removed.md deleted file mode 100644 index a91e76d6acd..00000000000 --- a/changelog/59917.removed.md +++ /dev/null @@ -1 +0,0 @@ -Remove and deprecate the __orchestration__ key from salt.runner and salt.wheel return data. To get it back, set features.enable_deprecated_orchestration_flag master configuration option to True. The flag will be completely removed in Salt 3008 Argon. diff --git a/changelog/60003.fixed.md b/changelog/60003.fixed.md deleted file mode 100644 index 7b0ccd4010c..00000000000 --- a/changelog/60003.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix salt-ssh when using imports with extra-filerefs. diff --git a/changelog/60154.added.md b/changelog/60154.added.md deleted file mode 100644 index 3957b19ce93..00000000000 --- a/changelog/60154.added.md +++ /dev/null @@ -1 +0,0 @@ -State module to manage SysFS attributes diff --git a/changelog/60170.fixed.md b/changelog/60170.fixed.md deleted file mode 100644 index b19324a76cd..00000000000 --- a/changelog/60170.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed cache directory corruption startup error diff --git a/changelog/60227.fixed.md b/changelog/60227.fixed.md deleted file mode 100644 index 60d46b46636..00000000000 --- a/changelog/60227.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Update docs remove dry_run in docstring of file.blockreplace state. diff --git a/changelog/60249.fixed.md b/changelog/60249.fixed.md deleted file mode 100644 index f44049f3f2b..00000000000 --- a/changelog/60249.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Adds Parrot to OS_Family_Map in grains. diff --git a/changelog/60365.fixed.md b/changelog/60365.fixed.md deleted file mode 100644 index 778334ee4b3..00000000000 --- a/changelog/60365.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed stdout and stderr being empty sometimes when use_vt=True for the cmd.run[*] functions diff --git a/changelog/60430.added.md b/changelog/60430.added.md deleted file mode 100644 index cee2d275854..00000000000 --- a/changelog/60430.added.md +++ /dev/null @@ -1 +0,0 @@ -Added ability for `salt.wait_for_event` to handle `event_id`s that have a list value. diff --git a/changelog/60467.fixed.md b/changelog/60467.fixed.md deleted file mode 100644 index 6adc3e29cbf..00000000000 --- a/changelog/60467.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Use return code in iptables --check to verify rule exists. diff --git a/changelog/60476.removed.md b/changelog/60476.removed.md deleted file mode 100644 index e72141263e1..00000000000 --- a/changelog/60476.removed.md +++ /dev/null @@ -1 +0,0 @@ -Removed distutils and replaced with setuptools, given distutils is deprecated and removed in Python 3.12 diff --git a/changelog/60518.added.md b/changelog/60518.added.md deleted file mode 100644 index 322ee04da17..00000000000 --- a/changelog/60518.added.md +++ /dev/null @@ -1 +0,0 @@ -Added suport for Linux ppc64le core grains (cpu_model, virtual, productname, manufacturer, serialnumber) and arm core grains (serialnumber, productname) diff --git a/changelog/60557.fixed.md b/changelog/60557.fixed.md deleted file mode 100644 index 0634bc83952..00000000000 --- a/changelog/60557.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix regression pip.installed does not pass env_vars when calling pip.list diff --git a/changelog/60700.added.md b/changelog/60700.added.md deleted file mode 100644 index 91eee4260d5..00000000000 --- a/changelog/60700.added.md +++ /dev/null @@ -1 +0,0 @@ -Added autostart option to virt.defined and virt.running states, along with virt.update execution modules. diff --git a/changelog/60722.added.md b/changelog/60722.added.md deleted file mode 100644 index 183fbc8b8e9..00000000000 --- a/changelog/60722.added.md +++ /dev/null @@ -1 +0,0 @@ -Added .0 back to our versioning scheme for future versions (e.g. 3006.0) diff --git a/changelog/60853.fixed.md b/changelog/60853.fixed.md deleted file mode 100644 index 3264c66ad7c..00000000000 --- a/changelog/60853.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix xfs module when additional output included in mkfs.xfs command. diff --git a/changelog/60915.fixed.md b/changelog/60915.fixed.md deleted file mode 100644 index f3c2644c723..00000000000 --- a/changelog/60915.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed parsing new format of terraform states in roster.terraform diff --git a/changelog/60994.fixed.md b/changelog/60994.fixed.md deleted file mode 100644 index 3c4be701488..00000000000 --- a/changelog/60994.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed recognizing installed ARMv7 rpm packages in compatible architectures. diff --git a/changelog/60995.fixed.md b/changelog/60995.fixed.md deleted file mode 100644 index 9a81e1b254a..00000000000 --- a/changelog/60995.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixing changes dict in pkg state to be consistent when installing and test=True. diff --git a/changelog/60997.fixed.md b/changelog/60997.fixed.md deleted file mode 100644 index 779005f5014..00000000000 --- a/changelog/60997.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix cron.present duplicating entries when changing timespec to special. diff --git a/changelog/61083.fixed.md b/changelog/61083.fixed.md deleted file mode 100644 index 2d78d777bd7..00000000000 --- a/changelog/61083.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Made salt-ssh respect --wipe again diff --git a/changelog/61092.fixed.md b/changelog/61092.fixed.md deleted file mode 100644 index 6ca66839c96..00000000000 --- a/changelog/61092.fixed.md +++ /dev/null @@ -1,3 +0,0 @@ -state.orchestrate_single only passes a pillar if it is set to the state -function. This allows it to be used with state functions that don't accept a -pillar keyword argument. diff --git a/changelog/61122.fixed.md b/changelog/61122.fixed.md deleted file mode 100644 index 85fc69674ae..00000000000 --- a/changelog/61122.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix ipset state when the comment kwarg is set. diff --git a/changelog/61153.added.md b/changelog/61153.added.md deleted file mode 100644 index ad7b978a7f2..00000000000 --- a/changelog/61153.added.md +++ /dev/null @@ -1 +0,0 @@ -Initial work to allow parallel startup of proxy minions when used as sub proxies with Deltaproxy. diff --git a/changelog/61245.added.md b/changelog/61245.added.md deleted file mode 100644 index 83b0b1ae60d..00000000000 --- a/changelog/61245.added.md +++ /dev/null @@ -1 +0,0 @@ -Added node label support for GCE diff --git a/changelog/61319.added.md b/changelog/61319.added.md deleted file mode 100644 index 990bd79c974..00000000000 --- a/changelog/61319.added.md +++ /dev/null @@ -1 +0,0 @@ -Support the --priority flag when adding sources to Chocolatey. diff --git a/changelog/61335.added.md b/changelog/61335.added.md deleted file mode 100644 index 25d64d763f7..00000000000 --- a/changelog/61335.added.md +++ /dev/null @@ -1 +0,0 @@ -Add namespace option to ext_pillar.http_json diff --git a/changelog/61409.changed.md b/changelog/61409.changed.md deleted file mode 100644 index 1c210d80b34..00000000000 --- a/changelog/61409.changed.md +++ /dev/null @@ -1,3 +0,0 @@ -Add missing MariaDB Grants to mysql module. -MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. -Also improved exception handling in `grant_add` which did not log the original error message and replaced it with a generic error. diff --git a/changelog/61420.added.md b/changelog/61420.added.md deleted file mode 100644 index 5ca782ff916..00000000000 --- a/changelog/61420.added.md +++ /dev/null @@ -1 +0,0 @@ -Added a filter function to ps module to get a list of processes on a minion according to their state. diff --git a/changelog/61422.fixed.md b/changelog/61422.fixed.md deleted file mode 100644 index ee9b1579e25..00000000000 --- a/changelog/61422.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix issue with archive.unzip where the password was not being encoded for the extract function diff --git a/changelog/61433.added.md b/changelog/61433.added.md deleted file mode 100644 index 9cc27679ece..00000000000 --- a/changelog/61433.added.md +++ /dev/null @@ -1 +0,0 @@ -Add postgres.timeout option to postgres module for limiting postgres query times diff --git a/changelog/61542.deprecated.md b/changelog/61542.deprecated.md deleted file mode 100644 index 121d646dd4b..00000000000 --- a/changelog/61542.deprecated.md +++ /dev/null @@ -1 +0,0 @@ -Removing all references to napalm-base which is no longer supported. diff --git a/changelog/61618.fixed.md b/changelog/61618.fixed.md deleted file mode 100644 index 0f38289e2cb..00000000000 --- a/changelog/61618.fixed.md +++ /dev/null @@ -1,4 +0,0 @@ -Some Linux distributions (like AlmaLinux, Astra Linux, Debian, Mendel, Linux -Mint, Pop!_OS, Rocky Linux) report different `oscodename`, `osfullname`, -`osfinger` grains if lsb-release is installed or not. They have been changed to -only derive these OS grains from `/etc/os-release`. diff --git a/changelog/61619.fixed.md b/changelog/61619.fixed.md deleted file mode 100644 index 4f9159792c9..00000000000 --- a/changelog/61619.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Pop!_OS uses the full version (YY.MM) in the osfinger grain now, not just the year. This allows differentiating for example between 20.04 and 20.10. diff --git a/changelog/61650.fixed.md b/changelog/61650.fixed.md deleted file mode 100644 index c60f78baa95..00000000000 --- a/changelog/61650.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix ssh config roster to correctly parse the ssh config files that contain spaces. diff --git a/changelog/61727.fixed.md b/changelog/61727.fixed.md deleted file mode 100644 index 296c6528e0a..00000000000 --- a/changelog/61727.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix SoftLayer configuration not raising an exception when a domain is missing diff --git a/changelog/61789.fixed.md b/changelog/61789.fixed.md deleted file mode 100644 index e7cae60262d..00000000000 --- a/changelog/61789.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Allow the minion to start or salt-call to run even if the user doesn't have permissions to read the root_dir value from the registry diff --git a/changelog/61805.fixed.md b/changelog/61805.fixed.md deleted file mode 100644 index 1a0339fb6a6..00000000000 --- a/changelog/61805.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Need to move the creation of the proxy object for the ProxyMinion further down in the initialization for sub proxies to ensure that all modules, especially any custom proxy modules, are available before attempting to run the init function. diff --git a/changelog/61814.fixed.md b/changelog/61814.fixed.md deleted file mode 100644 index 6d06855ebb8..00000000000 --- a/changelog/61814.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed malformed state return when merge-serializing to an improperly formatted file diff --git a/changelog/61816.fixed.md b/changelog/61816.fixed.md deleted file mode 100644 index f45856f2b5e..00000000000 --- a/changelog/61816.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Made cmdmod._run[_all]_quiet work during minion startup on MacOS with runas specified (which fixed mac_service) diff --git a/changelog/61821.fixed.md b/changelog/61821.fixed.md deleted file mode 100644 index 6ff1221f543..00000000000 --- a/changelog/61821.fixed.md +++ /dev/null @@ -1 +0,0 @@ -When deleting the vault cache, also delete from the session cache diff --git a/changelog/61827.fixed.md b/changelog/61827.fixed.md deleted file mode 100644 index 57747ce1ee5..00000000000 --- a/changelog/61827.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Ignore errors on reading license info with dpkg_lowpkg to prevent tracebacks on getting package information. diff --git a/changelog/61857.added.md b/changelog/61857.added.md deleted file mode 100644 index d9400702845..00000000000 --- a/changelog/61857.added.md +++ /dev/null @@ -1 +0,0 @@ -Added new optional vault option, ``config_location``. This can be either ``master`` or ``local`` and defines where vault will look for connection details, either requesting them from the master or using the local config. diff --git a/changelog/61859.fixed.md b/changelog/61859.fixed.md deleted file mode 100644 index 1bfcbec99b0..00000000000 --- a/changelog/61859.fixed.md +++ /dev/null @@ -1 +0,0 @@ -win_lgpo: Display conflicting policy names when more than one policy is found diff --git a/changelog/61860.fixed.md b/changelog/61860.fixed.md deleted file mode 100644 index 3b64fade195..00000000000 --- a/changelog/61860.fixed.md +++ /dev/null @@ -1 +0,0 @@ -win_lgpo: Fixed intermittent KeyError when getting policy setting using lgpo.get_policy diff --git a/changelog/61931.added.md b/changelog/61931.added.md deleted file mode 100644 index c6b1d318e78..00000000000 --- a/changelog/61931.added.md +++ /dev/null @@ -1 +0,0 @@ -Add ipwrap() jinja filter to wrap IPv6 addresses with brackets. diff --git a/changelog/61966.fixed.md b/changelog/61966.fixed.md deleted file mode 100644 index e772fcf33af..00000000000 --- a/changelog/61966.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed listing minions on OpenBSD diff --git a/changelog/62009.added.md b/changelog/62009.added.md deleted file mode 100644 index 7a8303d4fec..00000000000 --- a/changelog/62009.added.md +++ /dev/null @@ -1 +0,0 @@ -'tcp' transport is now available in ipv6-only network diff --git a/changelog/62009.deprecated.md b/changelog/62009.deprecated.md deleted file mode 100644 index e9455f07a7b..00000000000 --- a/changelog/62009.deprecated.md +++ /dev/null @@ -1 +0,0 @@ -The 'ip_bracket' function has been moved from salt/utils/zeromq.py in salt/utils/network.py diff --git a/changelog/62019.fixed.md b/changelog/62019.fixed.md deleted file mode 100644 index 8a772963e47..00000000000 --- a/changelog/62019.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Make Salt to return an error on "pkg" modules and states when targeting duplicated package names diff --git a/changelog/62022.fixed.md b/changelog/62022.fixed.md deleted file mode 100644 index 49084228f9c..00000000000 --- a/changelog/62022.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix return of REST-returned permissions when auth_list is set diff --git a/changelog/62029.fixed.md b/changelog/62029.fixed.md deleted file mode 100644 index b468d5a1498..00000000000 --- a/changelog/62029.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Normalize package names once on using pkg.installed/removed with yum to make it possible to install packages with the name containing a part similar to a name of architecture. diff --git a/changelog/62030.fixed.md b/changelog/62030.fixed.md deleted file mode 100644 index bd604636069..00000000000 --- a/changelog/62030.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix inconsitency regarding name and pkgs parameters between zypperpkg.upgrade() and yumpkg.upgrade() diff --git a/changelog/62031.added.md b/changelog/62031.added.md deleted file mode 100644 index f0b66ff96f5..00000000000 --- a/changelog/62031.added.md +++ /dev/null @@ -1 +0,0 @@ -Add `diff_attr` parameter to pkg.upgrade() (zypper/yum). diff --git a/changelog/62032.fixed.md b/changelog/62032.fixed.md deleted file mode 100644 index ceb3cc89b95..00000000000 --- a/changelog/62032.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix attr=all handling in pkg.list_pkgs() (yum/zypper). diff --git a/changelog/62053.fixed.md b/changelog/62053.fixed.md deleted file mode 100644 index 24d281b5f47..00000000000 --- a/changelog/62053.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed the humanname being ignored in pkgrepo.managed on openSUSE Leap diff --git a/changelog/62058.fixed.md b/changelog/62058.fixed.md deleted file mode 100644 index 9329631635c..00000000000 --- a/changelog/62058.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed issue with some LGPO policies having whitespace at the beginning or end of the element alias diff --git a/changelog/62074.fixed.md b/changelog/62074.fixed.md deleted file mode 100644 index 9910d51c1b7..00000000000 --- a/changelog/62074.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix ordering of args to libcloud_storage.download_object module diff --git a/changelog/62082.fixed.md b/changelog/62082.fixed.md deleted file mode 100644 index 02e5f5ff407..00000000000 --- a/changelog/62082.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Ignore extend declarations in sls files that are excluded. diff --git a/changelog/62089.changed.md b/changelog/62089.changed.md deleted file mode 100644 index 09feb2e9225..00000000000 --- a/changelog/62089.changed.md +++ /dev/null @@ -1 +0,0 @@ -Use VENV_PIP_TARGET environment variable as a default target for pip if present. diff --git a/changelog/62101.fixed.md b/changelog/62101.fixed.md deleted file mode 100644 index 99de5bbf0a3..00000000000 --- a/changelog/62101.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Remove leftover usage of impacket diff --git a/changelog/62120.added.md b/changelog/62120.added.md deleted file mode 100644 index 4303d124f0b..00000000000 --- a/changelog/62120.added.md +++ /dev/null @@ -1,4 +0,0 @@ -Config option pass_variable_prefix allows to distinguish variables that contain paths to pass secrets. -Config option pass_strict_fetch allows to error out when a secret cannot be fetched from pass. -Config option pass_dir allows setting the PASSWORD_STORE_DIR env for pass. -Config option pass_gnupghome allows setting the $GNUPGHOME env for pass. diff --git a/changelog/62120.fixed.md b/changelog/62120.fixed.md deleted file mode 100644 index 22a97113833..00000000000 --- a/changelog/62120.fixed.md +++ /dev/null @@ -1,4 +0,0 @@ -Pass executable path from _get_path_exec() is used when calling the program. -The $HOME env is no longer modified globally. -Only trailing newlines are stripped from the fetched secret. -Pass process arguments are handled in a secure way. diff --git a/changelog/62131.fixed.md b/changelog/62131.fixed.md deleted file mode 100644 index 67c772568f3..00000000000 --- a/changelog/62131.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Ignore some command return codes in openbsdrcctl_service to prevent spurious errors diff --git a/changelog/62139.fixed.md b/changelog/62139.fixed.md deleted file mode 100644 index d9dfd2428a4..00000000000 --- a/changelog/62139.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed extra period in filename output in tls module. Instead of "server.crt." it will now be "server.crt". diff --git a/changelog/62152.fixed.md b/changelog/62152.fixed.md deleted file mode 100644 index 752188afe75..00000000000 --- a/changelog/62152.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Make sure lingering PAexec-*.exe files in the Windows directory are cleaned up diff --git a/changelog/62168.changed.md b/changelog/62168.changed.md deleted file mode 100644 index 564579b4ba7..00000000000 --- a/changelog/62168.changed.md +++ /dev/null @@ -1 +0,0 @@ -Disabled FQDNs grains on macOS by default diff --git a/changelog/62178.added.md b/changelog/62178.added.md deleted file mode 100644 index 6ada2946584..00000000000 --- a/changelog/62178.added.md +++ /dev/null @@ -1 +0,0 @@ -Add file.pruned state and expanded file.rmdir exec module functionality diff --git a/changelog/62185.fixed.md b/changelog/62185.fixed.md deleted file mode 100644 index e0329c8bf33..00000000000 --- a/changelog/62185.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Restored Salt's DeprecationWarnings diff --git a/changelog/62197.fixed.md b/changelog/62197.fixed.md deleted file mode 100644 index 081a576eb12..00000000000 --- a/changelog/62197.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed issue with forward slashes on Windows with file.recurse and clean=True diff --git a/changelog/62198.fixed.md b/changelog/62198.fixed.md deleted file mode 100644 index 9a33558a11d..00000000000 --- a/changelog/62198.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Recognize OSMC as Debian-based diff --git a/changelog/62204.fixed.md b/changelog/62204.fixed.md deleted file mode 100644 index 59f1914593f..00000000000 --- a/changelog/62204.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed Zypper module failing on RPM lock file being temporarily unavailable. diff --git a/changelog/62211.fixed.md b/changelog/62211.fixed.md deleted file mode 100644 index 92a021023a1..00000000000 --- a/changelog/62211.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Improved error handling and diagnostics in the proxmox salt-cloud driver diff --git a/changelog/62218.changed.md b/changelog/62218.changed.md deleted file mode 100644 index 52fca5c3927..00000000000 --- a/changelog/62218.changed.md +++ /dev/null @@ -1 +0,0 @@ -Replaced pyroute2.IPDB with pyroute2.NDB, as the former is deprecated diff --git a/changelog/62220.fixed.md b/changelog/62220.fixed.md deleted file mode 100644 index ab3eec5d151..00000000000 --- a/changelog/62220.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Added EndeavourOS to the Arch os_family. diff --git a/changelog/62235.fixed.md b/changelog/62235.fixed.md deleted file mode 100644 index a38c9e127d4..00000000000 --- a/changelog/62235.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix salt-ssh not detecting `platform-python` as a valid interpreter on EL8 diff --git a/changelog/62239.removed.md b/changelog/62239.removed.md deleted file mode 100644 index c065051cc9a..00000000000 --- a/changelog/62239.removed.md +++ /dev/null @@ -1 +0,0 @@ -Removed ``runtests`` targets from ``noxfile.py`` diff --git a/changelog/62248.fixed.md b/changelog/62248.fixed.md deleted file mode 100644 index 50cb42bf406..00000000000 --- a/changelog/62248.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix pkg.version_cmp on openEuler and a few other os flavors. diff --git a/changelog/62273.fixed.md b/changelog/62273.fixed.md deleted file mode 100644 index 1f4caad6085..00000000000 --- a/changelog/62273.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix localhost detection in glusterfs.peers diff --git a/changelog/62275.added.md b/changelog/62275.added.md deleted file mode 100644 index 7e9d9052545..00000000000 --- a/changelog/62275.added.md +++ /dev/null @@ -1 +0,0 @@ -Added "dig.PTR" function to resolve PTR records for IPs, as well as tests and documentation diff --git a/changelog/62281.fixed.md b/changelog/62281.fixed.md deleted file mode 100644 index f8bf23a7ec7..00000000000 --- a/changelog/62281.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix Salt Package Manager (SPM) exception when calling spm create_repo . diff --git a/changelog/62283.fixed.md b/changelog/62283.fixed.md deleted file mode 100644 index 2a5d60d658b..00000000000 --- a/changelog/62283.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix matcher slowness due to loader invocation diff --git a/changelog/62323.fixed.md b/changelog/62323.fixed.md deleted file mode 100644 index 02fc14e8479..00000000000 --- a/changelog/62323.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixes the Puppet module for non-aio Puppet packages for example running the Puppet module on FreeBSD. diff --git a/changelog/62334.fixed.md b/changelog/62334.fixed.md deleted file mode 100644 index 37e12d2a86f..00000000000 --- a/changelog/62334.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Issue 62334: Displays a debug log message instead of an error log message when the publisher fails to connect diff --git a/changelog/62336.fixed.md b/changelog/62336.fixed.md deleted file mode 100644 index 300de31a017..00000000000 --- a/changelog/62336.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix pyobjects renderer access to opts and sls diff --git a/changelog/62346.changed.md b/changelog/62346.changed.md deleted file mode 100644 index 1e131d3f715..00000000000 --- a/changelog/62346.changed.md +++ /dev/null @@ -1 +0,0 @@ -Enhance capture of error messages for Zypper calls in zypperpkg module. diff --git a/changelog/62366.added.md b/changelog/62366.added.md deleted file mode 100644 index 00871a8ca85..00000000000 --- a/changelog/62366.added.md +++ /dev/null @@ -1 +0,0 @@ -Added the ability to remove a KB using the DISM state/execution modules diff --git a/changelog/62372.fixed.md b/changelog/62372.fixed.md deleted file mode 100644 index 1d460b9d0e6..00000000000 --- a/changelog/62372.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix use of random shuffle and sample functions as Jinja filters diff --git a/changelog/62377.fixed.md b/changelog/62377.fixed.md deleted file mode 100644 index 1a4bef889cb..00000000000 --- a/changelog/62377.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix groups with duplicate GIDs are not returned by get_group_list diff --git a/changelog/62381.added.md b/changelog/62381.added.md deleted file mode 100644 index 8bea04f2ea4..00000000000 --- a/changelog/62381.added.md +++ /dev/null @@ -1 +0,0 @@ -Add " python" subcommand to allow execution or arbitrary scripts via bundled Python runtime diff --git a/changelog/62390.fixed.md b/changelog/62390.fixed.md deleted file mode 100644 index e5fee65205f..00000000000 --- a/changelog/62390.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix the "zpool.present" state when enabling zpool features that are already active. diff --git a/changelog/62398.fixed.md b/changelog/62398.fixed.md deleted file mode 100644 index c5e10154aeb..00000000000 --- a/changelog/62398.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix ability to execute remote file client methods in saltcheck diff --git a/changelog/62400.fixed.md b/changelog/62400.fixed.md deleted file mode 100644 index 290866b1f53..00000000000 --- a/changelog/62400.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Update all platforms to use pycparser 2.21 or greater for Py 3.9 or higher, fixes fips fault with openssl v3.x diff --git a/changelog/62405.fixed.md b/changelog/62405.fixed.md deleted file mode 100644 index a8077992fe1..00000000000 --- a/changelog/62405.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Due to changes in the Netmiko library for the exception paths, need to check the version of Netmiko python library and then import the exceptions from different locations depending on the result. diff --git a/changelog/62408.fixed.md b/changelog/62408.fixed.md deleted file mode 100644 index 741af586a9c..00000000000 --- a/changelog/62408.fixed.md +++ /dev/null @@ -1 +0,0 @@ -When using preq on a state, then prereq state will first be run with test=True to determine if there are changes. When there are changes, the state with the prereq option will be run prior to the prereq state. If this state fails then the prereq state will not run and the state output uses the test=True run. However, the proposed changes are included for the prereq state are included from the test=True run. We should pull those out as there weren't actually changes since the prereq state did not run. diff --git a/changelog/62426.fixed.md b/changelog/62426.fixed.md deleted file mode 100644 index 03242a22d01..00000000000 --- a/changelog/62426.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Added directory mode for file.copy with makedirs diff --git a/changelog/62432.removed.md b/changelog/62432.removed.md deleted file mode 100644 index b696136a208..00000000000 --- a/changelog/62432.removed.md +++ /dev/null @@ -1,5 +0,0 @@ -Removed the PyObjC dependency. - -This addresses problems with building a one dir build for macOS. -It became problematic because depending on the macOS version, it pulls different dependencies, and we would either have to build a macos onedir for each macOS supported release, or ship a crippled onedir(because it would be tied to the macOS version where the onedir was built). -Since it's currently not being used, it's removed. diff --git a/changelog/62435.fixed.md b/changelog/62435.fixed.md deleted file mode 100644 index 54286a58850..00000000000 --- a/changelog/62435.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Provide better error handling in the various napalm proxy minion functions when the device is not accessible. diff --git a/changelog/62439.fixed.md b/changelog/62439.fixed.md deleted file mode 100644 index 5863b52c2d2..00000000000 --- a/changelog/62439.fixed.md +++ /dev/null @@ -1 +0,0 @@ -When handling aggregation, change the order to ensure that the requisites are aggregated first and then the state functions are aggregated. Caching whether aggregate functions are available for particular states so we don't need to attempt to load them everytime. diff --git a/changelog/62446.added.md b/changelog/62446.added.md deleted file mode 100644 index 86ad064ee97..00000000000 --- a/changelog/62446.added.md +++ /dev/null @@ -1 +0,0 @@ -Add ability to provide conditions which convert normal state actions to no-op when true diff --git a/changelog/62451.fixed.md b/changelog/62451.fixed.md deleted file mode 100644 index 13164f86955..00000000000 --- a/changelog/62451.fixed.md +++ /dev/null @@ -1 +0,0 @@ -The patch allows to boostrap kubernetes clusters in the version above 1.13 via salt module diff --git a/changelog/62461.fixed.md b/changelog/62461.fixed.md deleted file mode 100644 index 4f8f76ad943..00000000000 --- a/changelog/62461.fixed.md +++ /dev/null @@ -1 +0,0 @@ -sysctl.persist now updates the in-memory value on FreeBSD even if the on-disk value was already correct. diff --git a/changelog/62474.fixed.md b/changelog/62474.fixed.md deleted file mode 100644 index bf45b04872a..00000000000 --- a/changelog/62474.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed parsing CDROM apt sources diff --git a/changelog/62480.added.md b/changelog/62480.added.md deleted file mode 100644 index 50044e2d1d9..00000000000 --- a/changelog/62480.added.md +++ /dev/null @@ -1 +0,0 @@ -Added debug log messages displaying the command being run when installing packages on Windows diff --git a/changelog/62483.fixed.md b/changelog/62483.fixed.md deleted file mode 100644 index 54201adde5d..00000000000 --- a/changelog/62483.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Update sanitizing masking for Salt SSH to include additional password like strings. diff --git a/changelog/62485.deprecated.md b/changelog/62485.deprecated.md deleted file mode 100644 index 64fdf586941..00000000000 --- a/changelog/62485.deprecated.md +++ /dev/null @@ -1 +0,0 @@ -The `expand_repo_def` function in `salt.modules.aptpkg` is now deprecated. It's only used in `salt.states.pkgrepo` and it has no use of being exposed to the CLI. diff --git a/changelog/62496.added.md b/changelog/62496.added.md deleted file mode 100644 index 873138fde96..00000000000 --- a/changelog/62496.added.md +++ /dev/null @@ -1 +0,0 @@ -Add biosvendor grain diff --git a/changelog/62499.fixed.md b/changelog/62499.fixed.md deleted file mode 100644 index 7b307a19d1d..00000000000 --- a/changelog/62499.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix user/group checking on file state functions in the test mode. diff --git a/changelog/62502.fixed.md b/changelog/62502.fixed.md deleted file mode 100644 index 5de34ad71be..00000000000 --- a/changelog/62502.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix user.present to allow removing groups using optional_groups parameter and enforcing idempotent group membership. diff --git a/changelog/62508.added.md b/changelog/62508.added.md deleted file mode 100644 index 7bf68b441d8..00000000000 --- a/changelog/62508.added.md +++ /dev/null @@ -1 +0,0 @@ -Add ifelse Jinja function as found in CFEngine diff --git a/changelog/62519.fixed.md b/changelog/62519.fixed.md deleted file mode 100644 index 4d4ac2c746a..00000000000 --- a/changelog/62519.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix possible tracebacks if there is a package with '------' or '======' in the description is installed on the Debian based minion. diff --git a/changelog/62521.fixed.md b/changelog/62521.fixed.md deleted file mode 100644 index 35e58e90298..00000000000 --- a/changelog/62521.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed the omitted "pool" parameter when cloning a VM with the proxmox salt-cloud driver diff --git a/changelog/62523.fixed.md b/changelog/62523.fixed.md deleted file mode 100644 index c77cc5d84c8..00000000000 --- a/changelog/62523.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix rendering of pyobjects states in saltcheck diff --git a/changelog/62527.fixed.md b/changelog/62527.fixed.md deleted file mode 100644 index 3c9b76ebc33..00000000000 --- a/changelog/62527.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixes pillar where a corrupted CacheDisk file forces the pillar to be rebuilt diff --git a/changelog/62539.added.md b/changelog/62539.added.md deleted file mode 100644 index 5f402d61c2d..00000000000 --- a/changelog/62539.added.md +++ /dev/null @@ -1 +0,0 @@ -Implementation of Amazon EC2 instance detection and setting `virtual_subtype` grain accordingly including the product if possible to identify. diff --git a/changelog/62546.fixed.md b/changelog/62546.fixed.md deleted file mode 100644 index 68ada1d2bc5..00000000000 --- a/changelog/62546.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Use str() method instead of repo_line for when python3-apt is installed or not in aptpkg.py. diff --git a/changelog/62547.fixed.md b/changelog/62547.fixed.md deleted file mode 100644 index 44b4ff4113d..00000000000 --- a/changelog/62547.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Remove the connection_timeout from netmiko_connection_args before netmiko_connection_args is added to __context__["netmiko_device"]["args"] which is passed along to the Netmiko library. diff --git a/changelog/62556.fixed.md b/changelog/62556.fixed.md deleted file mode 100644 index 0dc3a7933ec..00000000000 --- a/changelog/62556.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix order specific mount.mounted options for persist diff --git a/changelog/62558.fixed.md b/changelog/62558.fixed.md deleted file mode 100644 index cdc2a8489db..00000000000 --- a/changelog/62558.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed salt-cloud cloning a proxmox VM with a specified new vmid. diff --git a/changelog/62565.fixed.md b/changelog/62565.fixed.md deleted file mode 100644 index 398b82e6d85..00000000000 --- a/changelog/62565.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix runas with cmd module when using the onedir bundled packages diff --git a/changelog/62576.fixed.md b/changelog/62576.fixed.md deleted file mode 100644 index e7f26a80d5e..00000000000 --- a/changelog/62576.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Update setproctitle version for all platforms diff --git a/changelog/62578.added.md b/changelog/62578.added.md deleted file mode 100644 index 1439da3da17..00000000000 --- a/changelog/62578.added.md +++ /dev/null @@ -1 +0,0 @@ -Adds __env__substitution to ext_pillar.stack; followup of #61531, improved exception handling for stacked template (jinja) template rendering and yaml parsing in ext_pillar.stack diff --git a/changelog/62580.fixed.md b/changelog/62580.fixed.md deleted file mode 100644 index f0c807c30cc..00000000000 --- a/changelog/62580.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed missing parameters when cloning a VM with the proxmox salt-cloud driver diff --git a/changelog/62587.fixed.md b/changelog/62587.fixed.md deleted file mode 100644 index fc5e2871d10..00000000000 --- a/changelog/62587.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Handle PermissionError when importing crypt when FIPS is enabled. diff --git a/changelog/62595.fixed.md b/changelog/62595.fixed.md deleted file mode 100644 index 5462ad7ddac..00000000000 --- a/changelog/62595.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Correctly reraise exceptions in states.http diff --git a/changelog/62618.fixed.md b/changelog/62618.fixed.md deleted file mode 100644 index aeb1ecff6aa..00000000000 --- a/changelog/62618.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed syndic eauth. Now jobs will be published when a valid eauth user is targeting allowed minions/functions. diff --git a/changelog/62624.fixed.md b/changelog/62624.fixed.md deleted file mode 100644 index 661f97e3b46..00000000000 --- a/changelog/62624.fixed.md +++ /dev/null @@ -1 +0,0 @@ -updated rest_cherry/app to properly detect arg sent as a string as curl will do when only one arg is supplied. diff --git a/changelog/62633.fixed.md b/changelog/62633.fixed.md deleted file mode 100644 index 1ab74f9122b..00000000000 --- a/changelog/62633.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Prevent possible tracebacks in core grains module by ignoring non utf8 characters in /proc/1/environ, /proc/1/cmdline, /proc/cmdline diff --git a/changelog/62644.deprecated.md b/changelog/62644.deprecated.md deleted file mode 100644 index 10a5e5fbd58..00000000000 --- a/changelog/62644.deprecated.md +++ /dev/null @@ -1 +0,0 @@ -Deprecated defunct Django returner diff --git a/changelog/62651.fixed.md b/changelog/62651.fixed.md deleted file mode 100644 index 402fd42c170..00000000000 --- a/changelog/62651.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed vault ext pillar return data for KV v2 diff --git a/changelog/62654.fixed.md b/changelog/62654.fixed.md deleted file mode 100644 index 67a265040ad..00000000000 --- a/changelog/62654.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix saltcheck _get_top_states doesn't pass saltenv to state.show_top diff --git a/changelog/62657.fixed.md b/changelog/62657.fixed.md deleted file mode 100644 index d6e83556c0e..00000000000 --- a/changelog/62657.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix groupadd.* functions hard code relative command name diff --git a/changelog/62670.fixed.md b/changelog/62670.fixed.md deleted file mode 100644 index 2fdcb6b8b84..00000000000 --- a/changelog/62670.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed pdbedit.create trying to use a bytes-like hash as string. diff --git a/changelog/62672.fixed.md b/changelog/62672.fixed.md deleted file mode 100644 index 579110cce91..00000000000 --- a/changelog/62672.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix depenency on legacy boto module in boto3 modules diff --git a/changelog/62676.fixed.md b/changelog/62676.fixed.md deleted file mode 100644 index 81e96f54669..00000000000 --- a/changelog/62676.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Modified "_get_flags" function so that it returns regex flags instead of integers diff --git a/changelog/62678.added.md b/changelog/62678.added.md deleted file mode 100644 index c43db8f964c..00000000000 --- a/changelog/62678.added.md +++ /dev/null @@ -1 +0,0 @@ -Increase file.tidied flexibility with regard to age and size diff --git a/changelog/62728.fixed.md b/changelog/62728.fixed.md deleted file mode 100644 index 770237cfd9c..00000000000 --- a/changelog/62728.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Change startup ReqServer log messages from error to info level. diff --git a/changelog/62754.deprecated.md b/changelog/62754.deprecated.md deleted file mode 100644 index 04b44764ca0..00000000000 --- a/changelog/62754.deprecated.md +++ /dev/null @@ -1 +0,0 @@ -Deprecate core ESXi and associated states and modules, vcenter and vsphere support in favor of Salt VMware Extensions diff --git a/changelog/62761.added.md b/changelog/62761.added.md deleted file mode 100644 index b0cd0d4a3cb..00000000000 --- a/changelog/62761.added.md +++ /dev/null @@ -1 +0,0 @@ -Added "connected_devices" feature to netbox pillar module. It contains extra information about devices connected to the minion diff --git a/changelog/62768.added.md b/changelog/62768.added.md deleted file mode 100644 index 85cf2b6b345..00000000000 --- a/changelog/62768.added.md +++ /dev/null @@ -1 +0,0 @@ -Add atomic file operation for symlink changes diff --git a/changelog/62772.fixed.md b/changelog/62772.fixed.md deleted file mode 100644 index c81a3a5908e..00000000000 --- a/changelog/62772.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix kmod.* functions hard code relative command name diff --git a/changelog/62793.fixed.md b/changelog/62793.fixed.md deleted file mode 100644 index 9e224483e3c..00000000000 --- a/changelog/62793.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix mac_brew_pkg to work with null taps diff --git a/changelog/62795.fixed.md b/changelog/62795.fixed.md deleted file mode 100644 index bbd035493fc..00000000000 --- a/changelog/62795.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixing a bug when listing the running schedule if "schedule.enable" and/or "schedule.disable" has been run, where the "enabled" items is being treated as a schedule item. diff --git a/changelog/62817.fixed.md b/changelog/62817.fixed.md deleted file mode 100644 index ff335f2916b..00000000000 --- a/changelog/62817.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Prevent annoying RuntimeWarning message about line buffering (buffering=1) not being supported in binary mode diff --git a/changelog/62818.fixed.md b/changelog/62818.fixed.md deleted file mode 100644 index 944d2227c7c..00000000000 --- a/changelog/62818.fixed.md +++ /dev/null @@ -1,2 +0,0 @@ -Include UID and GID checks in modules.file.check_perms as well as comparing -ownership by username and group name. diff --git a/changelog/62826.fixed.md b/changelog/62826.fixed.md deleted file mode 100644 index 2f923e70e69..00000000000 --- a/changelog/62826.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix presence events on TCP transport by removing a client's presence when minion disconnects from publish channel correctly diff --git a/changelog/62845.fixed.md b/changelog/62845.fixed.md deleted file mode 100644 index 1bfa3f24293..00000000000 --- a/changelog/62845.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Remove Azure deprecation messages from functions that always run w/ salt-cloud diff --git a/changelog/62854.fixed.md b/changelog/62854.fixed.md deleted file mode 100644 index 13e6df4fe39..00000000000 --- a/changelog/62854.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Use select instead of iterating over entrypoints as a dictionary for importlib_metadata>=5.0.0 diff --git a/changelog/62856.added.md b/changelog/62856.added.md deleted file mode 100644 index 94783785aa5..00000000000 --- a/changelog/62856.added.md +++ /dev/null @@ -1 +0,0 @@ -Add password/account locking/unlocking in user.present state on supported operating systems diff --git a/changelog/62858.fixed.md b/changelog/62858.fixed.md deleted file mode 100644 index bae029fc895..00000000000 --- a/changelog/62858.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed master job scheduler using when diff --git a/changelog/62867.added.md b/changelog/62867.added.md deleted file mode 100644 index fd9ad1d278a..00000000000 --- a/changelog/62867.added.md +++ /dev/null @@ -1 +0,0 @@ -Added onchange configuration for script engine diff --git a/changelog/62873.fixed.md b/changelog/62873.fixed.md deleted file mode 100644 index 10d1a8c573c..00000000000 --- a/changelog/62873.fixed.md +++ /dev/null @@ -1 +0,0 @@ -LGPO: Added support for missing domain controller policies: VulnerableChannelAllowList and LdapEnforceChannelBinding diff --git a/changelog/62878.fixed.md b/changelog/62878.fixed.md deleted file mode 100644 index edcc25ec1f0..00000000000 --- a/changelog/62878.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix unnecessarily complex gce metadata grains code to use googles metadata service more effectively. diff --git a/changelog/62882.fixed.md b/changelog/62882.fixed.md deleted file mode 100644 index 015b55fdfaf..00000000000 --- a/changelog/62882.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed dockermod version_info function for docker-py 6.0.0+ diff --git a/changelog/62886.fixed.md b/changelog/62886.fixed.md deleted file mode 100644 index 0c20e2bfa4e..00000000000 --- a/changelog/62886.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Moving setting the LOAD_BALANCING_POLICY_MAP dictionary into the try except block that determines if the cassandra_cql module should be made available. diff --git a/changelog/62895.changed.md b/changelog/62895.changed.md deleted file mode 100644 index d5bff3866b9..00000000000 --- a/changelog/62895.changed.md +++ /dev/null @@ -1 +0,0 @@ -Removed GPG_1_3_1 check diff --git a/changelog/62900.fixed.md b/changelog/62900.fixed.md deleted file mode 100644 index 437c1edcef2..00000000000 --- a/changelog/62900.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Updating various MongoDB module functions to work with latest version of pymongo. diff --git a/changelog/62914.deprecated.md b/changelog/62914.deprecated.md deleted file mode 100644 index 555240fc163..00000000000 --- a/changelog/62914.deprecated.md +++ /dev/null @@ -1 +0,0 @@ -Removing manufacture grain which has been deprecated. diff --git a/changelog/62915.deprecated.md b/changelog/62915.deprecated.md deleted file mode 100644 index b17d168b3b2..00000000000 --- a/changelog/62915.deprecated.md +++ /dev/null @@ -1 +0,0 @@ -Removing deprecated utils/boto3_elasticsearch.py diff --git a/changelog/62917.deprecated.md b/changelog/62917.deprecated.md deleted file mode 100644 index 0b0f522a84b..00000000000 --- a/changelog/62917.deprecated.md +++ /dev/null @@ -1 +0,0 @@ -Removing support for the now deprecated _ext_nodes from salt/master.py. diff --git a/changelog/62933.fixed.md b/changelog/62933.fixed.md deleted file mode 100644 index 1b34722a729..00000000000 --- a/changelog/62933.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Restored channel for Syndic minions to send job returns to the Salt master. diff --git a/changelog/62934.fixed.md b/changelog/62934.fixed.md deleted file mode 100644 index 7a12ce3dd5c..00000000000 --- a/changelog/62934.fixed.md +++ /dev/null @@ -1 +0,0 @@ -removed _resolve_deps as it required a library that is not generally avalible. and switched to apt-get for everything as that can auto resolve dependencies. diff --git a/changelog/62937.fixed.md b/changelog/62937.fixed.md deleted file mode 100644 index 09af559e1ec..00000000000 --- a/changelog/62937.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Updated pyzmq to version 22.0.3 on Windows builds because the old version was causing salt-minion/salt-call to hang diff --git a/changelog/62940.fixed.md b/changelog/62940.fixed.md deleted file mode 100644 index 1bb38d7a71f..00000000000 --- a/changelog/62940.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Allow root user to modify crontab lines for non-root users (except AIX and Solaris). Align crontab line changes with the file ones and also with listing crontab. diff --git a/changelog/62942.fixed.md b/changelog/62942.fixed.md deleted file mode 100644 index f11a010d588..00000000000 --- a/changelog/62942.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix systemd_service.* functions hard code relative command name diff --git a/changelog/62953.fixed.md b/changelog/62953.fixed.md deleted file mode 100644 index df38b5c4ab0..00000000000 --- a/changelog/62953.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix file.symlink backupname operation can copy remote contents to local disk diff --git a/changelog/62968.fixed.md b/changelog/62968.fixed.md deleted file mode 100644 index 891c319c423..00000000000 --- a/changelog/62968.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Issue #62968: Fix issue where cloud deployments were putting the keys in the wrong location on Windows hosts diff --git a/changelog/62977.fixed.md b/changelog/62977.fixed.md deleted file mode 100644 index da2b640a640..00000000000 --- a/changelog/62977.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed gpg_passphrase issue with gpg decrypt/encrypt functions diff --git a/changelog/62978.added.md b/changelog/62978.added.md deleted file mode 100644 index 3262ce53a0b..00000000000 --- a/changelog/62978.added.md +++ /dev/null @@ -1 +0,0 @@ -Added output and bare functionality to export_key gpg module function diff --git a/changelog/62983.added.md b/changelog/62983.added.md deleted file mode 100644 index 673c9f2239a..00000000000 --- a/changelog/62983.added.md +++ /dev/null @@ -1 +0,0 @@ -Add keyvalue serializer for environment files diff --git a/changelog/62986.fixed.md b/changelog/62986.fixed.md deleted file mode 100644 index e2e5c1b029a..00000000000 --- a/changelog/62986.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix file.tidied FileNotFoundError diff --git a/changelog/62988.fixed.md b/changelog/62988.fixed.md deleted file mode 100644 index b525e2f38ac..00000000000 --- a/changelog/62988.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed bug where module.wait states were detected as running legacy module.run syntax diff --git a/changelog/62993.fixed.md b/changelog/62993.fixed.md deleted file mode 100644 index de6e8dca6e7..00000000000 --- a/changelog/62993.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed issue with win_wua module where it wouldn't load if the CryptSvc was set to Manual start diff --git a/changelog/63012.changed.md b/changelog/63012.changed.md deleted file mode 100644 index ab5dfae2f38..00000000000 --- a/changelog/63012.changed.md +++ /dev/null @@ -1 +0,0 @@ -Requisite state chunks now all consistently contain `__id__`, `__sls__` and `name`. diff --git a/changelog/63013.fixed.md b/changelog/63013.fixed.md deleted file mode 100644 index 28cd29c7f37..00000000000 --- a/changelog/63013.fixed.md +++ /dev/null @@ -1,3 +0,0 @@ -The `__opts__` dunder dictionary is now added to the loader's `pack` if not -already present, which makes it accessible via the -`salt.loader.context.NamedLoaderContext` class. diff --git a/changelog/63024.fixed.md b/changelog/63024.fixed.md deleted file mode 100644 index e3544b9bc14..00000000000 --- a/changelog/63024.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Issue #63024: Fix issue where grains and config data were being place in the wrong location on Windows hosts diff --git a/changelog/63025.fixed.md b/changelog/63025.fixed.md deleted file mode 100644 index 11546d63bb1..00000000000 --- a/changelog/63025.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix btrfs.subvolume_snapshot command failing diff --git a/changelog/63033.fixed.md b/changelog/63033.fixed.md deleted file mode 100644 index 11687bd183c..00000000000 --- a/changelog/63033.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix file.retention_schedule always reports changes diff --git a/changelog/63042.added.md b/changelog/63042.added.md deleted file mode 100644 index 2999b8fcb91..00000000000 --- a/changelog/63042.added.md +++ /dev/null @@ -1 +0,0 @@ -Add ability to ignore symlinks in file.tidied diff --git a/changelog/63050.changed.md b/changelog/63050.changed.md deleted file mode 100644 index c8323b39ab8..00000000000 --- a/changelog/63050.changed.md +++ /dev/null @@ -1,5 +0,0 @@ -netapi_enable_clients option to allow enabling/disabling of clients in salt-api. -By default all clients will now be disabled. Users of salt-api will need -to update their master config to enable the clients that they use. Not adding -the netapi_enable_clients option with required clients to the master config will -disable salt-api. diff --git a/changelog/63058.fixed.md b/changelog/63058.fixed.md deleted file mode 100644 index aab3c539bc0..00000000000 --- a/changelog/63058.fixed.md +++ /dev/null @@ -1,3 +0,0 @@ -Fix mongo authentication for mongo ext_pillar and mongo returner - -This fix also include the ability to use the mongo connection string for mongo ext_pillar diff --git a/changelog/63067.added.md b/changelog/63067.added.md deleted file mode 100644 index bd99632107b..00000000000 --- a/changelog/63067.added.md +++ /dev/null @@ -1 +0,0 @@ -salt-cloud support IMDSv2 tokens when using 'use-instance-role-credentials' diff --git a/changelog/63093.added.md b/changelog/63093.added.md deleted file mode 100644 index 1a401125088..00000000000 --- a/changelog/63093.added.md +++ /dev/null @@ -1 +0,0 @@ -Add ability for file.symlink to not set ownership on existing links diff --git a/changelog/63095.added.md b/changelog/63095.added.md deleted file mode 100644 index 1802d356fd4..00000000000 --- a/changelog/63095.added.md +++ /dev/null @@ -1 +0,0 @@ -Restore the previous slack engine and deprecate it, rename replace the slack engine to slack_bolt until deprecation diff --git a/changelog/63095.deprecated.md b/changelog/63095.deprecated.md deleted file mode 100644 index d652a377be0..00000000000 --- a/changelog/63095.deprecated.md +++ /dev/null @@ -1 +0,0 @@ -Deprecating the Salt Slack engine in favor of the Salt Slack Bolt Engine. diff --git a/changelog/63098.added.md b/changelog/63098.added.md deleted file mode 100644 index db6ef8d4f58..00000000000 --- a/changelog/63098.added.md +++ /dev/null @@ -1 +0,0 @@ -Add functions that will return the underlying block device, mount point, and filesystem type for a given path diff --git a/changelog/63103.fixed.md b/changelog/63103.fixed.md deleted file mode 100644 index 65595f61ff8..00000000000 --- a/changelog/63103.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed x509.create_csr creates invalid CSR by default in the new cryptography x509 module. diff --git a/changelog/63120.fixed.md b/changelog/63120.fixed.md deleted file mode 100644 index 80ed0d754e3..00000000000 --- a/changelog/63120.fixed.md +++ /dev/null @@ -1 +0,0 @@ -TCP transport documentation now contains proper master/minion-side filtering information diff --git a/changelog/63128.added.md b/changelog/63128.added.md deleted file mode 100644 index edbc81fb481..00000000000 --- a/changelog/63128.added.md +++ /dev/null @@ -1 +0,0 @@ -Add ethtool execution and state module functions for pause diff --git a/changelog/63131.added.md b/changelog/63131.added.md deleted file mode 100644 index 3376c7e97cd..00000000000 --- a/changelog/63131.added.md +++ /dev/null @@ -1 +0,0 @@ -Add boardname grain diff --git a/changelog/63145.fixed.md b/changelog/63145.fixed.md deleted file mode 100644 index 2e38588344c..00000000000 --- a/changelog/63145.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed gpg.verify does not respect gnupghome diff --git a/changelog/63208.fixed.md b/changelog/63208.fixed.md deleted file mode 100644 index e8ee88a7b1a..00000000000 --- a/changelog/63208.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Made pillar cache pass extra minion data as well diff --git a/changelog/63231.fixed.md b/changelog/63231.fixed.md deleted file mode 100644 index cda743d7bc4..00000000000 --- a/changelog/63231.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix serious performance issues with the file.tidied module diff --git a/changelog/63248.added.md b/changelog/63248.added.md deleted file mode 100644 index 5c72116f055..00000000000 --- a/changelog/63248.added.md +++ /dev/null @@ -1 +0,0 @@ -Added management of ECDSA/EdDSA private keys with x509 modules in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. diff --git a/changelog/63249.added.md b/changelog/63249.added.md deleted file mode 100644 index 0b56b2146f2..00000000000 --- a/changelog/63249.added.md +++ /dev/null @@ -1 +0,0 @@ -Added x509 modules support for different output formats in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. diff --git a/changelog/63315.added.md b/changelog/63315.added.md deleted file mode 100644 index 950abc93277..00000000000 --- a/changelog/63315.added.md +++ /dev/null @@ -1 +0,0 @@ -Added deprecation_warning test state for ensuring that deprecation warnings are correctly emitted. diff --git a/changelog/63316.added.md b/changelog/63316.added.md deleted file mode 100644 index 253308c8ec1..00000000000 --- a/changelog/63316.added.md +++ /dev/null @@ -1,3 +0,0 @@ -Adds a state_events option to state.highstate, state.apply, state.sls, state.sls_id. -This allows users to enable state_events on a per use basis rather than having to -enable them globally for all state runs. diff --git a/changelog/63317.fixed.md b/changelog/63317.fixed.md deleted file mode 100644 index 8059d90b12d..00000000000 --- a/changelog/63317.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fix rpm_lowpkg version comparison logic when using rpm-vercmp and only one version has a release number. diff --git a/changelog/63350.fixed.md b/changelog/63350.fixed.md deleted file mode 100644 index a544d15d1e4..00000000000 --- a/changelog/63350.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Import StrictVersion and LooseVersion from setuptools.distutils.verison or setuptools._distutils.version, if first not available diff --git a/changelog/63356.added.md b/changelog/63356.added.md deleted file mode 100644 index 994e7a70d57..00000000000 --- a/changelog/63356.added.md +++ /dev/null @@ -1 +0,0 @@ -Allow max queue size setting for state runs to prevent performance problems from queue growth diff --git a/changelog/63383.changed.md b/changelog/63383.changed.md deleted file mode 100644 index d0553dc0624..00000000000 --- a/changelog/63383.changed.md +++ /dev/null @@ -1 +0,0 @@ -Stop relying on `salt/_version.py` to write Salt's version. Instead use `salt/_version.txt` which only contains the version string. diff --git a/changelog/63383.deprecated.md b/changelog/63383.deprecated.md deleted file mode 100644 index 5131a151314..00000000000 --- a/changelog/63383.deprecated.md +++ /dev/null @@ -1 +0,0 @@ -`salt.utils.version.StrictVersion` is now deprecated and it's use should be replaced with `salt.utils.version.Version`. diff --git a/changelog/63577.fixed.md b/changelog/63577.fixed.md deleted file mode 100644 index ddc2ce0cf1c..00000000000 --- a/changelog/63577.fixed.md +++ /dev/null @@ -1,2 +0,0 @@ -``service.status`` on Windows does no longer throws a CommandExecutionError if -the service is not found on the system. It now returns "Not Found" instead. diff --git a/changelog/63590.fixed.md b/changelog/63590.fixed.md deleted file mode 100644 index 0b7ea3dae4a..00000000000 --- a/changelog/63590.fixed.md +++ /dev/null @@ -1 +0,0 @@ -When the shell is passed as powershell or pwsh, only wrapper the shell in quotes if cmd.run is running on Windows. When quoted on Linux hosts, this results in an error when the keyword arguments are appended. diff --git a/changelog/63595.changed.md b/changelog/63595.changed.md deleted file mode 100644 index ab38a24a4a5..00000000000 --- a/changelog/63595.changed.md +++ /dev/null @@ -1 +0,0 @@ -Set enable_fqdns_grains to be False by default. diff --git a/changelog/63596.fixed.md b/changelog/63596.fixed.md deleted file mode 100644 index 38c412786a0..00000000000 --- a/changelog/63596.fixed.md +++ /dev/null @@ -1 +0,0 @@ -LGPO: Added support for "Relax minimum password length limits" diff --git a/changelog/63606.added.md b/changelog/63606.added.md deleted file mode 100644 index 563eed173f8..00000000000 --- a/changelog/63606.added.md +++ /dev/null @@ -1 +0,0 @@ -Add support of exposing meta_server_grains for Azure VMs diff --git a/changelog/63650.fixed.md b/changelog/63650.fixed.md deleted file mode 100644 index 2b7d3010ce3..00000000000 --- a/changelog/63650.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed the ability to set a scheduled task to auto delete if not scheduled to run again (``delete_after``) diff --git a/changelog/63699.fixed.md b/changelog/63699.fixed.md deleted file mode 100644 index 9a125c959c4..00000000000 --- a/changelog/63699.fixed.md +++ /dev/null @@ -1 +0,0 @@ -When a job is disabled only increase it's _next_fire_time value if the job would have run at the current time, eg. the current _next_fire_time == now. diff --git a/changelog/63710.changed.md b/changelog/63710.changed.md deleted file mode 100644 index 799e0a7aafa..00000000000 --- a/changelog/63710.changed.md +++ /dev/null @@ -1 +0,0 @@ -Changelog snippet files must now have a `.md` file extension to be more explicit on what type of rendering is done when they are included in the main `CHANGELOG.md` file. diff --git a/changelog/63724.fixed.md b/changelog/63724.fixed.md deleted file mode 100644 index ac12302e88e..00000000000 --- a/changelog/63724.fixed.md +++ /dev/null @@ -1 +0,0 @@ -have salt.template.compile_template_str cleanup its temp files. diff --git a/changelog/63729.fixed.md b/changelog/63729.fixed.md deleted file mode 100644 index 0c6aff3b508..00000000000 --- a/changelog/63729.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Check file is not empty before attempting to read pillar disk cache file diff --git a/changelog/63742.fixed.md b/changelog/63742.fixed.md deleted file mode 100644 index 0358da15161..00000000000 --- a/changelog/63742.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Fixed an issue with generating fingerprints for public keys with different line endings diff --git a/changelog/63806.fixed.md b/changelog/63806.fixed.md deleted file mode 100644 index f4c5ec38432..00000000000 --- a/changelog/63806.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Change default GPG keyserver from pgp.mit.edu to keys.openpgp.org. diff --git a/changelog/63827.added.md b/changelog/63827.added.md deleted file mode 100644 index 08c3acdb050..00000000000 --- a/changelog/63827.added.md +++ /dev/null @@ -1 +0,0 @@ -Include the version of `relenv` in the versions report. diff --git a/changelog/63835.fixed.md b/changelog/63835.fixed.md deleted file mode 100644 index 78709b4e74d..00000000000 --- a/changelog/63835.fixed.md +++ /dev/null @@ -1 +0,0 @@ -fix cherrypy 400 error output to be less generic. diff --git a/changelog/63847.fixed.md b/changelog/63847.fixed.md deleted file mode 100644 index 430ee039d27..00000000000 --- a/changelog/63847.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Ensure kwargs is passed along to _call_apt when passed into install function. diff --git a/changelog/63866.added.md b/changelog/63866.added.md deleted file mode 100644 index 4aa7872dedc..00000000000 --- a/changelog/63866.added.md +++ /dev/null @@ -1 +0,0 @@ -Added debug log messages displaying the command being run when removing packages on Windows diff --git a/changelog/63874.removed.md b/changelog/63874.removed.md deleted file mode 100644 index 2760e312667..00000000000 --- a/changelog/63874.removed.md +++ /dev/null @@ -1 +0,0 @@ -Removed `SixRedirectImporter` from Salt. Salt hasn't shipped `six` since Salt 3004. diff --git a/changelog/63879.fixed.md b/changelog/63879.fixed.md deleted file mode 100644 index 149567a41fa..00000000000 --- a/changelog/63879.fixed.md +++ /dev/null @@ -1 +0,0 @@ -remove eval and update logging to be more informative on bad config diff --git a/changelog/63882.security.md b/changelog/63882.security.md deleted file mode 100644 index 90374cb2839..00000000000 --- a/changelog/63882.security.md +++ /dev/null @@ -1,9 +0,0 @@ -Upgrade Requirements Due to Security Issues. - -* Upgrade to `cryptography>=39.0.1` due to: - * https://github.com/advisories/GHSA-x4qr-2fvf-3mr5 - * https://github.com/advisories/GHSA-w7pp-m8wf-vj6r -* Upgrade to `pyopenssl==23.0.0` due to the cryptography upgrade. -* Update to `markdown-it-py==2.2.0` due to: - * https://github.com/advisories/GHSA-jrwr-5x3p-hvc3 - * https://github.com/advisories/GHSA-vrjv-mxr7-vjf8 diff --git a/changelog/63883.changed.md b/changelog/63883.changed.md deleted file mode 100644 index 4e98d1d946f..00000000000 --- a/changelog/63883.changed.md +++ /dev/null @@ -1 +0,0 @@ -Upgraded to `relenv==0.9.0` diff --git a/changelog/63904.fixed.md b/changelog/63904.fixed.md deleted file mode 100644 index 8aff8d12b50..00000000000 --- a/changelog/63904.fixed.md +++ /dev/null @@ -1 +0,0 @@ -add linux_distribution to util to stop dep warning diff --git a/changelog/63923.fixed.md b/changelog/63923.fixed.md deleted file mode 100644 index 21c93161ac7..00000000000 --- a/changelog/63923.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Handle the situation when a sub proxy minion does not init properly, eg. an exception happens, and the sub proxy object is not available. diff --git a/changelog/63929.fixed.md b/changelog/63929.fixed.md deleted file mode 100644 index db802ce2c25..00000000000 --- a/changelog/63929.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Clarifying documentation for extension_modules configuration option. diff --git a/changelog/63935.fixed.md b/changelog/63935.fixed.md deleted file mode 100644 index 565a7559af5..00000000000 --- a/changelog/63935.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Windows pkg module now properly handles versions containing strings diff --git a/changelog/63948.fixed.md b/changelog/63948.fixed.md deleted file mode 100644 index 77e1f524b2d..00000000000 --- a/changelog/63948.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Handle the scenario when the check_cmd requisite is used with a state function when the state has a local check_cmd function but that function isn't used by that function. diff --git a/changelog/63981.fixed.md b/changelog/63981.fixed.md deleted file mode 100644 index 5bf4755be68..00000000000 --- a/changelog/63981.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Issue #63981: Allow users to pass verify_ssl to pkg.install/pkg.installed on Windows diff --git a/changelog/64114.fixed.md b/changelog/64114.fixed.md new file mode 100644 index 00000000000..f01c5ea9127 --- /dev/null +++ b/changelog/64114.fixed.md @@ -0,0 +1 @@ +Fix running setup.py when passing in --salt-config-dir and --salt-cache-dir arguments. diff --git a/cicd/amis.yml b/cicd/amis.yml index f1a3b0f5a9f..47edcf0184b 100644 --- a/cicd/amis.yml +++ b/cicd/amis.yml @@ -1,15 +1 @@ -alma-8-x86_64: ami-0e38e779c7e9a58cb -amazon-2-x86_64: ami-0808ff1e4bd65c26e -arch-lts-x86_64: ami-05cb9be3cdb8f9ded -centos-7-x86_64: ami-062de6e6b1bea1987 -centosstream-9-x86_64: ami-0a8429c3f5f933d85 -debian-10-amd64: ami-01c864e5f37943e82 -debian-11-arm64: ami-0f0687d3bed6d0f9e -debian-11-amd64: ami-097a7bcb88c641a4f -opensuse-15-x86_64: ami-053085867e8e2a437 -photon-3-x86_64: ami-0c60abf0038288d5b -ubuntu-2004-arm64: ami-090c51d35099a31fc -ubuntu-2004-amd64: ami-0d6b6f0ee825d6cc0 -ubuntu-2204-amd64: ami-0eba94938aad408da -windows-2016-x64: ami-09e918f01701cbaca -windows-2019-x64: ami-072893e306bcedd6e +centosstream-9-x86_64: ami-044545f7a74d46acc diff --git a/cicd/golden-images.json b/cicd/golden-images.json index ed3b9f8deac..0f338a3992b 100644 --- a/cicd/golden-images.json +++ b/cicd/golden-images.json @@ -1,28 +1,58 @@ { + "almalinux-8-arm64": { + "ami": "ami-0fc1e14bf9ff422aa", + "ami_description": "CI Image of AlmaLinux 8 arm64", + "ami_name": "salt-project/ci/almalinux/8/arm64/20230418.1731", + "arch": "arm64", + "cloudwatch-agent-available": "true", + "instance_type": "m6g.large", + "is_windows": "false", + "ssh_username": "ec2-user" + }, "almalinux-8": { - "ami": "ami-0e38e779c7e9a58cb", + "ami": "ami-0bae4158c1f126271", "ami_description": "CI Image of AlmaLinux 8 x86_64", - "ami_name": "salt-project/ci/almalinux/8/x86_64/20230306.1703", + "ami_name": "salt-project/ci/almalinux/8/x86_64/20230418.1732", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", "is_windows": "false", "ssh_username": "ec2-user" }, + "almalinux-9-arm64": { + "ami": "ami-08f4d0fbf5d53c3ab", + "ami_description": "CI Image of AlmaLinux 9 arm64", + "ami_name": "salt-project/ci/almalinux/9/arm64/20230418.1732", + "arch": "arm64", + "cloudwatch-agent-available": "true", + "instance_type": "m6g.large", + "is_windows": "false", + "ssh_username": "ec2-user" + }, "almalinux-9": { - "ami": "ami-0e478b3a983a8aa3a", + "ami": "ami-00404c1cc5c5a08bd", "ami_description": "CI Image of AlmaLinux 9 x86_64", - "ami_name": "salt-project/ci/almalinux/9/x86_64/20230306.1703", + "ami_name": "salt-project/ci/almalinux/9/x86_64/20230418.1738", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", "is_windows": "false", "ssh_username": "ec2-user" }, + "amazonlinux-2-arm64": { + "ami": "ami-05fbdb644d06c27b6", + "ami_description": "CI Image of AmazonLinux 2 arm64", + "ami_name": "salt-project/ci/amazonlinux/2/arm64/20230418.1717", + "arch": "arm64", + "cloudwatch-agent-available": "true", + "instance_type": "m6g.large", + "is_windows": "false", + "ssh_username": "ec2-user" + }, "amazonlinux-2": { - "ami": "ami-0808ff1e4bd65c26e", + "ami": "ami-014171e6c30ec8387", "ami_description": "CI Image of AmazonLinux 2 x86_64", - "ami_name": "salt-project/ci/amazonlinux/2/x86_64/20230306.1703", + "ami_name": "salt-project/ci/amazonlinux/2/x86_64/20230418.1718", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", @@ -30,49 +60,89 @@ "ssh_username": "ec2-user" }, "archlinux-lts": { - "ami": "ami-05cb9be3cdb8f9ded", + "ami": "ami-00cff81ed2e2fb0f4", "ami_description": "CI Image of ArchLinux lts x86_64", - "ami_name": "salt-project/ci/archlinux/lts/x86_64/20230306.1703", + "ami_name": "salt-project/ci/archlinux/lts/x86_64/20230418.1717", "arch": "x86_64", "cloudwatch-agent-available": "false", "instance_type": "t3a.large", "is_windows": "false", "ssh_username": "arch" }, + "centos-7-arm64": { + "ami": "ami-051cef43c13fcc0c9", + "ami_description": "CI Image of CentOS 7 arm64", + "ami_name": "salt-project/ci/centos/7/arm64/20230418.1743", + "arch": "arm64", + "cloudwatch-agent-available": "true", + "instance_type": "m6g.large", + "is_windows": "false", + "ssh_username": "centos" + }, "centos-7": { - "ami": "ami-062de6e6b1bea1987", + "ami": "ami-0dcc94e1bea829149", "ami_description": "CI Image of CentOS 7 x86_64", - "ami_name": "salt-project/ci/centos/7/x86_64/20230306.1703", + "ami_name": "salt-project/ci/centos/7/x86_64/20230418.1743", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", "is_windows": "false", "ssh_username": "centos" }, + "centosstream-8-arm64": { + "ami": "ami-02783136c1080c782", + "ami_description": "CI Image of CentOSStream 8 arm64", + "ami_name": "salt-project/ci/centosstream/8/arm64/20230418.1717", + "arch": "arm64", + "cloudwatch-agent-available": "true", + "instance_type": "m6g.large", + "is_windows": "false", + "ssh_username": "cloud-user" + }, "centosstream-8": { - "ami": "ami-00b1e2790dced55ba", + "ami": "ami-055e35dc7180defad", "ami_description": "CI Image of CentOSStream 8 x86_64", - "ami_name": "salt-project/ci/centosstream/8/x86_64/20230306.1703", + "ami_name": "salt-project/ci/centosstream/8/x86_64/20230418.1717", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", "is_windows": "false", - "ssh_username": "cloud-user" + "ssh_username": "centos" + }, + "centosstream-9-arm64": { + "ami": "ami-06fd13f7c7c702fc4", + "ami_description": "CI Image of CentOSStream 9 arm64", + "ami_name": "salt-project/ci/centosstream/9/arm64/20230418.1717", + "arch": "arm64", + "cloudwatch-agent-available": "true", + "instance_type": "m6g.large", + "is_windows": "false", + "ssh_username": "ec2-user" }, "centosstream-9": { - "ami": "ami-0a8429c3f5f933d85", + "ami": "ami-044545f7a74d46acc", "ami_description": "CI Image of CentOSStream 9 x86_64", - "ami_name": "salt-project/ci/centosstream/9/x86_64/20230306.1703", + "ami_name": "salt-project/ci/centosstream/9/x86_64/20230418.1717", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", "is_windows": "false", "ssh_username": "ec2-user" }, + "debian-10-arm64": { + "ami": "ami-045aedc47e7ddfbf1", + "ami_description": "CI Image of Debian 10 arm64", + "ami_name": "salt-project/ci/debian/10/arm64/20230418.1739", + "arch": "arm64", + "cloudwatch-agent-available": "false", + "instance_type": "m6g.large", + "is_windows": "false", + "ssh_username": "admin" + }, "debian-10": { - "ami": "ami-01c864e5f37943e82", + "ami": "ami-0a205a9361210b291", "ami_description": "CI Image of Debian 10 x86_64", - "ami_name": "salt-project/ci/debian/10/x86_64/20230306.1703", + "ami_name": "salt-project/ci/debian/10/x86_64/20230418.1739", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", @@ -80,9 +150,9 @@ "ssh_username": "admin" }, "debian-11-arm64": { - "ami": "ami-0f0687d3bed6d0f9e", + "ami": "ami-0be71acc27a8efa60", "ami_description": "CI Image of Debian 11 arm64", - "ami_name": "salt-project/ci/debian/11/arm64/20230306.1703", + "ami_name": "salt-project/ci/debian/11/arm64/20230418.1739", "arch": "arm64", "cloudwatch-agent-available": "false", "instance_type": "m6g.large", @@ -90,39 +160,69 @@ "ssh_username": "admin" }, "debian-11": { - "ami": "ami-097a7bcb88c641a4f", + "ami": "ami-0ad354da27b34289b", "ami_description": "CI Image of Debian 11 x86_64", - "ami_name": "salt-project/ci/debian/11/x86_64/20230306.1703", + "ami_name": "salt-project/ci/debian/11/x86_64/20230418.1742", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", "is_windows": "false", "ssh_username": "admin" }, + "fedora-36-arm64": { + "ami": "ami-00c0ab2829c887922", + "ami_description": "CI Image of Fedora 36 arm64", + "ami_name": "salt-project/ci/fedora/36/arm64/20230418.1726", + "arch": "arm64", + "cloudwatch-agent-available": "true", + "instance_type": "m6g.large", + "is_windows": "false", + "ssh_username": "fedora" + }, "fedora-36": { - "ami": "ami-04d3d4001c7eb6084", + "ami": "ami-0185a1189bff7c771", "ami_description": "CI Image of Fedora 36 x86_64", - "ami_name": "salt-project/ci/fedora/36/x86_64/20230306.1703", + "ami_name": "salt-project/ci/fedora/36/x86_64/20230418.1726", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", "is_windows": "false", "ssh_username": "fedora" }, + "fedora-37-arm64": { + "ami": "ami-075c52fda843ace1b", + "ami_description": "CI Image of Fedora 37 arm64", + "ami_name": "salt-project/ci/fedora/37/arm64/20230418.1726", + "arch": "arm64", + "cloudwatch-agent-available": "true", + "instance_type": "m6g.large", + "is_windows": "false", + "ssh_username": "fedora" + }, "fedora-37": { - "ami": "ami-047f01d4d1b8eade2", + "ami": "ami-099a68403d6c65733", "ami_description": "CI Image of Fedora 37 x86_64", - "ami_name": "salt-project/ci/fedora/37/x86_64/20230306.1703", + "ami_name": "salt-project/ci/fedora/37/x86_64/20230418.1726", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", "is_windows": "false", "ssh_username": "fedora" }, + "fedora-38-arm64": { + "ami": "ami-02fa22d081a9be052", + "ami_description": "CI Image of Fedora 38 arm64", + "ami_name": "salt-project/ci/fedora/38/arm64/20230418.1727", + "arch": "arm64", + "cloudwatch-agent-available": "true", + "instance_type": "m6g.large", + "is_windows": "false", + "ssh_username": "fedora" + }, "fedora-38": { - "ami": "ami-04600a36ca6b94c1c", + "ami": "ami-0a8d949d0bb15bbc0", "ami_description": "CI Image of Fedora 38 x86_64", - "ami_name": "salt-project/ci/fedora/38/x86_64/20230306.1703", + "ami_name": "salt-project/ci/fedora/38/x86_64/20230418.1727", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", @@ -130,9 +230,9 @@ "ssh_username": "fedora" }, "opensuse-15": { - "ami": "ami-053085867e8e2a437", + "ami": "ami-089ac311f924f131f", "ami_description": "CI Image of Opensuse 15 x86_64", - "ami_name": "salt-project/ci/opensuse/15/x86_64/20230306.1703", + "ami_name": "salt-project/ci/opensuse/15/x86_64/20230418.1744", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", @@ -140,9 +240,9 @@ "ssh_username": "ec2-user" }, "photonos-3": { - "ami": "ami-0c60abf0038288d5b", + "ami": "ami-03ce6db789f90957b", "ami_description": "CI Image of PhotonOS 3 x86_64", - "ami_name": "salt-project/ci/photonos/3/x86_64/20230306.1703", + "ami_name": "salt-project/ci/photonos/3/x86_64/20230418.1717", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", @@ -150,9 +250,9 @@ "ssh_username": "root" }, "photonos-4": { - "ami": "ami-0f05edd4afe1b852b", + "ami": "ami-0ef9996c398479d65", "ami_description": "CI Image of PhotonOS 4 x86_64", - "ami_name": "salt-project/ci/photonos/4/x86_64/20230306.1703", + "ami_name": "salt-project/ci/photonos/4/x86_64/20230418.1717", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", @@ -160,9 +260,9 @@ "ssh_username": "root" }, "ubuntu-20.04-arm64": { - "ami": "ami-090c51d35099a31fc", + "ami": "ami-0c4d21e0772489c0d", "ami_description": "CI Image of Ubuntu 20.04 arm64", - "ami_name": "salt-project/ci/ubuntu/20.04/arm64/20230306.1703", + "ami_name": "salt-project/ci/ubuntu/20.04/arm64/20230418.1728", "arch": "arm64", "cloudwatch-agent-available": "true", "instance_type": "m6g.large", @@ -170,9 +270,9 @@ "ssh_username": "ubuntu" }, "ubuntu-20.04": { - "ami": "ami-0d6b6f0ee825d6cc0", + "ami": "ami-09ae6200865b29b9b", "ami_description": "CI Image of Ubuntu 20.04 x86_64", - "ami_name": "salt-project/ci/ubuntu/20.04/x86_64/20230306.1703", + "ami_name": "salt-project/ci/ubuntu/20.04/x86_64/20230418.1728", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", @@ -180,9 +280,9 @@ "ssh_username": "ubuntu" }, "ubuntu-22.04-arm64": { - "ami": "ami-01b52de1f19e79343", + "ami": "ami-024fe5d0b838f88f7", "ami_description": "CI Image of Ubuntu 22.04 arm64", - "ami_name": "salt-project/ci/ubuntu/22.04/arm64/20230306.1703", + "ami_name": "salt-project/ci/ubuntu/22.04/arm64/20230418.1731", "arch": "arm64", "cloudwatch-agent-available": "true", "instance_type": "m6g.large", @@ -190,9 +290,9 @@ "ssh_username": "ubuntu" }, "ubuntu-22.04": { - "ami": "ami-0eba94938aad408da", + "ami": "ami-0d83f00f084d91451", "ami_description": "CI Image of Ubuntu 22.04 x86_64", - "ami_name": "salt-project/ci/ubuntu/22.04/x86_64/20230306.1704", + "ami_name": "salt-project/ci/ubuntu/22.04/x86_64/20230418.1732", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.large", @@ -200,9 +300,9 @@ "ssh_username": "ubuntu" }, "windows-2016": { - "ami": "ami-09e918f01701cbaca", + "ami": "ami-078d9229cfaf24d1b", "ami_description": "CI Image of Windows 2016 x86_64", - "ami_name": "salt-project/ci/windows/2016/x86_64/20230306.1703", + "ami_name": "salt-project/ci/windows/2016/x86_64/20230418.1717", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.xlarge", @@ -210,9 +310,9 @@ "ssh_username": "Administrator" }, "windows-2019": { - "ami": "ami-072893e306bcedd6e", + "ami": "ami-0ab20823965e1aa7a", "ami_description": "CI Image of Windows 2019 x86_64", - "ami_name": "salt-project/ci/windows/2019/x86_64/20230306.1703", + "ami_name": "salt-project/ci/windows/2019/x86_64/20230418.1717", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.xlarge", @@ -220,9 +320,9 @@ "ssh_username": "Administrator" }, "windows-2022": { - "ami": "ami-0cfbb2e681636b902", + "ami": "ami-054c4cf04c0f31eb1", "ami_description": "CI Image of Windows 2022 x86_64", - "ami_name": "salt-project/ci/windows/2022/x86_64/20230306.1703", + "ami_name": "salt-project/ci/windows/2022/x86_64/20230418.1717", "arch": "x86_64", "cloudwatch-agent-available": "true", "instance_type": "t3a.xlarge", diff --git a/cicd/shared-gh-workflows-context.yml b/cicd/shared-gh-workflows-context.yml new file mode 100644 index 00000000000..c6e88fc0c3d --- /dev/null +++ b/cicd/shared-gh-workflows-context.yml @@ -0,0 +1,4 @@ +python_version_linux: "3.10.11" +python_version_macos: "3.10.11" +python_version_windows: "3.10.11" +relenv_version: "0.11.2" diff --git a/doc/man/salt-api.1 b/doc/man/salt-api.1 index 07c0e5e989a..0935a743675 100644 --- a/doc/man/salt-api.1 +++ b/doc/man/salt-api.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SALT-API" "1" "Generated on March 29, 2023 at 07:32:38 PM UTC." "3006.0" "Salt" +.TH "SALT-API" "1" "Generated on April 18, 2023 at 08:56:37 PM UTC." "3006.0" "Salt" .SH NAME salt-api \- salt-api Command .sp diff --git a/doc/man/salt-call.1 b/doc/man/salt-call.1 index 5562ee3ba2e..f81101ae003 100644 --- a/doc/man/salt-call.1 +++ b/doc/man/salt-call.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SALT-CALL" "1" "Generated on March 29, 2023 at 07:32:38 PM UTC." "3006.0" "Salt" +.TH "SALT-CALL" "1" "Generated on April 18, 2023 at 08:56:37 PM UTC." "3006.0" "Salt" .SH NAME salt-call \- salt-call Documentation .SH SYNOPSIS diff --git a/doc/man/salt-cloud.1 b/doc/man/salt-cloud.1 index baec7121eaf..c0bc776c4f1 100644 --- a/doc/man/salt-cloud.1 +++ b/doc/man/salt-cloud.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SALT-CLOUD" "1" "Generated on March 29, 2023 at 07:32:38 PM UTC." "3006.0" "Salt" +.TH "SALT-CLOUD" "1" "Generated on April 18, 2023 at 08:56:37 PM UTC." "3006.0" "Salt" .SH NAME salt-cloud \- Salt Cloud Command .sp diff --git a/doc/man/salt-cp.1 b/doc/man/salt-cp.1 index 7670169a63b..c9cfd69ba8b 100644 --- a/doc/man/salt-cp.1 +++ b/doc/man/salt-cp.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SALT-CP" "1" "Generated on March 29, 2023 at 07:32:38 PM UTC." "3006.0" "Salt" +.TH "SALT-CP" "1" "Generated on April 18, 2023 at 08:56:37 PM UTC." "3006.0" "Salt" .SH NAME salt-cp \- salt-cp Documentation .sp diff --git a/doc/man/salt-key.1 b/doc/man/salt-key.1 index c381dd2a87f..0ff7822c6f9 100644 --- a/doc/man/salt-key.1 +++ b/doc/man/salt-key.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SALT-KEY" "1" "Generated on March 29, 2023 at 07:32:38 PM UTC." "3006.0" "Salt" +.TH "SALT-KEY" "1" "Generated on April 18, 2023 at 08:56:37 PM UTC." "3006.0" "Salt" .SH NAME salt-key \- salt-key Documentation .SH SYNOPSIS diff --git a/doc/man/salt-master.1 b/doc/man/salt-master.1 index 1cd78d9d357..8eb527cadf3 100644 --- a/doc/man/salt-master.1 +++ b/doc/man/salt-master.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SALT-MASTER" "1" "Generated on March 29, 2023 at 07:32:38 PM UTC." "3006.0" "Salt" +.TH "SALT-MASTER" "1" "Generated on April 18, 2023 at 08:56:37 PM UTC." "3006.0" "Salt" .SH NAME salt-master \- salt-master Documentation .sp diff --git a/doc/man/salt-minion.1 b/doc/man/salt-minion.1 index 57f3d9c5bad..32421a3f24f 100644 --- a/doc/man/salt-minion.1 +++ b/doc/man/salt-minion.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SALT-MINION" "1" "Generated on March 29, 2023 at 07:32:38 PM UTC." "3006.0" "Salt" +.TH "SALT-MINION" "1" "Generated on April 18, 2023 at 08:56:37 PM UTC." "3006.0" "Salt" .SH NAME salt-minion \- salt-minion Documentation .sp diff --git a/doc/man/salt-proxy.1 b/doc/man/salt-proxy.1 index dac6f9e5d62..57084cc6101 100644 --- a/doc/man/salt-proxy.1 +++ b/doc/man/salt-proxy.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SALT-PROXY" "1" "Generated on March 29, 2023 at 07:32:38 PM UTC." "3006.0" "Salt" +.TH "SALT-PROXY" "1" "Generated on April 18, 2023 at 08:56:37 PM UTC." "3006.0" "Salt" .SH NAME salt-proxy \- salt-proxy Documentation .sp diff --git a/doc/man/salt-run.1 b/doc/man/salt-run.1 index b87059d9a44..69b75f76854 100644 --- a/doc/man/salt-run.1 +++ b/doc/man/salt-run.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SALT-RUN" "1" "Generated on March 29, 2023 at 07:32:38 PM UTC." "3006.0" "Salt" +.TH "SALT-RUN" "1" "Generated on April 18, 2023 at 08:56:37 PM UTC." "3006.0" "Salt" .SH NAME salt-run \- salt-run Documentation .sp diff --git a/doc/man/salt-ssh.1 b/doc/man/salt-ssh.1 index cd9573302ba..d3d9749f531 100644 --- a/doc/man/salt-ssh.1 +++ b/doc/man/salt-ssh.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SALT-SSH" "1" "Generated on March 29, 2023 at 07:32:38 PM UTC." "3006.0" "Salt" +.TH "SALT-SSH" "1" "Generated on April 18, 2023 at 08:56:37 PM UTC." "3006.0" "Salt" .SH NAME salt-ssh \- salt-ssh Documentation .SH SYNOPSIS diff --git a/doc/man/salt-syndic.1 b/doc/man/salt-syndic.1 index 0848560f5d6..9480755a145 100644 --- a/doc/man/salt-syndic.1 +++ b/doc/man/salt-syndic.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SALT-SYNDIC" "1" "Generated on March 29, 2023 at 07:32:38 PM UTC." "3006.0" "Salt" +.TH "SALT-SYNDIC" "1" "Generated on April 18, 2023 at 08:56:37 PM UTC." "3006.0" "Salt" .SH NAME salt-syndic \- salt-syndic Documentation .sp diff --git a/doc/man/salt.1 b/doc/man/salt.1 index 8888b6af466..0d522736c30 100644 --- a/doc/man/salt.1 +++ b/doc/man/salt.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SALT" "1" "Generated on March 29, 2023 at 07:32:38 PM UTC." "3006.0" "Salt" +.TH "SALT" "1" "Generated on April 18, 2023 at 08:56:37 PM UTC." "3006.0" "Salt" .SH NAME salt \- salt .SH SYNOPSIS diff --git a/doc/man/salt.7 b/doc/man/salt.7 index eead0f9a7f2..7a08e3aac1b 100644 --- a/doc/man/salt.7 +++ b/doc/man/salt.7 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SALT" "7" "Generated on March 29, 2023 at 07:32:38 PM UTC." "3006.0" "Salt" +.TH "SALT" "7" "Generated on April 18, 2023 at 08:56:37 PM UTC." "3006.0" "Salt" .SH NAME salt \- Salt Documentation .SH SALT PROJECT @@ -1301,7 +1301,7 @@ Now you can run your tests: .sp .nf .ft C -python \-m nox \-e \(dqpytest\-3.7(coverage=False)\(dq \-\- tests/unit/cli/test_batch.py +python \-m nox \-e \(dqtest\-3(coverage=False)\(dq \-\- tests/unit/cli/test_batch.py .ft P .fi .UNINDENT @@ -1316,13 +1316,48 @@ this: .sp .nf .ft C -python \-m nox \-e \(dqpytest\-3.7(coverage=False)\(dq \-\- tests/unit/cli/test_batch.py; espeak \(dqTests done, woohoo!\(dq +python \-m nox \-e \(dqtest\-3(coverage=False)\(dq \-\- tests/unit/cli/test_batch.py; espeak \(dqTests done, woohoo!\(dq .ft P .fi .UNINDENT .UNINDENT .sp That way you don\(aqt have to keep monitoring the actual test run. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +python \-m nox \-e \(dqtest\-3(coverage=False)\(dq \-\- \-\-core\-tests +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +You can enable or disable test groups locally by passing their respected flag: +.INDENT 0.0 +.IP \(bu 2 +\-\-no\-fast\-tests \- Tests that are ~10s or faster. Fast tests make up ~75% of tests and can run in 10 to 20 minutes. +.IP \(bu 2 +\-\-slow\-tests \- Tests that are ~10s or slower. +.IP \(bu 2 +\-\-core\-tests \- Tests of any speed that test the root parts of salt. +.IP \(bu 2 +\-\-flaky\-jail \- Test that need to be temporarily skipped. +.UNINDENT +.sp +In Your PR, you can enable or disable test groups by setting a label. +All fast, slow, and core tests specified in the change file will always run. +.INDENT 0.0 +.IP \(bu 2 +test:no\-fast +.IP \(bu 2 +test:core +.IP \(bu 2 +test:slow +.IP \(bu 2 +test:flaky\-jail +.UNINDENT .SS Changelog and commit! .sp When you write your commit message you should use imperative style. Do @@ -1957,9 +1992,27 @@ Set the default timeout for the salt command and api. .sp Default: \fB60\fP .sp -The loop_interval option controls the seconds for the master\(aqs maintenance +The loop_interval option controls the seconds for the master\(aqs Maintenance process check cycle. This process updates file server backends, cleans the job cache and executes the scheduler. +.SS \fBmaintenance_interval\fP +.sp +New in version 3006.0. + +.sp +Default: \fB3600\fP +.sp +Defines how often to restart the master\(aqs Maintenance process. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +maintenance_interval: 9600 +.ft P +.fi +.UNINDENT +.UNINDENT .SS \fBoutput\fP .sp Default: \fBnested\fP @@ -6217,6 +6270,24 @@ s3fs_update_interval: 120 .fi .UNINDENT .UNINDENT +.SS \fBfileserver_interval\fP +.sp +New in version 3006.0. + +.sp +Default: \fB3600\fP +.sp +Defines how often to restart the master\(aqs FilesServerUpdate process. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +fileserver_interval: 9600 +.ft P +.fi +.UNINDENT +.UNINDENT .SS Pillar Configuration .SS \fBpillar_roots\fP .sp @@ -19830,6 +19901,13 @@ specifying both the file path and the environment to search. The individual environments can span across multiple directory roots to create overlays and to allow for files to be organized in many flexible ways. +.SS Periodic Restarts +.sp +The file server will restart periodically. The reason for this is to prevent any +files erver backends which may not properly handle resources from endlessly +consuming memory. A notable example of this is using a git backend with the +pygit2 library. How often the file server restarts can be controlled with the +\fBfileserver_interval\fP in your master\(aqs config file. .SS Environments .sp The Salt file server defaults to the mandatory \fBbase\fP environment. This @@ -31280,6 +31358,10 @@ A Python data structure .SS salt.renderers.mako .sp Mako Renderer for Salt +.sp +This renderer requires the Mako library. +.sp +To install Mako, do the following: .INDENT 0.0 .TP .B salt.renderers.mako.render(template_file, saltenv=\(aqbase\(aq, sls=\(aq\(aq, context=None, tmplpath=None, **kws) @@ -50514,6 +50596,98 @@ def test_issue_58763_a(tmp_path, modules, state_tree, caplog): .fi .UNINDENT .UNINDENT +.SS Test Groups +.sp +Salt has four groups +.INDENT 0.0 +.IP \(bu 2 +fast \- Tests that are ~10s or faster. Fast tests make up ~75% of tests and can run in 10 to 20 minutes. +.IP \(bu 2 +slow \- Tests that are ~10s or slower. +.IP \(bu 2 +core \- Tests of any speed that test the root parts of salt. +.IP \(bu 2 +flaky\-jail \- Test that need to be temporarily skipped. +.UNINDENT +.sp +Pytest Decorators +.INDENT 0.0 +.IP \(bu 2 +@pytest.mark.slow_test +.IP \(bu 2 +@pytest.mark.core_test +.IP \(bu 2 +@pytest.mark.flaky_jail +.UNINDENT +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +@pytest.mark.core_test +def test_ping(self): + \(dq\(dq\(dq + test.ping + \(dq\(dq\(dq + self.assertTrue(self.run_function(\(dqtest.ping\(dq)) +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +You can also mark all the tests in file. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +pytestmark = [ + pytest.mark.core_test, +] + + +def test_ping(self): + \(dq\(dq\(dq + test.ping + \(dq\(dq\(dq + self.assertTrue(self.run_function(\(dqtest.ping\(dq)) + + +def test_ping2(self): + \(dq\(dq\(dq + test.ping + \(dq\(dq\(dq + for _ in range(10): + self.assertTrue(self.run_function(\(dqtest.ping\(dq)) +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +You can enable or disable test groups locally by passing there respected flag: +.INDENT 0.0 +.IP \(bu 2 +\-\-no\-fast\-tests +.IP \(bu 2 +\-\-slow\-tests +.IP \(bu 2 +\-\-core\-tests +.IP \(bu 2 +\-\-flaky\-jail +.UNINDENT +.sp +In Your PR you can enable or disable test groups by setting a label. +All thought the fast, slow and core tests specified in the change file will always run. +.INDENT 0.0 +.IP \(bu 2 +test:no\-fast +.IP \(bu 2 +test:slow +.IP \(bu 2 +test:core +.IP \(bu 2 +test:flaky\-jail +.UNINDENT .SS Automated Test Runs .sp SaltStack maintains a Jenkins server which can be viewed at @@ -57424,6 +57598,34 @@ test: .UNINDENT .UNINDENT +.sp +Changed in version 3006.0: Since the \fBunless\fP requisite utilizes \fBcmd.retcode\fP, certain parameters +included in the state are passed along to \fBcmd.retcode\fP\&. On occasion this +can cause issues, particularly if the \fBshell\fP option in a \fBuser.present\fP +is set to /sbin/nologin and this shell is passed along to \fBcmd.retcode\fP\&. +This would cause \fBcmd.retcode\fP to run the command using that shell which +would fail regardless of the result of the command. +.sp +By including \fBshell\fP in \fBcmd_opts_exclude\fP, that parameter would not be +passed along to the call to \fBcmd.retcode\fP\&. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +jim_nologin: + user.present: + \- name: jim + \- shell: /sbin/nologin + \- unless: + \- echo hello world + \- cmd_opts_exclude: + \- shell +.ft P +.fi +.UNINDENT +.UNINDENT + .SS onlyif .sp New in version 2014.7.0. @@ -57533,6 +57735,34 @@ test: .UNINDENT .UNINDENT +.sp +Changed in version 3006.0: Since the \fBonlyif\fP requisite utilizes \fBcmd.retcode\fP, certain parameters +included in the state are passed along to \fBcmd.retcode\fP\&. On occasion this +can cause issues, particularly if the \fBshell\fP option in a \fBuser.present\fP +is set to /sbin/nologin and this shell is passed along to \fBcmd.retcode\fP\&. +This would cause \fBcmd.retcode\fP to run the command using that shell which +would fail regardless of the result of the command. +.sp +By including \fBshell\fP in \fBcmd_opts_exclude\fP, that parameter would not be +passed along to the call to \fBcmd.retcode\fP\&. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +jim_nologin: + user.present: + \- name: jim + \- shell: /sbin/nologin + \- onlyif: + \- echo hello world + \- cmd_opts_exclude: + \- shell +.ft P +.fi +.UNINDENT +.UNINDENT + .SS Creates .sp New in version 3001. @@ -84894,7 +85124,7 @@ Fetch Native Python Build: .sp .nf .ft C -relenv fetch \-\-python= +relenv fetch \-\-python= .ft P .fi .UNINDENT @@ -84910,7 +85140,7 @@ Create relenv environment: .sp .nf .ft C -relenv create \-\-python=3.10.10 +relenv create \-\-python= .ft P .fi .UNINDENT @@ -84926,7 +85156,7 @@ Add Salt into onedir. .sp .nf .ft C -path/to//bin/pip install /path/to/salt +/bin/pip install /path/to/salt .ft P .fi .UNINDENT @@ -84945,17 +85175,13 @@ Install the dependencies: .sp .nf .ft C -yum \-y install python3 python3\-pip openssl git rpmdevtools rpmlint systemd\-units libxcrypt\-compat git +yum \-y install python3 python3\-pip openssl git rpmdevtools rpmlint systemd\-units libxcrypt\-compat git gnupg2 jq createrepo rpm\-sign rustc cargo epel\-release +yum \-y install patchelf +pip install awscli .ft P .fi .UNINDENT .UNINDENT -.UNINDENT -.UNINDENT -.IP 2. 3 -(Optional) To build a specific Salt version, you will need to install tools and changelog dependencies: -.INDENT 3.0 -.INDENT 3.5 .INDENT 0.0 .INDENT 3.5 .sp @@ -84966,6 +85192,12 @@ pip install \-r requirements/static/ci/py{python_version}/tools.txt .fi .UNINDENT .UNINDENT +.UNINDENT +.UNINDENT +.IP 2. 3 +(Optional) To build a specific Salt version, you will need to install tools and changelog dependencies: +.INDENT 3.0 +.INDENT 3.5 .INDENT 0.0 .INDENT 3.5 .sp @@ -84987,7 +85219,7 @@ Ensure you are in the current Salt cloned git repo: .sp .nf .ft C -cd salt +cd .ft P .fi .UNINDENT @@ -85003,7 +85235,7 @@ cd salt .sp .nf .ft C -tools changelog update\-rpm +tools changelog update\-rpm .ft P .fi .UNINDENT @@ -85011,15 +85243,16 @@ tools changelog update\-rpm .UNINDENT .UNINDENT .IP 5. 3 -Run rpmbuild in the Salt repo: +Build the RPM: .INDENT 3.0 .INDENT 3.5 +Only the arch argument is required, the rest are optional. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C -rpmbuild \-bb \-\-define=\(dq_salt_src $(pwd)\(dq $(pwd)/pkg/rpm/salt.spec +tools pkg build rpm \-\-relenv\-version \-\-python\-version \-\-arch .ft P .fi .UNINDENT @@ -85038,17 +85271,11 @@ Install the dependencies: .sp .nf .ft C -apt install \-y bash\-completion build\-essential debhelper devscripts git patchelf python3 python3\-pip python3\-venv rustc +apt install \-y apt\-utils gnupg jq awscli python3 python3\-venv python3\-pip build\-essential devscripts debhelper bash\-completion git patchelf rustc .ft P .fi .UNINDENT .UNINDENT -.UNINDENT -.UNINDENT -.IP 2. 3 -(Optional) To build a specific Salt version, you will need to install tools and changelog dependencies: -.INDENT 3.0 -.INDENT 3.5 .INDENT 0.0 .INDENT 3.5 .sp @@ -85059,6 +85286,12 @@ pip install \-r requirements/static/ci/py{python_version}/tools.txt .fi .UNINDENT .UNINDENT +.UNINDENT +.UNINDENT +.IP 2. 3 +(Optional) To build a specific Salt version, you will need to install changelog dependencies: +.INDENT 3.0 +.INDENT 3.5 .INDENT 0.0 .INDENT 3.5 .sp @@ -85080,7 +85313,7 @@ Ensure you are in the current Salt cloned git repo.: .sp .nf .ft C -cd salt +cd .ft P .fi .UNINDENT @@ -85096,7 +85329,7 @@ cd salt .sp .nf .ft C -tools changelog update\-deb +tools changelog update\-deb .ft P .fi .UNINDENT @@ -85104,16 +85337,16 @@ tools changelog update\-deb .UNINDENT .UNINDENT .IP 5. 3 -Add a symlink and run debuild in the Salt repo: +Build the deb package: .INDENT 3.0 .INDENT 3.5 +Only the arch argument is required, the rest are optional. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C -ln \-sf pkg/debian/ . -debuild \-uc \-us +tools pkg build deb \-\-relenv\-version \-\-python\-version \-\-arch .ft P .fi .UNINDENT @@ -193696,7 +193929,7 @@ Passes through all the parameters described in the \fI\%utils.http.query function\fP: .INDENT 7.0 .TP -.B salt.utils.http.query(url, method=\(aqGET\(aq, params=None, data=None, data_file=None, header_dict=None, header_list=None, header_file=None, username=None, password=None, auth=None, decode=False, decode_type=\(aqauto\(aq, status=False, headers=False, text=False, cookies=None, cookie_jar=None, cookie_format=\(aqlwp\(aq, persist_session=False, session_cookie_jar=None, data_render=False, data_renderer=None, header_render=False, header_renderer=None, template_dict=None, test=False, test_url=None, node=\(aqminion\(aq, port=80, opts=None, backend=None, ca_bundle=None, verify_ssl=None, cert=None, text_out=None, headers_out=None, decode_out=None, stream=False, streaming_callback=None, header_callback=None, handle=False, agent=\(aqSalt/3006.0rc3\(aq, hide_fields=None, raise_error=True, formdata=False, formdata_fieldname=None, formdata_filename=None, decode_body=True, **kwargs) +.B salt.utils.http.query(url, method=\(aqGET\(aq, params=None, data=None, data_file=None, header_dict=None, header_list=None, header_file=None, username=None, password=None, auth=None, decode=False, decode_type=\(aqauto\(aq, status=False, headers=False, text=False, cookies=None, cookie_jar=None, cookie_format=\(aqlwp\(aq, persist_session=False, session_cookie_jar=None, data_render=False, data_renderer=None, header_render=False, header_renderer=None, template_dict=None, test=False, test_url=None, node=\(aqminion\(aq, port=80, opts=None, backend=None, ca_bundle=None, verify_ssl=None, cert=None, text_out=None, headers_out=None, decode_out=None, stream=False, streaming_callback=None, header_callback=None, handle=False, agent=\(aqSalt/3006.0\(aq, hide_fields=None, raise_error=True, formdata=False, formdata_fieldname=None, formdata_filename=None, decode_body=True, **kwargs) Query a resource, and decode the return data .UNINDENT .INDENT 7.0 @@ -329175,6 +329408,9 @@ values is returned. .sp Changed in version 2018.3.0: The service name can now be a glob (e.g. \fBsalt*\fP) +.sp +Changed in version 3006.0: Returns \(dqNot Found\(dq if the service is not found on the system + .INDENT 7.0 .TP .B Parameters @@ -329183,6 +329419,7 @@ Changed in version 2018.3.0: The service name can now be a glob (e.g. \fBsalt*\f .B Returns True if running, False otherwise dict: Maps service name to True if running, False otherwise +str: Not Found if the service is not found on the system .TP .B Return type \fI\%bool\fP @@ -466355,7 +466592,7 @@ Now you can run your tests: .sp .nf .ft C -python \-m nox \-e \(dqpytest\-3.7(coverage=False)\(dq \-\- tests/unit/cli/test_batch.py +python \-m nox \-e \(dqtest\-3(coverage=False)\(dq \-\- tests/unit/cli/test_batch.py .ft P .fi .UNINDENT @@ -466370,13 +466607,48 @@ this: .sp .nf .ft C -python \-m nox \-e \(dqpytest\-3.7(coverage=False)\(dq \-\- tests/unit/cli/test_batch.py; espeak \(dqTests done, woohoo!\(dq +python \-m nox \-e \(dqtest\-3(coverage=False)\(dq \-\- tests/unit/cli/test_batch.py; espeak \(dqTests done, woohoo!\(dq .ft P .fi .UNINDENT .UNINDENT .sp That way you don\(aqt have to keep monitoring the actual test run. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +python \-m nox \-e \(dqtest\-3(coverage=False)\(dq \-\- \-\-core\-tests +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +You can enable or disable test groups locally by passing their respected flag: +.INDENT 0.0 +.IP \(bu 2 +\-\-no\-fast\-tests \- Tests that are ~10s or faster. Fast tests make up ~75% of tests and can run in 10 to 20 minutes. +.IP \(bu 2 +\-\-slow\-tests \- Tests that are ~10s or slower. +.IP \(bu 2 +\-\-core\-tests \- Tests of any speed that test the root parts of salt. +.IP \(bu 2 +\-\-flaky\-jail \- Test that need to be temporarily skipped. +.UNINDENT +.sp +In Your PR, you can enable or disable test groups by setting a label. +All fast, slow, and core tests specified in the change file will always run. +.INDENT 0.0 +.IP \(bu 2 +test:no\-fast +.IP \(bu 2 +test:core +.IP \(bu 2 +test:slow +.IP \(bu 2 +test:flaky\-jail +.UNINDENT .SS Changelog and commit! .sp When you write your commit message you should use imperative style. Do @@ -468142,6 +468414,78 @@ changes outside of the salt directory .UNINDENT .UNINDENT .UNINDENT +.SS Release Notes +.sp +You can edit the release notes to highlight a new feature being added +to a given release. The release notes are templatized with Jinja and +are generated at release time. +.SS How do I edit the release notes +.sp +To edit the release notes you need to look in doc/topics/releases/templates +for your given release and edit the template. Do not edit the release note +files in doc/topics/releases/, as this will be written over with the content +in the template file. For example, if you want to add content to the 3006.0 +release notes you would edit the doc/topics/releases/templates/3006.0.md.template +file. Do not edit the changelog portion of the template file, since that is +auto generated with the content generated for the changelog for each release. +.SS How to generate the release notes +.sp +This step is only used when we need to generate the release notes before releasing. +You should NOT need to run these steps as they are ran in the pipeline, but this +is documented so you can test your changes to the release notes template. +.sp +To generate the release notes requires the \fItools\fP command. The instructions below +will detail how to install and use \fItools\fP\&. +.SS Installing \fItools\fP +.sp +To view the output the release notes will produce before generating them +you can run \fItools\fP in draft mode: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +tools changelog update\-release\-notes \-\-draft +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +To generate the release notes just remove the \fI\-\-draft\fP argument: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +tools changelog update\-release\-notes +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +To specify a specific Salt version you add that version as an argument: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +tools changelog update\-release\-notes 3006.0 +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +To only generate the template for a new release +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +tools changelog update\-release\-notes \-\-template\-only +.ft P +.fi +.UNINDENT +.UNINDENT .SS Reporting Bugs .sp Salt uses GitHub to track open issues and feature requests. @@ -475484,7 +475828,7 @@ about the version numbering scheme. .UNINDENT .SS Upcoming release (release\-3006.0)= -.SS Salt 3006.0 release notes \- Codename Sulfur +.SS Salt 3006.0 release notes .SS Onedir packaging .sp Going forward from the 3006.0 release, the Salt Project will only provide onedir @@ -475492,6 +475836,34 @@ packages to install or upgrade Salt. The classic, non\-onedir packages will not be provided for supported operating systems. See \fI\%Upgrade to onedir\fP in the \fI\%Salt Install Guide\fP for information about upgrading from the classic packages to the onedir packages. +.SS Linux Packaging Salt Master Salt User and Group +.sp +The linux Salt Master packages will now add a Salt user and group +by default. The packages will add the \fBuser: salt\fP config option +to the Salt Master config. The Salt Master service will run as this +user. If you do not want to run the Salt Master as a different user +you can remove the \fBuser: salt\fP config from /etc/salt/master or change +the user to the desired user to run the Salt Master. +.sp +Since the Salt Master is running as a different user, you will need +to ensure you set the owner and group to \fBsalt\fP for your file_roots +and pillar_roots(commonly \fB/srv/salt\fP and \fB/srv/pillar\fP). +.sp +If you are running a Salt Master, Salt\-Api and a Salt Minion on the same +host using the new \fBsalt\fP user and you install a pip dependency into +the onedir environment using \fBsalt\-pip\fP or the \fBpip\fP module, you +need to to chown the directory \fB/opt/saltstack/salt/lib//site\-packages/\fP +with the \fBsalt\fP user and group. +.SS Caveat of salt\-pip +.sp +Salt ships with a wrapper script around pip called \fBsalt\-pip\fP\&. Users should +use \fBsalt\-pip\fP to install any python packages needed to extend Salt. +\fBsalt\-pip\fP installs python packages into an \fBextras\-3.10\fP directory located +in the root of the ondir directory, by setting the \fB\-\-target\fP argument for +pip. This ensures those packages remain installed when upgrading Salt. There is +a known bug in pip when using \fB\-\-target\fP where scripts and other non\-python +assets may not be cleaned up properly when un\-installing. The Salt team is +working to resolve this bug in the up\-stream pip project. .SS Dropping support for Python 3.5 and 3.6 .sp Python 3.5 and 3.6 will no longer be supported by Salt since they @@ -475502,7 +475874,8 @@ for more information. .sp All netapi clients, which provide the functionality to \fBsalt\-api\fP, will now be disabled by default as a security precaution. If you use \fBsalt\-api\fP, you -must add the new \fBnetapi_enable_clients\fP option to your salt master config.This is a breaking change and the \fBsalt\-api\fP will not function without this +must add the new \fBnetapi_enable_clients\fP option to your salt master config. +This is a breaking change and the \fBsalt\-api\fP will not function without this new configuration option. See \fI\%Enabling netapi client interfaces\fP for more information. .SS How do I migrate to the onedir packages? @@ -475559,1182 +475932,6 @@ Removed the PyObjC dependency. This addresses problems with building a one dir build for macOS. It became problematic because depending on the macOS version, it pulls different dependencies, and we would either have to build a macos onedir for each macOS supported release, or ship a crippled onedir(because it would be tied to the macOS version where the onedir was built). Since it\(aqs currently not being used, it\(aqs removed. \fI\%#62432\fP -.UNINDENT -.SS Deprecated -.INDENT 0.0 -.IP \(bu 2 -renamed \fBkeep_jobs\fP, specifying job cache TTL in hours, to \fBkeep_jobs_seconds\fP, specifying TTL in seconds. -\fBkeep_jobs\fP will be removed in the Argon release \fI\%#55295\fP -.IP \(bu 2 -Removing all references to napalm\-base which is no longer supported. \fI\%#61542\fP -.IP \(bu 2 -The \(aqip_bracket\(aq function has been moved from salt/utils/zeromq.py in salt/utils/network.py \fI\%#62009\fP -.IP \(bu 2 -The \fBexpand_repo_def\fP function in \fBsalt.modules.aptpkg\fP is now deprecated. It\(aqs only used in \fBsalt.states.pkgrepo\fP and it has no use of being exposed to the CLI. \fI\%#62485\fP -.IP \(bu 2 -Deprecated defunct Django returner \fI\%#62644\fP -.IP \(bu 2 -Deprecate core ESXi and associated states and modules, vcenter and vsphere support in favor of Salt VMware Extensions \fI\%#62754\fP -.IP \(bu 2 -Removing manufacture grain which has been deprecated. \fI\%#62914\fP -.IP \(bu 2 -Removing deprecated utils/boto3_elasticsearch.py \fI\%#62915\fP -.IP \(bu 2 -Removing support for the now deprecated _ext_nodes from salt/master.py. \fI\%#62917\fP -.IP \(bu 2 -Deprecating the Salt Slack engine in favor of the Salt Slack Bolt Engine. \fI\%#63095\fP -.IP \(bu 2 -\fBsalt.utils.version.StrictVersion\fP is now deprecated and it\(aqs use should be replaced with \fBsalt.utils.version.Version\fP\&. \fI\%#63383\fP -.UNINDENT -.SS Changed -.INDENT 0.0 -.IP \(bu 2 -More intelligent diffing in changes of file.serialize state. \fI\%#48609\fP -.IP \(bu 2 -Move deprecation of the neutron module to Argon. Please migrate to the neutronng module instead. \fI\%#49430\fP -.IP \(bu 2 -\fBumask\fP is now a global state argument, instead of only applying to \fBcmd\fP -states. \fI\%#57803\fP -.IP \(bu 2 -Update pillar.obfuscate to accept kwargs in addition to args. This is useful when passing in keyword arguments like saltenv that are then passed along to pillar.items. \fI\%#58971\fP -.IP \(bu 2 -Improve support for listing macOS brew casks \fI\%#59439\fP -.IP \(bu 2 -Add missing MariaDB Grants to mysql module. -MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. -Also improved exception handling in \fBgrant_add\fP which did not log the original error message and replaced it with a generic error. \fI\%#61409\fP -.IP \(bu 2 -Use VENV_PIP_TARGET environment variable as a default target for pip if present. \fI\%#62089\fP -.IP \(bu 2 -Disabled FQDNs grains on macOS by default \fI\%#62168\fP -.IP \(bu 2 -Replaced pyroute2.IPDB with pyroute2.NDB, as the former is deprecated \fI\%#62218\fP -.IP \(bu 2 -Enhance capture of error messages for Zypper calls in zypperpkg module. \fI\%#62346\fP -.IP \(bu 2 -Removed GPG_1_3_1 check \fI\%#62895\fP -.IP \(bu 2 -Requisite state chunks now all consistently contain \fB__id__\fP, \fB__sls__\fP and \fBname\fP\&. \fI\%#63012\fP -.IP \(bu 2 -netapi_enable_clients option to allow enabling/disabling of clients in salt\-api. -By default all clients will now be disabled. Users of salt\-api will need -to update their master config to enable the clients that they use. Not adding -the netapi_enable_clients option with required clients to the master config will -disable salt\-api. \fI\%#63050\fP -.IP \(bu 2 -Stop relying on \fBsalt/_version.py\fP to write Salt\(aqs version. Instead use \fBsalt/_version.txt\fP which only contains the version string. \fI\%#63383\fP -.IP \(bu 2 -Set enable_fqdns_grains to be False by default. \fI\%#63595\fP -.IP \(bu 2 -Changelog snippet files must now have a \fB\&.md\fP file extension to be more explicit on what type of rendering is done when they are included in the main \fBCHANGELOG.md\fP file. \fI\%#63710\fP -.UNINDENT -.SS Fixed -.INDENT 0.0 -.IP \(bu 2 -Add kwargs to handle extra parameters for http.query \fI\%#36138\fP -.IP \(bu 2 -Fix mounted bind mounts getting active mount options added \fI\%#39292\fP -.IP \(bu 2 -Fix \fBsysctl.present\fP converts spaces to tabs. \fI\%#40054\fP -.IP \(bu 2 -Fixes state pkg.purged to purge removed packages on Debian family systems \fI\%#42306\fP -.IP \(bu 2 -Fix fun_args missing from syndic returns \fI\%#45823\fP -.IP \(bu 2 -Fix mount.mounted with \(aqmount: False\(aq reports unmounted file system as unchanged when running with test=True \fI\%#47201\fP -.IP \(bu 2 -Issue #49310: Allow users to touch a file with Unix date of birth \fI\%#49310\fP -.IP \(bu 2 -Do not raise an exception in pkg.info_installed on nonzero return code \fI\%#51620\fP -.IP \(bu 2 -Passes the value of the force parameter from file.copy to its call to file.remove so that files with the read\-only attribute are handled. \fI\%#51739\fP -.IP \(bu 2 -Fixed x509.certificate_managed creates new certificate every run in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. \fI\%#52167\fP -.IP \(bu 2 -Don\(aqt check for cached pillar errors on state.apply \fI\%#52354\fP, \fI\%#57180\fP, \fI\%#59339\fP -.IP \(bu 2 -Swapping out args and kwargs for arg and kwarg respectively in the Slack engine when the command passed is a runner. \fI\%#52400\fP -.IP \(bu 2 -Ensure when we\(aqre adding chunks to the rules when running aggregation with the iptables state module we use a copy of the chunk otherwise we end up with a recursive mess. \fI\%#53353\fP -.IP \(bu 2 -When user_create or user_remove fail, return False instead of returning the error. \fI\%#53377\fP -.IP \(bu 2 -Include sync_roster when sync_all is called. \fI\%#53914\fP -.IP \(bu 2 -Avoid warning noise in lograte.get \fI\%#53988\fP -.IP \(bu 2 -Fixed listing revoked keys with gpg.list_keys \fI\%#54347\fP -.IP \(bu 2 -Fix mount.mounted does not handle blanks properly \fI\%#54508\fP -.IP \(bu 2 -Fixed grain num_cpus get wrong CPUs count in case of inconsistent CPU numbering. \fI\%#54682\fP -.IP \(bu 2 -Fix spelling error for python_shell argument in dpkg_lower module \fI\%#54907\fP -.IP \(bu 2 -Cleaned up bytes response data before sending to non\-bytes compatible returners (postgres, mysql) \fI\%#55226\fP -.IP \(bu 2 -Fixed malformed state return when testing file.managed with unavailable source file \fI\%#55269\fP -.IP \(bu 2 -Included stdout in error message for Zypper calls in zypperpkg module. \fI\%#56016\fP -.IP \(bu 2 -Fixed pillar.filter_by with salt\-ssh \fI\%#56093\fP -.IP \(bu 2 -Fix boto_route53 issue with (multiple) VPCs. \fI\%#57139\fP -.IP \(bu 2 -Remove log from mine runner which was not used. \fI\%#57463\fP -.IP \(bu 2 -Fixed x509.read_certificate error when reading a Microsoft CA issued certificate in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. \fI\%#57535\fP -.IP \(bu 2 -Updating Slack engine to use slack_bolt library. \fI\%#57842\fP -.IP \(bu 2 -Fixed warning about replace=True with x509.certificate_managed in the new cryptography x509 module. \fI\%#58165\fP -.IP \(bu 2 -Fix salt.modules.pip:is_installed doesn\(aqt handle locally installed packages \fI\%#58202\fP -.IP \(bu 2 -Add missing MariaDB Grants to mysql module. MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. \fI\%#58297\fP -.IP \(bu 2 -linux_shadow: Fix cases where malformed shadow entries cause \fBuser.present\fP -states to fail. \fI\%#58423\fP -.IP \(bu 2 -Fixed salt.utils.compat.cmp to work with dictionaries \fI\%#58729\fP -.IP \(bu 2 -Fixed formatting for terse output mode \fI\%#58953\fP -.IP \(bu 2 -Fixed RecursiveDictDiffer with added nested dicts \fI\%#59017\fP -.IP \(bu 2 -Fixed x509.certificate_managed has DoS effect on master in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. \fI\%#59169\fP -.IP \(bu 2 -Fixed saltnado websockets disconnecting immediately \fI\%#59183\fP -.IP \(bu 2 -Fixed x509.certificate_managed rolls certificates every now and then in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. \fI\%#59315\fP -.IP \(bu 2 -Fix postgres_privileges.present not idempotent for functions \fI\%#59585\fP -.IP \(bu 2 -Fixed influxdb_continuous_query.present state to provide the client args to the underlying module on create. \fI\%#59766\fP -.IP \(bu 2 -Warn when using insecure (http:// based) key_urls for apt\-based systems in pkgrepo.managed, and add a kwarg that determines the validity of such a url. \fI\%#59786\fP -.IP \(bu 2 -add load balancing policy default option and ensure the module can be executed with arguments from CLI \fI\%#59909\fP -.IP \(bu 2 -Fix salt\-ssh when using imports with extra\-filerefs. \fI\%#60003\fP -.IP \(bu 2 -Fixed cache directory corruption startup error \fI\%#60170\fP -.IP \(bu 2 -Update docs remove dry_run in docstring of file.blockreplace state. \fI\%#60227\fP -.IP \(bu 2 -Adds Parrot to OS_Family_Map in grains. \fI\%#60249\fP -.IP \(bu 2 -Fixed stdout and stderr being empty sometimes when use_vt=True for the cmd.run[*] functions \fI\%#60365\fP -.IP \(bu 2 -Use return code in iptables \-\-check to verify rule exists. \fI\%#60467\fP -.IP \(bu 2 -Fix regression pip.installed does not pass env_vars when calling pip.list \fI\%#60557\fP -.IP \(bu 2 -Fix xfs module when additional output included in mkfs.xfs command. \fI\%#60853\fP -.IP \(bu 2 -Fixed parsing new format of terraform states in roster.terraform \fI\%#60915\fP -.IP \(bu 2 -Fixed recognizing installed ARMv7 rpm packages in compatible architectures. \fI\%#60994\fP -.IP \(bu 2 -Fixing changes dict in pkg state to be consistent when installing and test=True. \fI\%#60995\fP -.IP \(bu 2 -Fix cron.present duplicating entries when changing timespec to special. \fI\%#60997\fP -.IP \(bu 2 -Made salt\-ssh respect \-\-wipe again \fI\%#61083\fP -.IP \(bu 2 -state.orchestrate_single only passes a pillar if it is set to the state -function. This allows it to be used with state functions that don\(aqt accept a -pillar keyword argument. \fI\%#61092\fP -.IP \(bu 2 -Fix ipset state when the comment kwarg is set. \fI\%#61122\fP -.IP \(bu 2 -Fix issue with archive.unzip where the password was not being encoded for the extract function \fI\%#61422\fP -.IP \(bu 2 -Some Linux distributions (like AlmaLinux, Astra Linux, Debian, Mendel, Linux -Mint, Pop!_OS, Rocky Linux) report different \fBoscodename\fP, \fBosfullname\fP, -\fBosfinger\fP grains if lsb\-release is installed or not. They have been changed to -only derive these OS grains from \fB/etc/os\-release\fP\&. \fI\%#61618\fP -.IP \(bu 2 -Pop!_OS uses the full version (\fI\%YY.MM\fP) in the osfinger grain now, not just the year. This allows differentiating for example between 20.04 and 20.10. \fI\%#61619\fP -.IP \(bu 2 -Fix ssh config roster to correctly parse the ssh config files that contain spaces. \fI\%#61650\fP -.IP \(bu 2 -Fix SoftLayer configuration not raising an exception when a domain is missing \fI\%#61727\fP -.IP \(bu 2 -Allow the minion to start or salt\-call to run even if the user doesn\(aqt have permissions to read the root_dir value from the registry \fI\%#61789\fP -.IP \(bu 2 -Need to move the creation of the proxy object for the ProxyMinion further down in the initialization for sub proxies to ensure that all modules, especially any custom proxy modules, are available before attempting to run the init function. \fI\%#61805\fP -.IP \(bu 2 -Fixed malformed state return when merge\-serializing to an improperly formatted file \fI\%#61814\fP -.IP \(bu 2 -Made cmdmod._run[_all]_quiet work during minion startup on MacOS with runas specified (which fixed mac_service) \fI\%#61816\fP -.IP \(bu 2 -When deleting the vault cache, also delete from the session cache \fI\%#61821\fP -.IP \(bu 2 -Ignore errors on reading license info with dpkg_lowpkg to prevent tracebacks on getting package information. \fI\%#61827\fP -.IP \(bu 2 -win_lgpo: Display conflicting policy names when more than one policy is found \fI\%#61859\fP -.IP \(bu 2 -win_lgpo: Fixed intermittent KeyError when getting policy setting using lgpo.get_policy \fI\%#61860\fP -.IP \(bu 2 -Fixed listing minions on OpenBSD \fI\%#61966\fP -.IP \(bu 2 -Make Salt to return an error on \(dqpkg\(dq modules and states when targeting duplicated package names \fI\%#62019\fP -.IP \(bu 2 -Fix return of REST\-returned permissions when auth_list is set \fI\%#62022\fP -.IP \(bu 2 -Normalize package names once on using pkg.installed/removed with yum to make it possible to install packages with the name containing a part similar to a name of architecture. \fI\%#62029\fP -.IP \(bu 2 -Fix inconsitency regarding name and pkgs parameters between zypperpkg.upgrade() and yumpkg.upgrade() \fI\%#62030\fP -.IP \(bu 2 -Fix attr=all handling in pkg.list_pkgs() (yum/zypper). \fI\%#62032\fP -.IP \(bu 2 -Fixed the humanname being ignored in pkgrepo.managed on openSUSE Leap \fI\%#62053\fP -.IP \(bu 2 -Fixed issue with some LGPO policies having whitespace at the beginning or end of the element alias \fI\%#62058\fP -.IP \(bu 2 -Fix ordering of args to libcloud_storage.download_object module \fI\%#62074\fP -.IP \(bu 2 -Ignore extend declarations in sls files that are excluded. \fI\%#62082\fP -.IP \(bu 2 -Remove leftover usage of impacket \fI\%#62101\fP -.IP \(bu 2 -Pass executable path from _get_path_exec() is used when calling the program. -The $HOME env is no longer modified globally. -Only trailing newlines are stripped from the fetched secret. -Pass process arguments are handled in a secure way. \fI\%#62120\fP -.IP \(bu 2 -Ignore some command return codes in openbsdrcctl_service to prevent spurious errors \fI\%#62131\fP -.IP \(bu 2 -Fixed extra period in filename output in tls module. Instead of \(dqserver.crt.\(dq it will now be \(dqserver.crt\(dq. \fI\%#62139\fP -.IP \(bu 2 -Make sure lingering PAexec\-*.exe files in the Windows directory are cleaned up \fI\%#62152\fP -.IP \(bu 2 -Restored Salt\(aqs DeprecationWarnings \fI\%#62185\fP -.IP \(bu 2 -Fixed issue with forward slashes on Windows with file.recurse and clean=True \fI\%#62197\fP -.IP \(bu 2 -Recognize OSMC as Debian\-based \fI\%#62198\fP -.IP \(bu 2 -Fixed Zypper module failing on RPM lock file being temporarily unavailable. \fI\%#62204\fP -.IP \(bu 2 -Improved error handling and diagnostics in the proxmox salt\-cloud driver \fI\%#62211\fP -.IP \(bu 2 -Added EndeavourOS to the Arch os_family. \fI\%#62220\fP -.IP \(bu 2 -Fix salt\-ssh not detecting \fBplatform\-python\fP as a valid interpreter on EL8 \fI\%#62235\fP -.IP \(bu 2 -Fix pkg.version_cmp on openEuler and a few other os flavors. \fI\%#62248\fP -.IP \(bu 2 -Fix localhost detection in glusterfs.peers \fI\%#62273\fP -.IP \(bu 2 -Fix Salt Package Manager (SPM) exception when calling spm create_repo . \fI\%#62281\fP -.IP \(bu 2 -Fix matcher slowness due to loader invocation \fI\%#62283\fP -.IP \(bu 2 -Fixes the Puppet module for non\-aio Puppet packages for example running the Puppet module on FreeBSD. \fI\%#62323\fP -.IP \(bu 2 -Issue 62334: Displays a debug log message instead of an error log message when the publisher fails to connect \fI\%#62334\fP -.IP \(bu 2 -Fix pyobjects renderer access to opts and sls \fI\%#62336\fP -.IP \(bu 2 -Fix use of random shuffle and sample functions as Jinja filters \fI\%#62372\fP -.IP \(bu 2 -Fix groups with duplicate GIDs are not returned by get_group_list \fI\%#62377\fP -.IP \(bu 2 -Fix the \(dqzpool.present\(dq state when enabling zpool features that are already active. \fI\%#62390\fP -.IP \(bu 2 -Fix ability to execute remote file client methods in saltcheck \fI\%#62398\fP -.IP \(bu 2 -Update all platforms to use pycparser 2.21 or greater for Py 3.9 or higher, fixes fips fault with openssl v3.x \fI\%#62400\fP -.IP \(bu 2 -Due to changes in the Netmiko library for the exception paths, need to check the version of Netmiko python library and then import the exceptions from different locations depending on the result. \fI\%#62405\fP -.IP \(bu 2 -When using preq on a state, then prereq state will first be run with test=True to determine if there are changes. When there are changes, the state with the prereq option will be run prior to the prereq state. If this state fails then the prereq state will not run and the state output uses the test=True run. However, the proposed changes are included for the prereq state are included from the test=True run. We should pull those out as there weren\(aqt actually changes since the prereq state did not run. \fI\%#62408\fP -.IP \(bu 2 -Added directory mode for file.copy with makedirs \fI\%#62426\fP -.IP \(bu 2 -Provide better error handling in the various napalm proxy minion functions when the device is not accessible. \fI\%#62435\fP -.IP \(bu 2 -When handling aggregation, change the order to ensure that the requisites are aggregated first and then the state functions are aggregated. Caching whether aggregate functions are available for particular states so we don\(aqt need to attempt to load them everytime. \fI\%#62439\fP -.IP \(bu 2 -The patch allows to boostrap kubernetes clusters in the version above 1.13 via salt module \fI\%#62451\fP -.IP \(bu 2 -sysctl.persist now updates the in\-memory value on FreeBSD even if the on\-disk value was already correct. \fI\%#62461\fP -.IP \(bu 2 -Fixed parsing CDROM apt sources \fI\%#62474\fP -.IP \(bu 2 -Update sanitizing masking for Salt SSH to include additional password like strings. \fI\%#62483\fP -.IP \(bu 2 -Fix user/group checking on file state functions in the test mode. \fI\%#62499\fP -.IP \(bu 2 -Fix user.present to allow removing groups using optional_groups parameter and enforcing idempotent group membership. \fI\%#62502\fP -.IP \(bu 2 -Fix possible tracebacks if there is a package with \(aq\-\-\-\-\-\-\(aq or \(aq======\(aq in the description is installed on the Debian based minion. \fI\%#62519\fP -.IP \(bu 2 -Fixed the omitted \(dqpool\(dq parameter when cloning a VM with the proxmox salt\-cloud driver \fI\%#62521\fP -.IP \(bu 2 -Fix rendering of pyobjects states in saltcheck \fI\%#62523\fP -.IP \(bu 2 -Fixes pillar where a corrupted CacheDisk file forces the pillar to be rebuilt \fI\%#62527\fP -.IP \(bu 2 -Use str() method instead of repo_line for when python3\-apt is installed or not in \fI\%aptpkg.py\fP\&. \fI\%#62546\fP -.IP \(bu 2 -Remove the connection_timeout from netmiko_connection_args before netmiko_connection_args is added to \fBcontext\fP[\(dqnetmiko_device\(dq][\(dqargs\(dq] which is passed along to the Netmiko library. \fI\%#62547\fP -.IP \(bu 2 -Fix order specific mount.mounted options for persist \fI\%#62556\fP -.IP \(bu 2 -Fixed salt\-cloud cloning a proxmox VM with a specified new vmid. \fI\%#62558\fP -.IP \(bu 2 -Fix runas with cmd module when using the onedir bundled packages \fI\%#62565\fP -.IP \(bu 2 -Update setproctitle version for all platforms \fI\%#62576\fP -.IP \(bu 2 -Fixed missing parameters when cloning a VM with the proxmox salt\-cloud driver \fI\%#62580\fP -.IP \(bu 2 -Handle PermissionError when importing crypt when FIPS is enabled. \fI\%#62587\fP -.IP \(bu 2 -Correctly reraise exceptions in states.http \fI\%#62595\fP -.IP \(bu 2 -Fixed syndic eauth. Now jobs will be published when a valid eauth user is targeting allowed minions/functions. \fI\%#62618\fP -.IP \(bu 2 -updated rest_cherry/app to properly detect arg sent as a string as curl will do when only one arg is supplied. \fI\%#62624\fP -.IP \(bu 2 -Prevent possible tracebacks in core grains module by ignoring non utf8 characters in /proc/1/environ, /proc/1/cmdline, /proc/cmdline \fI\%#62633\fP -.IP \(bu 2 -Fixed vault ext pillar return data for KV v2 \fI\%#62651\fP -.IP \(bu 2 -Fix saltcheck _get_top_states doesn\(aqt pass saltenv to state.show_top \fI\%#62654\fP -.IP \(bu 2 -Fix groupadd.* functions hard code relative command name \fI\%#62657\fP -.IP \(bu 2 -Fixed pdbedit.create trying to use a bytes\-like hash as string. \fI\%#62670\fP -.IP \(bu 2 -Fix depenency on legacy boto module in boto3 modules \fI\%#62672\fP -.IP \(bu 2 -Modified \(dq_get_flags\(dq function so that it returns regex flags instead of integers \fI\%#62676\fP -.IP \(bu 2 -Change startup ReqServer log messages from error to info level. \fI\%#62728\fP -.IP \(bu 2 -Fix kmod.* functions hard code relative command name \fI\%#62772\fP -.IP \(bu 2 -Fix mac_brew_pkg to work with null taps \fI\%#62793\fP -.IP \(bu 2 -Fixing a bug when listing the running schedule if \(dqschedule.enable\(dq and/or \(dqschedule.disable\(dq has been run, where the \(dqenabled\(dq items is being treated as a schedule item. \fI\%#62795\fP -.IP \(bu 2 -Prevent annoying RuntimeWarning message about line buffering (buffering=1) not being supported in binary mode \fI\%#62817\fP -.IP \(bu 2 -Include UID and GID checks in modules.file.check_perms as well as comparing -ownership by username and group name. \fI\%#62818\fP -.IP \(bu 2 -Fix presence events on TCP transport by removing a client\(aqs presence when minion disconnects from publish channel correctly \fI\%#62826\fP -.IP \(bu 2 -Remove Azure deprecation messages from functions that always run w/ salt\-cloud \fI\%#62845\fP -.IP \(bu 2 -Use select instead of iterating over entrypoints as a dictionary for importlib_metadata>=5.0.0 \fI\%#62854\fP -.IP \(bu 2 -Fixed master job scheduler using when \fI\%#62858\fP -.IP \(bu 2 -LGPO: Added support for missing domain controller policies: VulnerableChannelAllowList and LdapEnforceChannelBinding \fI\%#62873\fP -.IP \(bu 2 -Fix unnecessarily complex gce metadata grains code to use googles metadata service more effectively. \fI\%#62878\fP -.IP \(bu 2 -Fixed dockermod version_info function for docker\-py 6.0.0+ \fI\%#62882\fP -.IP \(bu 2 -Moving setting the LOAD_BALANCING_POLICY_MAP dictionary into the try except block that determines if the cassandra_cql module should be made available. \fI\%#62886\fP -.IP \(bu 2 -Updating various MongoDB module functions to work with latest version of pymongo. \fI\%#62900\fP -.IP \(bu 2 -Restored channel for Syndic minions to send job returns to the Salt master. \fI\%#62933\fP -.IP \(bu 2 -removed _resolve_deps as it required a library that is not generally avalible. and switched to apt\-get for everything as that can auto resolve dependencies. \fI\%#62934\fP -.IP \(bu 2 -Updated pyzmq to version 22.0.3 on Windows builds because the old version was causing salt\-minion/salt\-call to hang \fI\%#62937\fP -.IP \(bu 2 -Allow root user to modify crontab lines for non\-root users (except AIX and Solaris). Align crontab line changes with the file ones and also with listing crontab. \fI\%#62940\fP -.IP \(bu 2 -Fix systemd_service.* functions hard code relative command name \fI\%#62942\fP -.IP \(bu 2 -Fix file.symlink backupname operation can copy remote contents to local disk \fI\%#62953\fP -.IP \(bu 2 -Issue #62968: Fix issue where cloud deployments were putting the keys in the wrong location on Windows hosts \fI\%#62968\fP -.IP \(bu 2 -Fixed gpg_passphrase issue with gpg decrypt/encrypt functions \fI\%#62977\fP -.IP \(bu 2 -Fix file.tidied FileNotFoundError \fI\%#62986\fP -.IP \(bu 2 -Fixed bug where module.wait states were detected as running legacy module.run syntax \fI\%#62988\fP -.IP \(bu 2 -Fixed issue with win_wua module where it wouldn\(aqt load if the CryptSvc was set to Manual start \fI\%#62993\fP -.IP \(bu 2 -The \fB__opts__\fP dunder dictionary is now added to the loader\(aqs \fBpack\fP if not -already present, which makes it accessible via the -\fBsalt.loader.context.NamedLoaderContext\fP class. \fI\%#63013\fP -.IP \(bu 2 -Issue #63024: Fix issue where grains and config data were being place in the wrong location on Windows hosts \fI\%#63024\fP -.IP \(bu 2 -Fix btrfs.subvolume_snapshot command failing \fI\%#63025\fP -.IP \(bu 2 -Fix file.retention_schedule always reports changes \fI\%#63033\fP -.IP \(bu 2 -Fix mongo authentication for mongo ext_pillar and mongo returner -.sp -This fix also include the ability to use the mongo connection string for mongo ext_pillar \fI\%#63058\fP -.IP \(bu 2 -Fixed x509.create_csr creates invalid CSR by default in the new cryptography x509 module. \fI\%#63103\fP -.IP \(bu 2 -TCP transport documentation now contains proper master/minion\-side filtering information \fI\%#63120\fP -.IP \(bu 2 -Fixed gpg.verify does not respect gnupghome \fI\%#63145\fP -.IP \(bu 2 -Made pillar cache pass extra minion data as well \fI\%#63208\fP -.IP \(bu 2 -Fix serious performance issues with the file.tidied module \fI\%#63231\fP -.IP \(bu 2 -Import StrictVersion and LooseVersion from setuptools.distutils.verison or setuptools._distutils.version, if first not available \fI\%#63350\fP -.IP \(bu 2 -When the shell is passed as powershell or pwsh, only wrapper the shell in quotes if cmd.run is running on Windows. When quoted on Linux hosts, this results in an error when the keyword arguments are appended. \fI\%#63590\fP -.IP \(bu 2 -LGPO: Added support for \(dqRelax minimum password length limits\(dq \fI\%#63596\fP -.IP \(bu 2 -Check file is not empty before attempting to read pillar disk cache file \fI\%#63729\fP -.UNINDENT -.SS Added -.INDENT 0.0 -.IP \(bu 2 -Introduce a \fBLIB_STATE_DIR\fP syspaths variable which defaults to \fBCONFIG_DIR\fP, -but can be individually customized during installation by specifying -\fB\-\-salt\-lib\-state\-dir\fP during installation. Change the default \fBpki_dir\fP to -\fB/pki/master\fP (for the master) and \fB/pki/minion\fP -(for the minion). \fI\%#3396\fP -.IP \(bu 2 -Allow users to enable \(aqqueue=True\(aq for all state runs via config file \fI\%#31468\fP -.IP \(bu 2 -Added pillar templating to vault policies \fI\%#43287\fP -.IP \(bu 2 -Add support for NVMeF as a transport protocol for hosts in a Pure Storage FlashArray \fI\%#51088\fP -.IP \(bu 2 -A new salt\-ssh roster that generates a roster by parses a known_hosts file. \fI\%#54679\fP -.IP \(bu 2 -Added Windows Event Viewer support \fI\%#54713\fP -.IP \(bu 2 -Added the win_lgpo_reg state and execution modules which will allow registry based group policy to be set directly in the Registry.pol file \fI\%#56013\fP -.IP \(bu 2 -Added resource tagging functions to boto_dynamodb execution module \fI\%#57500\fP -.IP \(bu 2 -Added \fBopenvswitch_db\fP state module and functions \fBbridge_to_parent\fP, -\fBbridge_to_vlan\fP, \fBdb_get\fP, and \fBdb_set\fP to the \fBopenvswitch\fP execution module. -Also added optional \fBparent\fP and \fBvlan\fP parameters to the -\fBopenvswitch_bridge.present\fP state module function and the -\fBopenvswitch.bridge_create\fP execution module function. \fI\%#58986\fP -.IP \(bu 2 -State module to manage SysFS attributes \fI\%#60154\fP -.IP \(bu 2 -Added ability for \fBsalt.wait_for_event\fP to handle \fBevent_id\fPs that have a list value. \fI\%#60430\fP -.IP \(bu 2 -Added suport for Linux ppc64le core grains (cpu_model, virtual, productname, manufacturer, serialnumber) and arm core grains (serialnumber, productname) \fI\%#60518\fP -.IP \(bu 2 -Added autostart option to virt.defined and virt.running states, along with virt.update execution modules. \fI\%#60700\fP -.IP \(bu 2 -Added .0 back to our versioning scheme for future versions (e.g. 3006.0) \fI\%#60722\fP -.IP \(bu 2 -Initial work to allow parallel startup of proxy minions when used as sub proxies with Deltaproxy. \fI\%#61153\fP -.IP \(bu 2 -Added node label support for GCE \fI\%#61245\fP -.IP \(bu 2 -Support the \-\-priority flag when adding sources to Chocolatey. \fI\%#61319\fP -.IP \(bu 2 -Add namespace option to ext_pillar.http_json \fI\%#61335\fP -.IP \(bu 2 -Added a filter function to ps module to get a list of processes on a minion according to their state. \fI\%#61420\fP -.IP \(bu 2 -Add postgres.timeout option to postgres module for limiting postgres query times \fI\%#61433\fP -.IP \(bu 2 -Added new optional vault option, \fBconfig_location\fP\&. This can be either \fBmaster\fP or \fBlocal\fP and defines where vault will look for connection details, either requesting them from the master or using the local config. \fI\%#61857\fP -.IP \(bu 2 -Add ipwrap() jinja filter to wrap IPv6 addresses with brackets. \fI\%#61931\fP -.IP \(bu 2 -\(aqtcp\(aq transport is now available in ipv6\-only network \fI\%#62009\fP -.IP \(bu 2 -Add \fBdiff_attr\fP parameter to pkg.upgrade() (zypper/yum). \fI\%#62031\fP -.IP \(bu 2 -Config option pass_variable_prefix allows to distinguish variables that contain paths to pass secrets. -Config option pass_strict_fetch allows to error out when a secret cannot be fetched from pass. -Config option pass_dir allows setting the PASSWORD_STORE_DIR env for pass. -Config option pass_gnupghome allows setting the $GNUPGHOME env for pass. \fI\%#62120\fP -.IP \(bu 2 -Add file.pruned state and expanded file.rmdir exec module functionality \fI\%#62178\fP -.IP \(bu 2 -Added \(dqdig.PTR\(dq function to resolve PTR records for IPs, as well as tests and documentation \fI\%#62275\fP -.IP \(bu 2 -Added the ability to remove a KB using the DISM state/execution modules \fI\%#62366\fP -.IP \(bu 2 -Add \(dq python\(dq subcommand to allow execution or arbitrary scripts via bundled Python runtime \fI\%#62381\fP -.IP \(bu 2 -Add ability to provide conditions which convert normal state actions to no\-op when true \fI\%#62446\fP -.IP \(bu 2 -Added debug log messages displaying the command being run when installing packages on Windows \fI\%#62480\fP -.IP \(bu 2 -Add biosvendor grain \fI\%#62496\fP -.IP \(bu 2 -Add ifelse Jinja function as found in CFEngine \fI\%#62508\fP -.IP \(bu 2 -Implementation of Amazon EC2 instance detection and setting \fBvirtual_subtype\fP grain accordingly including the product if possible to identify. \fI\%#62539\fP -.IP \(bu 2 -Adds __env__substitution to ext_pillar.stack; followup of #61531, improved exception handling for stacked template (jinja) template rendering and yaml parsing in ext_pillar.stack \fI\%#62578\fP -.IP \(bu 2 -Increase file.tidied flexibility with regard to age and size \fI\%#62678\fP -.IP \(bu 2 -Added \(dqconnected_devices\(dq feature to netbox pillar module. It contains extra information about devices connected to the minion \fI\%#62761\fP -.IP \(bu 2 -Add atomic file operation for symlink changes \fI\%#62768\fP -.IP \(bu 2 -Add password/account locking/unlocking in user.present state on supported operating systems \fI\%#62856\fP -.IP \(bu 2 -Added onchange configuration for script engine \fI\%#62867\fP -.IP \(bu 2 -Added output and bare functionality to export_key gpg module function \fI\%#62978\fP -.IP \(bu 2 -Add keyvalue serializer for environment files \fI\%#62983\fP -.IP \(bu 2 -Add ability to ignore symlinks in file.tidied \fI\%#63042\fP -.IP \(bu 2 -salt\-cloud support IMDSv2 tokens when using \(aquse\-instance\-role\-credentials\(aq \fI\%#63067\fP -.IP \(bu 2 -Add ability for file.symlink to not set ownership on existing links \fI\%#63093\fP -.IP \(bu 2 -Restore the previous slack engine and deprecate it, rename replace the slack engine to slack_bolt until deprecation \fI\%#63095\fP -.IP \(bu 2 -Add functions that will return the underlying block device, mount point, and filesystem type for a given path \fI\%#63098\fP -.IP \(bu 2 -Add ethtool execution and state module functions for pause \fI\%#63128\fP -.IP \(bu 2 -Add boardname grain \fI\%#63131\fP -.IP \(bu 2 -Added management of ECDSA/EdDSA private keys with x509 modules in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. \fI\%#63248\fP -.IP \(bu 2 -Added x509 modules support for different output formats in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. \fI\%#63249\fP -.IP \(bu 2 -Added deprecation_warning test state for ensuring that deprecation warnings are correctly emitted. \fI\%#63315\fP -.IP \(bu 2 -Adds a state_events option to state.highstate, state.apply, state.sls, state.sls_id. -This allows users to enable state_events on a per use basis rather than having to -enable them globally for all state runs. \fI\%#63316\fP -.IP \(bu 2 -Allow max queue size setting for state runs to prevent performance problems from queue growth \fI\%#63356\fP -.IP \(bu 2 -Add support of exposing meta_server_grains for Azure VMs \fI\%#63606\fP -.UNINDENT -.SS Changelog -.SS Removed -.INDENT 0.0 -.IP \(bu 2 -Remove and deprecate the \fBorchestration\fP key from salt.runner and salt.wheel return data. To get it back, set features.enable_deprecated_orchestration_flag master configuration option to True. The flag will be completely removed in Salt 3008 Argon. \fI\%#59917\fP -.IP \(bu 2 -Removed distutils and replaced with setuptools, given distutils is deprecated and removed in Python 3.12 \fI\%#60476\fP -.IP \(bu 2 -Removed \fBruntests\fP targets from \fBnoxfile.py\fP \fI\%#62239\fP -.IP \(bu 2 -Removed the PyObjC dependency. -.sp -This addresses problems with building a one dir build for macOS. -It became problematic because depending on the macOS version, it pulls different dependencies, and we would either have to build a macos onedir for each macOS supported release, or ship a crippled onedir(because it would be tied to the macOS version where the onedir was built). -Since it\(aqs currently not being used, it\(aqs removed. \fI\%#62432\fP -.IP \(bu 2 -Removed \fBSixRedirectImporter\fP from Salt. Salt hasn\(aqt shipped \fBsix\fP since Salt 3004. \fI\%#63874\fP -.UNINDENT -.SS Deprecated -.INDENT 0.0 -.IP \(bu 2 -renamed \fBkeep_jobs\fP, specifying job cache TTL in hours, to \fBkeep_jobs_seconds\fP, specifying TTL in seconds. -\fBkeep_jobs\fP will be removed in the Argon release \fI\%#55295\fP -.IP \(bu 2 -Removing all references to napalm\-base which is no longer supported. \fI\%#61542\fP -.IP \(bu 2 -The \(aqip_bracket\(aq function has been moved from salt/utils/zeromq.py in salt/utils/network.py \fI\%#62009\fP -.IP \(bu 2 -The \fBexpand_repo_def\fP function in \fBsalt.modules.aptpkg\fP is now deprecated. It\(aqs only used in \fBsalt.states.pkgrepo\fP and it has no use of being exposed to the CLI. \fI\%#62485\fP -.IP \(bu 2 -Deprecated defunct Django returner \fI\%#62644\fP -.IP \(bu 2 -Deprecate core ESXi and associated states and modules, vcenter and vsphere support in favor of Salt VMware Extensions \fI\%#62754\fP -.IP \(bu 2 -Removing manufacture grain which has been deprecated. \fI\%#62914\fP -.IP \(bu 2 -Removing deprecated utils/boto3_elasticsearch.py \fI\%#62915\fP -.IP \(bu 2 -Removing support for the now deprecated _ext_nodes from salt/master.py. \fI\%#62917\fP -.IP \(bu 2 -Deprecating the Salt Slack engine in favor of the Salt Slack Bolt Engine. \fI\%#63095\fP -.IP \(bu 2 -\fBsalt.utils.version.StrictVersion\fP is now deprecated and it\(aqs use should be replaced with \fBsalt.utils.version.Version\fP\&. \fI\%#63383\fP -.UNINDENT -.SS Changed -.INDENT 0.0 -.IP \(bu 2 -More intelligent diffing in changes of file.serialize state. \fI\%#48609\fP -.IP \(bu 2 -Move deprecation of the neutron module to Argon. Please migrate to the neutronng module instead. \fI\%#49430\fP -.IP \(bu 2 -\fBumask\fP is now a global state argument, instead of only applying to \fBcmd\fP -states. \fI\%#57803\fP -.IP \(bu 2 -Update pillar.obfuscate to accept kwargs in addition to args. This is useful when passing in keyword arguments like saltenv that are then passed along to pillar.items. \fI\%#58971\fP -.IP \(bu 2 -Improve support for listing macOS brew casks \fI\%#59439\fP -.IP \(bu 2 -Add missing MariaDB Grants to mysql module. -MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. -Also improved exception handling in \fBgrant_add\fP which did not log the original error message and replaced it with a generic error. \fI\%#61409\fP -.IP \(bu 2 -Use VENV_PIP_TARGET environment variable as a default target for pip if present. \fI\%#62089\fP -.IP \(bu 2 -Disabled FQDNs grains on macOS by default \fI\%#62168\fP -.IP \(bu 2 -Replaced pyroute2.IPDB with pyroute2.NDB, as the former is deprecated \fI\%#62218\fP -.IP \(bu 2 -Enhance capture of error messages for Zypper calls in zypperpkg module. \fI\%#62346\fP -.IP \(bu 2 -Removed GPG_1_3_1 check \fI\%#62895\fP -.IP \(bu 2 -Requisite state chunks now all consistently contain \fB__id__\fP, \fB__sls__\fP and \fBname\fP\&. \fI\%#63012\fP -.IP \(bu 2 -netapi_enable_clients option to allow enabling/disabling of clients in salt\-api. -By default all clients will now be disabled. Users of salt\-api will need -to update their master config to enable the clients that they use. Not adding -the netapi_enable_clients option with required clients to the master config will -disable salt\-api. \fI\%#63050\fP -.IP \(bu 2 -Stop relying on \fBsalt/_version.py\fP to write Salt\(aqs version. Instead use \fBsalt/_version.txt\fP which only contains the version string. \fI\%#63383\fP -.IP \(bu 2 -Set enable_fqdns_grains to be False by default. \fI\%#63595\fP -.IP \(bu 2 -Changelog snippet files must now have a \fB\&.md\fP file extension to be more explicit on what type of rendering is done when they are included in the main \fBCHANGELOG.md\fP file. \fI\%#63710\fP -.UNINDENT -.SS Fixed -.INDENT 0.0 -.IP \(bu 2 -Add kwargs to handle extra parameters for http.query \fI\%#36138\fP -.IP \(bu 2 -Fix mounted bind mounts getting active mount options added \fI\%#39292\fP -.IP \(bu 2 -Fix \fBsysctl.present\fP converts spaces to tabs. \fI\%#40054\fP -.IP \(bu 2 -Fixes state pkg.purged to purge removed packages on Debian family systems \fI\%#42306\fP -.IP \(bu 2 -Fix fun_args missing from syndic returns \fI\%#45823\fP -.IP \(bu 2 -Fix mount.mounted with \(aqmount: False\(aq reports unmounted file system as unchanged when running with test=True \fI\%#47201\fP -.IP \(bu 2 -Issue #49310: Allow users to touch a file with Unix date of birth \fI\%#49310\fP -.IP \(bu 2 -Do not raise an exception in pkg.info_installed on nonzero return code \fI\%#51620\fP -.IP \(bu 2 -Passes the value of the force parameter from file.copy to its call to file.remove so that files with the read\-only attribute are handled. \fI\%#51739\fP -.IP \(bu 2 -Fixed x509.certificate_managed creates new certificate every run in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. \fI\%#52167\fP -.IP \(bu 2 -Don\(aqt check for cached pillar errors on state.apply \fI\%#52354\fP, \fI\%#57180\fP, \fI\%#59339\fP -.IP \(bu 2 -Swapping out args and kwargs for arg and kwarg respectively in the Slack engine when the command passed is a runner. \fI\%#52400\fP -.IP \(bu 2 -Ensure when we\(aqre adding chunks to the rules when running aggregation with the iptables state module we use a copy of the chunk otherwise we end up with a recursive mess. \fI\%#53353\fP -.IP \(bu 2 -When user_create or user_remove fail, return False instead of returning the error. \fI\%#53377\fP -.IP \(bu 2 -Include sync_roster when sync_all is called. \fI\%#53914\fP -.IP \(bu 2 -Avoid warning noise in lograte.get \fI\%#53988\fP -.IP \(bu 2 -Fixed listing revoked keys with gpg.list_keys \fI\%#54347\fP -.IP \(bu 2 -Fix mount.mounted does not handle blanks properly \fI\%#54508\fP -.IP \(bu 2 -Fixed grain num_cpus get wrong CPUs count in case of inconsistent CPU numbering. \fI\%#54682\fP -.IP \(bu 2 -Fix spelling error for python_shell argument in dpkg_lower module \fI\%#54907\fP -.IP \(bu 2 -Cleaned up bytes response data before sending to non\-bytes compatible returners (postgres, mysql) \fI\%#55226\fP -.IP \(bu 2 -Fixed malformed state return when testing file.managed with unavailable source file \fI\%#55269\fP -.IP \(bu 2 -Included stdout in error message for Zypper calls in zypperpkg module. \fI\%#56016\fP -.IP \(bu 2 -Fixed pillar.filter_by with salt\-ssh \fI\%#56093\fP -.IP \(bu 2 -Fix boto_route53 issue with (multiple) VPCs. \fI\%#57139\fP -.IP \(bu 2 -Remove log from mine runner which was not used. \fI\%#57463\fP -.IP \(bu 2 -Fixed x509.read_certificate error when reading a Microsoft CA issued certificate in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. \fI\%#57535\fP -.IP \(bu 2 -Updating Slack engine to use slack_bolt library. \fI\%#57842\fP -.IP \(bu 2 -Fixed warning about replace=True with x509.certificate_managed in the new cryptography x509 module. \fI\%#58165\fP -.IP \(bu 2 -Fix salt.modules.pip:is_installed doesn\(aqt handle locally installed packages \fI\%#58202\fP -.IP \(bu 2 -Add missing MariaDB Grants to mysql module. MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. \fI\%#58297\fP -.IP \(bu 2 -linux_shadow: Fix cases where malformed shadow entries cause \fBuser.present\fP -states to fail. \fI\%#58423\fP -.IP \(bu 2 -Fixed salt.utils.compat.cmp to work with dictionaries \fI\%#58729\fP -.IP \(bu 2 -Fixed formatting for terse output mode \fI\%#58953\fP -.IP \(bu 2 -Fixed RecursiveDictDiffer with added nested dicts \fI\%#59017\fP -.IP \(bu 2 -Fixed x509.certificate_managed has DoS effect on master in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. \fI\%#59169\fP -.IP \(bu 2 -Fixed saltnado websockets disconnecting immediately \fI\%#59183\fP -.IP \(bu 2 -Fixed x509.certificate_managed rolls certificates every now and then in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. \fI\%#59315\fP -.IP \(bu 2 -Fix postgres_privileges.present not idempotent for functions \fI\%#59585\fP -.IP \(bu 2 -Fixed influxdb_continuous_query.present state to provide the client args to the underlying module on create. \fI\%#59766\fP -.IP \(bu 2 -Warn when using insecure (http:// based) key_urls for apt\-based systems in pkgrepo.managed, and add a kwarg that determines the validity of such a url. \fI\%#59786\fP -.IP \(bu 2 -add load balancing policy default option and ensure the module can be executed with arguments from CLI \fI\%#59909\fP -.IP \(bu 2 -Fix salt\-ssh when using imports with extra\-filerefs. \fI\%#60003\fP -.IP \(bu 2 -Fixed cache directory corruption startup error \fI\%#60170\fP -.IP \(bu 2 -Update docs remove dry_run in docstring of file.blockreplace state. \fI\%#60227\fP -.IP \(bu 2 -Adds Parrot to OS_Family_Map in grains. \fI\%#60249\fP -.IP \(bu 2 -Fixed stdout and stderr being empty sometimes when use_vt=True for the cmd.run[*] functions \fI\%#60365\fP -.IP \(bu 2 -Use return code in iptables \-\-check to verify rule exists. \fI\%#60467\fP -.IP \(bu 2 -Fix regression pip.installed does not pass env_vars when calling pip.list \fI\%#60557\fP -.IP \(bu 2 -Fix xfs module when additional output included in mkfs.xfs command. \fI\%#60853\fP -.IP \(bu 2 -Fixed parsing new format of terraform states in roster.terraform \fI\%#60915\fP -.IP \(bu 2 -Fixed recognizing installed ARMv7 rpm packages in compatible architectures. \fI\%#60994\fP -.IP \(bu 2 -Fixing changes dict in pkg state to be consistent when installing and test=True. \fI\%#60995\fP -.IP \(bu 2 -Fix cron.present duplicating entries when changing timespec to special. \fI\%#60997\fP -.IP \(bu 2 -Made salt\-ssh respect \-\-wipe again \fI\%#61083\fP -.IP \(bu 2 -state.orchestrate_single only passes a pillar if it is set to the state -function. This allows it to be used with state functions that don\(aqt accept a -pillar keyword argument. \fI\%#61092\fP -.IP \(bu 2 -Fix ipset state when the comment kwarg is set. \fI\%#61122\fP -.IP \(bu 2 -Fix issue with archive.unzip where the password was not being encoded for the extract function \fI\%#61422\fP -.IP \(bu 2 -Some Linux distributions (like AlmaLinux, Astra Linux, Debian, Mendel, Linux -Mint, Pop!_OS, Rocky Linux) report different \fBoscodename\fP, \fBosfullname\fP, -\fBosfinger\fP grains if lsb\-release is installed or not. They have been changed to -only derive these OS grains from \fB/etc/os\-release\fP\&. \fI\%#61618\fP -.IP \(bu 2 -Pop!_OS uses the full version (\fI\%YY.MM\fP) in the osfinger grain now, not just the year. This allows differentiating for example between 20.04 and 20.10. \fI\%#61619\fP -.IP \(bu 2 -Fix ssh config roster to correctly parse the ssh config files that contain spaces. \fI\%#61650\fP -.IP \(bu 2 -Fix SoftLayer configuration not raising an exception when a domain is missing \fI\%#61727\fP -.IP \(bu 2 -Allow the minion to start or salt\-call to run even if the user doesn\(aqt have permissions to read the root_dir value from the registry \fI\%#61789\fP -.IP \(bu 2 -Need to move the creation of the proxy object for the ProxyMinion further down in the initialization for sub proxies to ensure that all modules, especially any custom proxy modules, are available before attempting to run the init function. \fI\%#61805\fP -.IP \(bu 2 -Fixed malformed state return when merge\-serializing to an improperly formatted file \fI\%#61814\fP -.IP \(bu 2 -Made cmdmod._run[_all]_quiet work during minion startup on MacOS with runas specified (which fixed mac_service) \fI\%#61816\fP -.IP \(bu 2 -When deleting the vault cache, also delete from the session cache \fI\%#61821\fP -.IP \(bu 2 -Ignore errors on reading license info with dpkg_lowpkg to prevent tracebacks on getting package information. \fI\%#61827\fP -.IP \(bu 2 -win_lgpo: Display conflicting policy names when more than one policy is found \fI\%#61859\fP -.IP \(bu 2 -win_lgpo: Fixed intermittent KeyError when getting policy setting using lgpo.get_policy \fI\%#61860\fP -.IP \(bu 2 -Fixed listing minions on OpenBSD \fI\%#61966\fP -.IP \(bu 2 -Make Salt to return an error on \(dqpkg\(dq modules and states when targeting duplicated package names \fI\%#62019\fP -.IP \(bu 2 -Fix return of REST\-returned permissions when auth_list is set \fI\%#62022\fP -.IP \(bu 2 -Normalize package names once on using pkg.installed/removed with yum to make it possible to install packages with the name containing a part similar to a name of architecture. \fI\%#62029\fP -.IP \(bu 2 -Fix inconsitency regarding name and pkgs parameters between zypperpkg.upgrade() and yumpkg.upgrade() \fI\%#62030\fP -.IP \(bu 2 -Fix attr=all handling in pkg.list_pkgs() (yum/zypper). \fI\%#62032\fP -.IP \(bu 2 -Fixed the humanname being ignored in pkgrepo.managed on openSUSE Leap \fI\%#62053\fP -.IP \(bu 2 -Fixed issue with some LGPO policies having whitespace at the beginning or end of the element alias \fI\%#62058\fP -.IP \(bu 2 -Fix ordering of args to libcloud_storage.download_object module \fI\%#62074\fP -.IP \(bu 2 -Ignore extend declarations in sls files that are excluded. \fI\%#62082\fP -.IP \(bu 2 -Remove leftover usage of impacket \fI\%#62101\fP -.IP \(bu 2 -Pass executable path from _get_path_exec() is used when calling the program. -The $HOME env is no longer modified globally. -Only trailing newlines are stripped from the fetched secret. -Pass process arguments are handled in a secure way. \fI\%#62120\fP -.IP \(bu 2 -Ignore some command return codes in openbsdrcctl_service to prevent spurious errors \fI\%#62131\fP -.IP \(bu 2 -Fixed extra period in filename output in tls module. Instead of \(dqserver.crt.\(dq it will now be \(dqserver.crt\(dq. \fI\%#62139\fP -.IP \(bu 2 -Make sure lingering PAexec\-*.exe files in the Windows directory are cleaned up \fI\%#62152\fP -.IP \(bu 2 -Restored Salt\(aqs DeprecationWarnings \fI\%#62185\fP -.IP \(bu 2 -Fixed issue with forward slashes on Windows with file.recurse and clean=True \fI\%#62197\fP -.IP \(bu 2 -Recognize OSMC as Debian\-based \fI\%#62198\fP -.IP \(bu 2 -Fixed Zypper module failing on RPM lock file being temporarily unavailable. \fI\%#62204\fP -.IP \(bu 2 -Improved error handling and diagnostics in the proxmox salt\-cloud driver \fI\%#62211\fP -.IP \(bu 2 -Added EndeavourOS to the Arch os_family. \fI\%#62220\fP -.IP \(bu 2 -Fix salt\-ssh not detecting \fBplatform\-python\fP as a valid interpreter on EL8 \fI\%#62235\fP -.IP \(bu 2 -Fix pkg.version_cmp on openEuler and a few other os flavors. \fI\%#62248\fP -.IP \(bu 2 -Fix localhost detection in glusterfs.peers \fI\%#62273\fP -.IP \(bu 2 -Fix Salt Package Manager (SPM) exception when calling spm create_repo . \fI\%#62281\fP -.IP \(bu 2 -Fix matcher slowness due to loader invocation \fI\%#62283\fP -.IP \(bu 2 -Fixes the Puppet module for non\-aio Puppet packages for example running the Puppet module on FreeBSD. \fI\%#62323\fP -.IP \(bu 2 -Issue 62334: Displays a debug log message instead of an error log message when the publisher fails to connect \fI\%#62334\fP -.IP \(bu 2 -Fix pyobjects renderer access to opts and sls \fI\%#62336\fP -.IP \(bu 2 -Fix use of random shuffle and sample functions as Jinja filters \fI\%#62372\fP -.IP \(bu 2 -Fix groups with duplicate GIDs are not returned by get_group_list \fI\%#62377\fP -.IP \(bu 2 -Fix the \(dqzpool.present\(dq state when enabling zpool features that are already active. \fI\%#62390\fP -.IP \(bu 2 -Fix ability to execute remote file client methods in saltcheck \fI\%#62398\fP -.IP \(bu 2 -Update all platforms to use pycparser 2.21 or greater for Py 3.9 or higher, fixes fips fault with openssl v3.x \fI\%#62400\fP -.IP \(bu 2 -Due to changes in the Netmiko library for the exception paths, need to check the version of Netmiko python library and then import the exceptions from different locations depending on the result. \fI\%#62405\fP -.IP \(bu 2 -When using preq on a state, then prereq state will first be run with test=True to determine if there are changes. When there are changes, the state with the prereq option will be run prior to the prereq state. If this state fails then the prereq state will not run and the state output uses the test=True run. However, the proposed changes are included for the prereq state are included from the test=True run. We should pull those out as there weren\(aqt actually changes since the prereq state did not run. \fI\%#62408\fP -.IP \(bu 2 -Added directory mode for file.copy with makedirs \fI\%#62426\fP -.IP \(bu 2 -Provide better error handling in the various napalm proxy minion functions when the device is not accessible. \fI\%#62435\fP -.IP \(bu 2 -When handling aggregation, change the order to ensure that the requisites are aggregated first and then the state functions are aggregated. Caching whether aggregate functions are available for particular states so we don\(aqt need to attempt to load them everytime. \fI\%#62439\fP -.IP \(bu 2 -The patch allows to boostrap kubernetes clusters in the version above 1.13 via salt module \fI\%#62451\fP -.IP \(bu 2 -sysctl.persist now updates the in\-memory value on FreeBSD even if the on\-disk value was already correct. \fI\%#62461\fP -.IP \(bu 2 -Fixed parsing CDROM apt sources \fI\%#62474\fP -.IP \(bu 2 -Update sanitizing masking for Salt SSH to include additional password like strings. \fI\%#62483\fP -.IP \(bu 2 -Fix user/group checking on file state functions in the test mode. \fI\%#62499\fP -.IP \(bu 2 -Fix user.present to allow removing groups using optional_groups parameter and enforcing idempotent group membership. \fI\%#62502\fP -.IP \(bu 2 -Fix possible tracebacks if there is a package with \(aq\-\-\-\-\-\-\(aq or \(aq======\(aq in the description is installed on the Debian based minion. \fI\%#62519\fP -.IP \(bu 2 -Fixed the omitted \(dqpool\(dq parameter when cloning a VM with the proxmox salt\-cloud driver \fI\%#62521\fP -.IP \(bu 2 -Fix rendering of pyobjects states in saltcheck \fI\%#62523\fP -.IP \(bu 2 -Fixes pillar where a corrupted CacheDisk file forces the pillar to be rebuilt \fI\%#62527\fP -.IP \(bu 2 -Use str() method instead of repo_line for when python3\-apt is installed or not in \fI\%aptpkg.py\fP\&. \fI\%#62546\fP -.IP \(bu 2 -Remove the connection_timeout from netmiko_connection_args before netmiko_connection_args is added to \fBcontext\fP[\(dqnetmiko_device\(dq][\(dqargs\(dq] which is passed along to the Netmiko library. \fI\%#62547\fP -.IP \(bu 2 -Fix order specific mount.mounted options for persist \fI\%#62556\fP -.IP \(bu 2 -Fixed salt\-cloud cloning a proxmox VM with a specified new vmid. \fI\%#62558\fP -.IP \(bu 2 -Fix runas with cmd module when using the onedir bundled packages \fI\%#62565\fP -.IP \(bu 2 -Update setproctitle version for all platforms \fI\%#62576\fP -.IP \(bu 2 -Fixed missing parameters when cloning a VM with the proxmox salt\-cloud driver \fI\%#62580\fP -.IP \(bu 2 -Handle PermissionError when importing crypt when FIPS is enabled. \fI\%#62587\fP -.IP \(bu 2 -Correctly reraise exceptions in states.http \fI\%#62595\fP -.IP \(bu 2 -Fixed syndic eauth. Now jobs will be published when a valid eauth user is targeting allowed minions/functions. \fI\%#62618\fP -.IP \(bu 2 -updated rest_cherry/app to properly detect arg sent as a string as curl will do when only one arg is supplied. \fI\%#62624\fP -.IP \(bu 2 -Prevent possible tracebacks in core grains module by ignoring non utf8 characters in /proc/1/environ, /proc/1/cmdline, /proc/cmdline \fI\%#62633\fP -.IP \(bu 2 -Fixed vault ext pillar return data for KV v2 \fI\%#62651\fP -.IP \(bu 2 -Fix saltcheck _get_top_states doesn\(aqt pass saltenv to state.show_top \fI\%#62654\fP -.IP \(bu 2 -Fix groupadd.* functions hard code relative command name \fI\%#62657\fP -.IP \(bu 2 -Fixed pdbedit.create trying to use a bytes\-like hash as string. \fI\%#62670\fP -.IP \(bu 2 -Fix depenency on legacy boto module in boto3 modules \fI\%#62672\fP -.IP \(bu 2 -Modified \(dq_get_flags\(dq function so that it returns regex flags instead of integers \fI\%#62676\fP -.IP \(bu 2 -Change startup ReqServer log messages from error to info level. \fI\%#62728\fP -.IP \(bu 2 -Fix kmod.* functions hard code relative command name \fI\%#62772\fP -.IP \(bu 2 -Fix mac_brew_pkg to work with null taps \fI\%#62793\fP -.IP \(bu 2 -Fixing a bug when listing the running schedule if \(dqschedule.enable\(dq and/or \(dqschedule.disable\(dq has been run, where the \(dqenabled\(dq items is being treated as a schedule item. \fI\%#62795\fP -.IP \(bu 2 -Prevent annoying RuntimeWarning message about line buffering (buffering=1) not being supported in binary mode \fI\%#62817\fP -.IP \(bu 2 -Include UID and GID checks in modules.file.check_perms as well as comparing -ownership by username and group name. \fI\%#62818\fP -.IP \(bu 2 -Fix presence events on TCP transport by removing a client\(aqs presence when minion disconnects from publish channel correctly \fI\%#62826\fP -.IP \(bu 2 -Remove Azure deprecation messages from functions that always run w/ salt\-cloud \fI\%#62845\fP -.IP \(bu 2 -Use select instead of iterating over entrypoints as a dictionary for importlib_metadata>=5.0.0 \fI\%#62854\fP -.IP \(bu 2 -Fixed master job scheduler using when \fI\%#62858\fP -.IP \(bu 2 -LGPO: Added support for missing domain controller policies: VulnerableChannelAllowList and LdapEnforceChannelBinding \fI\%#62873\fP -.IP \(bu 2 -Fix unnecessarily complex gce metadata grains code to use googles metadata service more effectively. \fI\%#62878\fP -.IP \(bu 2 -Fixed dockermod version_info function for docker\-py 6.0.0+ \fI\%#62882\fP -.IP \(bu 2 -Moving setting the LOAD_BALANCING_POLICY_MAP dictionary into the try except block that determines if the cassandra_cql module should be made available. \fI\%#62886\fP -.IP \(bu 2 -Updating various MongoDB module functions to work with latest version of pymongo. \fI\%#62900\fP -.IP \(bu 2 -Restored channel for Syndic minions to send job returns to the Salt master. \fI\%#62933\fP -.IP \(bu 2 -removed _resolve_deps as it required a library that is not generally avalible. and switched to apt\-get for everything as that can auto resolve dependencies. \fI\%#62934\fP -.IP \(bu 2 -Updated pyzmq to version 22.0.3 on Windows builds because the old version was causing salt\-minion/salt\-call to hang \fI\%#62937\fP -.IP \(bu 2 -Allow root user to modify crontab lines for non\-root users (except AIX and Solaris). Align crontab line changes with the file ones and also with listing crontab. \fI\%#62940\fP -.IP \(bu 2 -Fix systemd_service.* functions hard code relative command name \fI\%#62942\fP -.IP \(bu 2 -Fix file.symlink backupname operation can copy remote contents to local disk \fI\%#62953\fP -.IP \(bu 2 -Issue #62968: Fix issue where cloud deployments were putting the keys in the wrong location on Windows hosts \fI\%#62968\fP -.IP \(bu 2 -Fixed gpg_passphrase issue with gpg decrypt/encrypt functions \fI\%#62977\fP -.IP \(bu 2 -Fix file.tidied FileNotFoundError \fI\%#62986\fP -.IP \(bu 2 -Fixed bug where module.wait states were detected as running legacy module.run syntax \fI\%#62988\fP -.IP \(bu 2 -Fixed issue with win_wua module where it wouldn\(aqt load if the CryptSvc was set to Manual start \fI\%#62993\fP -.IP \(bu 2 -The \fB__opts__\fP dunder dictionary is now added to the loader\(aqs \fBpack\fP if not -already present, which makes it accessible via the -\fBsalt.loader.context.NamedLoaderContext\fP class. \fI\%#63013\fP -.IP \(bu 2 -Issue #63024: Fix issue where grains and config data were being place in the wrong location on Windows hosts \fI\%#63024\fP -.IP \(bu 2 -Fix btrfs.subvolume_snapshot command failing \fI\%#63025\fP -.IP \(bu 2 -Fix file.retention_schedule always reports changes \fI\%#63033\fP -.IP \(bu 2 -Fix mongo authentication for mongo ext_pillar and mongo returner -.sp -This fix also include the ability to use the mongo connection string for mongo ext_pillar \fI\%#63058\fP -.IP \(bu 2 -Fixed x509.create_csr creates invalid CSR by default in the new cryptography x509 module. \fI\%#63103\fP -.IP \(bu 2 -TCP transport documentation now contains proper master/minion\-side filtering information \fI\%#63120\fP -.IP \(bu 2 -Fixed gpg.verify does not respect gnupghome \fI\%#63145\fP -.IP \(bu 2 -Made pillar cache pass extra minion data as well \fI\%#63208\fP -.IP \(bu 2 -Fix serious performance issues with the file.tidied module \fI\%#63231\fP -.IP \(bu 2 -Fix rpm_lowpkg version comparison logic when using rpm\-vercmp and only one version has a release number. \fI\%#63317\fP -.IP \(bu 2 -Import StrictVersion and LooseVersion from setuptools.distutils.verison or setuptools._distutils.version, if first not available \fI\%#63350\fP -.IP \(bu 2 -When the shell is passed as powershell or pwsh, only wrapper the shell in quotes if cmd.run is running on Windows. When quoted on Linux hosts, this results in an error when the keyword arguments are appended. \fI\%#63590\fP -.IP \(bu 2 -LGPO: Added support for \(dqRelax minimum password length limits\(dq \fI\%#63596\fP -.IP \(bu 2 -When a job is disabled only increase it\(aqs _next_fire_time value if the job would have run at the current time, eg. the current _next_fire_time == now. \fI\%#63699\fP -.IP \(bu 2 -Check file is not empty before attempting to read pillar disk cache file \fI\%#63729\fP -.IP \(bu 2 -fix cherrypy 400 error output to be less generic. \fI\%#63835\fP -.IP \(bu 2 -remove eval and update logging to be more informative on bad config \fI\%#63879\fP -.UNINDENT -.SS Added -.INDENT 0.0 -.IP \(bu 2 -Introduce a \fBLIB_STATE_DIR\fP syspaths variable which defaults to \fBCONFIG_DIR\fP, -but can be individually customized during installation by specifying -\fB\-\-salt\-lib\-state\-dir\fP during installation. Change the default \fBpki_dir\fP to -\fB/pki/master\fP (for the master) and \fB/pki/minion\fP -(for the minion). \fI\%#3396\fP -.IP \(bu 2 -Allow users to enable \(aqqueue=True\(aq for all state runs via config file \fI\%#31468\fP -.IP \(bu 2 -Added pillar templating to vault policies \fI\%#43287\fP -.IP \(bu 2 -Add support for NVMeF as a transport protocol for hosts in a Pure Storage FlashArray \fI\%#51088\fP -.IP \(bu 2 -A new salt\-ssh roster that generates a roster by parses a known_hosts file. \fI\%#54679\fP -.IP \(bu 2 -Added Windows Event Viewer support \fI\%#54713\fP -.IP \(bu 2 -Added the win_lgpo_reg state and execution modules which will allow registry based group policy to be set directly in the Registry.pol file \fI\%#56013\fP -.IP \(bu 2 -Added resource tagging functions to boto_dynamodb execution module \fI\%#57500\fP -.IP \(bu 2 -Added \fBopenvswitch_db\fP state module and functions \fBbridge_to_parent\fP, -\fBbridge_to_vlan\fP, \fBdb_get\fP, and \fBdb_set\fP to the \fBopenvswitch\fP execution module. -Also added optional \fBparent\fP and \fBvlan\fP parameters to the -\fBopenvswitch_bridge.present\fP state module function and the -\fBopenvswitch.bridge_create\fP execution module function. \fI\%#58986\fP -.IP \(bu 2 -State module to manage SysFS attributes \fI\%#60154\fP -.IP \(bu 2 -Added ability for \fBsalt.wait_for_event\fP to handle \fBevent_id\fPs that have a list value. \fI\%#60430\fP -.IP \(bu 2 -Added suport for Linux ppc64le core grains (cpu_model, virtual, productname, manufacturer, serialnumber) and arm core grains (serialnumber, productname) \fI\%#60518\fP -.IP \(bu 2 -Added autostart option to virt.defined and virt.running states, along with virt.update execution modules. \fI\%#60700\fP -.IP \(bu 2 -Added .0 back to our versioning scheme for future versions (e.g. 3006.0) \fI\%#60722\fP -.IP \(bu 2 -Initial work to allow parallel startup of proxy minions when used as sub proxies with Deltaproxy. \fI\%#61153\fP -.IP \(bu 2 -Added node label support for GCE \fI\%#61245\fP -.IP \(bu 2 -Support the \-\-priority flag when adding sources to Chocolatey. \fI\%#61319\fP -.IP \(bu 2 -Add namespace option to ext_pillar.http_json \fI\%#61335\fP -.IP \(bu 2 -Added a filter function to ps module to get a list of processes on a minion according to their state. \fI\%#61420\fP -.IP \(bu 2 -Add postgres.timeout option to postgres module for limiting postgres query times \fI\%#61433\fP -.IP \(bu 2 -Added new optional vault option, \fBconfig_location\fP\&. This can be either \fBmaster\fP or \fBlocal\fP and defines where vault will look for connection details, either requesting them from the master or using the local config. \fI\%#61857\fP -.IP \(bu 2 -Add ipwrap() jinja filter to wrap IPv6 addresses with brackets. \fI\%#61931\fP -.IP \(bu 2 -\(aqtcp\(aq transport is now available in ipv6\-only network \fI\%#62009\fP -.IP \(bu 2 -Add \fBdiff_attr\fP parameter to pkg.upgrade() (zypper/yum). \fI\%#62031\fP -.IP \(bu 2 -Config option pass_variable_prefix allows to distinguish variables that contain paths to pass secrets. -Config option pass_strict_fetch allows to error out when a secret cannot be fetched from pass. -Config option pass_dir allows setting the PASSWORD_STORE_DIR env for pass. -Config option pass_gnupghome allows setting the $GNUPGHOME env for pass. \fI\%#62120\fP -.IP \(bu 2 -Add file.pruned state and expanded file.rmdir exec module functionality \fI\%#62178\fP -.IP \(bu 2 -Added \(dqdig.PTR\(dq function to resolve PTR records for IPs, as well as tests and documentation \fI\%#62275\fP -.IP \(bu 2 -Added the ability to remove a KB using the DISM state/execution modules \fI\%#62366\fP -.IP \(bu 2 -Add \(dq python\(dq subcommand to allow execution or arbitrary scripts via bundled Python runtime \fI\%#62381\fP -.IP \(bu 2 -Add ability to provide conditions which convert normal state actions to no\-op when true \fI\%#62446\fP -.IP \(bu 2 -Added debug log messages displaying the command being run when installing packages on Windows \fI\%#62480\fP -.IP \(bu 2 -Add biosvendor grain \fI\%#62496\fP -.IP \(bu 2 -Add ifelse Jinja function as found in CFEngine \fI\%#62508\fP -.IP \(bu 2 -Implementation of Amazon EC2 instance detection and setting \fBvirtual_subtype\fP grain accordingly including the product if possible to identify. \fI\%#62539\fP -.IP \(bu 2 -Adds __env__substitution to ext_pillar.stack; followup of #61531, improved exception handling for stacked template (jinja) template rendering and yaml parsing in ext_pillar.stack \fI\%#62578\fP -.IP \(bu 2 -Increase file.tidied flexibility with regard to age and size \fI\%#62678\fP -.IP \(bu 2 -Added \(dqconnected_devices\(dq feature to netbox pillar module. It contains extra information about devices connected to the minion \fI\%#62761\fP -.IP \(bu 2 -Add atomic file operation for symlink changes \fI\%#62768\fP -.IP \(bu 2 -Add password/account locking/unlocking in user.present state on supported operating systems \fI\%#62856\fP -.IP \(bu 2 -Added onchange configuration for script engine \fI\%#62867\fP -.IP \(bu 2 -Added output and bare functionality to export_key gpg module function \fI\%#62978\fP -.IP \(bu 2 -Add keyvalue serializer for environment files \fI\%#62983\fP -.IP \(bu 2 -Add ability to ignore symlinks in file.tidied \fI\%#63042\fP -.IP \(bu 2 -salt\-cloud support IMDSv2 tokens when using \(aquse\-instance\-role\-credentials\(aq \fI\%#63067\fP -.IP \(bu 2 -Add ability for file.symlink to not set ownership on existing links \fI\%#63093\fP -.IP \(bu 2 -Restore the previous slack engine and deprecate it, rename replace the slack engine to slack_bolt until deprecation \fI\%#63095\fP -.IP \(bu 2 -Add functions that will return the underlying block device, mount point, and filesystem type for a given path \fI\%#63098\fP -.IP \(bu 2 -Add ethtool execution and state module functions for pause \fI\%#63128\fP -.IP \(bu 2 -Add boardname grain \fI\%#63131\fP -.IP \(bu 2 -Added management of ECDSA/EdDSA private keys with x509 modules in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. \fI\%#63248\fP -.IP \(bu 2 -Added x509 modules support for different output formats in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. \fI\%#63249\fP -.IP \(bu 2 -Added deprecation_warning test state for ensuring that deprecation warnings are correctly emitted. \fI\%#63315\fP -.IP \(bu 2 -Adds a state_events option to state.highstate, state.apply, state.sls, state.sls_id. -This allows users to enable state_events on a per use basis rather than having to -enable them globally for all state runs. \fI\%#63316\fP -.IP \(bu 2 -Allow max queue size setting for state runs to prevent performance problems from queue growth \fI\%#63356\fP -.IP \(bu 2 -Add support of exposing meta_server_grains for Azure VMs \fI\%#63606\fP -.IP \(bu 2 -Include the version of \fBrelenv\fP in the versions report. \fI\%#63827\fP -.IP \(bu 2 -Added debug log messages displaying the command being run when removing packages on Windows \fI\%#63866\fP -.UNINDENT -.SS Changelog -.SS Removed -.INDENT 0.0 -.IP \(bu 2 -Remove and deprecate the \fBorchestration\fP key from salt.runner and salt.wheel return data. To get it back, set features.enable_deprecated_orchestration_flag master configuration option to True. The flag will be completely removed in Salt 3008 Argon. \fI\%#59917\fP -.IP \(bu 2 -Removed distutils and replaced with setuptools, given distutils is deprecated and removed in Python 3.12 \fI\%#60476\fP -.IP \(bu 2 -Removed \fBruntests\fP targets from \fBnoxfile.py\fP \fI\%#62239\fP -.IP \(bu 2 -Removed the PyObjC dependency. -.sp -This addresses problems with building a one dir build for macOS. -It became problematic because depending on the macOS version, it pulls different dependencies, and we would either have to build a macos onedir for each macOS supported release, or ship a crippled onedir(because it would be tied to the macOS version where the onedir was built). -Since it\(aqs currently not being used, it\(aqs removed. \fI\%#62432\fP .IP \(bu 2 Removed \fBSixRedirectImporter\fP from Salt. Salt hasn\(aqt shipped \fBsix\fP since Salt 3004. \fI\%#63874\fP .UNINDENT @@ -477098,6 +476295,8 @@ Change startup ReqServer log messages from error to info level. \fI\%#62728\fP .IP \(bu 2 Fix kmod.* functions hard code relative command name \fI\%#62772\fP .IP \(bu 2 +Remove mako as a dependency in Windows and macOS. \fI\%#62785\fP +.IP \(bu 2 Fix mac_brew_pkg to work with null taps \fI\%#62793\fP .IP \(bu 2 Fixing a bug when listing the running schedule if \(dqschedule.enable\(dq and/or \(dqschedule.disable\(dq has been run, where the \(dqenabled\(dq items is being treated as a schedule item. \fI\%#62795\fP @@ -477167,6 +476366,8 @@ TCP transport documentation now contains proper master/minion\-side filtering in .IP \(bu 2 Fixed gpg.verify does not respect gnupghome \fI\%#63145\fP .IP \(bu 2 +User responsible for the runner is now correctly reported in the events on the event bus for the runner. \fI\%#63148\fP +.IP \(bu 2 Made pillar cache pass extra minion data as well \fI\%#63208\fP .IP \(bu 2 Fix serious performance issues with the file.tidied module \fI\%#63231\fP @@ -477175,6 +476376,9 @@ Fix rpm_lowpkg version comparison logic when using rpm\-vercmp and only one vers .IP \(bu 2 Import StrictVersion and LooseVersion from setuptools.distutils.verison or setuptools._distutils.version, if first not available \fI\%#63350\fP .IP \(bu 2 +\fBservice.status\fP on Windows does no longer throws a CommandExecutionError if +the service is not found on the system. It now returns \(dqNot Found\(dq instead. \fI\%#63577\fP +.IP \(bu 2 When the shell is passed as powershell or pwsh, only wrapper the shell in quotes if cmd.run is running on Windows. When quoted on Linux hosts, this results in an error when the keyword arguments are appended. \fI\%#63590\fP .IP \(bu 2 LGPO: Added support for \(dqRelax minimum password length limits\(dq \fI\%#63596\fP @@ -477189,6 +476393,10 @@ Check file is not empty before attempting to read pillar disk cache file \fI\%#6 .IP \(bu 2 Fixed an issue with generating fingerprints for public keys with different line endings \fI\%#63742\fP .IP \(bu 2 +Add \fBfileserver_interval\fP and \fBmaintenance_interval\fP master configuration options. These options control how often to restart the FileServerUpdate and Maintenance processes. Some file server and pillar configurations are known to cause memory leaks over time. A notable example of this are configurations that use pygit2. Salt can not guarantee dependency libraries like pygit2 won\(aqt leak memory. Restarting any long running processes that use pygit2 guarantees we can keep the master\(aqs memory usage in check. \fI\%#63747\fP +.IP \(bu 2 +mac_xattr.list and mac_xattr.read will replace undecode\-able bytes to avoid raising CommandExecutionError. \fI\%#63779\fP \fI\%#63779\fP +.IP \(bu 2 Change default GPG keyserver from \fI\%pgp.mit.edu\fP to \fI\%keys.openpgp.org\fP\&. \fI\%#63806\fP .IP \(bu 2 fix cherrypy 400 error output to be less generic. \fI\%#63835\fP @@ -477199,6 +476407,8 @@ remove eval and update logging to be more informative on bad config \fI\%#63879\ .IP \(bu 2 add linux_distribution to util to stop dep warning \fI\%#63904\fP .IP \(bu 2 +Fix valuerror when trying to close fileclient. Remove usage of \fBdel\fP and close the filclient properly. \fI\%#63920\fP +.IP \(bu 2 Handle the situation when a sub proxy minion does not init properly, eg. an exception happens, and the sub proxy object is not available. \fI\%#63923\fP .IP \(bu 2 Clarifying documentation for extension_modules configuration option. \fI\%#63929\fP @@ -477208,6 +476418,8 @@ Windows pkg module now properly handles versions containing strings \fI\%#63935\ Handle the scenario when the check_cmd requisite is used with a state function when the state has a local check_cmd function but that function isn\(aqt used by that function. \fI\%#63948\fP .IP \(bu 2 Issue #63981: Allow users to pass verify_ssl to pkg.install/pkg.installed on Windows \fI\%#63981\fP +.IP \(bu 2 +Hardened permissions on workers.ipc and master_event_pub.ipc. \fI\%#64063\fP .UNINDENT .SS Added .INDENT 0.0 @@ -477311,6 +476523,8 @@ Add ability to ignore symlinks in file.tidied \fI\%#63042\fP .IP \(bu 2 salt\-cloud support IMDSv2 tokens when using \(aquse\-instance\-role\-credentials\(aq \fI\%#63067\fP .IP \(bu 2 +Fix running fast tests twice and add git labels to suite. \fI\%#63081\fP +.IP \(bu 2 Add ability for file.symlink to not set ownership on existing links \fI\%#63093\fP .IP \(bu 2 Restore the previous slack engine and deprecate it, rename replace the slack engine to slack_bolt until deprecation \fI\%#63095\fP @@ -477338,6 +476552,10 @@ Add support of exposing meta_server_grains for Azure VMs \fI\%#63606\fP Include the version of \fBrelenv\fP in the versions report. \fI\%#63827\fP .IP \(bu 2 Added debug log messages displaying the command being run when removing packages on Windows \fI\%#63866\fP +.IP \(bu 2 +Adding the ability to exclude arguments from a state that end up passed to cmd.retcode when requisites such as onlyif or unless are used. \fI\%#63956\fP +.IP \(bu 2 +Add \-\-next\-release argument to salt/version.py, which prints the next upcoming release. \fI\%#64023\fP .UNINDENT .SS Security .INDENT 0.0 diff --git a/doc/man/spm.1 b/doc/man/spm.1 index a2f1eb819f9..b680a20ddab 100644 --- a/doc/man/spm.1 +++ b/doc/man/spm.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SPM" "1" "Generated on March 29, 2023 at 07:32:38 PM UTC." "3006.0" "Salt" +.TH "SPM" "1" "Generated on April 18, 2023 at 08:56:37 PM UTC." "3006.0" "Salt" .SH NAME spm \- Salt Package Manager Command .sp diff --git a/doc/ref/configuration/master.rst b/doc/ref/configuration/master.rst index 712a79c9c91..a6022c94ee1 100644 --- a/doc/ref/configuration/master.rst +++ b/doc/ref/configuration/master.rst @@ -371,10 +371,24 @@ Set the default timeout for the salt command and api. Default: ``60`` -The loop_interval option controls the seconds for the master's maintenance +The loop_interval option controls the seconds for the master's Maintenance process check cycle. This process updates file server backends, cleans the job cache and executes the scheduler. +``maintenance_interval`` +------------------------ + +.. versionadded:: 3006.0 + +Default: ``3600`` + +Defines how often to restart the master's Maintenance process. + +.. code-block:: yaml + + maintenance_interval: 9600 + + .. conf_master:: output ``output`` @@ -4077,6 +4091,19 @@ This option defines the update interval (in seconds) for s3fs. s3fs_update_interval: 120 +``fileserver_interval`` +*********************** + +.. versionadded:: 3006.0 + +Default: ``3600`` + +Defines how often to restart the master's FilesServerUpdate process. + +.. code-block:: yaml + + fileserver_interval: 9600 + .. _pillar-configuration-master: diff --git a/doc/ref/file_server/file_roots.rst b/doc/ref/file_server/file_roots.rst index dddd248785b..8622e4905fa 100644 --- a/doc/ref/file_server/file_roots.rst +++ b/doc/ref/file_server/file_roots.rst @@ -13,6 +13,15 @@ individual environments can span across multiple directory roots to create overlays and to allow for files to be organized in many flexible ways. +Periodic Restarts +================= + +The file server will restart periodically. The reason for this is to prevent any +files erver backends which may not properly handle resources from endlessly +consuming memory. A notable example of this is using a git backend with the +pygit2 library. How often the file server restarts can be controlled with the +``fileserver_interval`` in your master's config file. + Environments ============ diff --git a/doc/ref/states/requisites.rst b/doc/ref/states/requisites.rst index e1cc6ec6526..bcfd7d4c3ed 100644 --- a/doc/ref/states/requisites.rst +++ b/doc/ref/states/requisites.rst @@ -917,6 +917,29 @@ In the above case, ``some_check`` will be run prior to _each_ name -- once for key: not-existing get_return: res +.. versionchanged:: 3006.0 + + Since the ``unless`` requisite utilizes ``cmd.retcode``, certain parameters + included in the state are passed along to ``cmd.retcode``. On occasion this + can cause issues, particularly if the ``shell`` option in a ``user.present`` + is set to /sbin/nologin and this shell is passed along to ``cmd.retcode``. + This would cause ``cmd.retcode`` to run the command using that shell which + would fail regardless of the result of the command. + + By including ``shell`` in ``cmd_opts_exclude``, that parameter would not be + passed along to the call to ``cmd.retcode``. + + .. code-block:: yaml + + jim_nologin: + user.present: + - name: jim + - shell: /sbin/nologin + - unless: + - echo hello world + - cmd_opts_exclude: + - shell + .. _onlyif-requisite: onlyif @@ -1005,6 +1028,28 @@ if the gluster commands return a 0 ret value. key: does-exist get_return: res +.. versionchanged:: 3006.0 + + Since the ``onlyif`` requisite utilizes ``cmd.retcode``, certain parameters + included in the state are passed along to ``cmd.retcode``. On occasion this + can cause issues, particularly if the ``shell`` option in a ``user.present`` + is set to /sbin/nologin and this shell is passed along to ``cmd.retcode``. + This would cause ``cmd.retcode`` to run the command using that shell which + would fail regardless of the result of the command. + + By including ``shell`` in ``cmd_opts_exclude``, that parameter would not be + passed along to the call to ``cmd.retcode``. + + .. code-block:: yaml + + jim_nologin: + user.present: + - name: jim + - shell: /sbin/nologin + - onlyif: + - echo hello world + - cmd_opts_exclude: + - shell .. _creates-requisite: diff --git a/doc/topics/development/releasenotes.rst b/doc/topics/development/releasenotes.rst new file mode 100644 index 00000000000..ecb2a70115a --- /dev/null +++ b/doc/topics/development/releasenotes.rst @@ -0,0 +1,71 @@ +.. _releasenotes: + +============= +Release Notes +============= + +You can edit the release notes to highlight a new feature being added +to a given release. The release notes are templatized with Jinja and +are generated at release time. + + +.. _edit-release-note: + +How do I edit the release notes +------------------------------- + +To edit the release notes you need to look in doc/topics/releases/templates +for your given release and edit the template. Do not edit the release note +files in doc/topics/releases/, as this will be written over with the content +in the template file. For example, if you want to add content to the 3006.0 +release notes you would edit the doc/topics/releases/templates/3006.0.md.template +file. Do not edit the changelog portion of the template file, since that is +auto generated with the content generated for the changelog for each release. + + +How to generate the release notes +--------------------------------- + +This step is only used when we need to generate the release notes before releasing. +You should NOT need to run these steps as they are ran in the pipeline, but this +is documented so you can test your changes to the release notes template. + +To generate the release notes requires the `tools` command. The instructions below +will detail how to install and use `tools`. + + +Installing `tools` +.................. + +.. code-block: bash + + python -m pip install -r requirements/static/ci/py3.10/tools.txt + + +To view the output the release notes will produce before generating them +you can run `tools` in draft mode: + +.. code-block:: bash + + tools changelog update-release-notes --draft + +To generate the release notes just remove the `--draft` argument: + +.. code-block:: bash + + tools changelog update-release-notes + + +To specify a specific Salt version you add that version as an argument: + +.. code-block:: bash + + tools changelog update-release-notes 3006.0 + + +To only generate the template for a new release + + +.. code-block:: bash + + tools changelog update-release-notes --template-only diff --git a/doc/topics/packaging/index.rst b/doc/topics/packaging/index.rst index d9997fd50bc..b16e062fa6c 100644 --- a/doc/topics/packaging/index.rst +++ b/doc/topics/packaging/index.rst @@ -36,19 +36,19 @@ How to build onedir only .. code-block:: bash - relenv fetch --python= + relenv fetch --python= #. Create relenv environment: .. code-block:: bash - relenv create --python=3.10.10 + relenv create --python= #. Add Salt into onedir. .. code-block:: bash - path/to//bin/pip install /path/to/salt + /bin/pip install /path/to/salt How to build rpm packages @@ -57,14 +57,17 @@ How to build rpm packages .. code-block:: bash - yum -y install python3 python3-pip openssl git rpmdevtools rpmlint systemd-units libxcrypt-compat git - -#. (Optional) To build a specific Salt version, you will need to install tools and changelog dependencies: + yum -y install python3 python3-pip openssl git rpmdevtools rpmlint systemd-units libxcrypt-compat git gnupg2 jq createrepo rpm-sign rustc cargo epel-release + yum -y install patchelf + pip install awscli .. code-block:: bash pip install -r requirements/static/ci/py{python_version}/tools.txt +#. (Optional) To build a specific Salt version, you will need to install tools and changelog dependencies: + + .. code-block:: bash pip install -r requirements/static/ci/py{python_version}/changelog.txt @@ -73,19 +76,22 @@ How to build rpm packages .. code-block:: bash - cd salt + cd #. (Optional) To build a specific Salt version, run tools and set Salt version: .. code-block:: bash - tools changelog update-rpm + tools changelog update-rpm -#. Run rpmbuild in the Salt repo: +#. Build the RPM: + + Only the arch argument is required, the rest are optional. .. code-block:: bash - rpmbuild -bb --define="_salt_src $(pwd)" $(pwd)/pkg/rpm/salt.spec + tools pkg build rpm --relenv-version --python-version --arch + How to build deb packages @@ -95,14 +101,14 @@ How to build deb packages .. code-block:: bash - apt install -y bash-completion build-essential debhelper devscripts git patchelf python3 python3-pip python3-venv rustc - -#. (Optional) To build a specific Salt version, you will need to install tools and changelog dependencies: + apt install -y apt-utils gnupg jq awscli python3 python3-venv python3-pip build-essential devscripts debhelper bash-completion git patchelf rustc .. code-block:: bash pip install -r requirements/static/ci/py{python_version}/tools.txt +#. (Optional) To build a specific Salt version, you will need to install changelog dependencies: + .. code-block:: bash pip install -r requirements/static/ci/py{python_version}/changelog.txt @@ -111,21 +117,22 @@ How to build deb packages .. code-block:: bash - cd salt + cd #. (Optional) To build a specific Salt version, run tools and set Salt version: .. code-block:: bash - tools changelog update-deb + tools changelog update-deb -#. Add a symlink and run debuild in the Salt repo: +#. Build the deb package: + + Only the arch argument is required, the rest are optional. .. code-block:: bash - ln -sf pkg/debian/ . - debuild -uc -us + tools pkg build deb --relenv-version --python-version --arch How to access python binary diff --git a/doc/topics/releases/3006.0.md b/doc/topics/releases/3006.0.md index 8f44d28cf5f..1e7cf924d6a 100644 --- a/doc/topics/releases/3006.0.md +++ b/doc/topics/releases/3006.0.md @@ -1,5 +1,16 @@ (release-3006.0)= -# Salt 3006.0 release notes - Codename Sulfur +# Salt 3006.0 release notes + + + + + ## Onedir packaging @@ -9,6 +20,37 @@ be provided for supported operating systems. See [Upgrade to onedir](https://doc in the [Salt Install Guide](https://docs.saltproject.io/salt/install-guide/en/latest) for information about upgrading from the classic packages to the onedir packages. +## Linux Packaging Salt Master Salt User and Group + +The linux Salt Master packages will now add a Salt user and group +by default. The packages will add the ``user: salt`` config option +to the Salt Master config. The Salt Master service will run as this +user. If you do not want to run the Salt Master as a different user +you can remove the ``user: salt`` config from /etc/salt/master or change +the user to the desired user to run the Salt Master. + +Since the Salt Master is running as a different user, you will need +to ensure you set the owner and group to ``salt`` for your file_roots +and pillar_roots(commonly `/srv/salt` and `/srv/pillar`). + +If you are running a Salt Master, Salt-Api and a Salt Minion on the same +host using the new ``salt`` user and you install a pip dependency into +the onedir environment using ``salt-pip`` or the ``pip`` module, you +need to to chown the directory ``/opt/saltstack/salt/lib//site-packages/`` +with the ``salt`` user and group. + + +## Caveat of salt-pip + +Salt ships with a wrapper script around pip called ``salt-pip``. Users should +use ``salt-pip`` to install any python packages needed to extend Salt. +``salt-pip`` installs python packages into an `extras-3.10` directory located +in the root of the ondir directory, by setting the ``--target`` argument for +pip. This ensures those packages remain installed when upgrading Salt. There is +a known bug in pip when using `--target` where scripts and other non-python +assets may not be cleaned up properly when un-installing. The Salt team is +working to resolve this bug in the up-stream pip project. + ## Dropping support for Python 3.5 and 3.6 @@ -22,7 +64,7 @@ for more information. All netapi clients, which provide the functionality to ``salt-api``, will now be disabled by default as a security precaution. If you use ``salt-api``, you -must add the new ``netapi_enable_clients`` option to your salt master config. +must add the new ``netapi_enable_clients`` option to your salt master config. This is a breaking change and the ``salt-api`` will not function without this new configuration option. See [Enabling netapi client interfaces](https://docs.saltproject.io/en/3006.0/topics/netapi/netapi-enable-clients.html#netapi-enable-clients) for more information. @@ -34,7 +76,7 @@ The migration path from the classic, non-onedir packages to the onedir packages will include: * Repo File: You need to update your repo file to point to the new repo paths - for your platform. After the repo file is updated, upgrade your Salt packages. + for your platform. After the repo file is updated, upgrade your Salt packages. * Pip packages: You need to ensure any 3rd party pip packages are installed in the correct onedir path. This can be accomplished in two ways: @@ -42,7 +84,7 @@ will include: * Using the ``pip.installed`` Salt state. To install python packages into the system python environment, user's must now -provide the ``pip_bin`` or ``bin_env`` to the pip state module. +provide the ``pip_bin`` or ``bin_env`` to the pip state module. For example: @@ -55,659 +97,10 @@ lib-bar: - bin_env: /usr/bin/python3 ``` -## Changelog - -### Removed - -- Remove and deprecate the __orchestration__ key from salt.runner and salt.wheel return data. To get it back, set features.enable_deprecated_orchestration_flag master configuration option to True. The flag will be completely removed in Salt 3008 Argon. [#59917](https://github.com/saltstack/salt/issues/59917) -- Removed distutils and replaced with setuptools, given distutils is deprecated and removed in Python 3.12 [#60476](https://github.com/saltstack/salt/issues/60476) -- Removed ``runtests`` targets from ``noxfile.py`` [#62239](https://github.com/saltstack/salt/issues/62239) -- Removed the PyObjC dependency. - - This addresses problems with building a one dir build for macOS. - It became problematic because depending on the macOS version, it pulls different dependencies, and we would either have to build a macos onedir for each macOS supported release, or ship a crippled onedir(because it would be tied to the macOS version where the onedir was built). - Since it's currently not being used, it's removed. [#62432](https://github.com/saltstack/salt/issues/62432) - - -### Deprecated - -- renamed `keep_jobs`, specifying job cache TTL in hours, to `keep_jobs_seconds`, specifying TTL in seconds. - `keep_jobs` will be removed in the Argon release [#55295](https://github.com/saltstack/salt/issues/55295) -- Removing all references to napalm-base which is no longer supported. [#61542](https://github.com/saltstack/salt/issues/61542) -- The 'ip_bracket' function has been moved from salt/utils/zeromq.py in salt/utils/network.py [#62009](https://github.com/saltstack/salt/issues/62009) -- The `expand_repo_def` function in `salt.modules.aptpkg` is now deprecated. It's only used in `salt.states.pkgrepo` and it has no use of being exposed to the CLI. [#62485](https://github.com/saltstack/salt/issues/62485) -- Deprecated defunct Django returner [#62644](https://github.com/saltstack/salt/issues/62644) -- Deprecate core ESXi and associated states and modules, vcenter and vsphere support in favor of Salt VMware Extensions [#62754](https://github.com/saltstack/salt/issues/62754) -- Removing manufacture grain which has been deprecated. [#62914](https://github.com/saltstack/salt/issues/62914) -- Removing deprecated utils/boto3_elasticsearch.py [#62915](https://github.com/saltstack/salt/issues/62915) -- Removing support for the now deprecated _ext_nodes from salt/master.py. [#62917](https://github.com/saltstack/salt/issues/62917) -- Deprecating the Salt Slack engine in favor of the Salt Slack Bolt Engine. [#63095](https://github.com/saltstack/salt/issues/63095) -- `salt.utils.version.StrictVersion` is now deprecated and it's use should be replaced with `salt.utils.version.Version`. [#63383](https://github.com/saltstack/salt/issues/63383) - - -### Changed - -- More intelligent diffing in changes of file.serialize state. [#48609](https://github.com/saltstack/salt/issues/48609) -- Move deprecation of the neutron module to Argon. Please migrate to the neutronng module instead. [#49430](https://github.com/saltstack/salt/issues/49430) -- ``umask`` is now a global state argument, instead of only applying to ``cmd`` - states. [#57803](https://github.com/saltstack/salt/issues/57803) -- Update pillar.obfuscate to accept kwargs in addition to args. This is useful when passing in keyword arguments like saltenv that are then passed along to pillar.items. [#58971](https://github.com/saltstack/salt/issues/58971) -- Improve support for listing macOS brew casks [#59439](https://github.com/saltstack/salt/issues/59439) -- Add missing MariaDB Grants to mysql module. - MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. - Also improved exception handling in `grant_add` which did not log the original error message and replaced it with a generic error. [#61409](https://github.com/saltstack/salt/issues/61409) -- Use VENV_PIP_TARGET environment variable as a default target for pip if present. [#62089](https://github.com/saltstack/salt/issues/62089) -- Disabled FQDNs grains on macOS by default [#62168](https://github.com/saltstack/salt/issues/62168) -- Replaced pyroute2.IPDB with pyroute2.NDB, as the former is deprecated [#62218](https://github.com/saltstack/salt/issues/62218) -- Enhance capture of error messages for Zypper calls in zypperpkg module. [#62346](https://github.com/saltstack/salt/issues/62346) -- Removed GPG_1_3_1 check [#62895](https://github.com/saltstack/salt/issues/62895) -- Requisite state chunks now all consistently contain `__id__`, `__sls__` and `name`. [#63012](https://github.com/saltstack/salt/issues/63012) -- netapi_enable_clients option to allow enabling/disabling of clients in salt-api. - By default all clients will now be disabled. Users of salt-api will need - to update their master config to enable the clients that they use. Not adding - the netapi_enable_clients option with required clients to the master config will - disable salt-api. [#63050](https://github.com/saltstack/salt/issues/63050) -- Stop relying on `salt/_version.py` to write Salt's version. Instead use `salt/_version.txt` which only contains the version string. [#63383](https://github.com/saltstack/salt/issues/63383) -- Set enable_fqdns_grains to be False by default. [#63595](https://github.com/saltstack/salt/issues/63595) -- Changelog snippet files must now have a `.md` file extension to be more explicit on what type of rendering is done when they are included in the main `CHANGELOG.md` file. [#63710](https://github.com/saltstack/salt/issues/63710) - - -### Fixed - -- Add kwargs to handle extra parameters for http.query [#36138](https://github.com/saltstack/salt/issues/36138) -- Fix mounted bind mounts getting active mount options added [#39292](https://github.com/saltstack/salt/issues/39292) -- Fix `sysctl.present` converts spaces to tabs. [#40054](https://github.com/saltstack/salt/issues/40054) -- Fixes state pkg.purged to purge removed packages on Debian family systems [#42306](https://github.com/saltstack/salt/issues/42306) -- Fix fun_args missing from syndic returns [#45823](https://github.com/saltstack/salt/issues/45823) -- Fix mount.mounted with 'mount: False' reports unmounted file system as unchanged when running with test=True [#47201](https://github.com/saltstack/salt/issues/47201) -- Issue #49310: Allow users to touch a file with Unix date of birth [#49310](https://github.com/saltstack/salt/issues/49310) -- Do not raise an exception in pkg.info_installed on nonzero return code [#51620](https://github.com/saltstack/salt/issues/51620) -- Passes the value of the force parameter from file.copy to its call to file.remove so that files with the read-only attribute are handled. [#51739](https://github.com/saltstack/salt/issues/51739) -- Fixed x509.certificate_managed creates new certificate every run in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#52167](https://github.com/saltstack/salt/issues/52167) -- Don't check for cached pillar errors on state.apply [#52354](https://github.com/saltstack/salt/issues/52354), [#57180](https://github.com/saltstack/salt/issues/57180), [#59339](https://github.com/saltstack/salt/issues/59339) -- Swapping out args and kwargs for arg and kwarg respectively in the Slack engine when the command passed is a runner. [#52400](https://github.com/saltstack/salt/issues/52400) -- Ensure when we're adding chunks to the rules when running aggregation with the iptables state module we use a copy of the chunk otherwise we end up with a recursive mess. [#53353](https://github.com/saltstack/salt/issues/53353) -- When user_create or user_remove fail, return False instead of returning the error. [#53377](https://github.com/saltstack/salt/issues/53377) -- Include sync_roster when sync_all is called. [#53914](https://github.com/saltstack/salt/issues/53914) -- Avoid warning noise in lograte.get [#53988](https://github.com/saltstack/salt/issues/53988) -- Fixed listing revoked keys with gpg.list_keys [#54347](https://github.com/saltstack/salt/issues/54347) -- Fix mount.mounted does not handle blanks properly [#54508](https://github.com/saltstack/salt/issues/54508) -- Fixed grain num_cpus get wrong CPUs count in case of inconsistent CPU numbering. [#54682](https://github.com/saltstack/salt/issues/54682) -- Fix spelling error for python_shell argument in dpkg_lower module [#54907](https://github.com/saltstack/salt/issues/54907) -- Cleaned up bytes response data before sending to non-bytes compatible returners (postgres, mysql) [#55226](https://github.com/saltstack/salt/issues/55226) -- Fixed malformed state return when testing file.managed with unavailable source file [#55269](https://github.com/saltstack/salt/issues/55269) -- Included stdout in error message for Zypper calls in zypperpkg module. [#56016](https://github.com/saltstack/salt/issues/56016) -- Fixed pillar.filter_by with salt-ssh [#56093](https://github.com/saltstack/salt/issues/56093) -- Fix boto_route53 issue with (multiple) VPCs. [#57139](https://github.com/saltstack/salt/issues/57139) -- Remove log from mine runner which was not used. [#57463](https://github.com/saltstack/salt/issues/57463) -- Fixed x509.read_certificate error when reading a Microsoft CA issued certificate in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#57535](https://github.com/saltstack/salt/issues/57535) -- Updating Slack engine to use slack_bolt library. [#57842](https://github.com/saltstack/salt/issues/57842) -- Fixed warning about replace=True with x509.certificate_managed in the new cryptography x509 module. [#58165](https://github.com/saltstack/salt/issues/58165) -- Fix salt.modules.pip:is_installed doesn't handle locally installed packages [#58202](https://github.com/saltstack/salt/issues/58202) -- Add missing MariaDB Grants to mysql module. MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. [#58297](https://github.com/saltstack/salt/issues/58297) -- linux_shadow: Fix cases where malformed shadow entries cause `user.present` - states to fail. [#58423](https://github.com/saltstack/salt/issues/58423) -- Fixed salt.utils.compat.cmp to work with dictionaries [#58729](https://github.com/saltstack/salt/issues/58729) -- Fixed formatting for terse output mode [#58953](https://github.com/saltstack/salt/issues/58953) -- Fixed RecursiveDictDiffer with added nested dicts [#59017](https://github.com/saltstack/salt/issues/59017) -- Fixed x509.certificate_managed has DoS effect on master in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#59169](https://github.com/saltstack/salt/issues/59169) -- Fixed saltnado websockets disconnecting immediately [#59183](https://github.com/saltstack/salt/issues/59183) -- Fixed x509.certificate_managed rolls certificates every now and then in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#59315](https://github.com/saltstack/salt/issues/59315) -- Fix postgres_privileges.present not idempotent for functions [#59585](https://github.com/saltstack/salt/issues/59585) -- Fixed influxdb_continuous_query.present state to provide the client args to the underlying module on create. [#59766](https://github.com/saltstack/salt/issues/59766) -- Warn when using insecure (http:// based) key_urls for apt-based systems in pkgrepo.managed, and add a kwarg that determines the validity of such a url. [#59786](https://github.com/saltstack/salt/issues/59786) -- add load balancing policy default option and ensure the module can be executed with arguments from CLI [#59909](https://github.com/saltstack/salt/issues/59909) -- Fix salt-ssh when using imports with extra-filerefs. [#60003](https://github.com/saltstack/salt/issues/60003) -- Fixed cache directory corruption startup error [#60170](https://github.com/saltstack/salt/issues/60170) -- Update docs remove dry_run in docstring of file.blockreplace state. [#60227](https://github.com/saltstack/salt/issues/60227) -- Adds Parrot to OS_Family_Map in grains. [#60249](https://github.com/saltstack/salt/issues/60249) -- Fixed stdout and stderr being empty sometimes when use_vt=True for the cmd.run[*] functions [#60365](https://github.com/saltstack/salt/issues/60365) -- Use return code in iptables --check to verify rule exists. [#60467](https://github.com/saltstack/salt/issues/60467) -- Fix regression pip.installed does not pass env_vars when calling pip.list [#60557](https://github.com/saltstack/salt/issues/60557) -- Fix xfs module when additional output included in mkfs.xfs command. [#60853](https://github.com/saltstack/salt/issues/60853) -- Fixed parsing new format of terraform states in roster.terraform [#60915](https://github.com/saltstack/salt/issues/60915) -- Fixed recognizing installed ARMv7 rpm packages in compatible architectures. [#60994](https://github.com/saltstack/salt/issues/60994) -- Fixing changes dict in pkg state to be consistent when installing and test=True. [#60995](https://github.com/saltstack/salt/issues/60995) -- Fix cron.present duplicating entries when changing timespec to special. [#60997](https://github.com/saltstack/salt/issues/60997) -- Made salt-ssh respect --wipe again [#61083](https://github.com/saltstack/salt/issues/61083) -- state.orchestrate_single only passes a pillar if it is set to the state - function. This allows it to be used with state functions that don't accept a - pillar keyword argument. [#61092](https://github.com/saltstack/salt/issues/61092) -- Fix ipset state when the comment kwarg is set. [#61122](https://github.com/saltstack/salt/issues/61122) -- Fix issue with archive.unzip where the password was not being encoded for the extract function [#61422](https://github.com/saltstack/salt/issues/61422) -- Some Linux distributions (like AlmaLinux, Astra Linux, Debian, Mendel, Linux - Mint, Pop!_OS, Rocky Linux) report different `oscodename`, `osfullname`, - `osfinger` grains if lsb-release is installed or not. They have been changed to - only derive these OS grains from `/etc/os-release`. [#61618](https://github.com/saltstack/salt/issues/61618) -- Pop!_OS uses the full version (YY.MM) in the osfinger grain now, not just the year. This allows differentiating for example between 20.04 and 20.10. [#61619](https://github.com/saltstack/salt/issues/61619) -- Fix ssh config roster to correctly parse the ssh config files that contain spaces. [#61650](https://github.com/saltstack/salt/issues/61650) -- Fix SoftLayer configuration not raising an exception when a domain is missing [#61727](https://github.com/saltstack/salt/issues/61727) -- Allow the minion to start or salt-call to run even if the user doesn't have permissions to read the root_dir value from the registry [#61789](https://github.com/saltstack/salt/issues/61789) -- Need to move the creation of the proxy object for the ProxyMinion further down in the initialization for sub proxies to ensure that all modules, especially any custom proxy modules, are available before attempting to run the init function. [#61805](https://github.com/saltstack/salt/issues/61805) -- Fixed malformed state return when merge-serializing to an improperly formatted file [#61814](https://github.com/saltstack/salt/issues/61814) -- Made cmdmod._run[_all]_quiet work during minion startup on MacOS with runas specified (which fixed mac_service) [#61816](https://github.com/saltstack/salt/issues/61816) -- When deleting the vault cache, also delete from the session cache [#61821](https://github.com/saltstack/salt/issues/61821) -- Ignore errors on reading license info with dpkg_lowpkg to prevent tracebacks on getting package information. [#61827](https://github.com/saltstack/salt/issues/61827) -- win_lgpo: Display conflicting policy names when more than one policy is found [#61859](https://github.com/saltstack/salt/issues/61859) -- win_lgpo: Fixed intermittent KeyError when getting policy setting using lgpo.get_policy [#61860](https://github.com/saltstack/salt/issues/61860) -- Fixed listing minions on OpenBSD [#61966](https://github.com/saltstack/salt/issues/61966) -- Make Salt to return an error on "pkg" modules and states when targeting duplicated package names [#62019](https://github.com/saltstack/salt/issues/62019) -- Fix return of REST-returned permissions when auth_list is set [#62022](https://github.com/saltstack/salt/issues/62022) -- Normalize package names once on using pkg.installed/removed with yum to make it possible to install packages with the name containing a part similar to a name of architecture. [#62029](https://github.com/saltstack/salt/issues/62029) -- Fix inconsitency regarding name and pkgs parameters between zypperpkg.upgrade() and yumpkg.upgrade() [#62030](https://github.com/saltstack/salt/issues/62030) -- Fix attr=all handling in pkg.list_pkgs() (yum/zypper). [#62032](https://github.com/saltstack/salt/issues/62032) -- Fixed the humanname being ignored in pkgrepo.managed on openSUSE Leap [#62053](https://github.com/saltstack/salt/issues/62053) -- Fixed issue with some LGPO policies having whitespace at the beginning or end of the element alias [#62058](https://github.com/saltstack/salt/issues/62058) -- Fix ordering of args to libcloud_storage.download_object module [#62074](https://github.com/saltstack/salt/issues/62074) -- Ignore extend declarations in sls files that are excluded. [#62082](https://github.com/saltstack/salt/issues/62082) -- Remove leftover usage of impacket [#62101](https://github.com/saltstack/salt/issues/62101) -- Pass executable path from _get_path_exec() is used when calling the program. - The $HOME env is no longer modified globally. - Only trailing newlines are stripped from the fetched secret. - Pass process arguments are handled in a secure way. [#62120](https://github.com/saltstack/salt/issues/62120) -- Ignore some command return codes in openbsdrcctl_service to prevent spurious errors [#62131](https://github.com/saltstack/salt/issues/62131) -- Fixed extra period in filename output in tls module. Instead of "server.crt." it will now be "server.crt". [#62139](https://github.com/saltstack/salt/issues/62139) -- Make sure lingering PAexec-*.exe files in the Windows directory are cleaned up [#62152](https://github.com/saltstack/salt/issues/62152) -- Restored Salt's DeprecationWarnings [#62185](https://github.com/saltstack/salt/issues/62185) -- Fixed issue with forward slashes on Windows with file.recurse and clean=True [#62197](https://github.com/saltstack/salt/issues/62197) -- Recognize OSMC as Debian-based [#62198](https://github.com/saltstack/salt/issues/62198) -- Fixed Zypper module failing on RPM lock file being temporarily unavailable. [#62204](https://github.com/saltstack/salt/issues/62204) -- Improved error handling and diagnostics in the proxmox salt-cloud driver [#62211](https://github.com/saltstack/salt/issues/62211) -- Added EndeavourOS to the Arch os_family. [#62220](https://github.com/saltstack/salt/issues/62220) -- Fix salt-ssh not detecting `platform-python` as a valid interpreter on EL8 [#62235](https://github.com/saltstack/salt/issues/62235) -- Fix pkg.version_cmp on openEuler and a few other os flavors. [#62248](https://github.com/saltstack/salt/issues/62248) -- Fix localhost detection in glusterfs.peers [#62273](https://github.com/saltstack/salt/issues/62273) -- Fix Salt Package Manager (SPM) exception when calling spm create_repo . [#62281](https://github.com/saltstack/salt/issues/62281) -- Fix matcher slowness due to loader invocation [#62283](https://github.com/saltstack/salt/issues/62283) -- Fixes the Puppet module for non-aio Puppet packages for example running the Puppet module on FreeBSD. [#62323](https://github.com/saltstack/salt/issues/62323) -- Issue 62334: Displays a debug log message instead of an error log message when the publisher fails to connect [#62334](https://github.com/saltstack/salt/issues/62334) -- Fix pyobjects renderer access to opts and sls [#62336](https://github.com/saltstack/salt/issues/62336) -- Fix use of random shuffle and sample functions as Jinja filters [#62372](https://github.com/saltstack/salt/issues/62372) -- Fix groups with duplicate GIDs are not returned by get_group_list [#62377](https://github.com/saltstack/salt/issues/62377) -- Fix the "zpool.present" state when enabling zpool features that are already active. [#62390](https://github.com/saltstack/salt/issues/62390) -- Fix ability to execute remote file client methods in saltcheck [#62398](https://github.com/saltstack/salt/issues/62398) -- Update all platforms to use pycparser 2.21 or greater for Py 3.9 or higher, fixes fips fault with openssl v3.x [#62400](https://github.com/saltstack/salt/issues/62400) -- Due to changes in the Netmiko library for the exception paths, need to check the version of Netmiko python library and then import the exceptions from different locations depending on the result. [#62405](https://github.com/saltstack/salt/issues/62405) -- When using preq on a state, then prereq state will first be run with test=True to determine if there are changes. When there are changes, the state with the prereq option will be run prior to the prereq state. If this state fails then the prereq state will not run and the state output uses the test=True run. However, the proposed changes are included for the prereq state are included from the test=True run. We should pull those out as there weren't actually changes since the prereq state did not run. [#62408](https://github.com/saltstack/salt/issues/62408) -- Added directory mode for file.copy with makedirs [#62426](https://github.com/saltstack/salt/issues/62426) -- Provide better error handling in the various napalm proxy minion functions when the device is not accessible. [#62435](https://github.com/saltstack/salt/issues/62435) -- When handling aggregation, change the order to ensure that the requisites are aggregated first and then the state functions are aggregated. Caching whether aggregate functions are available for particular states so we don't need to attempt to load them everytime. [#62439](https://github.com/saltstack/salt/issues/62439) -- The patch allows to boostrap kubernetes clusters in the version above 1.13 via salt module [#62451](https://github.com/saltstack/salt/issues/62451) -- sysctl.persist now updates the in-memory value on FreeBSD even if the on-disk value was already correct. [#62461](https://github.com/saltstack/salt/issues/62461) -- Fixed parsing CDROM apt sources [#62474](https://github.com/saltstack/salt/issues/62474) -- Update sanitizing masking for Salt SSH to include additional password like strings. [#62483](https://github.com/saltstack/salt/issues/62483) -- Fix user/group checking on file state functions in the test mode. [#62499](https://github.com/saltstack/salt/issues/62499) -- Fix user.present to allow removing groups using optional_groups parameter and enforcing idempotent group membership. [#62502](https://github.com/saltstack/salt/issues/62502) -- Fix possible tracebacks if there is a package with '------' or '======' in the description is installed on the Debian based minion. [#62519](https://github.com/saltstack/salt/issues/62519) -- Fixed the omitted "pool" parameter when cloning a VM with the proxmox salt-cloud driver [#62521](https://github.com/saltstack/salt/issues/62521) -- Fix rendering of pyobjects states in saltcheck [#62523](https://github.com/saltstack/salt/issues/62523) -- Fixes pillar where a corrupted CacheDisk file forces the pillar to be rebuilt [#62527](https://github.com/saltstack/salt/issues/62527) -- Use str() method instead of repo_line for when python3-apt is installed or not in aptpkg.py. [#62546](https://github.com/saltstack/salt/issues/62546) -- Remove the connection_timeout from netmiko_connection_args before netmiko_connection_args is added to __context__["netmiko_device"]["args"] which is passed along to the Netmiko library. [#62547](https://github.com/saltstack/salt/issues/62547) -- Fix order specific mount.mounted options for persist [#62556](https://github.com/saltstack/salt/issues/62556) -- Fixed salt-cloud cloning a proxmox VM with a specified new vmid. [#62558](https://github.com/saltstack/salt/issues/62558) -- Fix runas with cmd module when using the onedir bundled packages [#62565](https://github.com/saltstack/salt/issues/62565) -- Update setproctitle version for all platforms [#62576](https://github.com/saltstack/salt/issues/62576) -- Fixed missing parameters when cloning a VM with the proxmox salt-cloud driver [#62580](https://github.com/saltstack/salt/issues/62580) -- Handle PermissionError when importing crypt when FIPS is enabled. [#62587](https://github.com/saltstack/salt/issues/62587) -- Correctly reraise exceptions in states.http [#62595](https://github.com/saltstack/salt/issues/62595) -- Fixed syndic eauth. Now jobs will be published when a valid eauth user is targeting allowed minions/functions. [#62618](https://github.com/saltstack/salt/issues/62618) -- updated rest_cherry/app to properly detect arg sent as a string as curl will do when only one arg is supplied. [#62624](https://github.com/saltstack/salt/issues/62624) -- Prevent possible tracebacks in core grains module by ignoring non utf8 characters in /proc/1/environ, /proc/1/cmdline, /proc/cmdline [#62633](https://github.com/saltstack/salt/issues/62633) -- Fixed vault ext pillar return data for KV v2 [#62651](https://github.com/saltstack/salt/issues/62651) -- Fix saltcheck _get_top_states doesn't pass saltenv to state.show_top [#62654](https://github.com/saltstack/salt/issues/62654) -- Fix groupadd.* functions hard code relative command name [#62657](https://github.com/saltstack/salt/issues/62657) -- Fixed pdbedit.create trying to use a bytes-like hash as string. [#62670](https://github.com/saltstack/salt/issues/62670) -- Fix depenency on legacy boto module in boto3 modules [#62672](https://github.com/saltstack/salt/issues/62672) -- Modified "_get_flags" function so that it returns regex flags instead of integers [#62676](https://github.com/saltstack/salt/issues/62676) -- Change startup ReqServer log messages from error to info level. [#62728](https://github.com/saltstack/salt/issues/62728) -- Fix kmod.* functions hard code relative command name [#62772](https://github.com/saltstack/salt/issues/62772) -- Fix mac_brew_pkg to work with null taps [#62793](https://github.com/saltstack/salt/issues/62793) -- Fixing a bug when listing the running schedule if "schedule.enable" and/or "schedule.disable" has been run, where the "enabled" items is being treated as a schedule item. [#62795](https://github.com/saltstack/salt/issues/62795) -- Prevent annoying RuntimeWarning message about line buffering (buffering=1) not being supported in binary mode [#62817](https://github.com/saltstack/salt/issues/62817) -- Include UID and GID checks in modules.file.check_perms as well as comparing - ownership by username and group name. [#62818](https://github.com/saltstack/salt/issues/62818) -- Fix presence events on TCP transport by removing a client's presence when minion disconnects from publish channel correctly [#62826](https://github.com/saltstack/salt/issues/62826) -- Remove Azure deprecation messages from functions that always run w/ salt-cloud [#62845](https://github.com/saltstack/salt/issues/62845) -- Use select instead of iterating over entrypoints as a dictionary for importlib_metadata>=5.0.0 [#62854](https://github.com/saltstack/salt/issues/62854) -- Fixed master job scheduler using when [#62858](https://github.com/saltstack/salt/issues/62858) -- LGPO: Added support for missing domain controller policies: VulnerableChannelAllowList and LdapEnforceChannelBinding [#62873](https://github.com/saltstack/salt/issues/62873) -- Fix unnecessarily complex gce metadata grains code to use googles metadata service more effectively. [#62878](https://github.com/saltstack/salt/issues/62878) -- Fixed dockermod version_info function for docker-py 6.0.0+ [#62882](https://github.com/saltstack/salt/issues/62882) -- Moving setting the LOAD_BALANCING_POLICY_MAP dictionary into the try except block that determines if the cassandra_cql module should be made available. [#62886](https://github.com/saltstack/salt/issues/62886) -- Updating various MongoDB module functions to work with latest version of pymongo. [#62900](https://github.com/saltstack/salt/issues/62900) -- Restored channel for Syndic minions to send job returns to the Salt master. [#62933](https://github.com/saltstack/salt/issues/62933) -- removed _resolve_deps as it required a library that is not generally avalible. and switched to apt-get for everything as that can auto resolve dependencies. [#62934](https://github.com/saltstack/salt/issues/62934) -- Updated pyzmq to version 22.0.3 on Windows builds because the old version was causing salt-minion/salt-call to hang [#62937](https://github.com/saltstack/salt/issues/62937) -- Allow root user to modify crontab lines for non-root users (except AIX and Solaris). Align crontab line changes with the file ones and also with listing crontab. [#62940](https://github.com/saltstack/salt/issues/62940) -- Fix systemd_service.* functions hard code relative command name [#62942](https://github.com/saltstack/salt/issues/62942) -- Fix file.symlink backupname operation can copy remote contents to local disk [#62953](https://github.com/saltstack/salt/issues/62953) -- Issue #62968: Fix issue where cloud deployments were putting the keys in the wrong location on Windows hosts [#62968](https://github.com/saltstack/salt/issues/62968) -- Fixed gpg_passphrase issue with gpg decrypt/encrypt functions [#62977](https://github.com/saltstack/salt/issues/62977) -- Fix file.tidied FileNotFoundError [#62986](https://github.com/saltstack/salt/issues/62986) -- Fixed bug where module.wait states were detected as running legacy module.run syntax [#62988](https://github.com/saltstack/salt/issues/62988) -- Fixed issue with win_wua module where it wouldn't load if the CryptSvc was set to Manual start [#62993](https://github.com/saltstack/salt/issues/62993) -- The `__opts__` dunder dictionary is now added to the loader's `pack` if not - already present, which makes it accessible via the - `salt.loader.context.NamedLoaderContext` class. [#63013](https://github.com/saltstack/salt/issues/63013) -- Issue #63024: Fix issue where grains and config data were being place in the wrong location on Windows hosts [#63024](https://github.com/saltstack/salt/issues/63024) -- Fix btrfs.subvolume_snapshot command failing [#63025](https://github.com/saltstack/salt/issues/63025) -- Fix file.retention_schedule always reports changes [#63033](https://github.com/saltstack/salt/issues/63033) -- Fix mongo authentication for mongo ext_pillar and mongo returner - - This fix also include the ability to use the mongo connection string for mongo ext_pillar [#63058](https://github.com/saltstack/salt/issues/63058) -- Fixed x509.create_csr creates invalid CSR by default in the new cryptography x509 module. [#63103](https://github.com/saltstack/salt/issues/63103) -- TCP transport documentation now contains proper master/minion-side filtering information [#63120](https://github.com/saltstack/salt/issues/63120) -- Fixed gpg.verify does not respect gnupghome [#63145](https://github.com/saltstack/salt/issues/63145) -- Made pillar cache pass extra minion data as well [#63208](https://github.com/saltstack/salt/issues/63208) -- Fix serious performance issues with the file.tidied module [#63231](https://github.com/saltstack/salt/issues/63231) -- Import StrictVersion and LooseVersion from setuptools.distutils.verison or setuptools._distutils.version, if first not available [#63350](https://github.com/saltstack/salt/issues/63350) -- When the shell is passed as powershell or pwsh, only wrapper the shell in quotes if cmd.run is running on Windows. When quoted on Linux hosts, this results in an error when the keyword arguments are appended. [#63590](https://github.com/saltstack/salt/issues/63590) -- LGPO: Added support for "Relax minimum password length limits" [#63596](https://github.com/saltstack/salt/issues/63596) -- Check file is not empty before attempting to read pillar disk cache file [#63729](https://github.com/saltstack/salt/issues/63729) - - -### Added - -- Introduce a `LIB_STATE_DIR` syspaths variable which defaults to `CONFIG_DIR`, - but can be individually customized during installation by specifying - `--salt-lib-state-dir` during installation. Change the default `pki_dir` to - `/pki/master` (for the master) and `/pki/minion` - (for the minion). [#3396](https://github.com/saltstack/salt/issues/3396) -- Allow users to enable 'queue=True' for all state runs via config file [#31468](https://github.com/saltstack/salt/issues/31468) -- Added pillar templating to vault policies [#43287](https://github.com/saltstack/salt/issues/43287) -- Add support for NVMeF as a transport protocol for hosts in a Pure Storage FlashArray [#51088](https://github.com/saltstack/salt/issues/51088) -- A new salt-ssh roster that generates a roster by parses a known_hosts file. [#54679](https://github.com/saltstack/salt/issues/54679) -- Added Windows Event Viewer support [#54713](https://github.com/saltstack/salt/issues/54713) -- Added the win_lgpo_reg state and execution modules which will allow registry based group policy to be set directly in the Registry.pol file [#56013](https://github.com/saltstack/salt/issues/56013) -- Added resource tagging functions to boto_dynamodb execution module [#57500](https://github.com/saltstack/salt/issues/57500) -- Added `openvswitch_db` state module and functions `bridge_to_parent`, - `bridge_to_vlan`, `db_get`, and `db_set` to the `openvswitch` execution module. - Also added optional `parent` and `vlan` parameters to the - `openvswitch_bridge.present` state module function and the - `openvswitch.bridge_create` execution module function. [#58986](https://github.com/saltstack/salt/issues/58986) -- State module to manage SysFS attributes [#60154](https://github.com/saltstack/salt/issues/60154) -- Added ability for `salt.wait_for_event` to handle `event_id`s that have a list value. [#60430](https://github.com/saltstack/salt/issues/60430) -- Added suport for Linux ppc64le core grains (cpu_model, virtual, productname, manufacturer, serialnumber) and arm core grains (serialnumber, productname) [#60518](https://github.com/saltstack/salt/issues/60518) -- Added autostart option to virt.defined and virt.running states, along with virt.update execution modules. [#60700](https://github.com/saltstack/salt/issues/60700) -- Added .0 back to our versioning scheme for future versions (e.g. 3006.0) [#60722](https://github.com/saltstack/salt/issues/60722) -- Initial work to allow parallel startup of proxy minions when used as sub proxies with Deltaproxy. [#61153](https://github.com/saltstack/salt/issues/61153) -- Added node label support for GCE [#61245](https://github.com/saltstack/salt/issues/61245) -- Support the --priority flag when adding sources to Chocolatey. [#61319](https://github.com/saltstack/salt/issues/61319) -- Add namespace option to ext_pillar.http_json [#61335](https://github.com/saltstack/salt/issues/61335) -- Added a filter function to ps module to get a list of processes on a minion according to their state. [#61420](https://github.com/saltstack/salt/issues/61420) -- Add postgres.timeout option to postgres module for limiting postgres query times [#61433](https://github.com/saltstack/salt/issues/61433) -- Added new optional vault option, ``config_location``. This can be either ``master`` or ``local`` and defines where vault will look for connection details, either requesting them from the master or using the local config. [#61857](https://github.com/saltstack/salt/issues/61857) -- Add ipwrap() jinja filter to wrap IPv6 addresses with brackets. [#61931](https://github.com/saltstack/salt/issues/61931) -- 'tcp' transport is now available in ipv6-only network [#62009](https://github.com/saltstack/salt/issues/62009) -- Add `diff_attr` parameter to pkg.upgrade() (zypper/yum). [#62031](https://github.com/saltstack/salt/issues/62031) -- Config option pass_variable_prefix allows to distinguish variables that contain paths to pass secrets. - Config option pass_strict_fetch allows to error out when a secret cannot be fetched from pass. - Config option pass_dir allows setting the PASSWORD_STORE_DIR env for pass. - Config option pass_gnupghome allows setting the $GNUPGHOME env for pass. [#62120](https://github.com/saltstack/salt/issues/62120) -- Add file.pruned state and expanded file.rmdir exec module functionality [#62178](https://github.com/saltstack/salt/issues/62178) -- Added "dig.PTR" function to resolve PTR records for IPs, as well as tests and documentation [#62275](https://github.com/saltstack/salt/issues/62275) -- Added the ability to remove a KB using the DISM state/execution modules [#62366](https://github.com/saltstack/salt/issues/62366) -- Add " python" subcommand to allow execution or arbitrary scripts via bundled Python runtime [#62381](https://github.com/saltstack/salt/issues/62381) -- Add ability to provide conditions which convert normal state actions to no-op when true [#62446](https://github.com/saltstack/salt/issues/62446) -- Added debug log messages displaying the command being run when installing packages on Windows [#62480](https://github.com/saltstack/salt/issues/62480) -- Add biosvendor grain [#62496](https://github.com/saltstack/salt/issues/62496) -- Add ifelse Jinja function as found in CFEngine [#62508](https://github.com/saltstack/salt/issues/62508) -- Implementation of Amazon EC2 instance detection and setting `virtual_subtype` grain accordingly including the product if possible to identify. [#62539](https://github.com/saltstack/salt/issues/62539) -- Adds __env__substitution to ext_pillar.stack; followup of #61531, improved exception handling for stacked template (jinja) template rendering and yaml parsing in ext_pillar.stack [#62578](https://github.com/saltstack/salt/issues/62578) -- Increase file.tidied flexibility with regard to age and size [#62678](https://github.com/saltstack/salt/issues/62678) -- Added "connected_devices" feature to netbox pillar module. It contains extra information about devices connected to the minion [#62761](https://github.com/saltstack/salt/issues/62761) -- Add atomic file operation for symlink changes [#62768](https://github.com/saltstack/salt/issues/62768) -- Add password/account locking/unlocking in user.present state on supported operating systems [#62856](https://github.com/saltstack/salt/issues/62856) -- Added onchange configuration for script engine [#62867](https://github.com/saltstack/salt/issues/62867) -- Added output and bare functionality to export_key gpg module function [#62978](https://github.com/saltstack/salt/issues/62978) -- Add keyvalue serializer for environment files [#62983](https://github.com/saltstack/salt/issues/62983) -- Add ability to ignore symlinks in file.tidied [#63042](https://github.com/saltstack/salt/issues/63042) -- salt-cloud support IMDSv2 tokens when using 'use-instance-role-credentials' [#63067](https://github.com/saltstack/salt/issues/63067) -- Add ability for file.symlink to not set ownership on existing links [#63093](https://github.com/saltstack/salt/issues/63093) -- Restore the previous slack engine and deprecate it, rename replace the slack engine to slack_bolt until deprecation [#63095](https://github.com/saltstack/salt/issues/63095) -- Add functions that will return the underlying block device, mount point, and filesystem type for a given path [#63098](https://github.com/saltstack/salt/issues/63098) -- Add ethtool execution and state module functions for pause [#63128](https://github.com/saltstack/salt/issues/63128) -- Add boardname grain [#63131](https://github.com/saltstack/salt/issues/63131) -- Added management of ECDSA/EdDSA private keys with x509 modules in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#63248](https://github.com/saltstack/salt/issues/63248) -- Added x509 modules support for different output formats in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#63249](https://github.com/saltstack/salt/issues/63249) -- Added deprecation_warning test state for ensuring that deprecation warnings are correctly emitted. [#63315](https://github.com/saltstack/salt/issues/63315) -- Adds a state_events option to state.highstate, state.apply, state.sls, state.sls_id. - This allows users to enable state_events on a per use basis rather than having to - enable them globally for all state runs. [#63316](https://github.com/saltstack/salt/issues/63316) -- Allow max queue size setting for state runs to prevent performance problems from queue growth [#63356](https://github.com/saltstack/salt/issues/63356) -- Add support of exposing meta_server_grains for Azure VMs [#63606](https://github.com/saltstack/salt/issues/63606) - -## Changelog - -### Removed - -- Remove and deprecate the __orchestration__ key from salt.runner and salt.wheel return data. To get it back, set features.enable_deprecated_orchestration_flag master configuration option to True. The flag will be completely removed in Salt 3008 Argon. [#59917](https://github.com/saltstack/salt/issues/59917) -- Removed distutils and replaced with setuptools, given distutils is deprecated and removed in Python 3.12 [#60476](https://github.com/saltstack/salt/issues/60476) -- Removed ``runtests`` targets from ``noxfile.py`` [#62239](https://github.com/saltstack/salt/issues/62239) -- Removed the PyObjC dependency. - - This addresses problems with building a one dir build for macOS. - It became problematic because depending on the macOS version, it pulls different dependencies, and we would either have to build a macos onedir for each macOS supported release, or ship a crippled onedir(because it would be tied to the macOS version where the onedir was built). - Since it's currently not being used, it's removed. [#62432](https://github.com/saltstack/salt/issues/62432) -- Removed `SixRedirectImporter` from Salt. Salt hasn't shipped `six` since Salt 3004. [#63874](https://github.com/saltstack/salt/issues/63874) - - -### Deprecated - -- renamed `keep_jobs`, specifying job cache TTL in hours, to `keep_jobs_seconds`, specifying TTL in seconds. - `keep_jobs` will be removed in the Argon release [#55295](https://github.com/saltstack/salt/issues/55295) -- Removing all references to napalm-base which is no longer supported. [#61542](https://github.com/saltstack/salt/issues/61542) -- The 'ip_bracket' function has been moved from salt/utils/zeromq.py in salt/utils/network.py [#62009](https://github.com/saltstack/salt/issues/62009) -- The `expand_repo_def` function in `salt.modules.aptpkg` is now deprecated. It's only used in `salt.states.pkgrepo` and it has no use of being exposed to the CLI. [#62485](https://github.com/saltstack/salt/issues/62485) -- Deprecated defunct Django returner [#62644](https://github.com/saltstack/salt/issues/62644) -- Deprecate core ESXi and associated states and modules, vcenter and vsphere support in favor of Salt VMware Extensions [#62754](https://github.com/saltstack/salt/issues/62754) -- Removing manufacture grain which has been deprecated. [#62914](https://github.com/saltstack/salt/issues/62914) -- Removing deprecated utils/boto3_elasticsearch.py [#62915](https://github.com/saltstack/salt/issues/62915) -- Removing support for the now deprecated _ext_nodes from salt/master.py. [#62917](https://github.com/saltstack/salt/issues/62917) -- Deprecating the Salt Slack engine in favor of the Salt Slack Bolt Engine. [#63095](https://github.com/saltstack/salt/issues/63095) -- `salt.utils.version.StrictVersion` is now deprecated and it's use should be replaced with `salt.utils.version.Version`. [#63383](https://github.com/saltstack/salt/issues/63383) - - -### Changed - -- More intelligent diffing in changes of file.serialize state. [#48609](https://github.com/saltstack/salt/issues/48609) -- Move deprecation of the neutron module to Argon. Please migrate to the neutronng module instead. [#49430](https://github.com/saltstack/salt/issues/49430) -- ``umask`` is now a global state argument, instead of only applying to ``cmd`` - states. [#57803](https://github.com/saltstack/salt/issues/57803) -- Update pillar.obfuscate to accept kwargs in addition to args. This is useful when passing in keyword arguments like saltenv that are then passed along to pillar.items. [#58971](https://github.com/saltstack/salt/issues/58971) -- Improve support for listing macOS brew casks [#59439](https://github.com/saltstack/salt/issues/59439) -- Add missing MariaDB Grants to mysql module. - MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. - Also improved exception handling in `grant_add` which did not log the original error message and replaced it with a generic error. [#61409](https://github.com/saltstack/salt/issues/61409) -- Use VENV_PIP_TARGET environment variable as a default target for pip if present. [#62089](https://github.com/saltstack/salt/issues/62089) -- Disabled FQDNs grains on macOS by default [#62168](https://github.com/saltstack/salt/issues/62168) -- Replaced pyroute2.IPDB with pyroute2.NDB, as the former is deprecated [#62218](https://github.com/saltstack/salt/issues/62218) -- Enhance capture of error messages for Zypper calls in zypperpkg module. [#62346](https://github.com/saltstack/salt/issues/62346) -- Removed GPG_1_3_1 check [#62895](https://github.com/saltstack/salt/issues/62895) -- Requisite state chunks now all consistently contain `__id__`, `__sls__` and `name`. [#63012](https://github.com/saltstack/salt/issues/63012) -- netapi_enable_clients option to allow enabling/disabling of clients in salt-api. - By default all clients will now be disabled. Users of salt-api will need - to update their master config to enable the clients that they use. Not adding - the netapi_enable_clients option with required clients to the master config will - disable salt-api. [#63050](https://github.com/saltstack/salt/issues/63050) -- Stop relying on `salt/_version.py` to write Salt's version. Instead use `salt/_version.txt` which only contains the version string. [#63383](https://github.com/saltstack/salt/issues/63383) -- Set enable_fqdns_grains to be False by default. [#63595](https://github.com/saltstack/salt/issues/63595) -- Changelog snippet files must now have a `.md` file extension to be more explicit on what type of rendering is done when they are included in the main `CHANGELOG.md` file. [#63710](https://github.com/saltstack/salt/issues/63710) - - -### Fixed - -- Add kwargs to handle extra parameters for http.query [#36138](https://github.com/saltstack/salt/issues/36138) -- Fix mounted bind mounts getting active mount options added [#39292](https://github.com/saltstack/salt/issues/39292) -- Fix `sysctl.present` converts spaces to tabs. [#40054](https://github.com/saltstack/salt/issues/40054) -- Fixes state pkg.purged to purge removed packages on Debian family systems [#42306](https://github.com/saltstack/salt/issues/42306) -- Fix fun_args missing from syndic returns [#45823](https://github.com/saltstack/salt/issues/45823) -- Fix mount.mounted with 'mount: False' reports unmounted file system as unchanged when running with test=True [#47201](https://github.com/saltstack/salt/issues/47201) -- Issue #49310: Allow users to touch a file with Unix date of birth [#49310](https://github.com/saltstack/salt/issues/49310) -- Do not raise an exception in pkg.info_installed on nonzero return code [#51620](https://github.com/saltstack/salt/issues/51620) -- Passes the value of the force parameter from file.copy to its call to file.remove so that files with the read-only attribute are handled. [#51739](https://github.com/saltstack/salt/issues/51739) -- Fixed x509.certificate_managed creates new certificate every run in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#52167](https://github.com/saltstack/salt/issues/52167) -- Don't check for cached pillar errors on state.apply [#52354](https://github.com/saltstack/salt/issues/52354), [#57180](https://github.com/saltstack/salt/issues/57180), [#59339](https://github.com/saltstack/salt/issues/59339) -- Swapping out args and kwargs for arg and kwarg respectively in the Slack engine when the command passed is a runner. [#52400](https://github.com/saltstack/salt/issues/52400) -- Ensure when we're adding chunks to the rules when running aggregation with the iptables state module we use a copy of the chunk otherwise we end up with a recursive mess. [#53353](https://github.com/saltstack/salt/issues/53353) -- When user_create or user_remove fail, return False instead of returning the error. [#53377](https://github.com/saltstack/salt/issues/53377) -- Include sync_roster when sync_all is called. [#53914](https://github.com/saltstack/salt/issues/53914) -- Avoid warning noise in lograte.get [#53988](https://github.com/saltstack/salt/issues/53988) -- Fixed listing revoked keys with gpg.list_keys [#54347](https://github.com/saltstack/salt/issues/54347) -- Fix mount.mounted does not handle blanks properly [#54508](https://github.com/saltstack/salt/issues/54508) -- Fixed grain num_cpus get wrong CPUs count in case of inconsistent CPU numbering. [#54682](https://github.com/saltstack/salt/issues/54682) -- Fix spelling error for python_shell argument in dpkg_lower module [#54907](https://github.com/saltstack/salt/issues/54907) -- Cleaned up bytes response data before sending to non-bytes compatible returners (postgres, mysql) [#55226](https://github.com/saltstack/salt/issues/55226) -- Fixed malformed state return when testing file.managed with unavailable source file [#55269](https://github.com/saltstack/salt/issues/55269) -- Included stdout in error message for Zypper calls in zypperpkg module. [#56016](https://github.com/saltstack/salt/issues/56016) -- Fixed pillar.filter_by with salt-ssh [#56093](https://github.com/saltstack/salt/issues/56093) -- Fix boto_route53 issue with (multiple) VPCs. [#57139](https://github.com/saltstack/salt/issues/57139) -- Remove log from mine runner which was not used. [#57463](https://github.com/saltstack/salt/issues/57463) -- Fixed x509.read_certificate error when reading a Microsoft CA issued certificate in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#57535](https://github.com/saltstack/salt/issues/57535) -- Updating Slack engine to use slack_bolt library. [#57842](https://github.com/saltstack/salt/issues/57842) -- Fixed warning about replace=True with x509.certificate_managed in the new cryptography x509 module. [#58165](https://github.com/saltstack/salt/issues/58165) -- Fix salt.modules.pip:is_installed doesn't handle locally installed packages [#58202](https://github.com/saltstack/salt/issues/58202) -- Add missing MariaDB Grants to mysql module. MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. [#58297](https://github.com/saltstack/salt/issues/58297) -- linux_shadow: Fix cases where malformed shadow entries cause `user.present` - states to fail. [#58423](https://github.com/saltstack/salt/issues/58423) -- Fixed salt.utils.compat.cmp to work with dictionaries [#58729](https://github.com/saltstack/salt/issues/58729) -- Fixed formatting for terse output mode [#58953](https://github.com/saltstack/salt/issues/58953) -- Fixed RecursiveDictDiffer with added nested dicts [#59017](https://github.com/saltstack/salt/issues/59017) -- Fixed x509.certificate_managed has DoS effect on master in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#59169](https://github.com/saltstack/salt/issues/59169) -- Fixed saltnado websockets disconnecting immediately [#59183](https://github.com/saltstack/salt/issues/59183) -- Fixed x509.certificate_managed rolls certificates every now and then in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#59315](https://github.com/saltstack/salt/issues/59315) -- Fix postgres_privileges.present not idempotent for functions [#59585](https://github.com/saltstack/salt/issues/59585) -- Fixed influxdb_continuous_query.present state to provide the client args to the underlying module on create. [#59766](https://github.com/saltstack/salt/issues/59766) -- Warn when using insecure (http:// based) key_urls for apt-based systems in pkgrepo.managed, and add a kwarg that determines the validity of such a url. [#59786](https://github.com/saltstack/salt/issues/59786) -- add load balancing policy default option and ensure the module can be executed with arguments from CLI [#59909](https://github.com/saltstack/salt/issues/59909) -- Fix salt-ssh when using imports with extra-filerefs. [#60003](https://github.com/saltstack/salt/issues/60003) -- Fixed cache directory corruption startup error [#60170](https://github.com/saltstack/salt/issues/60170) -- Update docs remove dry_run in docstring of file.blockreplace state. [#60227](https://github.com/saltstack/salt/issues/60227) -- Adds Parrot to OS_Family_Map in grains. [#60249](https://github.com/saltstack/salt/issues/60249) -- Fixed stdout and stderr being empty sometimes when use_vt=True for the cmd.run[*] functions [#60365](https://github.com/saltstack/salt/issues/60365) -- Use return code in iptables --check to verify rule exists. [#60467](https://github.com/saltstack/salt/issues/60467) -- Fix regression pip.installed does not pass env_vars when calling pip.list [#60557](https://github.com/saltstack/salt/issues/60557) -- Fix xfs module when additional output included in mkfs.xfs command. [#60853](https://github.com/saltstack/salt/issues/60853) -- Fixed parsing new format of terraform states in roster.terraform [#60915](https://github.com/saltstack/salt/issues/60915) -- Fixed recognizing installed ARMv7 rpm packages in compatible architectures. [#60994](https://github.com/saltstack/salt/issues/60994) -- Fixing changes dict in pkg state to be consistent when installing and test=True. [#60995](https://github.com/saltstack/salt/issues/60995) -- Fix cron.present duplicating entries when changing timespec to special. [#60997](https://github.com/saltstack/salt/issues/60997) -- Made salt-ssh respect --wipe again [#61083](https://github.com/saltstack/salt/issues/61083) -- state.orchestrate_single only passes a pillar if it is set to the state - function. This allows it to be used with state functions that don't accept a - pillar keyword argument. [#61092](https://github.com/saltstack/salt/issues/61092) -- Fix ipset state when the comment kwarg is set. [#61122](https://github.com/saltstack/salt/issues/61122) -- Fix issue with archive.unzip where the password was not being encoded for the extract function [#61422](https://github.com/saltstack/salt/issues/61422) -- Some Linux distributions (like AlmaLinux, Astra Linux, Debian, Mendel, Linux - Mint, Pop!_OS, Rocky Linux) report different `oscodename`, `osfullname`, - `osfinger` grains if lsb-release is installed or not. They have been changed to - only derive these OS grains from `/etc/os-release`. [#61618](https://github.com/saltstack/salt/issues/61618) -- Pop!_OS uses the full version (YY.MM) in the osfinger grain now, not just the year. This allows differentiating for example between 20.04 and 20.10. [#61619](https://github.com/saltstack/salt/issues/61619) -- Fix ssh config roster to correctly parse the ssh config files that contain spaces. [#61650](https://github.com/saltstack/salt/issues/61650) -- Fix SoftLayer configuration not raising an exception when a domain is missing [#61727](https://github.com/saltstack/salt/issues/61727) -- Allow the minion to start or salt-call to run even if the user doesn't have permissions to read the root_dir value from the registry [#61789](https://github.com/saltstack/salt/issues/61789) -- Need to move the creation of the proxy object for the ProxyMinion further down in the initialization for sub proxies to ensure that all modules, especially any custom proxy modules, are available before attempting to run the init function. [#61805](https://github.com/saltstack/salt/issues/61805) -- Fixed malformed state return when merge-serializing to an improperly formatted file [#61814](https://github.com/saltstack/salt/issues/61814) -- Made cmdmod._run[_all]_quiet work during minion startup on MacOS with runas specified (which fixed mac_service) [#61816](https://github.com/saltstack/salt/issues/61816) -- When deleting the vault cache, also delete from the session cache [#61821](https://github.com/saltstack/salt/issues/61821) -- Ignore errors on reading license info with dpkg_lowpkg to prevent tracebacks on getting package information. [#61827](https://github.com/saltstack/salt/issues/61827) -- win_lgpo: Display conflicting policy names when more than one policy is found [#61859](https://github.com/saltstack/salt/issues/61859) -- win_lgpo: Fixed intermittent KeyError when getting policy setting using lgpo.get_policy [#61860](https://github.com/saltstack/salt/issues/61860) -- Fixed listing minions on OpenBSD [#61966](https://github.com/saltstack/salt/issues/61966) -- Make Salt to return an error on "pkg" modules and states when targeting duplicated package names [#62019](https://github.com/saltstack/salt/issues/62019) -- Fix return of REST-returned permissions when auth_list is set [#62022](https://github.com/saltstack/salt/issues/62022) -- Normalize package names once on using pkg.installed/removed with yum to make it possible to install packages with the name containing a part similar to a name of architecture. [#62029](https://github.com/saltstack/salt/issues/62029) -- Fix inconsitency regarding name and pkgs parameters between zypperpkg.upgrade() and yumpkg.upgrade() [#62030](https://github.com/saltstack/salt/issues/62030) -- Fix attr=all handling in pkg.list_pkgs() (yum/zypper). [#62032](https://github.com/saltstack/salt/issues/62032) -- Fixed the humanname being ignored in pkgrepo.managed on openSUSE Leap [#62053](https://github.com/saltstack/salt/issues/62053) -- Fixed issue with some LGPO policies having whitespace at the beginning or end of the element alias [#62058](https://github.com/saltstack/salt/issues/62058) -- Fix ordering of args to libcloud_storage.download_object module [#62074](https://github.com/saltstack/salt/issues/62074) -- Ignore extend declarations in sls files that are excluded. [#62082](https://github.com/saltstack/salt/issues/62082) -- Remove leftover usage of impacket [#62101](https://github.com/saltstack/salt/issues/62101) -- Pass executable path from _get_path_exec() is used when calling the program. - The $HOME env is no longer modified globally. - Only trailing newlines are stripped from the fetched secret. - Pass process arguments are handled in a secure way. [#62120](https://github.com/saltstack/salt/issues/62120) -- Ignore some command return codes in openbsdrcctl_service to prevent spurious errors [#62131](https://github.com/saltstack/salt/issues/62131) -- Fixed extra period in filename output in tls module. Instead of "server.crt." it will now be "server.crt". [#62139](https://github.com/saltstack/salt/issues/62139) -- Make sure lingering PAexec-*.exe files in the Windows directory are cleaned up [#62152](https://github.com/saltstack/salt/issues/62152) -- Restored Salt's DeprecationWarnings [#62185](https://github.com/saltstack/salt/issues/62185) -- Fixed issue with forward slashes on Windows with file.recurse and clean=True [#62197](https://github.com/saltstack/salt/issues/62197) -- Recognize OSMC as Debian-based [#62198](https://github.com/saltstack/salt/issues/62198) -- Fixed Zypper module failing on RPM lock file being temporarily unavailable. [#62204](https://github.com/saltstack/salt/issues/62204) -- Improved error handling and diagnostics in the proxmox salt-cloud driver [#62211](https://github.com/saltstack/salt/issues/62211) -- Added EndeavourOS to the Arch os_family. [#62220](https://github.com/saltstack/salt/issues/62220) -- Fix salt-ssh not detecting `platform-python` as a valid interpreter on EL8 [#62235](https://github.com/saltstack/salt/issues/62235) -- Fix pkg.version_cmp on openEuler and a few other os flavors. [#62248](https://github.com/saltstack/salt/issues/62248) -- Fix localhost detection in glusterfs.peers [#62273](https://github.com/saltstack/salt/issues/62273) -- Fix Salt Package Manager (SPM) exception when calling spm create_repo . [#62281](https://github.com/saltstack/salt/issues/62281) -- Fix matcher slowness due to loader invocation [#62283](https://github.com/saltstack/salt/issues/62283) -- Fixes the Puppet module for non-aio Puppet packages for example running the Puppet module on FreeBSD. [#62323](https://github.com/saltstack/salt/issues/62323) -- Issue 62334: Displays a debug log message instead of an error log message when the publisher fails to connect [#62334](https://github.com/saltstack/salt/issues/62334) -- Fix pyobjects renderer access to opts and sls [#62336](https://github.com/saltstack/salt/issues/62336) -- Fix use of random shuffle and sample functions as Jinja filters [#62372](https://github.com/saltstack/salt/issues/62372) -- Fix groups with duplicate GIDs are not returned by get_group_list [#62377](https://github.com/saltstack/salt/issues/62377) -- Fix the "zpool.present" state when enabling zpool features that are already active. [#62390](https://github.com/saltstack/salt/issues/62390) -- Fix ability to execute remote file client methods in saltcheck [#62398](https://github.com/saltstack/salt/issues/62398) -- Update all platforms to use pycparser 2.21 or greater for Py 3.9 or higher, fixes fips fault with openssl v3.x [#62400](https://github.com/saltstack/salt/issues/62400) -- Due to changes in the Netmiko library for the exception paths, need to check the version of Netmiko python library and then import the exceptions from different locations depending on the result. [#62405](https://github.com/saltstack/salt/issues/62405) -- When using preq on a state, then prereq state will first be run with test=True to determine if there are changes. When there are changes, the state with the prereq option will be run prior to the prereq state. If this state fails then the prereq state will not run and the state output uses the test=True run. However, the proposed changes are included for the prereq state are included from the test=True run. We should pull those out as there weren't actually changes since the prereq state did not run. [#62408](https://github.com/saltstack/salt/issues/62408) -- Added directory mode for file.copy with makedirs [#62426](https://github.com/saltstack/salt/issues/62426) -- Provide better error handling in the various napalm proxy minion functions when the device is not accessible. [#62435](https://github.com/saltstack/salt/issues/62435) -- When handling aggregation, change the order to ensure that the requisites are aggregated first and then the state functions are aggregated. Caching whether aggregate functions are available for particular states so we don't need to attempt to load them everytime. [#62439](https://github.com/saltstack/salt/issues/62439) -- The patch allows to boostrap kubernetes clusters in the version above 1.13 via salt module [#62451](https://github.com/saltstack/salt/issues/62451) -- sysctl.persist now updates the in-memory value on FreeBSD even if the on-disk value was already correct. [#62461](https://github.com/saltstack/salt/issues/62461) -- Fixed parsing CDROM apt sources [#62474](https://github.com/saltstack/salt/issues/62474) -- Update sanitizing masking for Salt SSH to include additional password like strings. [#62483](https://github.com/saltstack/salt/issues/62483) -- Fix user/group checking on file state functions in the test mode. [#62499](https://github.com/saltstack/salt/issues/62499) -- Fix user.present to allow removing groups using optional_groups parameter and enforcing idempotent group membership. [#62502](https://github.com/saltstack/salt/issues/62502) -- Fix possible tracebacks if there is a package with '------' or '======' in the description is installed on the Debian based minion. [#62519](https://github.com/saltstack/salt/issues/62519) -- Fixed the omitted "pool" parameter when cloning a VM with the proxmox salt-cloud driver [#62521](https://github.com/saltstack/salt/issues/62521) -- Fix rendering of pyobjects states in saltcheck [#62523](https://github.com/saltstack/salt/issues/62523) -- Fixes pillar where a corrupted CacheDisk file forces the pillar to be rebuilt [#62527](https://github.com/saltstack/salt/issues/62527) -- Use str() method instead of repo_line for when python3-apt is installed or not in aptpkg.py. [#62546](https://github.com/saltstack/salt/issues/62546) -- Remove the connection_timeout from netmiko_connection_args before netmiko_connection_args is added to __context__["netmiko_device"]["args"] which is passed along to the Netmiko library. [#62547](https://github.com/saltstack/salt/issues/62547) -- Fix order specific mount.mounted options for persist [#62556](https://github.com/saltstack/salt/issues/62556) -- Fixed salt-cloud cloning a proxmox VM with a specified new vmid. [#62558](https://github.com/saltstack/salt/issues/62558) -- Fix runas with cmd module when using the onedir bundled packages [#62565](https://github.com/saltstack/salt/issues/62565) -- Update setproctitle version for all platforms [#62576](https://github.com/saltstack/salt/issues/62576) -- Fixed missing parameters when cloning a VM with the proxmox salt-cloud driver [#62580](https://github.com/saltstack/salt/issues/62580) -- Handle PermissionError when importing crypt when FIPS is enabled. [#62587](https://github.com/saltstack/salt/issues/62587) -- Correctly reraise exceptions in states.http [#62595](https://github.com/saltstack/salt/issues/62595) -- Fixed syndic eauth. Now jobs will be published when a valid eauth user is targeting allowed minions/functions. [#62618](https://github.com/saltstack/salt/issues/62618) -- updated rest_cherry/app to properly detect arg sent as a string as curl will do when only one arg is supplied. [#62624](https://github.com/saltstack/salt/issues/62624) -- Prevent possible tracebacks in core grains module by ignoring non utf8 characters in /proc/1/environ, /proc/1/cmdline, /proc/cmdline [#62633](https://github.com/saltstack/salt/issues/62633) -- Fixed vault ext pillar return data for KV v2 [#62651](https://github.com/saltstack/salt/issues/62651) -- Fix saltcheck _get_top_states doesn't pass saltenv to state.show_top [#62654](https://github.com/saltstack/salt/issues/62654) -- Fix groupadd.* functions hard code relative command name [#62657](https://github.com/saltstack/salt/issues/62657) -- Fixed pdbedit.create trying to use a bytes-like hash as string. [#62670](https://github.com/saltstack/salt/issues/62670) -- Fix depenency on legacy boto module in boto3 modules [#62672](https://github.com/saltstack/salt/issues/62672) -- Modified "_get_flags" function so that it returns regex flags instead of integers [#62676](https://github.com/saltstack/salt/issues/62676) -- Change startup ReqServer log messages from error to info level. [#62728](https://github.com/saltstack/salt/issues/62728) -- Fix kmod.* functions hard code relative command name [#62772](https://github.com/saltstack/salt/issues/62772) -- Fix mac_brew_pkg to work with null taps [#62793](https://github.com/saltstack/salt/issues/62793) -- Fixing a bug when listing the running schedule if "schedule.enable" and/or "schedule.disable" has been run, where the "enabled" items is being treated as a schedule item. [#62795](https://github.com/saltstack/salt/issues/62795) -- Prevent annoying RuntimeWarning message about line buffering (buffering=1) not being supported in binary mode [#62817](https://github.com/saltstack/salt/issues/62817) -- Include UID and GID checks in modules.file.check_perms as well as comparing - ownership by username and group name. [#62818](https://github.com/saltstack/salt/issues/62818) -- Fix presence events on TCP transport by removing a client's presence when minion disconnects from publish channel correctly [#62826](https://github.com/saltstack/salt/issues/62826) -- Remove Azure deprecation messages from functions that always run w/ salt-cloud [#62845](https://github.com/saltstack/salt/issues/62845) -- Use select instead of iterating over entrypoints as a dictionary for importlib_metadata>=5.0.0 [#62854](https://github.com/saltstack/salt/issues/62854) -- Fixed master job scheduler using when [#62858](https://github.com/saltstack/salt/issues/62858) -- LGPO: Added support for missing domain controller policies: VulnerableChannelAllowList and LdapEnforceChannelBinding [#62873](https://github.com/saltstack/salt/issues/62873) -- Fix unnecessarily complex gce metadata grains code to use googles metadata service more effectively. [#62878](https://github.com/saltstack/salt/issues/62878) -- Fixed dockermod version_info function for docker-py 6.0.0+ [#62882](https://github.com/saltstack/salt/issues/62882) -- Moving setting the LOAD_BALANCING_POLICY_MAP dictionary into the try except block that determines if the cassandra_cql module should be made available. [#62886](https://github.com/saltstack/salt/issues/62886) -- Updating various MongoDB module functions to work with latest version of pymongo. [#62900](https://github.com/saltstack/salt/issues/62900) -- Restored channel for Syndic minions to send job returns to the Salt master. [#62933](https://github.com/saltstack/salt/issues/62933) -- removed _resolve_deps as it required a library that is not generally avalible. and switched to apt-get for everything as that can auto resolve dependencies. [#62934](https://github.com/saltstack/salt/issues/62934) -- Updated pyzmq to version 22.0.3 on Windows builds because the old version was causing salt-minion/salt-call to hang [#62937](https://github.com/saltstack/salt/issues/62937) -- Allow root user to modify crontab lines for non-root users (except AIX and Solaris). Align crontab line changes with the file ones and also with listing crontab. [#62940](https://github.com/saltstack/salt/issues/62940) -- Fix systemd_service.* functions hard code relative command name [#62942](https://github.com/saltstack/salt/issues/62942) -- Fix file.symlink backupname operation can copy remote contents to local disk [#62953](https://github.com/saltstack/salt/issues/62953) -- Issue #62968: Fix issue where cloud deployments were putting the keys in the wrong location on Windows hosts [#62968](https://github.com/saltstack/salt/issues/62968) -- Fixed gpg_passphrase issue with gpg decrypt/encrypt functions [#62977](https://github.com/saltstack/salt/issues/62977) -- Fix file.tidied FileNotFoundError [#62986](https://github.com/saltstack/salt/issues/62986) -- Fixed bug where module.wait states were detected as running legacy module.run syntax [#62988](https://github.com/saltstack/salt/issues/62988) -- Fixed issue with win_wua module where it wouldn't load if the CryptSvc was set to Manual start [#62993](https://github.com/saltstack/salt/issues/62993) -- The `__opts__` dunder dictionary is now added to the loader's `pack` if not - already present, which makes it accessible via the - `salt.loader.context.NamedLoaderContext` class. [#63013](https://github.com/saltstack/salt/issues/63013) -- Issue #63024: Fix issue where grains and config data were being place in the wrong location on Windows hosts [#63024](https://github.com/saltstack/salt/issues/63024) -- Fix btrfs.subvolume_snapshot command failing [#63025](https://github.com/saltstack/salt/issues/63025) -- Fix file.retention_schedule always reports changes [#63033](https://github.com/saltstack/salt/issues/63033) -- Fix mongo authentication for mongo ext_pillar and mongo returner - - This fix also include the ability to use the mongo connection string for mongo ext_pillar [#63058](https://github.com/saltstack/salt/issues/63058) -- Fixed x509.create_csr creates invalid CSR by default in the new cryptography x509 module. [#63103](https://github.com/saltstack/salt/issues/63103) -- TCP transport documentation now contains proper master/minion-side filtering information [#63120](https://github.com/saltstack/salt/issues/63120) -- Fixed gpg.verify does not respect gnupghome [#63145](https://github.com/saltstack/salt/issues/63145) -- Made pillar cache pass extra minion data as well [#63208](https://github.com/saltstack/salt/issues/63208) -- Fix serious performance issues with the file.tidied module [#63231](https://github.com/saltstack/salt/issues/63231) -- Fix rpm_lowpkg version comparison logic when using rpm-vercmp and only one version has a release number. [#63317](https://github.com/saltstack/salt/issues/63317) -- Import StrictVersion and LooseVersion from setuptools.distutils.verison or setuptools._distutils.version, if first not available [#63350](https://github.com/saltstack/salt/issues/63350) -- When the shell is passed as powershell or pwsh, only wrapper the shell in quotes if cmd.run is running on Windows. When quoted on Linux hosts, this results in an error when the keyword arguments are appended. [#63590](https://github.com/saltstack/salt/issues/63590) -- LGPO: Added support for "Relax minimum password length limits" [#63596](https://github.com/saltstack/salt/issues/63596) -- When a job is disabled only increase it's _next_fire_time value if the job would have run at the current time, eg. the current _next_fire_time == now. [#63699](https://github.com/saltstack/salt/issues/63699) -- Check file is not empty before attempting to read pillar disk cache file [#63729](https://github.com/saltstack/salt/issues/63729) -- fix cherrypy 400 error output to be less generic. [#63835](https://github.com/saltstack/salt/issues/63835) -- remove eval and update logging to be more informative on bad config [#63879](https://github.com/saltstack/salt/issues/63879) - - -### Added - -- Introduce a `LIB_STATE_DIR` syspaths variable which defaults to `CONFIG_DIR`, - but can be individually customized during installation by specifying - `--salt-lib-state-dir` during installation. Change the default `pki_dir` to - `/pki/master` (for the master) and `/pki/minion` - (for the minion). [#3396](https://github.com/saltstack/salt/issues/3396) -- Allow users to enable 'queue=True' for all state runs via config file [#31468](https://github.com/saltstack/salt/issues/31468) -- Added pillar templating to vault policies [#43287](https://github.com/saltstack/salt/issues/43287) -- Add support for NVMeF as a transport protocol for hosts in a Pure Storage FlashArray [#51088](https://github.com/saltstack/salt/issues/51088) -- A new salt-ssh roster that generates a roster by parses a known_hosts file. [#54679](https://github.com/saltstack/salt/issues/54679) -- Added Windows Event Viewer support [#54713](https://github.com/saltstack/salt/issues/54713) -- Added the win_lgpo_reg state and execution modules which will allow registry based group policy to be set directly in the Registry.pol file [#56013](https://github.com/saltstack/salt/issues/56013) -- Added resource tagging functions to boto_dynamodb execution module [#57500](https://github.com/saltstack/salt/issues/57500) -- Added `openvswitch_db` state module and functions `bridge_to_parent`, - `bridge_to_vlan`, `db_get`, and `db_set` to the `openvswitch` execution module. - Also added optional `parent` and `vlan` parameters to the - `openvswitch_bridge.present` state module function and the - `openvswitch.bridge_create` execution module function. [#58986](https://github.com/saltstack/salt/issues/58986) -- State module to manage SysFS attributes [#60154](https://github.com/saltstack/salt/issues/60154) -- Added ability for `salt.wait_for_event` to handle `event_id`s that have a list value. [#60430](https://github.com/saltstack/salt/issues/60430) -- Added suport for Linux ppc64le core grains (cpu_model, virtual, productname, manufacturer, serialnumber) and arm core grains (serialnumber, productname) [#60518](https://github.com/saltstack/salt/issues/60518) -- Added autostart option to virt.defined and virt.running states, along with virt.update execution modules. [#60700](https://github.com/saltstack/salt/issues/60700) -- Added .0 back to our versioning scheme for future versions (e.g. 3006.0) [#60722](https://github.com/saltstack/salt/issues/60722) -- Initial work to allow parallel startup of proxy minions when used as sub proxies with Deltaproxy. [#61153](https://github.com/saltstack/salt/issues/61153) -- Added node label support for GCE [#61245](https://github.com/saltstack/salt/issues/61245) -- Support the --priority flag when adding sources to Chocolatey. [#61319](https://github.com/saltstack/salt/issues/61319) -- Add namespace option to ext_pillar.http_json [#61335](https://github.com/saltstack/salt/issues/61335) -- Added a filter function to ps module to get a list of processes on a minion according to their state. [#61420](https://github.com/saltstack/salt/issues/61420) -- Add postgres.timeout option to postgres module for limiting postgres query times [#61433](https://github.com/saltstack/salt/issues/61433) -- Added new optional vault option, ``config_location``. This can be either ``master`` or ``local`` and defines where vault will look for connection details, either requesting them from the master or using the local config. [#61857](https://github.com/saltstack/salt/issues/61857) -- Add ipwrap() jinja filter to wrap IPv6 addresses with brackets. [#61931](https://github.com/saltstack/salt/issues/61931) -- 'tcp' transport is now available in ipv6-only network [#62009](https://github.com/saltstack/salt/issues/62009) -- Add `diff_attr` parameter to pkg.upgrade() (zypper/yum). [#62031](https://github.com/saltstack/salt/issues/62031) -- Config option pass_variable_prefix allows to distinguish variables that contain paths to pass secrets. - Config option pass_strict_fetch allows to error out when a secret cannot be fetched from pass. - Config option pass_dir allows setting the PASSWORD_STORE_DIR env for pass. - Config option pass_gnupghome allows setting the $GNUPGHOME env for pass. [#62120](https://github.com/saltstack/salt/issues/62120) -- Add file.pruned state and expanded file.rmdir exec module functionality [#62178](https://github.com/saltstack/salt/issues/62178) -- Added "dig.PTR" function to resolve PTR records for IPs, as well as tests and documentation [#62275](https://github.com/saltstack/salt/issues/62275) -- Added the ability to remove a KB using the DISM state/execution modules [#62366](https://github.com/saltstack/salt/issues/62366) -- Add " python" subcommand to allow execution or arbitrary scripts via bundled Python runtime [#62381](https://github.com/saltstack/salt/issues/62381) -- Add ability to provide conditions which convert normal state actions to no-op when true [#62446](https://github.com/saltstack/salt/issues/62446) -- Added debug log messages displaying the command being run when installing packages on Windows [#62480](https://github.com/saltstack/salt/issues/62480) -- Add biosvendor grain [#62496](https://github.com/saltstack/salt/issues/62496) -- Add ifelse Jinja function as found in CFEngine [#62508](https://github.com/saltstack/salt/issues/62508) -- Implementation of Amazon EC2 instance detection and setting `virtual_subtype` grain accordingly including the product if possible to identify. [#62539](https://github.com/saltstack/salt/issues/62539) -- Adds __env__substitution to ext_pillar.stack; followup of #61531, improved exception handling for stacked template (jinja) template rendering and yaml parsing in ext_pillar.stack [#62578](https://github.com/saltstack/salt/issues/62578) -- Increase file.tidied flexibility with regard to age and size [#62678](https://github.com/saltstack/salt/issues/62678) -- Added "connected_devices" feature to netbox pillar module. It contains extra information about devices connected to the minion [#62761](https://github.com/saltstack/salt/issues/62761) -- Add atomic file operation for symlink changes [#62768](https://github.com/saltstack/salt/issues/62768) -- Add password/account locking/unlocking in user.present state on supported operating systems [#62856](https://github.com/saltstack/salt/issues/62856) -- Added onchange configuration for script engine [#62867](https://github.com/saltstack/salt/issues/62867) -- Added output and bare functionality to export_key gpg module function [#62978](https://github.com/saltstack/salt/issues/62978) -- Add keyvalue serializer for environment files [#62983](https://github.com/saltstack/salt/issues/62983) -- Add ability to ignore symlinks in file.tidied [#63042](https://github.com/saltstack/salt/issues/63042) -- salt-cloud support IMDSv2 tokens when using 'use-instance-role-credentials' [#63067](https://github.com/saltstack/salt/issues/63067) -- Add ability for file.symlink to not set ownership on existing links [#63093](https://github.com/saltstack/salt/issues/63093) -- Restore the previous slack engine and deprecate it, rename replace the slack engine to slack_bolt until deprecation [#63095](https://github.com/saltstack/salt/issues/63095) -- Add functions that will return the underlying block device, mount point, and filesystem type for a given path [#63098](https://github.com/saltstack/salt/issues/63098) -- Add ethtool execution and state module functions for pause [#63128](https://github.com/saltstack/salt/issues/63128) -- Add boardname grain [#63131](https://github.com/saltstack/salt/issues/63131) -- Added management of ECDSA/EdDSA private keys with x509 modules in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#63248](https://github.com/saltstack/salt/issues/63248) -- Added x509 modules support for different output formats in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#63249](https://github.com/saltstack/salt/issues/63249) -- Added deprecation_warning test state for ensuring that deprecation warnings are correctly emitted. [#63315](https://github.com/saltstack/salt/issues/63315) -- Adds a state_events option to state.highstate, state.apply, state.sls, state.sls_id. - This allows users to enable state_events on a per use basis rather than having to - enable them globally for all state runs. [#63316](https://github.com/saltstack/salt/issues/63316) -- Allow max queue size setting for state runs to prevent performance problems from queue growth [#63356](https://github.com/saltstack/salt/issues/63356) -- Add support of exposing meta_server_grains for Azure VMs [#63606](https://github.com/saltstack/salt/issues/63606) -- Include the version of `relenv` in the versions report. [#63827](https://github.com/saltstack/salt/issues/63827) -- Added debug log messages displaying the command being run when removing packages on Windows [#63866](https://github.com/saltstack/salt/issues/63866) - + ## Changelog ### Removed @@ -917,6 +310,7 @@ lib-bar: - Modified "_get_flags" function so that it returns regex flags instead of integers [#62676](https://github.com/saltstack/salt/issues/62676) - Change startup ReqServer log messages from error to info level. [#62728](https://github.com/saltstack/salt/issues/62728) - Fix kmod.* functions hard code relative command name [#62772](https://github.com/saltstack/salt/issues/62772) +- Remove mako as a dependency in Windows and macOS. [#62785](https://github.com/saltstack/salt/issues/62785) - Fix mac_brew_pkg to work with null taps [#62793](https://github.com/saltstack/salt/issues/62793) - Fixing a bug when listing the running schedule if "schedule.enable" and/or "schedule.disable" has been run, where the "enabled" items is being treated as a schedule item. [#62795](https://github.com/saltstack/salt/issues/62795) - Prevent annoying RuntimeWarning message about line buffering (buffering=1) not being supported in binary mode [#62817](https://github.com/saltstack/salt/issues/62817) @@ -954,10 +348,13 @@ lib-bar: - Fixed x509.create_csr creates invalid CSR by default in the new cryptography x509 module. [#63103](https://github.com/saltstack/salt/issues/63103) - TCP transport documentation now contains proper master/minion-side filtering information [#63120](https://github.com/saltstack/salt/issues/63120) - Fixed gpg.verify does not respect gnupghome [#63145](https://github.com/saltstack/salt/issues/63145) +- User responsible for the runner is now correctly reported in the events on the event bus for the runner. [#63148](https://github.com/saltstack/salt/issues/63148) - Made pillar cache pass extra minion data as well [#63208](https://github.com/saltstack/salt/issues/63208) - Fix serious performance issues with the file.tidied module [#63231](https://github.com/saltstack/salt/issues/63231) - Fix rpm_lowpkg version comparison logic when using rpm-vercmp and only one version has a release number. [#63317](https://github.com/saltstack/salt/issues/63317) - Import StrictVersion and LooseVersion from setuptools.distutils.verison or setuptools._distutils.version, if first not available [#63350](https://github.com/saltstack/salt/issues/63350) +- ``service.status`` on Windows does no longer throws a CommandExecutionError if + the service is not found on the system. It now returns "Not Found" instead. [#63577](https://github.com/saltstack/salt/issues/63577) - When the shell is passed as powershell or pwsh, only wrapper the shell in quotes if cmd.run is running on Windows. When quoted on Linux hosts, this results in an error when the keyword arguments are appended. [#63590](https://github.com/saltstack/salt/issues/63590) - LGPO: Added support for "Relax minimum password length limits" [#63596](https://github.com/saltstack/salt/issues/63596) - Fixed the ability to set a scheduled task to auto delete if not scheduled to run again (``delete_after``) [#63650](https://github.com/saltstack/salt/issues/63650) @@ -965,16 +362,20 @@ lib-bar: - have salt.template.compile_template_str cleanup its temp files. [#63724](https://github.com/saltstack/salt/issues/63724) - Check file is not empty before attempting to read pillar disk cache file [#63729](https://github.com/saltstack/salt/issues/63729) - Fixed an issue with generating fingerprints for public keys with different line endings [#63742](https://github.com/saltstack/salt/issues/63742) +- Add `fileserver_interval` and `maintenance_interval` master configuration options. These options control how often to restart the FileServerUpdate and Maintenance processes. Some file server and pillar configurations are known to cause memory leaks over time. A notable example of this are configurations that use pygit2. Salt can not guarantee dependency libraries like pygit2 won't leak memory. Restarting any long running processes that use pygit2 guarantees we can keep the master's memory usage in check. [#63747](https://github.com/saltstack/salt/issues/63747) +- mac_xattr.list and mac_xattr.read will replace undecode-able bytes to avoid raising CommandExecutionError. [#63779](https://github.com/saltstack/salt/issues/63779) [#63779](https://github.com/saltstack/salt/issues/63779) - Change default GPG keyserver from pgp.mit.edu to keys.openpgp.org. [#63806](https://github.com/saltstack/salt/issues/63806) - fix cherrypy 400 error output to be less generic. [#63835](https://github.com/saltstack/salt/issues/63835) - Ensure kwargs is passed along to _call_apt when passed into install function. [#63847](https://github.com/saltstack/salt/issues/63847) - remove eval and update logging to be more informative on bad config [#63879](https://github.com/saltstack/salt/issues/63879) - add linux_distribution to util to stop dep warning [#63904](https://github.com/saltstack/salt/issues/63904) +- Fix valuerror when trying to close fileclient. Remove usage of __del__ and close the filclient properly. [#63920](https://github.com/saltstack/salt/issues/63920) - Handle the situation when a sub proxy minion does not init properly, eg. an exception happens, and the sub proxy object is not available. [#63923](https://github.com/saltstack/salt/issues/63923) - Clarifying documentation for extension_modules configuration option. [#63929](https://github.com/saltstack/salt/issues/63929) - Windows pkg module now properly handles versions containing strings [#63935](https://github.com/saltstack/salt/issues/63935) - Handle the scenario when the check_cmd requisite is used with a state function when the state has a local check_cmd function but that function isn't used by that function. [#63948](https://github.com/saltstack/salt/issues/63948) - Issue #63981: Allow users to pass verify_ssl to pkg.install/pkg.installed on Windows [#63981](https://github.com/saltstack/salt/issues/63981) +- Hardened permissions on workers.ipc and master_event_pub.ipc. [#64063](https://github.com/saltstack/salt/issues/64063) ### Added @@ -1034,6 +435,7 @@ lib-bar: - Add keyvalue serializer for environment files [#62983](https://github.com/saltstack/salt/issues/62983) - Add ability to ignore symlinks in file.tidied [#63042](https://github.com/saltstack/salt/issues/63042) - salt-cloud support IMDSv2 tokens when using 'use-instance-role-credentials' [#63067](https://github.com/saltstack/salt/issues/63067) +- Fix running fast tests twice and add git labels to suite. [#63081](https://github.com/saltstack/salt/issues/63081) - Add ability for file.symlink to not set ownership on existing links [#63093](https://github.com/saltstack/salt/issues/63093) - Restore the previous slack engine and deprecate it, rename replace the slack engine to slack_bolt until deprecation [#63095](https://github.com/saltstack/salt/issues/63095) - Add functions that will return the underlying block device, mount point, and filesystem type for a given path [#63098](https://github.com/saltstack/salt/issues/63098) @@ -1049,6 +451,8 @@ lib-bar: - Add support of exposing meta_server_grains for Azure VMs [#63606](https://github.com/saltstack/salt/issues/63606) - Include the version of `relenv` in the versions report. [#63827](https://github.com/saltstack/salt/issues/63827) - Added debug log messages displaying the command being run when removing packages on Windows [#63866](https://github.com/saltstack/salt/issues/63866) +- Adding the ability to exclude arguments from a state that end up passed to cmd.retcode when requisites such as onlyif or unless are used. [#63956](https://github.com/saltstack/salt/issues/63956) +- Add --next-release argument to salt/version.py, which prints the next upcoming release. [#64023](https://github.com/saltstack/salt/issues/64023) ### Security diff --git a/doc/topics/releases/templates/3006.0.md.template b/doc/topics/releases/templates/3006.0.md.template new file mode 100644 index 00000000000..29d4e41c49e --- /dev/null +++ b/doc/topics/releases/templates/3006.0.md.template @@ -0,0 +1,99 @@ +(release-3006.0)= +# Salt 3006.0 release notes{{ unreleased }} +{{ warning }} + + + +## Onedir packaging + +Going forward from the 3006.0 release, the Salt Project will only provide onedir +packages to install or upgrade Salt. The classic, non-onedir packages will not +be provided for supported operating systems. See [Upgrade to onedir](https://docs.saltproject.io/salt/install-guide/en/latest/topics/upgrade-to-onedir.html) +in the [Salt Install Guide](https://docs.saltproject.io/salt/install-guide/en/latest) for information about upgrading from the classic packages to the onedir +packages. + +## Linux Packaging Salt Master Salt User and Group + +The linux Salt Master packages will now add a Salt user and group +by default. The packages will add the ``user: salt`` config option +to the Salt Master config. The Salt Master service will run as this +user. If you do not want to run the Salt Master as a different user +you can remove the ``user: salt`` config from /etc/salt/master or change +the user to the desired user to run the Salt Master. + +Since the Salt Master is running as a different user, you will need +to ensure you set the owner and group to ``salt`` for your file_roots +and pillar_roots(commonly `/srv/salt` and `/srv/pillar`). + +If you are running a Salt Master, Salt-Api and a Salt Minion on the same +host using the new ``salt`` user and you install a pip dependency into +the onedir environment using ``salt-pip`` or the ``pip`` module, you +need to to chown the directory ``/opt/saltstack/salt/lib//site-packages/`` +with the ``salt`` user and group. + + +## Caveat of salt-pip + +Salt ships with a wrapper script around pip called ``salt-pip``. Users should +use ``salt-pip`` to install any python packages needed to extend Salt. +``salt-pip`` installs python packages into an `extras-3.10` directory located +in the root of the ondir directory, by setting the ``--target`` argument for +pip. This ensures those packages remain installed when upgrading Salt. There is +a known bug in pip when using `--target` where scripts and other non-python +assets may not be cleaned up properly when un-installing. The Salt team is +working to resolve this bug in the up-stream pip project. + + +## Dropping support for Python 3.5 and 3.6 + +Python 3.5 and 3.6 will no longer be supported by Salt since they +are end of life. Going forward our policy will be to align with Python's +supported versions. See [Salt support for Python versions](https://docs.saltproject.io/salt/install-guide/en/latest/topics/salt-python-version-support.html) +for more information. + + +## All salt-api functionality disabled by default + +All netapi clients, which provide the functionality to ``salt-api``, will now +be disabled by default as a security precaution. If you use ``salt-api``, you +must add the new ``netapi_enable_clients`` option to your salt master config. +This is a breaking change and the ``salt-api`` will not function without this +new configuration option. See [Enabling netapi client interfaces](https://docs.saltproject.io/en/3006.0/topics/netapi/netapi-enable-clients.html#netapi-enable-clients) +for more information. + + +## How do I migrate to the onedir packages? + +The migration path from the classic, non-onedir packages to the onedir packages +will include: + +* Repo File: You need to update your repo file to point to the new repo paths + for your platform. After the repo file is updated, upgrade your Salt packages. +* Pip packages: You need to ensure any 3rd party pip packages are installed in + the correct onedir path. This can be accomplished in two ways: + + * ``salt-pip install `` + * Using the ``pip.installed`` Salt state. + +To install python packages into the system python environment, user's must now +provide the ``pip_bin`` or ``bin_env`` to the pip state module. + +For example: + +```yaml +lib-foo: + pip.installed: + - pip_bin: /usr/bin/pip3 +lib-bar: + pip.installed: + - bin_env: /usr/bin/python3 +``` + + +## Changelog +{{ changelog }} diff --git a/doc/topics/releases/templates/3007.0.md.template b/doc/topics/releases/templates/3007.0.md.template new file mode 100644 index 00000000000..6a583f94254 --- /dev/null +++ b/doc/topics/releases/templates/3007.0.md.template @@ -0,0 +1,15 @@ +(release-3007.0)= +# Salt 3007.0 release notes{{ unreleased }} +{{ warning }} + + + + + +## Changelog +{{ changelog }} diff --git a/doc/topics/tutorials/writing_tests.rst b/doc/topics/tutorials/writing_tests.rst index c7dc82069d3..b0505060215 100644 --- a/doc/topics/tutorials/writing_tests.rst +++ b/doc/topics/tutorials/writing_tests.rst @@ -452,6 +452,69 @@ can be used ) +Test Groups +=========== +Salt has four groups + +* fast - Tests that are ~10s or faster. Fast tests make up ~75% of tests and can run in 10 to 20 minutes. +* slow - Tests that are ~10s or slower. +* core - Tests of any speed that test the root parts of salt. +* flaky-jail - Test that need to be temporarily skipped. + + +Pytest Decorators + +* @pytest.mark.slow_test +* @pytest.mark.core_test +* @pytest.mark.flaky_jail + +.. code-block:: python + + @pytest.mark.core_test + def test_ping(self): + """ + test.ping + """ + self.assertTrue(self.run_function("test.ping")) + +You can also mark all the tests in file. + +.. code-block:: python + + pytestmark = [ + pytest.mark.core_test, + ] + + + def test_ping(self): + """ + test.ping + """ + self.assertTrue(self.run_function("test.ping")) + + + def test_ping2(self): + """ + test.ping + """ + for _ in range(10): + self.assertTrue(self.run_function("test.ping")) + +You can enable or disable test groups locally by passing there respected flag: + +* --no-fast-tests +* --slow-tests +* --core-tests +* --flaky-jail + +In Your PR you can enable or disable test groups by setting a label. +All thought the fast, slow and core tests specified in the change file will always run. + +* test:no-fast +* test:slow +* test:core +* test:flaky-jail + Automated Test Runs =================== diff --git a/noxfile.py b/noxfile.py index 826864f8fb0..9a7afa93bdc 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1790,6 +1790,7 @@ def test_pkgs_onedir(session): env = { "ONEDIR_TESTRUN": "1", + "PKG_TEST_TYPE": chunk, } if chunk == "upgrade-classic": diff --git a/pkg/common/conf/master b/pkg/common/conf/master new file mode 100644 index 00000000000..fcad1961c10 --- /dev/null +++ b/pkg/common/conf/master @@ -0,0 +1,1358 @@ +##### Primary configuration settings ##### +########################################## +# This configuration file is used to manage the behavior of the Salt Master. +# Values that are commented out but have an empty line after the comment are +# defaults that do not need to be set in the config. If there is no blank line +# after the comment then the value is presented as an example and is not the +# default. + +# Per default, the master will automatically include all config files +# from master.d/*.conf (master.d is a directory in the same directory +# as the main master config file). +#default_include: master.d/*.conf + +# The address of the interface to bind to: +#interface: 0.0.0.0 + +# Whether the master should listen for IPv6 connections. If this is set to True, +# the interface option must be adjusted, too. (For example: "interface: '::'") +#ipv6: False + +# The tcp port used by the publisher: +#publish_port: 4505 + +# The user under which the salt master will run. Salt will update all +# permissions to allow the specified user to run the master. The exception is +# the job cache, which must be deleted if this user is changed. If the +# modified files cause conflicts, set verify_env to False. +user: salt + +# Tell the master to also use salt-ssh when running commands against minions. +#enable_ssh_minions: False + +# The port used by the communication interface. The ret (return) port is the +# interface used for the file server, authentication, job returns, etc. +#ret_port: 4506 + +# Specify the location of the daemon process ID file: +#pidfile: /var/run/salt-master.pid + +# The root directory prepended to these options: pki_dir, cachedir, +# sock_dir, log_file, autosign_file, autoreject_file, extension_modules, +# key_logfile, pidfile, autosign_grains_dir: +#root_dir: / + +# The path to the master's configuration file. +#conf_file: /etc/salt/master + +# Directory used to store public key data: +#pki_dir: /etc/salt/pki/master + +# Key cache. Increases master speed for large numbers of accepted +# keys. Available options: 'sched'. (Updates on a fixed schedule.) +# Note that enabling this feature means that minions will not be +# available to target for up to the length of the maintenance loop +# which by default is 60s. +#key_cache: '' + +# Directory to store job and cache data: +# This directory may contain sensitive data and should be protected accordingly. +# +#cachedir: /var/cache/salt/master + +# Directory where custom modules sync to. This directory can contain +# subdirectories for each of Salt's module types such as "runners", +# "output", "wheel", "modules", "states", "returners", "engines", +# "utils", etc. +# +# Note, any directories or files not found in the `module_dirs` +# location will be removed from the extension_modules path. + +#extension_modules: /var/cache/salt/master/extmods + +# Directory for custom modules. This directory can contain subdirectories for +# each of Salt's module types such as "runners", "output", "wheel", "modules", +# "states", "returners", "engines", "utils", etc. +#module_dirs: [] + +# Verify and set permissions on configuration directories at startup: +#verify_env: True + +# Set the number of hours to keep old job information in the job cache. +# This option is deprecated by the keep_jobs_seconds option. +#keep_jobs: 24 + +# Set the number of seconds to keep old job information in the job cache: +#keep_jobs_seconds: 86400 + +# The number of seconds to wait when the client is requesting information +# about running jobs. +#gather_job_timeout: 10 + +# Set the default timeout for the salt command and api. The default is 5 +# seconds. +#timeout: 5 + +# The loop_interval option controls the seconds for the master's maintenance +# process check cycle. This process updates file server backends, cleans the +# job cache and executes the scheduler. +#loop_interval: 60 + +# Set the default outputter used by the salt command. The default is "nested". +#output: nested + +# To set a list of additional directories to search for salt outputters, set the +# outputter_dirs option. +#outputter_dirs: [] + +# Set the default output file used by the salt command. Default is to output +# to the CLI and not to a file. Functions the same way as the "--out-file" +# CLI option, only sets this to a single file for all salt commands. +#output_file: None + +# Return minions that timeout when running commands like test.ping +#show_timeout: True + +# Tell the client to display the jid when a job is published. +#show_jid: False + +# By default, output is colored. To disable colored output, set the color value +# to False. +#color: True + +# Do not strip off the colored output from nested results and state outputs +# (true by default). +# strip_colors: False + +# To display a summary of the number of minions targeted, the number of +# minions returned, and the number of minions that did not return, set the +# cli_summary value to True. (False by default.) +# +#cli_summary: False + +# Set the directory used to hold unix sockets: +#sock_dir: /var/run/salt/master + +# The master can take a while to start up when lspci and/or dmidecode is used +# to populate the grains for the master. Enable if you want to see GPU hardware +# data for your master. +# enable_gpu_grains: False + +# The master maintains a job cache. While this is a great addition, it can be +# a burden on the master for larger deployments (over 5000 minions). +# Disabling the job cache will make previously executed jobs unavailable to +# the jobs system and is not generally recommended. +#job_cache: True + +# Cache minion grains, pillar and mine data via the cache subsystem in the +# cachedir or a database. +#minion_data_cache: True + +# Cache subsystem module to use for minion data cache. +#cache: localfs +# Enables a fast in-memory cache booster and sets the expiration time. +#memcache_expire_seconds: 0 +# Set a memcache limit in items (bank + key) per cache storage (driver + driver_opts). +#memcache_max_items: 1024 +# Each time a cache storage got full cleanup all the expired items not just the oldest one. +#memcache_full_cleanup: False +# Enable collecting the memcache stats and log it on `debug` log level. +#memcache_debug: False + +# Store all returns in the given returner. +# Setting this option requires that any returner-specific configuration also +# be set. See various returners in salt/returners for details on required +# configuration values. (See also, event_return_queue, and event_return_queue_max_seconds below.) +# +#event_return: mysql + +# On busy systems, enabling event_returns can cause a considerable load on +# the storage system for returners. Events can be queued on the master and +# stored in a batched fashion using a single transaction for multiple events. +# By default, events are not queued. +#event_return_queue: 0 + +# In some cases enabling event return queueing can be very helpful, but the bus +# may not busy enough to flush the queue consistently. Setting this to a reasonable +# value (1-30 seconds) will cause the queue to be flushed when the oldest event is older +# than `event_return_queue_max_seconds` regardless of how many events are in the queue. +#event_return_queue_max_seconds: 0 + +# Only return events matching tags in a whitelist, supports glob matches. +#event_return_whitelist: +# - salt/master/a_tag +# - salt/run/*/ret + +# Store all event returns **except** the tags in a blacklist, supports globs. +#event_return_blacklist: +# - salt/master/not_this_tag +# - salt/wheel/*/ret + +# Passing very large events can cause the minion to consume large amounts of +# memory. This value tunes the maximum size of a message allowed onto the +# master event bus. The value is expressed in bytes. +#max_event_size: 1048576 + +# Windows platforms lack posix IPC and must rely on slower TCP based inter- +# process communications. Set ipc_mode to 'tcp' on such systems +#ipc_mode: ipc + +# Overwrite the default tcp ports used by the minion when ipc_mode is set to 'tcp' +#tcp_master_pub_port: 4510 +#tcp_master_pull_port: 4511 + +# By default, the master AES key rotates every 24 hours. The next command +# following a key rotation will trigger a key refresh from the minion which may +# result in minions which do not respond to the first command after a key refresh. +# +# To tell the master to ping all minions immediately after an AES key refresh, set +# ping_on_rotate to True. This should mitigate the issue where a minion does not +# appear to initially respond after a key is rotated. +# +# Note that ping_on_rotate may cause high load on the master immediately after +# the key rotation event as minions reconnect. Consider this carefully if this +# salt master is managing a large number of minions. +# +# If disabled, it is recommended to handle this event by listening for the +# 'aes_key_rotate' event with the 'key' tag and acting appropriately. +# ping_on_rotate: False + +# By default, the master deletes its cache of minion data when the key for that +# minion is removed. To preserve the cache after key deletion, set +# 'preserve_minion_cache' to True. +# +# WARNING: This may have security implications if compromised minions auth with +# a previous deleted minion ID. +#preserve_minion_cache: False + +# Allow or deny minions from requesting their own key revocation +#allow_minion_key_revoke: True + +# If max_minions is used in large installations, the master might experience +# high-load situations because of having to check the number of connected +# minions for every authentication. This cache provides the minion-ids of +# all connected minions to all MWorker-processes and greatly improves the +# performance of max_minions. +# con_cache: False + +# The master can include configuration from other files. To enable this, +# pass a list of paths to this option. The paths can be either relative or +# absolute; if relative, they are considered to be relative to the directory +# the main master configuration file lives in (this file). Paths can make use +# of shell-style globbing. If no files are matched by a path passed to this +# option, then the master will log a warning message. +# +# Include a config file from some other path: +# include: /etc/salt/extra_config +# +# Include config from several files and directories: +# include: +# - /etc/salt/extra_config + + +##### Large-scale tuning settings ##### +########################################## +# Max open files +# +# Each minion connecting to the master uses AT LEAST one file descriptor, the +# master subscription connection. If enough minions connect you might start +# seeing on the console (and then salt-master crashes): +# Too many open files (tcp_listener.cpp:335) +# Aborted (core dumped) +# +# By default this value will be the one of `ulimit -Hn`, ie, the hard limit for +# max open files. +# +# If you wish to set a different value than the default one, uncomment and +# configure this setting. Remember that this value CANNOT be higher than the +# hard limit. Raising the hard limit depends on your OS and/or distribution, +# a good way to find the limit is to search the internet. For example: +# raise max open files hard limit debian +# +#max_open_files: 100000 + +# The number of worker threads to start. These threads are used to manage +# return calls made from minions to the master. If the master seems to be +# running slowly, increase the number of threads. This setting can not be +# set lower than 3. +#worker_threads: 5 + +# Set the ZeroMQ high water marks +# http://api.zeromq.org/3-2:zmq-setsockopt + +# The listen queue size / backlog +#zmq_backlog: 1000 + +# The publisher interface ZeroMQPubServerChannel +#pub_hwm: 1000 + +# The master may allocate memory per-event and not +# reclaim it. +# To set a high-water mark for memory allocation, use +# ipc_write_buffer to set a high-water mark for message +# buffering. +# Value: In bytes. Set to 'dynamic' to have Salt select +# a value for you. Default is disabled. +# ipc_write_buffer: 'dynamic' + +# These two batch settings, batch_safe_limit and batch_safe_size, are used to +# automatically switch to a batch mode execution. If a command would have been +# sent to more than minions, then run the command in +# batches of . If no batch_safe_size is specified, a default +# of 8 will be used. If no batch_safe_limit is specified, then no automatic +# batching will occur. +#batch_safe_limit: 100 +#batch_safe_size: 8 + +# Master stats enables stats events to be fired from the master at close +# to the defined interval +#master_stats: False +#master_stats_event_iter: 60 + + +##### Security settings ##### +########################################## +# Enable passphrase protection of Master private key. Although a string value +# is acceptable; passwords should be stored in an external vaulting mechanism +# and retrieved via sdb. See https://docs.saltproject.io/en/latest/topics/sdb/. +# Passphrase protection is off by default but an example of an sdb profile and +# query is as follows. +# masterkeyring: +# driver: keyring +# service: system +# +# key_pass: sdb://masterkeyring/key_pass + +# Enable passphrase protection of the Master signing_key. This only applies if +# master_sign_pubkey is set to True. This is disabled by default. +# master_sign_pubkey: True +# signing_key_pass: sdb://masterkeyring/signing_pass + +# Enable "open mode", this mode still maintains encryption, but turns off +# authentication, this is only intended for highly secure environments or for +# the situation where your keys end up in a bad state. If you run in open mode +# you do so at your own risk! +#open_mode: False + +# Enable auto_accept, this setting will automatically accept all incoming +# public keys from the minions. Note that this is insecure. +#auto_accept: False + +# The size of key that should be generated when creating new keys. +#keysize: 2048 + +# Time in minutes that an incoming public key with a matching name found in +# pki_dir/minion_autosign/keyid is automatically accepted. Expired autosign keys +# are removed when the master checks the minion_autosign directory. +# 0 equals no timeout +# autosign_timeout: 120 + +# If the autosign_file is specified, incoming keys specified in the +# autosign_file will be automatically accepted. This is insecure. Regular +# expressions as well as globing lines are supported. The file must be readonly +# except for the owner. Use permissive_pki_access to allow the group write access. +#autosign_file: /etc/salt/autosign.conf + +# Works like autosign_file, but instead allows you to specify minion IDs for +# which keys will automatically be rejected. Will override both membership in +# the autosign_file and the auto_accept setting. +#autoreject_file: /etc/salt/autoreject.conf + +# If the autosign_grains_dir is specified, incoming keys from minions with grain +# values matching those defined in files in this directory will be accepted +# automatically. This is insecure. Minions need to be configured to send the grains. +#autosign_grains_dir: /etc/salt/autosign_grains + +# Enable permissive access to the salt keys. This allows you to run the +# master or minion as root, but have a non-root group be given access to +# your pki_dir. To make the access explicit, root must belong to the group +# you've given access to. This is potentially quite insecure. If an autosign_file +# is specified, enabling permissive_pki_access will allow group access to that +# specific file. +#permissive_pki_access: False + +# Allow users on the master access to execute specific commands on minions. +# This setting should be treated with care since it opens up execution +# capabilities to non root users. By default this capability is completely +# disabled. +#publisher_acl: +# larry: +# - test.ping +# - network.* +# +# Blacklist any of the following users or modules +# +# This example would blacklist all non sudo users, including root from +# running any commands. It would also blacklist any use of the "cmd" +# module. This is completely disabled by default. +# +# +# Check the list of configured users in client ACL against users on the +# system and throw errors if they do not exist. +#client_acl_verify: True +# +#publisher_acl_blacklist: +# users: +# - root +# - '^(?!sudo_).*$' # all non sudo users +# modules: +# - cmd + +# Enforce publisher_acl & publisher_acl_blacklist when users have sudo +# access to the salt command. +# +#sudo_acl: False + +# The external auth system uses the Salt auth modules to authenticate and +# validate users to access areas of the Salt system. +#external_auth: +# pam: +# fred: +# - test.* +# +# Time (in seconds) for a newly generated token to live. Default: 12 hours +#token_expire: 43200 +# +# Allow eauth users to specify the expiry time of the tokens they generate. +# A boolean applies to all users or a dictionary of whitelisted eauth backends +# and usernames may be given. +# token_expire_user_override: +# pam: +# - fred +# - tom +# ldap: +# - gary +# +#token_expire_user_override: False + +# Set to True to enable keeping the calculated user's auth list in the token +# file. This is disabled by default and the auth list is calculated or requested +# from the eauth driver each time. +# +# Note: `keep_acl_in_token` will be forced to True when using external authentication +# for REST API (`rest` is present under `external_auth`). This is because the REST API +# does not store the password, and can therefore not retroactively fetch the ACL, so +# the ACL must be stored in the token. +#keep_acl_in_token: False + +# Auth subsystem module to use to get authorized access list for a user. By default it's +# the same module used for external authentication. +#eauth_acl_module: django + +# Allow minions to push files to the master. This is disabled by default, for +# security purposes. +#file_recv: False + +# Set a hard-limit on the size of the files that can be pushed to the master. +# It will be interpreted as megabytes. Default: 100 +#file_recv_max_size: 100 + +# Signature verification on messages published from the master. +# This causes the master to cryptographically sign all messages published to its event +# bus, and minions then verify that signature before acting on the message. +# +# This is False by default. +# +# Note that to facilitate interoperability with masters and minions that are different +# versions, if sign_pub_messages is True but a message is received by a minion with +# no signature, it will still be accepted, and a warning message will be logged. +# Conversely, if sign_pub_messages is False, but a minion receives a signed +# message it will be accepted, the signature will not be checked, and a warning message +# will be logged. This behavior went away in Salt 2014.1.0 and these two situations +# will cause minion to throw an exception and drop the message. +# sign_pub_messages: False + +# Signature verification on messages published from minions +# This requires that minions cryptographically sign the messages they +# publish to the master. If minions are not signing, then log this information +# at loglevel 'INFO' and drop the message without acting on it. +# require_minion_sign_messages: False + +# The below will drop messages when their signatures do not validate. +# Note that when this option is False but `require_minion_sign_messages` is True +# minions MUST sign their messages but the validity of their signatures +# is ignored. +# These two config options exist so a Salt infrastructure can be moved +# to signing minion messages gradually. +# drop_messages_signature_fail: False + +# Use TLS/SSL encrypted connection between master and minion. +# Can be set to a dictionary containing keyword arguments corresponding to Python's +# 'ssl.wrap_socket' method. +# Default is None. +#ssl: +# keyfile: +# certfile: +# ssl_version: PROTOCOL_TLSv1_2 + +##### Salt-SSH Configuration ##### +########################################## +# Define the default salt-ssh roster module to use +#roster: flat + +# Pass in an alternative location for the salt-ssh `flat` roster file +#roster_file: /etc/salt/roster + +# Define locations for `flat` roster files so they can be chosen when using Salt API. +# An administrator can place roster files into these locations. Then when +# calling Salt API, parameter 'roster_file' should contain a relative path to +# these locations. That is, "roster_file=/foo/roster" will be resolved as +# "/etc/salt/roster.d/foo/roster" etc. This feature prevents passing insecure +# custom rosters through the Salt API. +# +#rosters: +# - /etc/salt/roster.d +# - /opt/salt/some/more/rosters + +# The ssh password to log in with. +#ssh_passwd: '' + +#The target system's ssh port number. +#ssh_port: 22 + +# Comma-separated list of ports to scan. +#ssh_scan_ports: 22 + +# Scanning socket timeout for salt-ssh. +#ssh_scan_timeout: 0.01 + +# Boolean to run command via sudo. +#ssh_sudo: False + +# Boolean to run ssh_pre_flight script defined in roster. By default +# the script will only run if the thin_dir does not exist on the targeted +# minion. This forces the script to run regardless of the thin dir existing +# or not. +#ssh_run_pre_flight: True + +# Number of seconds to wait for a response when establishing an SSH connection. +#ssh_timeout: 60 + +# The user to log in as. +#ssh_user: root + +# The log file of the salt-ssh command: +#ssh_log_file: /var/log/salt/ssh + +# Pass in minion option overrides that will be inserted into the SHIM for +# salt-ssh calls. The local minion config is not used for salt-ssh. Can be +# overridden on a per-minion basis in the roster (`minion_opts`) +#ssh_minion_opts: +# gpg_keydir: /root/gpg + +# Set this to True to default to using ~/.ssh/id_rsa for salt-ssh +# authentication with minions +#ssh_use_home_key: False + +# Set this to True to default salt-ssh to run with ``-o IdentitiesOnly=yes``. +# This option is intended for situations where the ssh-agent offers many +# different identities and allows ssh to ignore those identities and use the +# only one specified in options. +#ssh_identities_only: False + +# List-only nodegroups for salt-ssh. Each group must be formed as either a +# comma-separated list, or a YAML list. This option is useful to group minions +# into easy-to-target groups when using salt-ssh. These groups can then be +# targeted with the normal -N argument to salt-ssh. +#ssh_list_nodegroups: {} + +# salt-ssh has the ability to update the flat roster file if a minion is not +# found in the roster. Set this to True to enable it. +#ssh_update_roster: False + +##### Master Module Management ##### +########################################## +# Manage how master side modules are loaded. + +# Add any additional locations to look for master runners: +#runner_dirs: [] + +# Add any additional locations to look for master utils: +#utils_dirs: [] + +# Enable Cython for master side modules: +#cython_enable: False + + +##### State System settings ##### +########################################## +# The state system uses a "top" file to tell the minions what environment to +# use and what modules to use. The state_top file is defined relative to the +# root of the base environment as defined in "File Server settings" below. +#state_top: top.sls + +# The master_tops option replaces the external_nodes option by creating +# a plugable system for the generation of external top data. The external_nodes +# option is deprecated by the master_tops option. +# +# To gain the capabilities of the classic external_nodes system, use the +# following configuration: +# master_tops: +# ext_nodes: +# +#master_tops: {} + +# The renderer to use on the minions to render the state data +#renderer: jinja|yaml + +# Default Jinja environment options for all templates except sls templates +#jinja_env: +# block_start_string: '{%' +# block_end_string: '%}' +# variable_start_string: '{{' +# variable_end_string: '}}' +# comment_start_string: '{#' +# comment_end_string: '#}' +# line_statement_prefix: +# line_comment_prefix: +# trim_blocks: False +# lstrip_blocks: False +# newline_sequence: '\n' +# keep_trailing_newline: False + +# Jinja environment options for sls templates +#jinja_sls_env: +# block_start_string: '{%' +# block_end_string: '%}' +# variable_start_string: '{{' +# variable_end_string: '}}' +# comment_start_string: '{#' +# comment_end_string: '#}' +# line_statement_prefix: +# line_comment_prefix: +# trim_blocks: False +# lstrip_blocks: False +# newline_sequence: '\n' +# keep_trailing_newline: False + +# The failhard option tells the minions to stop immediately after the first +# failure detected in the state execution, defaults to False +#failhard: False + +# The state_verbose and state_output settings can be used to change the way +# state system data is printed to the display. By default all data is printed. +# The state_verbose setting can be set to True or False, when set to False +# all data that has a result of True and no changes will be suppressed. +#state_verbose: True + +# The state_output setting controls which results will be output full multi line +# full, terse - each state will be full/terse +# mixed - only states with errors will be full +# changes - states with changes and errors will be full +# full_id, mixed_id, changes_id and terse_id are also allowed; +# when set, the state ID will be used as name in the output +#state_output: full + +# The state_output_diff setting changes whether or not the output from +# successful states is returned. Useful when even the terse output of these +# states is cluttering the logs. Set it to True to ignore them. +#state_output_diff: False + +# The state_output_profile setting changes whether profile information +# will be shown for each state run. +#state_output_profile: True + +# The state_output_pct setting changes whether success and failure information +# as a percent of total actions will be shown for each state run. +#state_output_pct: False + +# The state_compress_ids setting aggregates information about states which have +# multiple "names" under the same state ID in the highstate output. +#state_compress_ids: False + +# Automatically aggregate all states that have support for mod_aggregate by +# setting to 'True'. Or pass a list of state module names to automatically +# aggregate just those types. +# +# state_aggregate: +# - pkg +# +#state_aggregate: False + +# Send progress events as each function in a state run completes execution +# by setting to 'True'. Progress events are in the format +# 'salt/job//prog//'. +#state_events: False + +##### File Server settings ##### +########################################## +# Salt runs a lightweight file server written in zeromq to deliver files to +# minions. This file server is built into the master daemon and does not +# require a dedicated port. + +# The file server works on environments passed to the master, each environment +# can have multiple root directories, the subdirectories in the multiple file +# roots cannot match, otherwise the downloaded files will not be able to be +# reliably ensured. A base environment is required to house the top file. +# Example: +# file_roots: +# base: +# - /srv/salt/ +# dev: +# - /srv/salt/dev/services +# - /srv/salt/dev/states +# prod: +# - /srv/salt/prod/services +# - /srv/salt/prod/states +# +#file_roots: +# base: +# - /srv/salt +# + +# The master_roots setting configures a master-only copy of the file_roots dictionary, +# used by the state compiler. +#master_roots: +# base: +# - /srv/salt-master + +# When using multiple environments, each with their own top file, the +# default behaviour is an unordered merge. To prevent top files from +# being merged together and instead to only use the top file from the +# requested environment, set this value to 'same'. +#top_file_merging_strategy: merge + +# To specify the order in which environments are merged, set the ordering +# in the env_order option. Given a conflict, the last matching value will +# win. +#env_order: ['base', 'dev', 'prod'] + +# If top_file_merging_strategy is set to 'same' and an environment does not +# contain a top file, the top file in the environment specified by default_top +# will be used instead. +#default_top: base + +# The hash_type is the hash to use when discovering the hash of a file on +# the master server. The default is sha256, but md5, sha1, sha224, sha384 and +# sha512 are also supported. +# +# WARNING: While md5 and sha1 are also supported, do not use them due to the +# high chance of possible collisions and thus security breach. +# +# Prior to changing this value, the master should be stopped and all Salt +# caches should be cleared. +#hash_type: sha256 + +# The buffer size in the file server can be adjusted here: +#file_buffer_size: 1048576 + +# A regular expression (or a list of expressions) that will be matched +# against the file path before syncing the modules and states to the minions. +# This includes files affected by the file.recurse state. +# For example, if you manage your custom modules and states in subversion +# and don't want all the '.svn' folders and content synced to your minions, +# you could set this to '/\.svn($|/)'. By default nothing is ignored. +#file_ignore_regex: +# - '/\.svn($|/)' +# - '/\.git($|/)' + +# A file glob (or list of file globs) that will be matched against the file +# path before syncing the modules and states to the minions. This is similar +# to file_ignore_regex above, but works on globs instead of regex. By default +# nothing is ignored. +# file_ignore_glob: +# - '*.pyc' +# - '*/somefolder/*.bak' +# - '*.swp' + +# File Server Backend +# +# Salt supports a modular fileserver backend system, this system allows +# the salt master to link directly to third party systems to gather and +# manage the files available to minions. Multiple backends can be +# configured and will be searched for the requested file in the order in which +# they are defined here. The default setting only enables the standard backend +# "roots" which uses the "file_roots" option. +#fileserver_backend: +# - roots +# +# To use multiple backends list them in the order they are searched: +#fileserver_backend: +# - git +# - roots +# +# Uncomment the line below if you do not want the file_server to follow +# symlinks when walking the filesystem tree. This is set to True +# by default. Currently this only applies to the default roots +# fileserver_backend. +#fileserver_followsymlinks: False +# +# Uncomment the line below if you do not want symlinks to be +# treated as the files they are pointing to. By default this is set to +# False. By uncommenting the line below, any detected symlink while listing +# files on the Master will not be returned to the Minion. +#fileserver_ignoresymlinks: True +# +# The fileserver can fire events off every time the fileserver is updated, +# these are disabled by default, but can be easily turned on by setting this +# flag to True +#fileserver_events: False + +# Git File Server Backend Configuration +# +# Optional parameter used to specify the provider to be used for gitfs. Must be +# either pygit2 or gitpython. If unset, then both will be tried (in that +# order), and the first one with a compatible version installed will be the +# provider that is used. +# +#gitfs_provider: pygit2 + +# Along with gitfs_password, is used to authenticate to HTTPS remotes. +# gitfs_user: '' + +# Along with gitfs_user, is used to authenticate to HTTPS remotes. +# This parameter is not required if the repository does not use authentication. +#gitfs_password: '' + +# By default, Salt will not authenticate to an HTTP (non-HTTPS) remote. +# This parameter enables authentication over HTTP. Enable this at your own risk. +#gitfs_insecure_auth: False + +# Along with gitfs_privkey (and optionally gitfs_passphrase), is used to +# authenticate to SSH remotes. This parameter (or its per-remote counterpart) +# is required for SSH remotes. +#gitfs_pubkey: '' + +# Along with gitfs_pubkey (and optionally gitfs_passphrase), is used to +# authenticate to SSH remotes. This parameter (or its per-remote counterpart) +# is required for SSH remotes. +#gitfs_privkey: '' + +# This parameter is optional, required only when the SSH key being used to +# authenticate is protected by a passphrase. +#gitfs_passphrase: '' + +# When using the git fileserver backend at least one git remote needs to be +# defined. The user running the salt master will need read access to the repo. +# +# The repos will be searched in order to find the file requested by a client +# and the first repo to have the file will return it. +# When using the git backend branches and tags are translated into salt +# environments. +# Note: file:// repos will be treated as a remote, so refs you want used must +# exist in that repo as *local* refs. +#gitfs_remotes: +# - git://github.com/saltstack/salt-states.git +# - file:///var/git/saltmaster +# +# The gitfs_ssl_verify option specifies whether to ignore ssl certificate +# errors when contacting the gitfs backend. You might want to set this to +# false if you're using a git backend that uses a self-signed certificate but +# keep in mind that setting this flag to anything other than the default of True +# is a security concern, you may want to try using the ssh transport. +#gitfs_ssl_verify: True +# +# The gitfs_root option gives the ability to serve files from a subdirectory +# within the repository. The path is defined relative to the root of the +# repository and defaults to the repository root. +#gitfs_root: somefolder/otherfolder +# +# The refspecs fetched by gitfs remotes +#gitfs_refspecs: +# - '+refs/heads/*:refs/remotes/origin/*' +# - '+refs/tags/*:refs/tags/*' +# +# +##### Pillar settings ##### +########################################## +# Salt Pillars allow for the building of global data that can be made selectively +# available to different minions based on minion grain filtering. The Salt +# Pillar is laid out in the same fashion as the file server, with environments, +# a top file and sls files. However, pillar data does not need to be in the +# highstate format, and is generally just key/value pairs. +#pillar_roots: +# base: +# - /srv/pillar +# +#ext_pillar: +# - hiera: /etc/hiera.yaml +# - cmd_yaml: cat /etc/salt/yaml + + +# A list of paths to be recursively decrypted during pillar compilation. +# Entries in this list can be formatted either as a simple string, or as a +# key/value pair, with the key being the pillar location, and the value being +# the renderer to use for pillar decryption. If the former is used, the +# renderer specified by decrypt_pillar_default will be used. +#decrypt_pillar: +# - 'foo:bar': gpg +# - 'lorem:ipsum:dolor' + +# The delimiter used to distinguish nested data structures in the +# decrypt_pillar option. +#decrypt_pillar_delimiter: ':' + +# The default renderer used for decryption, if one is not specified for a given +# pillar key in decrypt_pillar. +#decrypt_pillar_default: gpg + +# List of renderers which are permitted to be used for pillar decryption. +#decrypt_pillar_renderers: +# - gpg + +# If this is `True` and the ciphertext could not be decrypted, then an error is +# raised. +#gpg_decrypt_must_succeed: False + +# The ext_pillar_first option allows for external pillar sources to populate +# before file system pillar. This allows for targeting file system pillar from +# ext_pillar. +#ext_pillar_first: False + +# The external pillars permitted to be used on-demand using pillar.ext +#on_demand_ext_pillar: +# - libvirt +# - virtkey + +# The pillar_gitfs_ssl_verify option specifies whether to ignore ssl certificate +# errors when contacting the pillar gitfs backend. You might want to set this to +# false if you're using a git backend that uses a self-signed certificate but +# keep in mind that setting this flag to anything other than the default of True +# is a security concern, you may want to try using the ssh transport. +#pillar_gitfs_ssl_verify: True + +# The pillar_opts option adds the master configuration file data to a dict in +# the pillar called "master". This is used to set simple configurations in the +# master config file that can then be used on minions. +#pillar_opts: False + +# The pillar_safe_render_error option prevents the master from passing pillar +# render errors to the minion. This is set on by default because the error could +# contain templating data which would give that minion information it shouldn't +# have, like a password! When set true the error message will only show: +# Rendering SLS 'my.sls' failed. Please see master log for details. +#pillar_safe_render_error: True + +# The pillar_source_merging_strategy option allows you to configure merging strategy +# between different sources. It accepts five values: none, recurse, aggregate, overwrite, +# or smart. None will not do any merging at all. Recurse will merge recursively mapping of data. +# Aggregate instructs aggregation of elements between sources that use the #!yamlex renderer. Overwrite +# will overwrite elements according the order in which they are processed. This is +# behavior of the 2014.1 branch and earlier. Smart guesses the best strategy based +# on the "renderer" setting and is the default value. +#pillar_source_merging_strategy: smart + +# Recursively merge lists by aggregating them instead of replacing them. +#pillar_merge_lists: False + +# Set this option to True to force the pillarenv to be the same as the effective +# saltenv when running states. If pillarenv is specified this option will be +# ignored. +#pillarenv_from_saltenv: False + +# Set this option to 'True' to force a 'KeyError' to be raised whenever an +# attempt to retrieve a named value from pillar fails. When this option is set +# to 'False', the failed attempt returns an empty string. Default is 'False'. +#pillar_raise_on_missing: False + +# Git External Pillar (git_pillar) Configuration Options +# +# Specify the provider to be used for git_pillar. Must be either pygit2 or +# gitpython. If unset, then both will be tried in that same order, and the +# first one with a compatible version installed will be the provider that +# is used. +#git_pillar_provider: pygit2 + +# If the desired branch matches this value, and the environment is omitted +# from the git_pillar configuration, then the environment for that git_pillar +# remote will be base. +#git_pillar_base: master + +# If the branch is omitted from a git_pillar remote, then this branch will +# be used instead +#git_pillar_branch: master + +# Environment to use for git_pillar remotes. This is normally derived from +# the branch/tag (or from a per-remote env parameter), but if set this will +# override the process of deriving the env from the branch/tag name. +#git_pillar_env: '' + +# Path relative to the root of the repository where the git_pillar top file +# and SLS files are located. +#git_pillar_root: '' + +# Specifies whether or not to ignore SSL certificate errors when contacting +# the remote repository. +#git_pillar_ssl_verify: False + +# When set to False, if there is an update/checkout lock for a git_pillar +# remote and the pid written to it is not running on the master, the lock +# file will be automatically cleared and a new lock will be obtained. +#git_pillar_global_lock: True + +# Git External Pillar Authentication Options +# +# Along with git_pillar_password, is used to authenticate to HTTPS remotes. +#git_pillar_user: '' + +# Along with git_pillar_user, is used to authenticate to HTTPS remotes. +# This parameter is not required if the repository does not use authentication. +#git_pillar_password: '' + +# By default, Salt will not authenticate to an HTTP (non-HTTPS) remote. +# This parameter enables authentication over HTTP. +#git_pillar_insecure_auth: False + +# Along with git_pillar_privkey (and optionally git_pillar_passphrase), +# is used to authenticate to SSH remotes. +#git_pillar_pubkey: '' + +# Along with git_pillar_pubkey (and optionally git_pillar_passphrase), +# is used to authenticate to SSH remotes. +#git_pillar_privkey: '' + +# This parameter is optional, required only when the SSH key being used +# to authenticate is protected by a passphrase. +#git_pillar_passphrase: '' + +# The refspecs fetched by git_pillar remotes +#git_pillar_refspecs: +# - '+refs/heads/*:refs/remotes/origin/*' +# - '+refs/tags/*:refs/tags/*' + +# A master can cache pillars locally to bypass the expense of having to render them +# for each minion on every request. This feature should only be enabled in cases +# where pillar rendering time is known to be unsatisfactory and any attendant security +# concerns about storing pillars in a master cache have been addressed. +# +# When enabling this feature, be certain to read through the additional ``pillar_cache_*`` +# configuration options to fully understand the tunable parameters and their implications. +# +# Note: setting ``pillar_cache: True`` has no effect on targeting Minions with Pillars. +# See https://docs.saltproject.io/en/latest/topics/targeting/pillar.html +#pillar_cache: False + +# If and only if a master has set ``pillar_cache: True``, the cache TTL controls the amount +# of time, in seconds, before the cache is considered invalid by a master and a fresh +# pillar is recompiled and stored. +#pillar_cache_ttl: 3600 + +# If and only if a master has set `pillar_cache: True`, one of several storage providers +# can be utilized. +# +# `disk`: The default storage backend. This caches rendered pillars to the master cache. +# Rendered pillars are serialized and deserialized as msgpack structures for speed. +# Note that pillars are stored UNENCRYPTED. Ensure that the master cache +# has permissions set appropriately. (Same defaults are provided.) +# +# memory: [EXPERIMENTAL] An optional backend for pillar caches which uses a pure-Python +# in-memory data structure for maximal performance. There are several caveats, +# however. First, because each master worker contains its own in-memory cache, +# there is no guarantee of cache consistency between minion requests. This +# works best in situations where the pillar rarely if ever changes. Secondly, +# and perhaps more importantly, this means that unencrypted pillars will +# be accessible to any process which can examine the memory of the ``salt-master``! +# This may represent a substantial security risk. +# +#pillar_cache_backend: disk + +# A master can also cache GPG data locally to bypass the expense of having to render them +# for each minion on every request. This feature should only be enabled in cases +# where pillar rendering time is known to be unsatisfactory and any attendant security +# concerns about storing decrypted GPG data in a master cache have been addressed. +# +# When enabling this feature, be certain to read through the additional ``gpg_cache_*`` +# configuration options to fully understand the tunable parameters and their implications. +#gpg_cache: False + +# If and only if a master has set ``gpg_cache: True``, the cache TTL controls the amount +# of time, in seconds, before the cache is considered invalid by a master and a fresh +# pillar is recompiled and stored. +#gpg_cache_ttl: 86400 + +# If and only if a master has set `gpg_cache: True`, one of several storage providers +# can be utilized. Available options are the same as ``pillar_cache_backend``. +#gpg_cache_backend: disk + + +###### Reactor Settings ##### +########################################### +# Define a salt reactor. See https://docs.saltproject.io/en/latest/topics/reactor/ +#reactor: [] + +#Set the TTL for the cache of the reactor configuration. +#reactor_refresh_interval: 60 + +#Configure the number of workers for the runner/wheel in the reactor. +#reactor_worker_threads: 10 + +#Define the queue size for workers in the reactor. +#reactor_worker_hwm: 10000 + + +##### Syndic settings ##### +########################################## +# The Salt syndic is used to pass commands through a master from a higher +# master. Using the syndic is simple. If this is a master that will have +# syndic servers(s) below it, then set the "order_masters" setting to True. +# +# If this is a master that will be running a syndic daemon for passthrough, then +# the "syndic_master" setting needs to be set to the location of the master server +# to receive commands from. + +# Set the order_masters setting to True if this master will command lower +# masters' syndic interfaces. +#order_masters: False + +# If this master will be running a salt syndic daemon, syndic_master tells +# this master where to receive commands from. +#syndic_master: masterofmasters + +# This is the 'ret_port' of the MasterOfMaster: +#syndic_master_port: 4506 + +# PID file of the syndic daemon: +#syndic_pidfile: /var/run/salt-syndic.pid + +# The log file of the salt-syndic daemon: +#syndic_log_file: /var/log/salt/syndic + +# The behaviour of the multi-syndic when connection to a master of masters failed. +# Can specify ``random`` (default) or ``ordered``. If set to ``random``, masters +# will be iterated in random order. If ``ordered`` is specified, the configured +# order will be used. +#syndic_failover: random + +# The number of seconds for the salt client to wait for additional syndics to +# check in with their lists of expected minions before giving up. +#syndic_wait: 5 + + +##### Peer Publish settings ##### +########################################## +# Salt minions can send commands to other minions, but only if the minion is +# allowed to. By default "Peer Publication" is disabled, and when enabled it +# is enabled for specific minions and specific commands. This allows secure +# compartmentalization of commands based on individual minions. + +# The configuration uses regular expressions to match minions and then a list +# of regular expressions to match functions. The following will allow the +# minion authenticated as foo.example.com to execute functions from the test +# and pkg modules. +#peer: +# foo.example.com: +# - test.* +# - pkg.* +# +# This will allow all minions to execute all commands: +#peer: +# .*: +# - .* +# +# This is not recommended, since it would allow anyone who gets root on any +# single minion to instantly have root on all of the minions! + +# Minions can also be allowed to execute runners from the salt master. +# Since executing a runner from the minion could be considered a security risk, +# it needs to be enabled. This setting functions just like the peer setting +# except that it opens up runners instead of module functions. +# +# All peer runner support is turned off by default and must be enabled before +# using. This will enable all peer runners for all minions: +#peer_run: +# .*: +# - .* +# +# To enable just the manage.up runner for the minion foo.example.com: +#peer_run: +# foo.example.com: +# - manage.up +# +# +##### Mine settings ##### +##################################### +# Restrict mine.get access from minions. By default any minion has a full access +# to get all mine data from master cache. In acl definion below, only pcre matches +# are allowed. +# mine_get: +# .*: +# - .* +# +# The example below enables minion foo.example.com to get 'network.interfaces' mine +# data only, minions web* to get all network.* and disk.* mine data and all other +# minions won't get any mine data. +# mine_get: +# foo.example.com: +# - network.interfaces +# web.*: +# - network.* +# - disk.* + + +##### Logging settings ##### +########################################## +# The location of the master log file +# The master log can be sent to a regular file, local path name, or network +# location. Remote logging works best when configured to use rsyslogd(8) (e.g.: +# ``file:///dev/log``), with rsyslogd(8) configured for network logging. The URI +# format is: ://:/ +#log_file: /var/log/salt/master +#log_file: file:///dev/log +#log_file: udp://loghost:10514 + +#log_file: /var/log/salt/master +#key_logfile: /var/log/salt/key + +# The level of messages to send to the console. +# One of 'garbage', 'trace', 'debug', info', 'warning', 'error', 'critical'. +# +# The following log levels are considered INSECURE and may log sensitive data: +# ['garbage', 'trace', 'debug'] +# +#log_level: warning + +# The level of messages to send to the log file. +# One of 'garbage', 'trace', 'debug', 'info', 'warning', 'error', 'critical'. +# If using 'log_granular_levels' this must be set to the highest desired level. +#log_level_logfile: warning + +# The date and time format used in log messages. Allowed date/time formatting +# can be seen here: http://docs.python.org/library/time.html#time.strftime +#log_datefmt: '%H:%M:%S' +#log_datefmt_logfile: '%Y-%m-%d %H:%M:%S' + +# The format of the console logging messages. Allowed formatting options can +# be seen here: http://docs.python.org/library/logging.html#logrecord-attributes +# +# Console log colors are specified by these additional formatters: +# +# %(colorlevel)s +# %(colorname)s +# %(colorprocess)s +# %(colormsg)s +# +# Since it is desirable to include the surrounding brackets, '[' and ']', in +# the coloring of the messages, these color formatters also include padding as +# well. Color LogRecord attributes are only available for console logging. +# +#log_fmt_console: '%(colorlevel)s %(colormsg)s' +#log_fmt_console: '[%(levelname)-8s] %(message)s' +# +#log_fmt_logfile: '%(asctime)s,%(msecs)03d [%(name)-17s][%(levelname)-8s] %(message)s' + +# This can be used to control logging levels more specificically. This +# example sets the main salt library at the 'warning' level, but sets +# 'salt.modules' to log at the 'debug' level: +# log_granular_levels: +# 'salt': 'warning' +# 'salt.modules': 'debug' +# +#log_granular_levels: {} + + +##### Node Groups ###### +########################################## +# Node groups allow for logical groupings of minion nodes. A group consists of +# a group name and a compound target. Nodgroups can reference other nodegroups +# with 'N@' classifier. Ensure that you do not have circular references. +# +#nodegroups: +# group1: 'L@foo.domain.com,bar.domain.com,baz.domain.com or bl*.domain.com' +# group2: 'G@os:Debian and foo.domain.com' +# group3: 'G@os:Debian and N@group1' +# group4: +# - 'G@foo:bar' +# - 'or' +# - 'G@foo:baz' + + +##### Range Cluster settings ##### +########################################## +# The range server (and optional port) that serves your cluster information +# https://github.com/ytoolshed/range/wiki/%22yamlfile%22-module-file-spec +# +#range_server: range:80 + + +##### Windows Software Repo settings ##### +########################################### +# Location of the repo on the master: +#winrepo_dir_ng: '/srv/salt/win/repo-ng' +# +# List of git repositories to include with the local repo: +#winrepo_remotes_ng: +# - 'https://github.com/saltstack/salt-winrepo-ng.git' + + +##### Windows Software Repo settings - Pre 2015.8 ##### +######################################################## +# Legacy repo settings for pre-2015.8 Windows minions. +# +# Location of the repo on the master: +#winrepo_dir: '/srv/salt/win/repo' +# +# Location of the master's repo cache file: +#winrepo_mastercachefile: '/srv/salt/win/repo/winrepo.p' +# +# List of git repositories to include with the local repo: +#winrepo_remotes: +# - 'https://github.com/saltstack/salt-winrepo.git' + +# The refspecs fetched by winrepo remotes +#winrepo_refspecs: +# - '+refs/heads/*:refs/remotes/origin/*' +# - '+refs/tags/*:refs/tags/*' +# + +##### Returner settings ###### +############################################ +# Which returner(s) will be used for minion's result: +#return: mysql + + +###### Miscellaneous settings ###### +############################################ +# Default match type for filtering events tags: startswith, endswith, find, regex, fnmatch +#event_match_type: startswith + +# Save runner returns to the job cache +#runner_returns: True + +# Permanently include any available Python 3rd party modules into thin and minimal Salt +# when they are generated for Salt-SSH or other purposes. +# The modules should be named by the names they are actually imported inside the Python. +# The value of the parameters can be either one module or a comma separated list of them. +#thin_extra_mods: foo,bar +#min_extra_mods: foo,bar,baz + + +###### Keepalive settings ###### +############################################ +# Warning: Failure to set TCP keepalives on the salt-master can result in +# not detecting the loss of a minion when the connection is lost or when +# its host has been terminated without first closing the socket. +# Salt's Presence System depends on this connection status to know if a minion +# is "present". +# ZeroMQ now includes support for configuring SO_KEEPALIVE if supported by +# the OS. If connections between the minion and the master pass through +# a state tracking device such as a firewall or VPN gateway, there is +# the risk that it could tear down the connection the master and minion +# without informing either party that their connection has been taken away. +# Enabling TCP Keepalives prevents this from happening. + +# Overall state of TCP Keepalives, enable (1 or True), disable (0 or False) +# or leave to the OS defaults (-1), on Linux, typically disabled. Default True, enabled. +#tcp_keepalive: True + +# How long before the first keepalive should be sent in seconds. Default 300 +# to send the first keepalive after 5 minutes, OS default (-1) is typically 7200 seconds +# on Linux see /proc/sys/net/ipv4/tcp_keepalive_time. +#tcp_keepalive_idle: 300 + +# How many lost probes are needed to consider the connection lost. Default -1 +# to use OS defaults, typically 9 on Linux, see /proc/sys/net/ipv4/tcp_keepalive_probes. +#tcp_keepalive_cnt: -1 + +# How often, in seconds, to send keepalives after the first one. Default -1 to +# use OS defaults, typically 75 seconds on Linux, see +# /proc/sys/net/ipv4/tcp_keepalive_intvl. +#tcp_keepalive_intvl: -1 + + +##### NetAPI settings ##### +############################################ +# Allow the raw_shell parameter to be used when calling Salt SSH client via API +#netapi_allow_raw_shell: True + +# Set a list of clients to enable in in the API +#netapi_enable_clients: [] diff --git a/pkg/debian/changelog b/pkg/debian/changelog index fa24b40697d..b014ff40a01 100644 --- a/pkg/debian/changelog +++ b/pkg/debian/changelog @@ -1,3 +1,368 @@ +salt (3006.0) stable; urgency=medium + + + # Removed + + * Remove and deprecate the __orchestration__ key from salt.runner and salt.wheel return data. To get it back, set features.enable_deprecated_orchestration_flag master configuration option to True. The flag will be completely removed in Salt 3008 Argon. [#59917](https://github.com/saltstack/salt/issues/59917) + * Removed distutils and replaced with setuptools, given distutils is deprecated and removed in Python 3.12 [#60476](https://github.com/saltstack/salt/issues/60476) + * Removed ``runtests`` targets from ``noxfile.py`` [#62239](https://github.com/saltstack/salt/issues/62239) + * Removed the PyObjC dependency. + + This addresses problems with building a one dir build for macOS. + It became problematic because depending on the macOS version, it pulls different dependencies, and we would either have to build a macos onedir for each macOS supported release, or ship a crippled onedir(because it would be tied to the macOS version where the onedir was built). + Since it's currently not being used, it's removed. [#62432](https://github.com/saltstack/salt/issues/62432) + * Removed `SixRedirectImporter` from Salt. Salt hasn't shipped `six` since Salt 3004. [#63874](https://github.com/saltstack/salt/issues/63874) + + # Deprecated + + * renamed `keep_jobs`, specifying job cache TTL in hours, to `keep_jobs_seconds`, specifying TTL in seconds. + `keep_jobs` will be removed in the Argon release [#55295](https://github.com/saltstack/salt/issues/55295) + * Removing all references to napalm-base which is no longer supported. [#61542](https://github.com/saltstack/salt/issues/61542) + * The 'ip_bracket' function has been moved from salt/utils/zeromq.py in salt/utils/network.py [#62009](https://github.com/saltstack/salt/issues/62009) + * The `expand_repo_def` function in `salt.modules.aptpkg` is now deprecated. It's only used in `salt.states.pkgrepo` and it has no use of being exposed to the CLI. [#62485](https://github.com/saltstack/salt/issues/62485) + * Deprecated defunct Django returner [#62644](https://github.com/saltstack/salt/issues/62644) + * Deprecate core ESXi and associated states and modules, vcenter and vsphere support in favor of Salt VMware Extensions [#62754](https://github.com/saltstack/salt/issues/62754) + * Removing manufacture grain which has been deprecated. [#62914](https://github.com/saltstack/salt/issues/62914) + * Removing deprecated utils/boto3_elasticsearch.py [#62915](https://github.com/saltstack/salt/issues/62915) + * Removing support for the now deprecated _ext_nodes from salt/master.py. [#62917](https://github.com/saltstack/salt/issues/62917) + * Deprecating the Salt Slack engine in favor of the Salt Slack Bolt Engine. [#63095](https://github.com/saltstack/salt/issues/63095) + * `salt.utils.version.StrictVersion` is now deprecated and it's use should be replaced with `salt.utils.version.Version`. [#63383](https://github.com/saltstack/salt/issues/63383) + + # Changed + + * More intelligent diffing in changes of file.serialize state. [#48609](https://github.com/saltstack/salt/issues/48609) + * Move deprecation of the neutron module to Argon. Please migrate to the neutronng module instead. [#49430](https://github.com/saltstack/salt/issues/49430) + * ``umask`` is now a global state argument, instead of only applying to ``cmd`` + states. [#57803](https://github.com/saltstack/salt/issues/57803) + * Update pillar.obfuscate to accept kwargs in addition to args. This is useful when passing in keyword arguments like saltenv that are then passed along to pillar.items. [#58971](https://github.com/saltstack/salt/issues/58971) + * Improve support for listing macOS brew casks [#59439](https://github.com/saltstack/salt/issues/59439) + * Add missing MariaDB Grants to mysql module. + MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. + Also improved exception handling in `grant_add` which did not log the original error message and replaced it with a generic error. [#61409](https://github.com/saltstack/salt/issues/61409) + * Use VENV_PIP_TARGET environment variable as a default target for pip if present. [#62089](https://github.com/saltstack/salt/issues/62089) + * Disabled FQDNs grains on macOS by default [#62168](https://github.com/saltstack/salt/issues/62168) + * Replaced pyroute2.IPDB with pyroute2.NDB, as the former is deprecated [#62218](https://github.com/saltstack/salt/issues/62218) + * Enhance capture of error messages for Zypper calls in zypperpkg module. [#62346](https://github.com/saltstack/salt/issues/62346) + * Removed GPG_1_3_1 check [#62895](https://github.com/saltstack/salt/issues/62895) + * Requisite state chunks now all consistently contain `__id__`, `__sls__` and `name`. [#63012](https://github.com/saltstack/salt/issues/63012) + * netapi_enable_clients option to allow enabling/disabling of clients in salt-api. + By default all clients will now be disabled. Users of salt*api will need + to update their master config to enable the clients that they use. Not adding + the netapi_enable_clients option with required clients to the master config will + disable salt*api. [#63050](https://github.com/saltstack/salt/issues/63050) + * Stop relying on `salt/_version.py` to write Salt's version. Instead use `salt/_version.txt` which only contains the version string. [#63383](https://github.com/saltstack/salt/issues/63383) + * Set enable_fqdns_grains to be False by default. [#63595](https://github.com/saltstack/salt/issues/63595) + * Changelog snippet files must now have a `.md` file extension to be more explicit on what type of rendering is done when they are included in the main `CHANGELOG.md` file. [#63710](https://github.com/saltstack/salt/issues/63710) + * Upgraded to `relenv==0.9.0` [#63883](https://github.com/saltstack/salt/issues/63883) + + # Fixed + + * Add kwargs to handle extra parameters for http.query [#36138](https://github.com/saltstack/salt/issues/36138) + * Fix mounted bind mounts getting active mount options added [#39292](https://github.com/saltstack/salt/issues/39292) + * Fix `sysctl.present` converts spaces to tabs. [#40054](https://github.com/saltstack/salt/issues/40054) + * Fixes state pkg.purged to purge removed packages on Debian family systems [#42306](https://github.com/saltstack/salt/issues/42306) + * Fix fun_args missing from syndic returns [#45823](https://github.com/saltstack/salt/issues/45823) + * Fix mount.mounted with 'mount: False' reports unmounted file system as unchanged when running with test=True [#47201](https://github.com/saltstack/salt/issues/47201) + * Issue #49310: Allow users to touch a file with Unix date of birth [#49310](https://github.com/saltstack/salt/issues/49310) + * Do not raise an exception in pkg.info_installed on nonzero return code [#51620](https://github.com/saltstack/salt/issues/51620) + * Passes the value of the force parameter from file.copy to its call to file.remove so that files with the read-only attribute are handled. [#51739](https://github.com/saltstack/salt/issues/51739) + * Fixed x509.certificate_managed creates new certificate every run in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#52167](https://github.com/saltstack/salt/issues/52167) + * Don't check for cached pillar errors on state.apply [#52354](https://github.com/saltstack/salt/issues/52354), [#57180](https://github.com/saltstack/salt/issues/57180), [#59339](https://github.com/saltstack/salt/issues/59339) + * Swapping out args and kwargs for arg and kwarg respectively in the Slack engine when the command passed is a runner. [#52400](https://github.com/saltstack/salt/issues/52400) + * Ensure when we're adding chunks to the rules when running aggregation with the iptables state module we use a copy of the chunk otherwise we end up with a recursive mess. [#53353](https://github.com/saltstack/salt/issues/53353) + * When user_create or user_remove fail, return False instead of returning the error. [#53377](https://github.com/saltstack/salt/issues/53377) + * Include sync_roster when sync_all is called. [#53914](https://github.com/saltstack/salt/issues/53914) + * Avoid warning noise in lograte.get [#53988](https://github.com/saltstack/salt/issues/53988) + * Fixed listing revoked keys with gpg.list_keys [#54347](https://github.com/saltstack/salt/issues/54347) + * Fix mount.mounted does not handle blanks properly [#54508](https://github.com/saltstack/salt/issues/54508) + * Fixed grain num_cpus get wrong CPUs count in case of inconsistent CPU numbering. [#54682](https://github.com/saltstack/salt/issues/54682) + * Fix spelling error for python_shell argument in dpkg_lower module [#54907](https://github.com/saltstack/salt/issues/54907) + * Cleaned up bytes response data before sending to non-bytes compatible returners (postgres, mysql) [#55226](https://github.com/saltstack/salt/issues/55226) + * Fixed malformed state return when testing file.managed with unavailable source file [#55269](https://github.com/saltstack/salt/issues/55269) + * Included stdout in error message for Zypper calls in zypperpkg module. [#56016](https://github.com/saltstack/salt/issues/56016) + * Fixed pillar.filter_by with salt-ssh [#56093](https://github.com/saltstack/salt/issues/56093) + * Fix boto_route53 issue with (multiple) VPCs. [#57139](https://github.com/saltstack/salt/issues/57139) + * Remove log from mine runner which was not used. [#57463](https://github.com/saltstack/salt/issues/57463) + * Fixed x509.read_certificate error when reading a Microsoft CA issued certificate in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#57535](https://github.com/saltstack/salt/issues/57535) + * Updating Slack engine to use slack_bolt library. [#57842](https://github.com/saltstack/salt/issues/57842) + * Fixed warning about replace=True with x509.certificate_managed in the new cryptography x509 module. [#58165](https://github.com/saltstack/salt/issues/58165) + * Fix salt.modules.pip:is_installed doesn't handle locally installed packages [#58202](https://github.com/saltstack/salt/issues/58202) + * Add missing MariaDB Grants to mysql module. MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. [#58297](https://github.com/saltstack/salt/issues/58297) + * linux_shadow: Fix cases where malformed shadow entries cause `user.present` + states to fail. [#58423](https://github.com/saltstack/salt/issues/58423) + * Fixed salt.utils.compat.cmp to work with dictionaries [#58729](https://github.com/saltstack/salt/issues/58729) + * Fixed formatting for terse output mode [#58953](https://github.com/saltstack/salt/issues/58953) + * Fixed RecursiveDictDiffer with added nested dicts [#59017](https://github.com/saltstack/salt/issues/59017) + * Fixed x509.certificate_managed has DoS effect on master in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#59169](https://github.com/saltstack/salt/issues/59169) + * Fixed saltnado websockets disconnecting immediately [#59183](https://github.com/saltstack/salt/issues/59183) + * Fixed x509.certificate_managed rolls certificates every now and then in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#59315](https://github.com/saltstack/salt/issues/59315) + * Fix postgres_privileges.present not idempotent for functions [#59585](https://github.com/saltstack/salt/issues/59585) + * Fixed influxdb_continuous_query.present state to provide the client args to the underlying module on create. [#59766](https://github.com/saltstack/salt/issues/59766) + * Warn when using insecure (http:// based) key_urls for apt-based systems in pkgrepo.managed, and add a kwarg that determines the validity of such a url. [#59786](https://github.com/saltstack/salt/issues/59786) + * add load balancing policy default option and ensure the module can be executed with arguments from CLI [#59909](https://github.com/saltstack/salt/issues/59909) + * Fix salt-ssh when using imports with extra-filerefs. [#60003](https://github.com/saltstack/salt/issues/60003) + * Fixed cache directory corruption startup error [#60170](https://github.com/saltstack/salt/issues/60170) + * Update docs remove dry_run in docstring of file.blockreplace state. [#60227](https://github.com/saltstack/salt/issues/60227) + * Adds Parrot to OS_Family_Map in grains. [#60249](https://github.com/saltstack/salt/issues/60249) + * Fixed stdout and stderr being empty sometimes when use_vt=True for the cmd.run[*] functions [#60365](https://github.com/saltstack/salt/issues/60365) + * Use return code in iptables --check to verify rule exists. [#60467](https://github.com/saltstack/salt/issues/60467) + * Fix regression pip.installed does not pass env_vars when calling pip.list [#60557](https://github.com/saltstack/salt/issues/60557) + * Fix xfs module when additional output included in mkfs.xfs command. [#60853](https://github.com/saltstack/salt/issues/60853) + * Fixed parsing new format of terraform states in roster.terraform [#60915](https://github.com/saltstack/salt/issues/60915) + * Fixed recognizing installed ARMv7 rpm packages in compatible architectures. [#60994](https://github.com/saltstack/salt/issues/60994) + * Fixing changes dict in pkg state to be consistent when installing and test=True. [#60995](https://github.com/saltstack/salt/issues/60995) + * Fix cron.present duplicating entries when changing timespec to special. [#60997](https://github.com/saltstack/salt/issues/60997) + * Made salt-ssh respect --wipe again [#61083](https://github.com/saltstack/salt/issues/61083) + * state.orchestrate_single only passes a pillar if it is set to the state + function. This allows it to be used with state functions that don't accept a + pillar keyword argument. [#61092](https://github.com/saltstack/salt/issues/61092) + * Fix ipset state when the comment kwarg is set. [#61122](https://github.com/saltstack/salt/issues/61122) + * Fix issue with archive.unzip where the password was not being encoded for the extract function [#61422](https://github.com/saltstack/salt/issues/61422) + * Some Linux distributions (like AlmaLinux, Astra Linux, Debian, Mendel, Linux + Mint, Pop!_OS, Rocky Linux) report different `oscodename`, `osfullname`, + `osfinger` grains if lsb*release is installed or not. They have been changed to + only derive these OS grains from `/etc/os*release`. [#61618](https://github.com/saltstack/salt/issues/61618) + * Pop!_OS uses the full version (YY.MM) in the osfinger grain now, not just the year. This allows differentiating for example between 20.04 and 20.10. [#61619](https://github.com/saltstack/salt/issues/61619) + * Fix ssh config roster to correctly parse the ssh config files that contain spaces. [#61650](https://github.com/saltstack/salt/issues/61650) + * Fix SoftLayer configuration not raising an exception when a domain is missing [#61727](https://github.com/saltstack/salt/issues/61727) + * Allow the minion to start or salt-call to run even if the user doesn't have permissions to read the root_dir value from the registry [#61789](https://github.com/saltstack/salt/issues/61789) + * Need to move the creation of the proxy object for the ProxyMinion further down in the initialization for sub proxies to ensure that all modules, especially any custom proxy modules, are available before attempting to run the init function. [#61805](https://github.com/saltstack/salt/issues/61805) + * Fixed malformed state return when merge-serializing to an improperly formatted file [#61814](https://github.com/saltstack/salt/issues/61814) + * Made cmdmod._run[_all]_quiet work during minion startup on MacOS with runas specified (which fixed mac_service) [#61816](https://github.com/saltstack/salt/issues/61816) + * When deleting the vault cache, also delete from the session cache [#61821](https://github.com/saltstack/salt/issues/61821) + * Ignore errors on reading license info with dpkg_lowpkg to prevent tracebacks on getting package information. [#61827](https://github.com/saltstack/salt/issues/61827) + * win_lgpo: Display conflicting policy names when more than one policy is found [#61859](https://github.com/saltstack/salt/issues/61859) + * win_lgpo: Fixed intermittent KeyError when getting policy setting using lgpo.get_policy [#61860](https://github.com/saltstack/salt/issues/61860) + * Fixed listing minions on OpenBSD [#61966](https://github.com/saltstack/salt/issues/61966) + * Make Salt to return an error on "pkg" modules and states when targeting duplicated package names [#62019](https://github.com/saltstack/salt/issues/62019) + * Fix return of REST-returned permissions when auth_list is set [#62022](https://github.com/saltstack/salt/issues/62022) + * Normalize package names once on using pkg.installed/removed with yum to make it possible to install packages with the name containing a part similar to a name of architecture. [#62029](https://github.com/saltstack/salt/issues/62029) + * Fix inconsitency regarding name and pkgs parameters between zypperpkg.upgrade() and yumpkg.upgrade() [#62030](https://github.com/saltstack/salt/issues/62030) + * Fix attr=all handling in pkg.list_pkgs() (yum/zypper). [#62032](https://github.com/saltstack/salt/issues/62032) + * Fixed the humanname being ignored in pkgrepo.managed on openSUSE Leap [#62053](https://github.com/saltstack/salt/issues/62053) + * Fixed issue with some LGPO policies having whitespace at the beginning or end of the element alias [#62058](https://github.com/saltstack/salt/issues/62058) + * Fix ordering of args to libcloud_storage.download_object module [#62074](https://github.com/saltstack/salt/issues/62074) + * Ignore extend declarations in sls files that are excluded. [#62082](https://github.com/saltstack/salt/issues/62082) + * Remove leftover usage of impacket [#62101](https://github.com/saltstack/salt/issues/62101) + * Pass executable path from _get_path_exec() is used when calling the program. + The $HOME env is no longer modified globally. + Only trailing newlines are stripped from the fetched secret. + Pass process arguments are handled in a secure way. [#62120](https://github.com/saltstack/salt/issues/62120) + * Ignore some command return codes in openbsdrcctl_service to prevent spurious errors [#62131](https://github.com/saltstack/salt/issues/62131) + * Fixed extra period in filename output in tls module. Instead of "server.crt." it will now be "server.crt". [#62139](https://github.com/saltstack/salt/issues/62139) + * Make sure lingering PAexec-*.exe files in the Windows directory are cleaned up [#62152](https://github.com/saltstack/salt/issues/62152) + * Restored Salt's DeprecationWarnings [#62185](https://github.com/saltstack/salt/issues/62185) + * Fixed issue with forward slashes on Windows with file.recurse and clean=True [#62197](https://github.com/saltstack/salt/issues/62197) + * Recognize OSMC as Debian-based [#62198](https://github.com/saltstack/salt/issues/62198) + * Fixed Zypper module failing on RPM lock file being temporarily unavailable. [#62204](https://github.com/saltstack/salt/issues/62204) + * Improved error handling and diagnostics in the proxmox salt-cloud driver [#62211](https://github.com/saltstack/salt/issues/62211) + * Added EndeavourOS to the Arch os_family. [#62220](https://github.com/saltstack/salt/issues/62220) + * Fix salt-ssh not detecting `platform-python` as a valid interpreter on EL8 [#62235](https://github.com/saltstack/salt/issues/62235) + * Fix pkg.version_cmp on openEuler and a few other os flavors. [#62248](https://github.com/saltstack/salt/issues/62248) + * Fix localhost detection in glusterfs.peers [#62273](https://github.com/saltstack/salt/issues/62273) + * Fix Salt Package Manager (SPM) exception when calling spm create_repo . [#62281](https://github.com/saltstack/salt/issues/62281) + * Fix matcher slowness due to loader invocation [#62283](https://github.com/saltstack/salt/issues/62283) + * Fixes the Puppet module for non-aio Puppet packages for example running the Puppet module on FreeBSD. [#62323](https://github.com/saltstack/salt/issues/62323) + * Issue 62334: Displays a debug log message instead of an error log message when the publisher fails to connect [#62334](https://github.com/saltstack/salt/issues/62334) + * Fix pyobjects renderer access to opts and sls [#62336](https://github.com/saltstack/salt/issues/62336) + * Fix use of random shuffle and sample functions as Jinja filters [#62372](https://github.com/saltstack/salt/issues/62372) + * Fix groups with duplicate GIDs are not returned by get_group_list [#62377](https://github.com/saltstack/salt/issues/62377) + * Fix the "zpool.present" state when enabling zpool features that are already active. [#62390](https://github.com/saltstack/salt/issues/62390) + * Fix ability to execute remote file client methods in saltcheck [#62398](https://github.com/saltstack/salt/issues/62398) + * Update all platforms to use pycparser 2.21 or greater for Py 3.9 or higher, fixes fips fault with openssl v3.x [#62400](https://github.com/saltstack/salt/issues/62400) + * Due to changes in the Netmiko library for the exception paths, need to check the version of Netmiko python library and then import the exceptions from different locations depending on the result. [#62405](https://github.com/saltstack/salt/issues/62405) + * When using preq on a state, then prereq state will first be run with test=True to determine if there are changes. When there are changes, the state with the prereq option will be run prior to the prereq state. If this state fails then the prereq state will not run and the state output uses the test=True run. However, the proposed changes are included for the prereq state are included from the test=True run. We should pull those out as there weren't actually changes since the prereq state did not run. [#62408](https://github.com/saltstack/salt/issues/62408) + * Added directory mode for file.copy with makedirs [#62426](https://github.com/saltstack/salt/issues/62426) + * Provide better error handling in the various napalm proxy minion functions when the device is not accessible. [#62435](https://github.com/saltstack/salt/issues/62435) + * When handling aggregation, change the order to ensure that the requisites are aggregated first and then the state functions are aggregated. Caching whether aggregate functions are available for particular states so we don't need to attempt to load them everytime. [#62439](https://github.com/saltstack/salt/issues/62439) + * The patch allows to boostrap kubernetes clusters in the version above 1.13 via salt module [#62451](https://github.com/saltstack/salt/issues/62451) + * sysctl.persist now updates the in-memory value on FreeBSD even if the on-disk value was already correct. [#62461](https://github.com/saltstack/salt/issues/62461) + * Fixed parsing CDROM apt sources [#62474](https://github.com/saltstack/salt/issues/62474) + * Update sanitizing masking for Salt SSH to include additional password like strings. [#62483](https://github.com/saltstack/salt/issues/62483) + * Fix user/group checking on file state functions in the test mode. [#62499](https://github.com/saltstack/salt/issues/62499) + * Fix user.present to allow removing groups using optional_groups parameter and enforcing idempotent group membership. [#62502](https://github.com/saltstack/salt/issues/62502) + * Fix possible tracebacks if there is a package with '------' or '======' in the description is installed on the Debian based minion. [#62519](https://github.com/saltstack/salt/issues/62519) + * Fixed the omitted "pool" parameter when cloning a VM with the proxmox salt-cloud driver [#62521](https://github.com/saltstack/salt/issues/62521) + * Fix rendering of pyobjects states in saltcheck [#62523](https://github.com/saltstack/salt/issues/62523) + * Fixes pillar where a corrupted CacheDisk file forces the pillar to be rebuilt [#62527](https://github.com/saltstack/salt/issues/62527) + * Use str() method instead of repo_line for when python3-apt is installed or not in aptpkg.py. [#62546](https://github.com/saltstack/salt/issues/62546) + * Remove the connection_timeout from netmiko_connection_args before netmiko_connection_args is added to __context__["netmiko_device"]["args"] which is passed along to the Netmiko library. [#62547](https://github.com/saltstack/salt/issues/62547) + * Fix order specific mount.mounted options for persist [#62556](https://github.com/saltstack/salt/issues/62556) + * Fixed salt-cloud cloning a proxmox VM with a specified new vmid. [#62558](https://github.com/saltstack/salt/issues/62558) + * Fix runas with cmd module when using the onedir bundled packages [#62565](https://github.com/saltstack/salt/issues/62565) + * Update setproctitle version for all platforms [#62576](https://github.com/saltstack/salt/issues/62576) + * Fixed missing parameters when cloning a VM with the proxmox salt-cloud driver [#62580](https://github.com/saltstack/salt/issues/62580) + * Handle PermissionError when importing crypt when FIPS is enabled. [#62587](https://github.com/saltstack/salt/issues/62587) + * Correctly reraise exceptions in states.http [#62595](https://github.com/saltstack/salt/issues/62595) + * Fixed syndic eauth. Now jobs will be published when a valid eauth user is targeting allowed minions/functions. [#62618](https://github.com/saltstack/salt/issues/62618) + * updated rest_cherry/app to properly detect arg sent as a string as curl will do when only one arg is supplied. [#62624](https://github.com/saltstack/salt/issues/62624) + * Prevent possible tracebacks in core grains module by ignoring non utf8 characters in /proc/1/environ, /proc/1/cmdline, /proc/cmdline [#62633](https://github.com/saltstack/salt/issues/62633) + * Fixed vault ext pillar return data for KV v2 [#62651](https://github.com/saltstack/salt/issues/62651) + * Fix saltcheck _get_top_states doesn't pass saltenv to state.show_top [#62654](https://github.com/saltstack/salt/issues/62654) + * Fix groupadd.* functions hard code relative command name [#62657](https://github.com/saltstack/salt/issues/62657) + * Fixed pdbedit.create trying to use a bytes-like hash as string. [#62670](https://github.com/saltstack/salt/issues/62670) + * Fix depenency on legacy boto module in boto3 modules [#62672](https://github.com/saltstack/salt/issues/62672) + * Modified "_get_flags" function so that it returns regex flags instead of integers [#62676](https://github.com/saltstack/salt/issues/62676) + * Change startup ReqServer log messages from error to info level. [#62728](https://github.com/saltstack/salt/issues/62728) + * Fix kmod.* functions hard code relative command name [#62772](https://github.com/saltstack/salt/issues/62772) + * Remove mako as a dependency in Windows and macOS. [#62785](https://github.com/saltstack/salt/issues/62785) + * Fix mac_brew_pkg to work with null taps [#62793](https://github.com/saltstack/salt/issues/62793) + * Fixing a bug when listing the running schedule if "schedule.enable" and/or "schedule.disable" has been run, where the "enabled" items is being treated as a schedule item. [#62795](https://github.com/saltstack/salt/issues/62795) + * Prevent annoying RuntimeWarning message about line buffering (buffering=1) not being supported in binary mode [#62817](https://github.com/saltstack/salt/issues/62817) + * Include UID and GID checks in modules.file.check_perms as well as comparing + ownership by username and group name. [#62818](https://github.com/saltstack/salt/issues/62818) + * Fix presence events on TCP transport by removing a client's presence when minion disconnects from publish channel correctly [#62826](https://github.com/saltstack/salt/issues/62826) + * Remove Azure deprecation messages from functions that always run w/ salt-cloud [#62845](https://github.com/saltstack/salt/issues/62845) + * Use select instead of iterating over entrypoints as a dictionary for importlib_metadata>=5.0.0 [#62854](https://github.com/saltstack/salt/issues/62854) + * Fixed master job scheduler using when [#62858](https://github.com/saltstack/salt/issues/62858) + * LGPO: Added support for missing domain controller policies: VulnerableChannelAllowList and LdapEnforceChannelBinding [#62873](https://github.com/saltstack/salt/issues/62873) + * Fix unnecessarily complex gce metadata grains code to use googles metadata service more effectively. [#62878](https://github.com/saltstack/salt/issues/62878) + * Fixed dockermod version_info function for docker-py 6.0.0+ [#62882](https://github.com/saltstack/salt/issues/62882) + * Moving setting the LOAD_BALANCING_POLICY_MAP dictionary into the try except block that determines if the cassandra_cql module should be made available. [#62886](https://github.com/saltstack/salt/issues/62886) + * Updating various MongoDB module functions to work with latest version of pymongo. [#62900](https://github.com/saltstack/salt/issues/62900) + * Restored channel for Syndic minions to send job returns to the Salt master. [#62933](https://github.com/saltstack/salt/issues/62933) + * removed _resolve_deps as it required a library that is not generally avalible. and switched to apt-get for everything as that can auto resolve dependencies. [#62934](https://github.com/saltstack/salt/issues/62934) + * Updated pyzmq to version 22.0.3 on Windows builds because the old version was causing salt-minion/salt-call to hang [#62937](https://github.com/saltstack/salt/issues/62937) + * Allow root user to modify crontab lines for non-root users (except AIX and Solaris). Align crontab line changes with the file ones and also with listing crontab. [#62940](https://github.com/saltstack/salt/issues/62940) + * Fix systemd_service.* functions hard code relative command name [#62942](https://github.com/saltstack/salt/issues/62942) + * Fix file.symlink backupname operation can copy remote contents to local disk [#62953](https://github.com/saltstack/salt/issues/62953) + * Issue #62968: Fix issue where cloud deployments were putting the keys in the wrong location on Windows hosts [#62968](https://github.com/saltstack/salt/issues/62968) + * Fixed gpg_passphrase issue with gpg decrypt/encrypt functions [#62977](https://github.com/saltstack/salt/issues/62977) + * Fix file.tidied FileNotFoundError [#62986](https://github.com/saltstack/salt/issues/62986) + * Fixed bug where module.wait states were detected as running legacy module.run syntax [#62988](https://github.com/saltstack/salt/issues/62988) + * Fixed issue with win_wua module where it wouldn't load if the CryptSvc was set to Manual start [#62993](https://github.com/saltstack/salt/issues/62993) + * The `__opts__` dunder dictionary is now added to the loader's `pack` if not + already present, which makes it accessible via the + `salt.loader.context.NamedLoaderContext` class. [#63013](https://github.com/saltstack/salt/issues/63013) + * Issue #63024: Fix issue where grains and config data were being place in the wrong location on Windows hosts [#63024](https://github.com/saltstack/salt/issues/63024) + * Fix btrfs.subvolume_snapshot command failing [#63025](https://github.com/saltstack/salt/issues/63025) + * Fix file.retention_schedule always reports changes [#63033](https://github.com/saltstack/salt/issues/63033) + * Fix mongo authentication for mongo ext_pillar and mongo returner + + This fix also include the ability to use the mongo connection string for mongo ext_pillar [#63058](https://github.com/saltstack/salt/issues/63058) + * Fixed x509.create_csr creates invalid CSR by default in the new cryptography x509 module. [#63103](https://github.com/saltstack/salt/issues/63103) + * TCP transport documentation now contains proper master/minion-side filtering information [#63120](https://github.com/saltstack/salt/issues/63120) + * Fixed gpg.verify does not respect gnupghome [#63145](https://github.com/saltstack/salt/issues/63145) + * User responsible for the runner is now correctly reported in the events on the event bus for the runner. [#63148](https://github.com/saltstack/salt/issues/63148) + * Made pillar cache pass extra minion data as well [#63208](https://github.com/saltstack/salt/issues/63208) + * Fix serious performance issues with the file.tidied module [#63231](https://github.com/saltstack/salt/issues/63231) + * Fix rpm_lowpkg version comparison logic when using rpm-vercmp and only one version has a release number. [#63317](https://github.com/saltstack/salt/issues/63317) + * Import StrictVersion and LooseVersion from setuptools.distutils.verison or setuptools._distutils.version, if first not available [#63350](https://github.com/saltstack/salt/issues/63350) + * ``service.status`` on Windows does no longer throws a CommandExecutionError if + the service is not found on the system. It now returns "Not Found" instead. [#63577](https://github.com/saltstack/salt/issues/63577) + * When the shell is passed as powershell or pwsh, only wrapper the shell in quotes if cmd.run is running on Windows. When quoted on Linux hosts, this results in an error when the keyword arguments are appended. [#63590](https://github.com/saltstack/salt/issues/63590) + * LGPO: Added support for "Relax minimum password length limits" [#63596](https://github.com/saltstack/salt/issues/63596) + * Fixed the ability to set a scheduled task to auto delete if not scheduled to run again (``delete_after``) [#63650](https://github.com/saltstack/salt/issues/63650) + * When a job is disabled only increase it's _next_fire_time value if the job would have run at the current time, eg. the current _next_fire_time == now. [#63699](https://github.com/saltstack/salt/issues/63699) + * have salt.template.compile_template_str cleanup its temp files. [#63724](https://github.com/saltstack/salt/issues/63724) + * Check file is not empty before attempting to read pillar disk cache file [#63729](https://github.com/saltstack/salt/issues/63729) + * Fixed an issue with generating fingerprints for public keys with different line endings [#63742](https://github.com/saltstack/salt/issues/63742) + * Add `fileserver_interval` and `maintenance_interval` master configuration options. These options control how often to restart the FileServerUpdate and Maintenance processes. Some file server and pillar configurations are known to cause memory leaks over time. A notable example of this are configurations that use pygit2. Salt can not guarantee dependency libraries like pygit2 won't leak memory. Restarting any long running processes that use pygit2 guarantees we can keep the master's memory usage in check. [#63747](https://github.com/saltstack/salt/issues/63747) + * mac_xattr.list and mac_xattr.read will replace undecode-able bytes to avoid raising CommandExecutionError. [#63779](https://github.com/saltstack/salt/issues/63779) [#63779](https://github.com/saltstack/salt/issues/63779) + * Change default GPG keyserver from pgp.mit.edu to keys.openpgp.org. [#63806](https://github.com/saltstack/salt/issues/63806) + * fix cherrypy 400 error output to be less generic. [#63835](https://github.com/saltstack/salt/issues/63835) + * Ensure kwargs is passed along to _call_apt when passed into install function. [#63847](https://github.com/saltstack/salt/issues/63847) + * remove eval and update logging to be more informative on bad config [#63879](https://github.com/saltstack/salt/issues/63879) + * add linux_distribution to util to stop dep warning [#63904](https://github.com/saltstack/salt/issues/63904) + * Fix valuerror when trying to close fileclient. Remove usage of __del__ and close the filclient properly. [#63920](https://github.com/saltstack/salt/issues/63920) + * Handle the situation when a sub proxy minion does not init properly, eg. an exception happens, and the sub proxy object is not available. [#63923](https://github.com/saltstack/salt/issues/63923) + * Clarifying documentation for extension_modules configuration option. [#63929](https://github.com/saltstack/salt/issues/63929) + * Windows pkg module now properly handles versions containing strings [#63935](https://github.com/saltstack/salt/issues/63935) + * Handle the scenario when the check_cmd requisite is used with a state function when the state has a local check_cmd function but that function isn't used by that function. [#63948](https://github.com/saltstack/salt/issues/63948) + * Issue #63981: Allow users to pass verify_ssl to pkg.install/pkg.installed on Windows [#63981](https://github.com/saltstack/salt/issues/63981) + * Hardened permissions on workers.ipc and master_event_pub.ipc. [#64063](https://github.com/saltstack/salt/issues/64063) + + # Added + + * Introduce a `LIB_STATE_DIR` syspaths variable which defaults to `CONFIG_DIR`, + but can be individually customized during installation by specifying + `*-salt-lib-state-dir` during installation. Change the default `pki_dir` to + `/pki/master` (for the master) and `/pki/minion` + (for the minion). [#3396](https://github.com/saltstack/salt/issues/3396) + * Allow users to enable 'queue=True' for all state runs via config file [#31468](https://github.com/saltstack/salt/issues/31468) + * Added pillar templating to vault policies [#43287](https://github.com/saltstack/salt/issues/43287) + * Add support for NVMeF as a transport protocol for hosts in a Pure Storage FlashArray [#51088](https://github.com/saltstack/salt/issues/51088) + * A new salt-ssh roster that generates a roster by parses a known_hosts file. [#54679](https://github.com/saltstack/salt/issues/54679) + * Added Windows Event Viewer support [#54713](https://github.com/saltstack/salt/issues/54713) + * Added the win_lgpo_reg state and execution modules which will allow registry based group policy to be set directly in the Registry.pol file [#56013](https://github.com/saltstack/salt/issues/56013) + * Added resource tagging functions to boto_dynamodb execution module [#57500](https://github.com/saltstack/salt/issues/57500) + * Added `openvswitch_db` state module and functions `bridge_to_parent`, + `bridge_to_vlan`, `db_get`, and `db_set` to the `openvswitch` execution module. + Also added optional `parent` and `vlan` parameters to the + `openvswitch_bridge.present` state module function and the + `openvswitch.bridge_create` execution module function. [#58986](https://github.com/saltstack/salt/issues/58986) + * State module to manage SysFS attributes [#60154](https://github.com/saltstack/salt/issues/60154) + * Added ability for `salt.wait_for_event` to handle `event_id`s that have a list value. [#60430](https://github.com/saltstack/salt/issues/60430) + * Added suport for Linux ppc64le core grains (cpu_model, virtual, productname, manufacturer, serialnumber) and arm core grains (serialnumber, productname) [#60518](https://github.com/saltstack/salt/issues/60518) + * Added autostart option to virt.defined and virt.running states, along with virt.update execution modules. [#60700](https://github.com/saltstack/salt/issues/60700) + * Added .0 back to our versioning scheme for future versions (e.g. 3006.0) [#60722](https://github.com/saltstack/salt/issues/60722) + * Initial work to allow parallel startup of proxy minions when used as sub proxies with Deltaproxy. [#61153](https://github.com/saltstack/salt/issues/61153) + * Added node label support for GCE [#61245](https://github.com/saltstack/salt/issues/61245) + * Support the --priority flag when adding sources to Chocolatey. [#61319](https://github.com/saltstack/salt/issues/61319) + * Add namespace option to ext_pillar.http_json [#61335](https://github.com/saltstack/salt/issues/61335) + * Added a filter function to ps module to get a list of processes on a minion according to their state. [#61420](https://github.com/saltstack/salt/issues/61420) + * Add postgres.timeout option to postgres module for limiting postgres query times [#61433](https://github.com/saltstack/salt/issues/61433) + * Added new optional vault option, ``config_location``. This can be either ``master`` or ``local`` and defines where vault will look for connection details, either requesting them from the master or using the local config. [#61857](https://github.com/saltstack/salt/issues/61857) + * Add ipwrap() jinja filter to wrap IPv6 addresses with brackets. [#61931](https://github.com/saltstack/salt/issues/61931) + * 'tcp' transport is now available in ipv6-only network [#62009](https://github.com/saltstack/salt/issues/62009) + * Add `diff_attr` parameter to pkg.upgrade() (zypper/yum). [#62031](https://github.com/saltstack/salt/issues/62031) + * Config option pass_variable_prefix allows to distinguish variables that contain paths to pass secrets. + Config option pass_strict_fetch allows to error out when a secret cannot be fetched from pass. + Config option pass_dir allows setting the PASSWORD_STORE_DIR env for pass. + Config option pass_gnupghome allows setting the $GNUPGHOME env for pass. [#62120](https://github.com/saltstack/salt/issues/62120) + * Add file.pruned state and expanded file.rmdir exec module functionality [#62178](https://github.com/saltstack/salt/issues/62178) + * Added "dig.PTR" function to resolve PTR records for IPs, as well as tests and documentation [#62275](https://github.com/saltstack/salt/issues/62275) + * Added the ability to remove a KB using the DISM state/execution modules [#62366](https://github.com/saltstack/salt/issues/62366) + * Add " python" subcommand to allow execution or arbitrary scripts via bundled Python runtime [#62381](https://github.com/saltstack/salt/issues/62381) + * Add ability to provide conditions which convert normal state actions to no-op when true [#62446](https://github.com/saltstack/salt/issues/62446) + * Added debug log messages displaying the command being run when installing packages on Windows [#62480](https://github.com/saltstack/salt/issues/62480) + * Add biosvendor grain [#62496](https://github.com/saltstack/salt/issues/62496) + * Add ifelse Jinja function as found in CFEngine [#62508](https://github.com/saltstack/salt/issues/62508) + * Implementation of Amazon EC2 instance detection and setting `virtual_subtype` grain accordingly including the product if possible to identify. [#62539](https://github.com/saltstack/salt/issues/62539) + * Adds __env__substitution to ext_pillar.stack; followup of #61531, improved exception handling for stacked template (jinja) template rendering and yaml parsing in ext_pillar.stack [#62578](https://github.com/saltstack/salt/issues/62578) + * Increase file.tidied flexibility with regard to age and size [#62678](https://github.com/saltstack/salt/issues/62678) + * Added "connected_devices" feature to netbox pillar module. It contains extra information about devices connected to the minion [#62761](https://github.com/saltstack/salt/issues/62761) + * Add atomic file operation for symlink changes [#62768](https://github.com/saltstack/salt/issues/62768) + * Add password/account locking/unlocking in user.present state on supported operating systems [#62856](https://github.com/saltstack/salt/issues/62856) + * Added onchange configuration for script engine [#62867](https://github.com/saltstack/salt/issues/62867) + * Added output and bare functionality to export_key gpg module function [#62978](https://github.com/saltstack/salt/issues/62978) + * Add keyvalue serializer for environment files [#62983](https://github.com/saltstack/salt/issues/62983) + * Add ability to ignore symlinks in file.tidied [#63042](https://github.com/saltstack/salt/issues/63042) + * salt-cloud support IMDSv2 tokens when using 'use-instance-role-credentials' [#63067](https://github.com/saltstack/salt/issues/63067) + * Fix running fast tests twice and add git labels to suite. [#63081](https://github.com/saltstack/salt/issues/63081) + * Add ability for file.symlink to not set ownership on existing links [#63093](https://github.com/saltstack/salt/issues/63093) + * Restore the previous slack engine and deprecate it, rename replace the slack engine to slack_bolt until deprecation [#63095](https://github.com/saltstack/salt/issues/63095) + * Add functions that will return the underlying block device, mount point, and filesystem type for a given path [#63098](https://github.com/saltstack/salt/issues/63098) + * Add ethtool execution and state module functions for pause [#63128](https://github.com/saltstack/salt/issues/63128) + * Add boardname grain [#63131](https://github.com/saltstack/salt/issues/63131) + * Added management of ECDSA/EdDSA private keys with x509 modules in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#63248](https://github.com/saltstack/salt/issues/63248) + * Added x509 modules support for different output formats in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#63249](https://github.com/saltstack/salt/issues/63249) + * Added deprecation_warning test state for ensuring that deprecation warnings are correctly emitted. [#63315](https://github.com/saltstack/salt/issues/63315) + * Adds a state_events option to state.highstate, state.apply, state.sls, state.sls_id. + This allows users to enable state_events on a per use basis rather than having to + enable them globally for all state runs. [#63316](https://github.com/saltstack/salt/issues/63316) + * Allow max queue size setting for state runs to prevent performance problems from queue growth [#63356](https://github.com/saltstack/salt/issues/63356) + * Add support of exposing meta_server_grains for Azure VMs [#63606](https://github.com/saltstack/salt/issues/63606) + * Include the version of `relenv` in the versions report. [#63827](https://github.com/saltstack/salt/issues/63827) + * Added debug log messages displaying the command being run when removing packages on Windows [#63866](https://github.com/saltstack/salt/issues/63866) + * Adding the ability to exclude arguments from a state that end up passed to cmd.retcode when requisites such as onlyif or unless are used. [#63956](https://github.com/saltstack/salt/issues/63956) + * Add --next-release argument to salt/version.py, which prints the next upcoming release. [#64023](https://github.com/saltstack/salt/issues/64023) + + # Security + + * Upgrade Requirements Due to Security Issues. + + * Upgrade to `cryptography>=39.0.1` due to: + * https://github.com/advisories/GHSA*x4qr-2fvf-3mr5 + * https://github.com/advisories/GHSA*w7pp-m8wf-vj6r + * Upgrade to `pyopenssl==23.0.0` due to the cryptography upgrade. + * Update to `markdown*it-py==2.2.0` due to: + * https://github.com/advisories/GHSA*jrwr-5x3p-hvc3 + * https://github.com/advisories/GHSA*vrjv-mxr7-vjf8 [#63882](https://github.com/saltstack/salt/issues/63882) + + + -- Salt Project Packaging Tue, 18 Apr 2023 20:56:10 +0000 + salt (1:3006.0rc3) stable; urgency=medium diff --git a/pkg/debian/rules b/pkg/debian/rules index 8a5a915b722..ebc6bdff52d 100755 --- a/pkg/debian/rules +++ b/pkg/debian/rules @@ -17,24 +17,18 @@ ifeq ("${SALT_ONEDIR_ARCHIVE}", "") override_dh_auto_build: mkdir -p build/onedir python3 -m venv --clear --copies build/onedir/venv - build/onedir/venv/bin/python3 -m pip install relenv + build/onedir/venv/bin/python3 -m pip install relenv==$${SALT_RELENV_VERSION} + export PY=$$(build/onedir/venv/bin/python3 -c 'import sys; sys.stdout.write("{}.{}".format(*sys.version_info)); sys.stdout.flush()') \ + && build/onedir/venv/bin/python3 -m pip install -r requirements/static/ci/py$${PY}/tools.txt build/onedir/venv/bin/relenv fetch build/onedir/venv/bin/relenv toolchain fetch - build/onedir/venv/bin/relenv create build/onedir/salt - build/onedir/salt/bin/python3 -m pip install "pip>=22.3.1,<23.0" "setuptools>=65.6.3,<66" "wheel" - export PY=$$(build/onedir/salt/bin/python3 -c 'import sys; sys.stdout.write("{}.{}".format(*sys.version_info)); sys.stdout.flush()') \ - && build/onedir/salt/bin/python3 -m pip install -r requirements/static/pkg/py$${PY}/linux.txt --no-binary=':all:' + build/onedir/venv/bin/tools pkg build onedir-dependencies --arch $${SALT_PACKAGE_ARCH} --python-version $${SALT_PYTHON_VERSION} --package-name build/onedir/salt --platform linux # Fix any hardcoded paths to the relenv python binary on any of the scripts installed in the /bin directory find build/onedir/salt/bin/ -type f -exec sed -i 's:#!/\(.*\)salt/bin/python3:#!/bin/sh\n"exec" "$$(dirname $$(readlink -f $$0))/python3" "$$0" "$$@":g' {} \; - export USE_STATIC_REQUIREMENTS=1 \ - && export RELENV_PIP_DIR=1 \ - && build/onedir/salt/bin/python3 -m pip install --no-warn-script-location . - build/onedir/salt/bin/python3 -m venv --clear --copies build/onedir/tools - export PY=$$(build/onedir/tools/bin/python3 -c 'import sys; sys.stdout.write("{}.{}".format(*sys.version_info)); sys.stdout.flush()') \ - && build/onedir/tools/bin/python3 -m pip install -r requirements/static/ci/py$${PY}/tools.txt - build/onedir/tools/bin/tools pkg pre-archive-cleanup --pkg build/onedir/salt + build/onedir/venv/bin/tools pkg build salt-onedir . --package-name build/onedir/salt --platform linux + build/onedir/venv/bin/tools pkg pre-archive-cleanup --pkg build/onedir/salt else override_dh_auto_build: # The relenv onedir is being provided, all setup up until Salt is installed diff --git a/pkg/debian/salt-common.dirs b/pkg/debian/salt-common.dirs index 1379962cb34..37d1dd556a8 100644 --- a/pkg/debian/salt-common.dirs +++ b/pkg/debian/salt-common.dirs @@ -1,4 +1,5 @@ /var/cache/salt /var/log/salt +/var/run/salt /usr/share/fish/vendor_completions.d -/opt/saltstack/salt/pypath +/opt/saltstack/salt diff --git a/pkg/debian/salt-master.dirs b/pkg/debian/salt-master.dirs index 2caa6c7a442..faa45743bbb 100644 --- a/pkg/debian/salt-master.dirs +++ b/pkg/debian/salt-master.dirs @@ -1 +1,14 @@ /etc/salt/master.d +/etc/salt/pki/master/minions +/etc/salt/pki/master/minions_autosign +/etc/salt/pki/master/minions_denied +/etc/salt/pki/master/minions_pre +/etc/salt/pki/master/minions_rejected +/var/cache/salt/master +/var/cache/salt/minion +/var/cache/salt/master/jobs +/var/cache/salt/master/proc +/var/cache/salt/master/queues +/var/cache/salt/master/roots +/var/cache/salt/master/syndics +/var/cache/salt/master/tokens diff --git a/pkg/debian/salt-master.install b/pkg/debian/salt-master.install index 1dc8a04ef55..35ea3571d08 100644 --- a/pkg/debian/salt-master.install +++ b/pkg/debian/salt-master.install @@ -1,2 +1,2 @@ -conf/master /etc/salt +pkg/common/conf/master /etc/salt pkg/common/salt-master.service /lib/systemd/system diff --git a/pkg/debian/salt-master.postinst b/pkg/debian/salt-master.postinst new file mode 100644 index 00000000000..6ac58f198f9 --- /dev/null +++ b/pkg/debian/salt-master.postinst @@ -0,0 +1,3 @@ +adduser --system salt --group +chown -R salt:salt /etc/salt /var/log/salt /opt/saltstack/salt/ /var/cache/salt/ /var/run/salt +if command -v systemctl; then systemctl enable salt-master; fi diff --git a/pkg/macos/package.sh b/pkg/macos/package.sh index bb1eaca61e3..6221fde2947 100755 --- a/pkg/macos/package.sh +++ b/pkg/macos/package.sh @@ -71,7 +71,7 @@ _usage() { echo "" echo " -h, --help this message" echo " -v, --version version of Salt display in the package" - echo " -n, --nightly don't sign the package" + echo " -s, --sign Sign the package" echo "" echo " To build the Salt package:" echo " example: $0 3006.1-1" @@ -105,6 +105,7 @@ _failure() { #------------------------------------------------------------------------------- # Get Parameters #------------------------------------------------------------------------------- +SIGN=0 while true; do if [[ -z "$1" ]]; then break; fi case "$1" in @@ -112,8 +113,8 @@ while true; do _usage exit 0 ;; - -n | --nightly ) - NIGHTLY=1 + -s | --sign ) + SIGN=1 shift ;; -v | --version ) @@ -249,10 +250,10 @@ else fi -if [ -z "${NIGHTLY}" ]; then +if [ "${SIGN}" -eq 1 ]; then _msg "Building the product package (signed)" # This is not a nightly build, so we want to sign it - FILE="$SCRIPT_DIR/salt-$VERSION-py3-$CPU_ARCH-signed.pkg" + FILE="$SCRIPT_DIR/salt-$VERSION-py3-$CPU_ARCH.pkg" if productbuild --resources="$SCRIPT_DIR/pkg-resources" \ --distribution="$DIST_XML" \ --package-path="$SCRIPT_DIR/salt-src-$VERSION-py3-$CPU_ARCH.pkg" \ diff --git a/pkg/rpm/salt.spec b/pkg/rpm/salt.spec index d0314181f3a..25a28ea59dd 100644 --- a/pkg/rpm/salt.spec +++ b/pkg/rpm/salt.spec @@ -21,7 +21,7 @@ %define fish_dir %{_datadir}/fish/vendor_functions.d Name: salt -Version: 3006.0~rc3 +Version: 3006.0 Release: 0 Summary: A parallel remote execution system Group: System Environment/Daemons @@ -39,14 +39,6 @@ Requires: pciutils Requires: which Requires: openssl - -%if 0%{?systemd_preun:1} -Requires(post): systemd-units -Requires(preun): systemd-units -Requires(postun): systemd-units -%endif - -BuildRequires: systemd-units BuildRequires: python3 BuildRequires: python3-pip BuildRequires: openssl @@ -136,26 +128,20 @@ cd $RPM_BUILD_DIR %if "%{getenv:SALT_ONEDIR_ARCHIVE}" == "" python3 -m venv --clear --copies build/venv - build/venv/bin/python3 -m pip install relenv + build/venv/bin/python3 -m pip install relenv==${SALT_RELENV_VERSION} + export PY=$(build/venv/bin/python3 -c 'import sys; sys.stdout.write("{}.{}".format(*sys.version_info)); sys.stdout.flush()') + build/venv/bin/python3 -m pip install -r %{_salt_src}/requirements/static/ci/py${PY}/tools.txt build/venv/bin/relenv fetch build/venv/bin/relenv toolchain fetch - build/venv/bin/relenv create build/salt - build/salt/bin/python3 -m pip install "pip>=22.3.1,<23.0" "setuptools>=65.6.3,<66" "wheel" - export PY=$(build/salt/bin/python3 -c 'import sys; sys.stdout.write("{}.{}".format(*sys.version_info)); sys.stdout.flush()') - build/salt/bin/python3 -m pip install -r %{_salt_src}/requirements/static/pkg/py${PY}/linux.txt --no-binary=':all:' + cd %{_salt_src} + $RPM_BUILD_DIR/build/venv/bin/tools pkg build onedir-dependencies --arch ${SALT_PACKAGE_ARCH} --python-version ${SALT_PYTHON_VERSION} --package-name $RPM_BUILD_DIR/build/salt --platform linux # Fix any hardcoded paths to the relenv python binary on any of the scripts installed in # the /bin directory - find build/salt/bin/ -type f -exec sed -i 's:#!/\(.*\)salt/bin/python3:#!/bin/sh\n"exec" "$(dirname $(readlink -f $0))/python3" "$0" "$@":g' {} \; + find $RPM_BUILD_DIR/build/salt/bin/ -type f -exec sed -i 's:#!/\(.*\)salt/bin/python3:#!/bin/sh\n"exec" "$(dirname $(readlink -f $0))/python3" "$0" "$@":g' {} \; - export USE_STATIC_REQUIREMENTS=1 - export RELENV_PIP_DIR=1 - build/salt/bin/python3 -m pip install --no-warn-script-location %{_salt_src} - - build/salt/bin/python3 -m venv --clear --copies build/tools - build/tools/bin/python3 -m pip install -r %{_salt_src}/requirements/static/ci/py${PY}/tools.txt - cd %{_salt_src} - $RPM_BUILD_DIR/build/tools/bin/tools pkg pre-archive-cleanup --pkg $RPM_BUILD_DIR/build/salt + $RPM_BUILD_DIR/build/venv/bin/tools pkg build salt-onedir . --package-name $RPM_BUILD_DIR/build/salt --platform linux + $RPM_BUILD_DIR/build/venv/bin/tools pkg pre-archive-cleanup --pkg $RPM_BUILD_DIR/build/salt %else # The relenv onedir is being provided, all setup up until Salt is installed # is expected to be done @@ -176,12 +162,26 @@ cp -R $RPM_BUILD_DIR/build/salt %{buildroot}/opt/saltstack/ # Add some directories install -d -m 0755 %{buildroot}%{_var}/log/salt +install -d -m 0755 %{buildroot}%{_var}/run/salt install -d -m 0755 %{buildroot}%{_var}/cache/salt +install -Dd -m 0750 %{buildroot}%{_var}/cache/salt/master +install -Dd -m 0750 %{buildroot}%{_var}/cache/salt/minion +install -Dd -m 0750 %{buildroot}%{_var}/cache/salt/master/jobs +install -Dd -m 0750 %{buildroot}%{_var}/cache/salt/master/proc +install -Dd -m 0750 %{buildroot}%{_var}/cache/salt/master/queues +install -Dd -m 0750 %{buildroot}%{_var}/cache/salt/master/roots +install -Dd -m 0750 %{buildroot}%{_var}/cache/salt/master/syndics +install -Dd -m 0750 %{buildroot}%{_var}/cache/salt/master/tokens install -d -m 0755 %{buildroot}%{_sysconfdir}/salt install -d -m 0755 %{buildroot}%{_sysconfdir}/salt/master.d install -d -m 0755 %{buildroot}%{_sysconfdir}/salt/minion.d install -d -m 0755 %{buildroot}%{_sysconfdir}/salt/pki install -d -m 0700 %{buildroot}%{_sysconfdir}/salt/pki/master +install -Dd -m 0750 %{buildroot}%{_sysconfdir}/salt/pki/master/minions +install -Dd -m 0750 %{buildroot}%{_sysconfdir}/salt/pki/master/minions_autosign +install -Dd -m 0750 %{buildroot}%{_sysconfdir}/salt/pki/master/minions_denied +install -Dd -m 0750 %{buildroot}%{_sysconfdir}/salt/pki/master/minions_pre +install -Dd -m 0750 %{buildroot}%{_sysconfdir}/salt/pki/master/minions_rejected install -d -m 0700 %{buildroot}%{_sysconfdir}/salt/pki/minion install -d -m 0700 %{buildroot}%{_sysconfdir}/salt/cloud.conf.d install -d -m 0700 %{buildroot}%{_sysconfdir}/salt/cloud.deploy.d @@ -208,7 +208,7 @@ install -m 0755 %{buildroot}/opt/saltstack/salt/salt-pip %{buildroot}%{_bindir}/ # Add the config files install -p -m 0640 %{_salt_src}/conf/minion %{buildroot}%{_sysconfdir}/salt/minion -install -p -m 0640 %{_salt_src}/conf/master %{buildroot}%{_sysconfdir}/salt/master +install -p -m 0640 %{_salt_src}/pkg/common/conf/master %{buildroot}%{_sysconfdir}/salt/master install -p -m 0640 %{_salt_src}/conf/cloud %{buildroot}%{_sysconfdir}/salt/cloud install -p -m 0640 %{_salt_src}/conf/roster %{buildroot}%{_sysconfdir}/salt/roster install -p -m 0640 %{_salt_src}/conf/proxy %{buildroot}%{_sysconfdir}/salt/proxy @@ -264,6 +264,7 @@ rm -rf %{buildroot} %{_sysconfdir}/bash_completion.d/salt.bash %config(noreplace) %{fish_dir}/salt*.fish %dir %{_var}/cache/salt +%dir %{_var}/run/salt %dir %{_var}/log/salt %doc %{_mandir}/man1/spm.1* %{_bindir}/spm @@ -292,6 +293,19 @@ rm -rf %{buildroot} %config(noreplace) %{_sysconfdir}/salt/master %dir %{_sysconfdir}/salt/master.d %config(noreplace) %{_sysconfdir}/salt/pki/master +%dir %attr(0750, salt, salt) %{_sysconfdir}/salt/pki/master/ +%dir %attr(0750, salt, salt) %{_sysconfdir}/salt/pki/master/minions/ +%dir %attr(0750, salt, salt) %{_sysconfdir}/salt/pki/master/minions_autosign/ +%dir %attr(0750, salt, salt) %{_sysconfdir}/salt/pki/master/minions_denied/ +%dir %attr(0750, salt, salt) %{_sysconfdir}/salt/pki/master/minions_pre/ +%dir %attr(0750, salt, salt) %{_sysconfdir}/salt/pki/master/minions_rejected/ +%dir %attr(0750, salt, salt) %{_var}/cache/salt/master/ +%dir %attr(0750, salt, salt) %{_var}/cache/salt/master/jobs/ +%dir %attr(0750, salt, salt) %{_var}/cache/salt/master/proc/ +%dir %attr(0750, salt, salt) %{_var}/cache/salt/master/queues/ +%dir %attr(0750, salt, salt) %{_var}/cache/salt/master/roots/ +%dir %attr(0750, salt, salt) %{_var}/cache/salt/master/syndics/ +%dir %attr(0750, salt, salt) %{_var}/cache/salt/master/tokens/ %files minion %defattr(-,root,root) @@ -307,6 +321,7 @@ rm -rf %{buildroot} %config(noreplace) %{_sysconfdir}/salt/proxy %config(noreplace) %{_sysconfdir}/salt/pki/minion %dir %{_sysconfdir}/salt/minion.d +%dir %attr(0750, root, root) %{_var}/cache/salt/minion/ %files syndic %doc %{_mandir}/man1/salt-syndic.1* @@ -334,6 +349,12 @@ rm -rf %{buildroot} %{_bindir}/salt-ssh %config(noreplace) %{_sysconfdir}/salt/roster +# Add salt user/group for Salt Master +%pre master +getent group salt >/dev/null || groupadd -r salt +getent passwd salt >/dev/null || \ + useradd -r -g salt -s /sbin/nologin \ + -c "Salt user for Salt Master" salt # assumes systemd for RHEL 7 & 8 & 9 %preun master @@ -369,6 +390,7 @@ if [ $1 -lt 2 ]; then /bin/openssl sha256 -r -hmac orboDeJITITejsirpADONivirpUkvarP /opt/saltstack/salt/lib/libcrypto.so.1.1 | cut -d ' ' -f 1 > /opt/saltstack/salt/lib/.libcrypto.so.1.1.hmac || : fi fi +chown -R salt:salt /etc/salt /var/log/salt /opt/saltstack/salt/ /var/cache/salt/ /var/run/salt/ %post syndic %systemd_post salt-syndic.service @@ -428,6 +450,368 @@ fi %changelog +* Tue Apr 18 2023 Salt Project Packaging - 3006.0 + +# Removed + +- Remove and deprecate the __orchestration__ key from salt.runner and salt.wheel return data. To get it back, set features.enable_deprecated_orchestration_flag master configuration option to True. The flag will be completely removed in Salt 3008 Argon. [#59917](https://github.com/saltstack/salt/issues/59917) +- Removed distutils and replaced with setuptools, given distutils is deprecated and removed in Python 3.12 [#60476](https://github.com/saltstack/salt/issues/60476) +- Removed ``runtests`` targets from ``noxfile.py`` [#62239](https://github.com/saltstack/salt/issues/62239) +- Removed the PyObjC dependency. + + This addresses problems with building a one dir build for macOS. + It became problematic because depending on the macOS version, it pulls different dependencies, and we would either have to build a macos onedir for each macOS supported release, or ship a crippled onedir(because it would be tied to the macOS version where the onedir was built). + Since it's currently not being used, it's removed. [#62432](https://github.com/saltstack/salt/issues/62432) +- Removed `SixRedirectImporter` from Salt. Salt hasn't shipped `six` since Salt 3004. [#63874](https://github.com/saltstack/salt/issues/63874) + +# Deprecated + +- renamed `keep_jobs`, specifying job cache TTL in hours, to `keep_jobs_seconds`, specifying TTL in seconds. + `keep_jobs` will be removed in the Argon release [#55295](https://github.com/saltstack/salt/issues/55295) +- Removing all references to napalm-base which is no longer supported. [#61542](https://github.com/saltstack/salt/issues/61542) +- The 'ip_bracket' function has been moved from salt/utils/zeromq.py in salt/utils/network.py [#62009](https://github.com/saltstack/salt/issues/62009) +- The `expand_repo_def` function in `salt.modules.aptpkg` is now deprecated. It's only used in `salt.states.pkgrepo` and it has no use of being exposed to the CLI. [#62485](https://github.com/saltstack/salt/issues/62485) +- Deprecated defunct Django returner [#62644](https://github.com/saltstack/salt/issues/62644) +- Deprecate core ESXi and associated states and modules, vcenter and vsphere support in favor of Salt VMware Extensions [#62754](https://github.com/saltstack/salt/issues/62754) +- Removing manufacture grain which has been deprecated. [#62914](https://github.com/saltstack/salt/issues/62914) +- Removing deprecated utils/boto3_elasticsearch.py [#62915](https://github.com/saltstack/salt/issues/62915) +- Removing support for the now deprecated _ext_nodes from salt/master.py. [#62917](https://github.com/saltstack/salt/issues/62917) +- Deprecating the Salt Slack engine in favor of the Salt Slack Bolt Engine. [#63095](https://github.com/saltstack/salt/issues/63095) +- `salt.utils.version.StrictVersion` is now deprecated and it's use should be replaced with `salt.utils.version.Version`. [#63383](https://github.com/saltstack/salt/issues/63383) + +# Changed + +- More intelligent diffing in changes of file.serialize state. [#48609](https://github.com/saltstack/salt/issues/48609) +- Move deprecation of the neutron module to Argon. Please migrate to the neutronng module instead. [#49430](https://github.com/saltstack/salt/issues/49430) +- ``umask`` is now a global state argument, instead of only applying to ``cmd`` + states. [#57803](https://github.com/saltstack/salt/issues/57803) +- Update pillar.obfuscate to accept kwargs in addition to args. This is useful when passing in keyword arguments like saltenv that are then passed along to pillar.items. [#58971](https://github.com/saltstack/salt/issues/58971) +- Improve support for listing macOS brew casks [#59439](https://github.com/saltstack/salt/issues/59439) +- Add missing MariaDB Grants to mysql module. + MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. + Also improved exception handling in `grant_add` which did not log the original error message and replaced it with a generic error. [#61409](https://github.com/saltstack/salt/issues/61409) +- Use VENV_PIP_TARGET environment variable as a default target for pip if present. [#62089](https://github.com/saltstack/salt/issues/62089) +- Disabled FQDNs grains on macOS by default [#62168](https://github.com/saltstack/salt/issues/62168) +- Replaced pyroute2.IPDB with pyroute2.NDB, as the former is deprecated [#62218](https://github.com/saltstack/salt/issues/62218) +- Enhance capture of error messages for Zypper calls in zypperpkg module. [#62346](https://github.com/saltstack/salt/issues/62346) +- Removed GPG_1_3_1 check [#62895](https://github.com/saltstack/salt/issues/62895) +- Requisite state chunks now all consistently contain `__id__`, `__sls__` and `name`. [#63012](https://github.com/saltstack/salt/issues/63012) +- netapi_enable_clients option to allow enabling/disabling of clients in salt-api. + By default all clients will now be disabled. Users of salt-api will need + to update their master config to enable the clients that they use. Not adding + the netapi_enable_clients option with required clients to the master config will + disable salt-api. [#63050](https://github.com/saltstack/salt/issues/63050) +- Stop relying on `salt/_version.py` to write Salt's version. Instead use `salt/_version.txt` which only contains the version string. [#63383](https://github.com/saltstack/salt/issues/63383) +- Set enable_fqdns_grains to be False by default. [#63595](https://github.com/saltstack/salt/issues/63595) +- Changelog snippet files must now have a `.md` file extension to be more explicit on what type of rendering is done when they are included in the main `CHANGELOG.md` file. [#63710](https://github.com/saltstack/salt/issues/63710) +- Upgraded to `relenv==0.9.0` [#63883](https://github.com/saltstack/salt/issues/63883) + +# Fixed + +- Add kwargs to handle extra parameters for http.query [#36138](https://github.com/saltstack/salt/issues/36138) +- Fix mounted bind mounts getting active mount options added [#39292](https://github.com/saltstack/salt/issues/39292) +- Fix `sysctl.present` converts spaces to tabs. [#40054](https://github.com/saltstack/salt/issues/40054) +- Fixes state pkg.purged to purge removed packages on Debian family systems [#42306](https://github.com/saltstack/salt/issues/42306) +- Fix fun_args missing from syndic returns [#45823](https://github.com/saltstack/salt/issues/45823) +- Fix mount.mounted with 'mount: False' reports unmounted file system as unchanged when running with test=True [#47201](https://github.com/saltstack/salt/issues/47201) +- Issue #49310: Allow users to touch a file with Unix date of birth [#49310](https://github.com/saltstack/salt/issues/49310) +- Do not raise an exception in pkg.info_installed on nonzero return code [#51620](https://github.com/saltstack/salt/issues/51620) +- Passes the value of the force parameter from file.copy to its call to file.remove so that files with the read-only attribute are handled. [#51739](https://github.com/saltstack/salt/issues/51739) +- Fixed x509.certificate_managed creates new certificate every run in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#52167](https://github.com/saltstack/salt/issues/52167) +- Don't check for cached pillar errors on state.apply [#52354](https://github.com/saltstack/salt/issues/52354), [#57180](https://github.com/saltstack/salt/issues/57180), [#59339](https://github.com/saltstack/salt/issues/59339) +- Swapping out args and kwargs for arg and kwarg respectively in the Slack engine when the command passed is a runner. [#52400](https://github.com/saltstack/salt/issues/52400) +- Ensure when we're adding chunks to the rules when running aggregation with the iptables state module we use a copy of the chunk otherwise we end up with a recursive mess. [#53353](https://github.com/saltstack/salt/issues/53353) +- When user_create or user_remove fail, return False instead of returning the error. [#53377](https://github.com/saltstack/salt/issues/53377) +- Include sync_roster when sync_all is called. [#53914](https://github.com/saltstack/salt/issues/53914) +- Avoid warning noise in lograte.get [#53988](https://github.com/saltstack/salt/issues/53988) +- Fixed listing revoked keys with gpg.list_keys [#54347](https://github.com/saltstack/salt/issues/54347) +- Fix mount.mounted does not handle blanks properly [#54508](https://github.com/saltstack/salt/issues/54508) +- Fixed grain num_cpus get wrong CPUs count in case of inconsistent CPU numbering. [#54682](https://github.com/saltstack/salt/issues/54682) +- Fix spelling error for python_shell argument in dpkg_lower module [#54907](https://github.com/saltstack/salt/issues/54907) +- Cleaned up bytes response data before sending to non-bytes compatible returners (postgres, mysql) [#55226](https://github.com/saltstack/salt/issues/55226) +- Fixed malformed state return when testing file.managed with unavailable source file [#55269](https://github.com/saltstack/salt/issues/55269) +- Included stdout in error message for Zypper calls in zypperpkg module. [#56016](https://github.com/saltstack/salt/issues/56016) +- Fixed pillar.filter_by with salt-ssh [#56093](https://github.com/saltstack/salt/issues/56093) +- Fix boto_route53 issue with (multiple) VPCs. [#57139](https://github.com/saltstack/salt/issues/57139) +- Remove log from mine runner which was not used. [#57463](https://github.com/saltstack/salt/issues/57463) +- Fixed x509.read_certificate error when reading a Microsoft CA issued certificate in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#57535](https://github.com/saltstack/salt/issues/57535) +- Updating Slack engine to use slack_bolt library. [#57842](https://github.com/saltstack/salt/issues/57842) +- Fixed warning about replace=True with x509.certificate_managed in the new cryptography x509 module. [#58165](https://github.com/saltstack/salt/issues/58165) +- Fix salt.modules.pip:is_installed doesn't handle locally installed packages [#58202](https://github.com/saltstack/salt/issues/58202) +- Add missing MariaDB Grants to mysql module. MariaDB has added some grants in 10.4.x and 10.5.x that are not present here, which results in an error when creating. [#58297](https://github.com/saltstack/salt/issues/58297) +- linux_shadow: Fix cases where malformed shadow entries cause `user.present` + states to fail. [#58423](https://github.com/saltstack/salt/issues/58423) +- Fixed salt.utils.compat.cmp to work with dictionaries [#58729](https://github.com/saltstack/salt/issues/58729) +- Fixed formatting for terse output mode [#58953](https://github.com/saltstack/salt/issues/58953) +- Fixed RecursiveDictDiffer with added nested dicts [#59017](https://github.com/saltstack/salt/issues/59017) +- Fixed x509.certificate_managed has DoS effect on master in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#59169](https://github.com/saltstack/salt/issues/59169) +- Fixed saltnado websockets disconnecting immediately [#59183](https://github.com/saltstack/salt/issues/59183) +- Fixed x509.certificate_managed rolls certificates every now and then in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#59315](https://github.com/saltstack/salt/issues/59315) +- Fix postgres_privileges.present not idempotent for functions [#59585](https://github.com/saltstack/salt/issues/59585) +- Fixed influxdb_continuous_query.present state to provide the client args to the underlying module on create. [#59766](https://github.com/saltstack/salt/issues/59766) +- Warn when using insecure (http:// based) key_urls for apt-based systems in pkgrepo.managed, and add a kwarg that determines the validity of such a url. [#59786](https://github.com/saltstack/salt/issues/59786) +- add load balancing policy default option and ensure the module can be executed with arguments from CLI [#59909](https://github.com/saltstack/salt/issues/59909) +- Fix salt-ssh when using imports with extra-filerefs. [#60003](https://github.com/saltstack/salt/issues/60003) +- Fixed cache directory corruption startup error [#60170](https://github.com/saltstack/salt/issues/60170) +- Update docs remove dry_run in docstring of file.blockreplace state. [#60227](https://github.com/saltstack/salt/issues/60227) +- Adds Parrot to OS_Family_Map in grains. [#60249](https://github.com/saltstack/salt/issues/60249) +- Fixed stdout and stderr being empty sometimes when use_vt=True for the cmd.run[*] functions [#60365](https://github.com/saltstack/salt/issues/60365) +- Use return code in iptables --check to verify rule exists. [#60467](https://github.com/saltstack/salt/issues/60467) +- Fix regression pip.installed does not pass env_vars when calling pip.list [#60557](https://github.com/saltstack/salt/issues/60557) +- Fix xfs module when additional output included in mkfs.xfs command. [#60853](https://github.com/saltstack/salt/issues/60853) +- Fixed parsing new format of terraform states in roster.terraform [#60915](https://github.com/saltstack/salt/issues/60915) +- Fixed recognizing installed ARMv7 rpm packages in compatible architectures. [#60994](https://github.com/saltstack/salt/issues/60994) +- Fixing changes dict in pkg state to be consistent when installing and test=True. [#60995](https://github.com/saltstack/salt/issues/60995) +- Fix cron.present duplicating entries when changing timespec to special. [#60997](https://github.com/saltstack/salt/issues/60997) +- Made salt-ssh respect --wipe again [#61083](https://github.com/saltstack/salt/issues/61083) +- state.orchestrate_single only passes a pillar if it is set to the state + function. This allows it to be used with state functions that don't accept a + pillar keyword argument. [#61092](https://github.com/saltstack/salt/issues/61092) +- Fix ipset state when the comment kwarg is set. [#61122](https://github.com/saltstack/salt/issues/61122) +- Fix issue with archive.unzip where the password was not being encoded for the extract function [#61422](https://github.com/saltstack/salt/issues/61422) +- Some Linux distributions (like AlmaLinux, Astra Linux, Debian, Mendel, Linux + Mint, Pop!_OS, Rocky Linux) report different `oscodename`, `osfullname`, + `osfinger` grains if lsb-release is installed or not. They have been changed to + only derive these OS grains from `/etc/os-release`. [#61618](https://github.com/saltstack/salt/issues/61618) +- Pop!_OS uses the full version (YY.MM) in the osfinger grain now, not just the year. This allows differentiating for example between 20.04 and 20.10. [#61619](https://github.com/saltstack/salt/issues/61619) +- Fix ssh config roster to correctly parse the ssh config files that contain spaces. [#61650](https://github.com/saltstack/salt/issues/61650) +- Fix SoftLayer configuration not raising an exception when a domain is missing [#61727](https://github.com/saltstack/salt/issues/61727) +- Allow the minion to start or salt-call to run even if the user doesn't have permissions to read the root_dir value from the registry [#61789](https://github.com/saltstack/salt/issues/61789) +- Need to move the creation of the proxy object for the ProxyMinion further down in the initialization for sub proxies to ensure that all modules, especially any custom proxy modules, are available before attempting to run the init function. [#61805](https://github.com/saltstack/salt/issues/61805) +- Fixed malformed state return when merge-serializing to an improperly formatted file [#61814](https://github.com/saltstack/salt/issues/61814) +- Made cmdmod._run[_all]_quiet work during minion startup on MacOS with runas specified (which fixed mac_service) [#61816](https://github.com/saltstack/salt/issues/61816) +- When deleting the vault cache, also delete from the session cache [#61821](https://github.com/saltstack/salt/issues/61821) +- Ignore errors on reading license info with dpkg_lowpkg to prevent tracebacks on getting package information. [#61827](https://github.com/saltstack/salt/issues/61827) +- win_lgpo: Display conflicting policy names when more than one policy is found [#61859](https://github.com/saltstack/salt/issues/61859) +- win_lgpo: Fixed intermittent KeyError when getting policy setting using lgpo.get_policy [#61860](https://github.com/saltstack/salt/issues/61860) +- Fixed listing minions on OpenBSD [#61966](https://github.com/saltstack/salt/issues/61966) +- Make Salt to return an error on "pkg" modules and states when targeting duplicated package names [#62019](https://github.com/saltstack/salt/issues/62019) +- Fix return of REST-returned permissions when auth_list is set [#62022](https://github.com/saltstack/salt/issues/62022) +- Normalize package names once on using pkg.installed/removed with yum to make it possible to install packages with the name containing a part similar to a name of architecture. [#62029](https://github.com/saltstack/salt/issues/62029) +- Fix inconsitency regarding name and pkgs parameters between zypperpkg.upgrade() and yumpkg.upgrade() [#62030](https://github.com/saltstack/salt/issues/62030) +- Fix attr=all handling in pkg.list_pkgs() (yum/zypper). [#62032](https://github.com/saltstack/salt/issues/62032) +- Fixed the humanname being ignored in pkgrepo.managed on openSUSE Leap [#62053](https://github.com/saltstack/salt/issues/62053) +- Fixed issue with some LGPO policies having whitespace at the beginning or end of the element alias [#62058](https://github.com/saltstack/salt/issues/62058) +- Fix ordering of args to libcloud_storage.download_object module [#62074](https://github.com/saltstack/salt/issues/62074) +- Ignore extend declarations in sls files that are excluded. [#62082](https://github.com/saltstack/salt/issues/62082) +- Remove leftover usage of impacket [#62101](https://github.com/saltstack/salt/issues/62101) +- Pass executable path from _get_path_exec() is used when calling the program. + The $HOME env is no longer modified globally. + Only trailing newlines are stripped from the fetched secret. + Pass process arguments are handled in a secure way. [#62120](https://github.com/saltstack/salt/issues/62120) +- Ignore some command return codes in openbsdrcctl_service to prevent spurious errors [#62131](https://github.com/saltstack/salt/issues/62131) +- Fixed extra period in filename output in tls module. Instead of "server.crt." it will now be "server.crt". [#62139](https://github.com/saltstack/salt/issues/62139) +- Make sure lingering PAexec-*.exe files in the Windows directory are cleaned up [#62152](https://github.com/saltstack/salt/issues/62152) +- Restored Salt's DeprecationWarnings [#62185](https://github.com/saltstack/salt/issues/62185) +- Fixed issue with forward slashes on Windows with file.recurse and clean=True [#62197](https://github.com/saltstack/salt/issues/62197) +- Recognize OSMC as Debian-based [#62198](https://github.com/saltstack/salt/issues/62198) +- Fixed Zypper module failing on RPM lock file being temporarily unavailable. [#62204](https://github.com/saltstack/salt/issues/62204) +- Improved error handling and diagnostics in the proxmox salt-cloud driver [#62211](https://github.com/saltstack/salt/issues/62211) +- Added EndeavourOS to the Arch os_family. [#62220](https://github.com/saltstack/salt/issues/62220) +- Fix salt-ssh not detecting `platform-python` as a valid interpreter on EL8 [#62235](https://github.com/saltstack/salt/issues/62235) +- Fix pkg.version_cmp on openEuler and a few other os flavors. [#62248](https://github.com/saltstack/salt/issues/62248) +- Fix localhost detection in glusterfs.peers [#62273](https://github.com/saltstack/salt/issues/62273) +- Fix Salt Package Manager (SPM) exception when calling spm create_repo . [#62281](https://github.com/saltstack/salt/issues/62281) +- Fix matcher slowness due to loader invocation [#62283](https://github.com/saltstack/salt/issues/62283) +- Fixes the Puppet module for non-aio Puppet packages for example running the Puppet module on FreeBSD. [#62323](https://github.com/saltstack/salt/issues/62323) +- Issue 62334: Displays a debug log message instead of an error log message when the publisher fails to connect [#62334](https://github.com/saltstack/salt/issues/62334) +- Fix pyobjects renderer access to opts and sls [#62336](https://github.com/saltstack/salt/issues/62336) +- Fix use of random shuffle and sample functions as Jinja filters [#62372](https://github.com/saltstack/salt/issues/62372) +- Fix groups with duplicate GIDs are not returned by get_group_list [#62377](https://github.com/saltstack/salt/issues/62377) +- Fix the "zpool.present" state when enabling zpool features that are already active. [#62390](https://github.com/saltstack/salt/issues/62390) +- Fix ability to execute remote file client methods in saltcheck [#62398](https://github.com/saltstack/salt/issues/62398) +- Update all platforms to use pycparser 2.21 or greater for Py 3.9 or higher, fixes fips fault with openssl v3.x [#62400](https://github.com/saltstack/salt/issues/62400) +- Due to changes in the Netmiko library for the exception paths, need to check the version of Netmiko python library and then import the exceptions from different locations depending on the result. [#62405](https://github.com/saltstack/salt/issues/62405) +- When using preq on a state, then prereq state will first be run with test=True to determine if there are changes. When there are changes, the state with the prereq option will be run prior to the prereq state. If this state fails then the prereq state will not run and the state output uses the test=True run. However, the proposed changes are included for the prereq state are included from the test=True run. We should pull those out as there weren't actually changes since the prereq state did not run. [#62408](https://github.com/saltstack/salt/issues/62408) +- Added directory mode for file.copy with makedirs [#62426](https://github.com/saltstack/salt/issues/62426) +- Provide better error handling in the various napalm proxy minion functions when the device is not accessible. [#62435](https://github.com/saltstack/salt/issues/62435) +- When handling aggregation, change the order to ensure that the requisites are aggregated first and then the state functions are aggregated. Caching whether aggregate functions are available for particular states so we don't need to attempt to load them everytime. [#62439](https://github.com/saltstack/salt/issues/62439) +- The patch allows to boostrap kubernetes clusters in the version above 1.13 via salt module [#62451](https://github.com/saltstack/salt/issues/62451) +- sysctl.persist now updates the in-memory value on FreeBSD even if the on-disk value was already correct. [#62461](https://github.com/saltstack/salt/issues/62461) +- Fixed parsing CDROM apt sources [#62474](https://github.com/saltstack/salt/issues/62474) +- Update sanitizing masking for Salt SSH to include additional password like strings. [#62483](https://github.com/saltstack/salt/issues/62483) +- Fix user/group checking on file state functions in the test mode. [#62499](https://github.com/saltstack/salt/issues/62499) +- Fix user.present to allow removing groups using optional_groups parameter and enforcing idempotent group membership. [#62502](https://github.com/saltstack/salt/issues/62502) +- Fix possible tracebacks if there is a package with '------' or '======' in the description is installed on the Debian based minion. [#62519](https://github.com/saltstack/salt/issues/62519) +- Fixed the omitted "pool" parameter when cloning a VM with the proxmox salt-cloud driver [#62521](https://github.com/saltstack/salt/issues/62521) +- Fix rendering of pyobjects states in saltcheck [#62523](https://github.com/saltstack/salt/issues/62523) +- Fixes pillar where a corrupted CacheDisk file forces the pillar to be rebuilt [#62527](https://github.com/saltstack/salt/issues/62527) +- Use str() method instead of repo_line for when python3-apt is installed or not in aptpkg.py. [#62546](https://github.com/saltstack/salt/issues/62546) +- Remove the connection_timeout from netmiko_connection_args before netmiko_connection_args is added to __context__["netmiko_device"]["args"] which is passed along to the Netmiko library. [#62547](https://github.com/saltstack/salt/issues/62547) +- Fix order specific mount.mounted options for persist [#62556](https://github.com/saltstack/salt/issues/62556) +- Fixed salt-cloud cloning a proxmox VM with a specified new vmid. [#62558](https://github.com/saltstack/salt/issues/62558) +- Fix runas with cmd module when using the onedir bundled packages [#62565](https://github.com/saltstack/salt/issues/62565) +- Update setproctitle version for all platforms [#62576](https://github.com/saltstack/salt/issues/62576) +- Fixed missing parameters when cloning a VM with the proxmox salt-cloud driver [#62580](https://github.com/saltstack/salt/issues/62580) +- Handle PermissionError when importing crypt when FIPS is enabled. [#62587](https://github.com/saltstack/salt/issues/62587) +- Correctly reraise exceptions in states.http [#62595](https://github.com/saltstack/salt/issues/62595) +- Fixed syndic eauth. Now jobs will be published when a valid eauth user is targeting allowed minions/functions. [#62618](https://github.com/saltstack/salt/issues/62618) +- updated rest_cherry/app to properly detect arg sent as a string as curl will do when only one arg is supplied. [#62624](https://github.com/saltstack/salt/issues/62624) +- Prevent possible tracebacks in core grains module by ignoring non utf8 characters in /proc/1/environ, /proc/1/cmdline, /proc/cmdline [#62633](https://github.com/saltstack/salt/issues/62633) +- Fixed vault ext pillar return data for KV v2 [#62651](https://github.com/saltstack/salt/issues/62651) +- Fix saltcheck _get_top_states doesn't pass saltenv to state.show_top [#62654](https://github.com/saltstack/salt/issues/62654) +- Fix groupadd.* functions hard code relative command name [#62657](https://github.com/saltstack/salt/issues/62657) +- Fixed pdbedit.create trying to use a bytes-like hash as string. [#62670](https://github.com/saltstack/salt/issues/62670) +- Fix depenency on legacy boto module in boto3 modules [#62672](https://github.com/saltstack/salt/issues/62672) +- Modified "_get_flags" function so that it returns regex flags instead of integers [#62676](https://github.com/saltstack/salt/issues/62676) +- Change startup ReqServer log messages from error to info level. [#62728](https://github.com/saltstack/salt/issues/62728) +- Fix kmod.* functions hard code relative command name [#62772](https://github.com/saltstack/salt/issues/62772) +- Remove mako as a dependency in Windows and macOS. [#62785](https://github.com/saltstack/salt/issues/62785) +- Fix mac_brew_pkg to work with null taps [#62793](https://github.com/saltstack/salt/issues/62793) +- Fixing a bug when listing the running schedule if "schedule.enable" and/or "schedule.disable" has been run, where the "enabled" items is being treated as a schedule item. [#62795](https://github.com/saltstack/salt/issues/62795) +- Prevent annoying RuntimeWarning message about line buffering (buffering=1) not being supported in binary mode [#62817](https://github.com/saltstack/salt/issues/62817) +- Include UID and GID checks in modules.file.check_perms as well as comparing + ownership by username and group name. [#62818](https://github.com/saltstack/salt/issues/62818) +- Fix presence events on TCP transport by removing a client's presence when minion disconnects from publish channel correctly [#62826](https://github.com/saltstack/salt/issues/62826) +- Remove Azure deprecation messages from functions that always run w/ salt-cloud [#62845](https://github.com/saltstack/salt/issues/62845) +- Use select instead of iterating over entrypoints as a dictionary for importlib_metadata>=5.0.0 [#62854](https://github.com/saltstack/salt/issues/62854) +- Fixed master job scheduler using when [#62858](https://github.com/saltstack/salt/issues/62858) +- LGPO: Added support for missing domain controller policies: VulnerableChannelAllowList and LdapEnforceChannelBinding [#62873](https://github.com/saltstack/salt/issues/62873) +- Fix unnecessarily complex gce metadata grains code to use googles metadata service more effectively. [#62878](https://github.com/saltstack/salt/issues/62878) +- Fixed dockermod version_info function for docker-py 6.0.0+ [#62882](https://github.com/saltstack/salt/issues/62882) +- Moving setting the LOAD_BALANCING_POLICY_MAP dictionary into the try except block that determines if the cassandra_cql module should be made available. [#62886](https://github.com/saltstack/salt/issues/62886) +- Updating various MongoDB module functions to work with latest version of pymongo. [#62900](https://github.com/saltstack/salt/issues/62900) +- Restored channel for Syndic minions to send job returns to the Salt master. [#62933](https://github.com/saltstack/salt/issues/62933) +- removed _resolve_deps as it required a library that is not generally avalible. and switched to apt-get for everything as that can auto resolve dependencies. [#62934](https://github.com/saltstack/salt/issues/62934) +- Updated pyzmq to version 22.0.3 on Windows builds because the old version was causing salt-minion/salt-call to hang [#62937](https://github.com/saltstack/salt/issues/62937) +- Allow root user to modify crontab lines for non-root users (except AIX and Solaris). Align crontab line changes with the file ones and also with listing crontab. [#62940](https://github.com/saltstack/salt/issues/62940) +- Fix systemd_service.* functions hard code relative command name [#62942](https://github.com/saltstack/salt/issues/62942) +- Fix file.symlink backupname operation can copy remote contents to local disk [#62953](https://github.com/saltstack/salt/issues/62953) +- Issue #62968: Fix issue where cloud deployments were putting the keys in the wrong location on Windows hosts [#62968](https://github.com/saltstack/salt/issues/62968) +- Fixed gpg_passphrase issue with gpg decrypt/encrypt functions [#62977](https://github.com/saltstack/salt/issues/62977) +- Fix file.tidied FileNotFoundError [#62986](https://github.com/saltstack/salt/issues/62986) +- Fixed bug where module.wait states were detected as running legacy module.run syntax [#62988](https://github.com/saltstack/salt/issues/62988) +- Fixed issue with win_wua module where it wouldn't load if the CryptSvc was set to Manual start [#62993](https://github.com/saltstack/salt/issues/62993) +- The `__opts__` dunder dictionary is now added to the loader's `pack` if not + already present, which makes it accessible via the + `salt.loader.context.NamedLoaderContext` class. [#63013](https://github.com/saltstack/salt/issues/63013) +- Issue #63024: Fix issue where grains and config data were being place in the wrong location on Windows hosts [#63024](https://github.com/saltstack/salt/issues/63024) +- Fix btrfs.subvolume_snapshot command failing [#63025](https://github.com/saltstack/salt/issues/63025) +- Fix file.retention_schedule always reports changes [#63033](https://github.com/saltstack/salt/issues/63033) +- Fix mongo authentication for mongo ext_pillar and mongo returner + + This fix also include the ability to use the mongo connection string for mongo ext_pillar [#63058](https://github.com/saltstack/salt/issues/63058) +- Fixed x509.create_csr creates invalid CSR by default in the new cryptography x509 module. [#63103](https://github.com/saltstack/salt/issues/63103) +- TCP transport documentation now contains proper master/minion-side filtering information [#63120](https://github.com/saltstack/salt/issues/63120) +- Fixed gpg.verify does not respect gnupghome [#63145](https://github.com/saltstack/salt/issues/63145) +- User responsible for the runner is now correctly reported in the events on the event bus for the runner. [#63148](https://github.com/saltstack/salt/issues/63148) +- Made pillar cache pass extra minion data as well [#63208](https://github.com/saltstack/salt/issues/63208) +- Fix serious performance issues with the file.tidied module [#63231](https://github.com/saltstack/salt/issues/63231) +- Fix rpm_lowpkg version comparison logic when using rpm-vercmp and only one version has a release number. [#63317](https://github.com/saltstack/salt/issues/63317) +- Import StrictVersion and LooseVersion from setuptools.distutils.verison or setuptools._distutils.version, if first not available [#63350](https://github.com/saltstack/salt/issues/63350) +- ``service.status`` on Windows does no longer throws a CommandExecutionError if + the service is not found on the system. It now returns "Not Found" instead. [#63577](https://github.com/saltstack/salt/issues/63577) +- When the shell is passed as powershell or pwsh, only wrapper the shell in quotes if cmd.run is running on Windows. When quoted on Linux hosts, this results in an error when the keyword arguments are appended. [#63590](https://github.com/saltstack/salt/issues/63590) +- LGPO: Added support for "Relax minimum password length limits" [#63596](https://github.com/saltstack/salt/issues/63596) +- Fixed the ability to set a scheduled task to auto delete if not scheduled to run again (``delete_after``) [#63650](https://github.com/saltstack/salt/issues/63650) +- When a job is disabled only increase it's _next_fire_time value if the job would have run at the current time, eg. the current _next_fire_time == now. [#63699](https://github.com/saltstack/salt/issues/63699) +- have salt.template.compile_template_str cleanup its temp files. [#63724](https://github.com/saltstack/salt/issues/63724) +- Check file is not empty before attempting to read pillar disk cache file [#63729](https://github.com/saltstack/salt/issues/63729) +- Fixed an issue with generating fingerprints for public keys with different line endings [#63742](https://github.com/saltstack/salt/issues/63742) +- Add `fileserver_interval` and `maintenance_interval` master configuration options. These options control how often to restart the FileServerUpdate and Maintenance processes. Some file server and pillar configurations are known to cause memory leaks over time. A notable example of this are configurations that use pygit2. Salt can not guarantee dependency libraries like pygit2 won't leak memory. Restarting any long running processes that use pygit2 guarantees we can keep the master's memory usage in check. [#63747](https://github.com/saltstack/salt/issues/63747) +- mac_xattr.list and mac_xattr.read will replace undecode-able bytes to avoid raising CommandExecutionError. [#63779](https://github.com/saltstack/salt/issues/63779) [#63779](https://github.com/saltstack/salt/issues/63779) +- Change default GPG keyserver from pgp.mit.edu to keys.openpgp.org. [#63806](https://github.com/saltstack/salt/issues/63806) +- fix cherrypy 400 error output to be less generic. [#63835](https://github.com/saltstack/salt/issues/63835) +- Ensure kwargs is passed along to _call_apt when passed into install function. [#63847](https://github.com/saltstack/salt/issues/63847) +- remove eval and update logging to be more informative on bad config [#63879](https://github.com/saltstack/salt/issues/63879) +- add linux_distribution to util to stop dep warning [#63904](https://github.com/saltstack/salt/issues/63904) +- Fix valuerror when trying to close fileclient. Remove usage of __del__ and close the filclient properly. [#63920](https://github.com/saltstack/salt/issues/63920) +- Handle the situation when a sub proxy minion does not init properly, eg. an exception happens, and the sub proxy object is not available. [#63923](https://github.com/saltstack/salt/issues/63923) +- Clarifying documentation for extension_modules configuration option. [#63929](https://github.com/saltstack/salt/issues/63929) +- Windows pkg module now properly handles versions containing strings [#63935](https://github.com/saltstack/salt/issues/63935) +- Handle the scenario when the check_cmd requisite is used with a state function when the state has a local check_cmd function but that function isn't used by that function. [#63948](https://github.com/saltstack/salt/issues/63948) +- Issue #63981: Allow users to pass verify_ssl to pkg.install/pkg.installed on Windows [#63981](https://github.com/saltstack/salt/issues/63981) +- Hardened permissions on workers.ipc and master_event_pub.ipc. [#64063](https://github.com/saltstack/salt/issues/64063) + +# Added + +- Introduce a `LIB_STATE_DIR` syspaths variable which defaults to `CONFIG_DIR`, + but can be individually customized during installation by specifying + `--salt-lib-state-dir` during installation. Change the default `pki_dir` to + `/pki/master` (for the master) and `/pki/minion` + (for the minion). [#3396](https://github.com/saltstack/salt/issues/3396) +- Allow users to enable 'queue=True' for all state runs via config file [#31468](https://github.com/saltstack/salt/issues/31468) +- Added pillar templating to vault policies [#43287](https://github.com/saltstack/salt/issues/43287) +- Add support for NVMeF as a transport protocol for hosts in a Pure Storage FlashArray [#51088](https://github.com/saltstack/salt/issues/51088) +- A new salt-ssh roster that generates a roster by parses a known_hosts file. [#54679](https://github.com/saltstack/salt/issues/54679) +- Added Windows Event Viewer support [#54713](https://github.com/saltstack/salt/issues/54713) +- Added the win_lgpo_reg state and execution modules which will allow registry based group policy to be set directly in the Registry.pol file [#56013](https://github.com/saltstack/salt/issues/56013) +- Added resource tagging functions to boto_dynamodb execution module [#57500](https://github.com/saltstack/salt/issues/57500) +- Added `openvswitch_db` state module and functions `bridge_to_parent`, + `bridge_to_vlan`, `db_get`, and `db_set` to the `openvswitch` execution module. + Also added optional `parent` and `vlan` parameters to the + `openvswitch_bridge.present` state module function and the + `openvswitch.bridge_create` execution module function. [#58986](https://github.com/saltstack/salt/issues/58986) +- State module to manage SysFS attributes [#60154](https://github.com/saltstack/salt/issues/60154) +- Added ability for `salt.wait_for_event` to handle `event_id`s that have a list value. [#60430](https://github.com/saltstack/salt/issues/60430) +- Added suport for Linux ppc64le core grains (cpu_model, virtual, productname, manufacturer, serialnumber) and arm core grains (serialnumber, productname) [#60518](https://github.com/saltstack/salt/issues/60518) +- Added autostart option to virt.defined and virt.running states, along with virt.update execution modules. [#60700](https://github.com/saltstack/salt/issues/60700) +- Added .0 back to our versioning scheme for future versions (e.g. 3006.0) [#60722](https://github.com/saltstack/salt/issues/60722) +- Initial work to allow parallel startup of proxy minions when used as sub proxies with Deltaproxy. [#61153](https://github.com/saltstack/salt/issues/61153) +- Added node label support for GCE [#61245](https://github.com/saltstack/salt/issues/61245) +- Support the --priority flag when adding sources to Chocolatey. [#61319](https://github.com/saltstack/salt/issues/61319) +- Add namespace option to ext_pillar.http_json [#61335](https://github.com/saltstack/salt/issues/61335) +- Added a filter function to ps module to get a list of processes on a minion according to their state. [#61420](https://github.com/saltstack/salt/issues/61420) +- Add postgres.timeout option to postgres module for limiting postgres query times [#61433](https://github.com/saltstack/salt/issues/61433) +- Added new optional vault option, ``config_location``. This can be either ``master`` or ``local`` and defines where vault will look for connection details, either requesting them from the master or using the local config. [#61857](https://github.com/saltstack/salt/issues/61857) +- Add ipwrap() jinja filter to wrap IPv6 addresses with brackets. [#61931](https://github.com/saltstack/salt/issues/61931) +- 'tcp' transport is now available in ipv6-only network [#62009](https://github.com/saltstack/salt/issues/62009) +- Add `diff_attr` parameter to pkg.upgrade() (zypper/yum). [#62031](https://github.com/saltstack/salt/issues/62031) +- Config option pass_variable_prefix allows to distinguish variables that contain paths to pass secrets. + Config option pass_strict_fetch allows to error out when a secret cannot be fetched from pass. + Config option pass_dir allows setting the PASSWORD_STORE_DIR env for pass. + Config option pass_gnupghome allows setting the $GNUPGHOME env for pass. [#62120](https://github.com/saltstack/salt/issues/62120) +- Add file.pruned state and expanded file.rmdir exec module functionality [#62178](https://github.com/saltstack/salt/issues/62178) +- Added "dig.PTR" function to resolve PTR records for IPs, as well as tests and documentation [#62275](https://github.com/saltstack/salt/issues/62275) +- Added the ability to remove a KB using the DISM state/execution modules [#62366](https://github.com/saltstack/salt/issues/62366) +- Add " python" subcommand to allow execution or arbitrary scripts via bundled Python runtime [#62381](https://github.com/saltstack/salt/issues/62381) +- Add ability to provide conditions which convert normal state actions to no-op when true [#62446](https://github.com/saltstack/salt/issues/62446) +- Added debug log messages displaying the command being run when installing packages on Windows [#62480](https://github.com/saltstack/salt/issues/62480) +- Add biosvendor grain [#62496](https://github.com/saltstack/salt/issues/62496) +- Add ifelse Jinja function as found in CFEngine [#62508](https://github.com/saltstack/salt/issues/62508) +- Implementation of Amazon EC2 instance detection and setting `virtual_subtype` grain accordingly including the product if possible to identify. [#62539](https://github.com/saltstack/salt/issues/62539) +- Adds __env__substitution to ext_pillar.stack; followup of #61531, improved exception handling for stacked template (jinja) template rendering and yaml parsing in ext_pillar.stack [#62578](https://github.com/saltstack/salt/issues/62578) +- Increase file.tidied flexibility with regard to age and size [#62678](https://github.com/saltstack/salt/issues/62678) +- Added "connected_devices" feature to netbox pillar module. It contains extra information about devices connected to the minion [#62761](https://github.com/saltstack/salt/issues/62761) +- Add atomic file operation for symlink changes [#62768](https://github.com/saltstack/salt/issues/62768) +- Add password/account locking/unlocking in user.present state on supported operating systems [#62856](https://github.com/saltstack/salt/issues/62856) +- Added onchange configuration for script engine [#62867](https://github.com/saltstack/salt/issues/62867) +- Added output and bare functionality to export_key gpg module function [#62978](https://github.com/saltstack/salt/issues/62978) +- Add keyvalue serializer for environment files [#62983](https://github.com/saltstack/salt/issues/62983) +- Add ability to ignore symlinks in file.tidied [#63042](https://github.com/saltstack/salt/issues/63042) +- salt-cloud support IMDSv2 tokens when using 'use-instance-role-credentials' [#63067](https://github.com/saltstack/salt/issues/63067) +- Fix running fast tests twice and add git labels to suite. [#63081](https://github.com/saltstack/salt/issues/63081) +- Add ability for file.symlink to not set ownership on existing links [#63093](https://github.com/saltstack/salt/issues/63093) +- Restore the previous slack engine and deprecate it, rename replace the slack engine to slack_bolt until deprecation [#63095](https://github.com/saltstack/salt/issues/63095) +- Add functions that will return the underlying block device, mount point, and filesystem type for a given path [#63098](https://github.com/saltstack/salt/issues/63098) +- Add ethtool execution and state module functions for pause [#63128](https://github.com/saltstack/salt/issues/63128) +- Add boardname grain [#63131](https://github.com/saltstack/salt/issues/63131) +- Added management of ECDSA/EdDSA private keys with x509 modules in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#63248](https://github.com/saltstack/salt/issues/63248) +- Added x509 modules support for different output formats in the new cryptography x509 module. Please migrate to the new cryptography x509 module for this improvement. [#63249](https://github.com/saltstack/salt/issues/63249) +- Added deprecation_warning test state for ensuring that deprecation warnings are correctly emitted. [#63315](https://github.com/saltstack/salt/issues/63315) +- Adds a state_events option to state.highstate, state.apply, state.sls, state.sls_id. + This allows users to enable state_events on a per use basis rather than having to + enable them globally for all state runs. [#63316](https://github.com/saltstack/salt/issues/63316) +- Allow max queue size setting for state runs to prevent performance problems from queue growth [#63356](https://github.com/saltstack/salt/issues/63356) +- Add support of exposing meta_server_grains for Azure VMs [#63606](https://github.com/saltstack/salt/issues/63606) +- Include the version of `relenv` in the versions report. [#63827](https://github.com/saltstack/salt/issues/63827) +- Added debug log messages displaying the command being run when removing packages on Windows [#63866](https://github.com/saltstack/salt/issues/63866) +- Adding the ability to exclude arguments from a state that end up passed to cmd.retcode when requisites such as onlyif or unless are used. [#63956](https://github.com/saltstack/salt/issues/63956) +- Add --next-release argument to salt/version.py, which prints the next upcoming release. [#64023](https://github.com/saltstack/salt/issues/64023) + +# Security + +- Upgrade Requirements Due to Security Issues. + + * Upgrade to `cryptography>=39.0.1` due to: + * https://github.com/advisories/GHSA-x4qr-2fvf-3mr5 + * https://github.com/advisories/GHSA-w7pp-m8wf-vj6r + * Upgrade to `pyopenssl==23.0.0` due to the cryptography upgrade. + * Update to `markdown-it-py==2.2.0` due to: + * https://github.com/advisories/GHSA-jrwr-5x3p-hvc3 + * https://github.com/advisories/GHSA-vrjv-mxr7-vjf8 [#63882](https://github.com/saltstack/salt/issues/63882) + + * Wed Mar 29 2023 Salt Project Packaging - 3006.0~rc3 # Removed diff --git a/pkg/tests/conftest.py b/pkg/tests/conftest.py index 45e48e5a8b5..d8b39e7070a 100644 --- a/pkg/tests/conftest.py +++ b/pkg/tests/conftest.py @@ -1,12 +1,17 @@ import logging +import os import pathlib import shutil +import subprocess +import sys import pytest +import yaml from pytestskipmarkers.utils import platform from saltfactories.utils import random_string from saltfactories.utils.tempfiles import SaltPillarTree, SaltStateTree +import salt.config from tests.support.helpers import ( CODE_DIR, TESTS_DIR, @@ -282,6 +287,44 @@ def salt_master(salt_factories, install_salt, state_tree, pillar_tree): "netapi_enable_clients": ["local"], "external_auth": {"auto": {"saltdev": [".*"]}}, } + test_user = False + master_config = install_salt.config_path / "master" + if master_config.exists(): + with open(master_config) as fp: + data = yaml.safe_load(fp) + if data and "user" in data: + test_user = True + # We are testing a different user, so we need to test the system + # configs, or else permissions will not be correct. + config_overrides["user"] = data["user"] + config_overrides["log_file"] = salt.config.DEFAULT_MASTER_OPTS.get( + "log_file" + ) + config_overrides["root_dir"] = salt.config.DEFAULT_MASTER_OPTS.get( + "root_dir" + ) + config_overrides["key_logfile"] = salt.config.DEFAULT_MASTER_OPTS.get( + "key_logfile" + ) + config_overrides["pki_dir"] = salt.config.DEFAULT_MASTER_OPTS.get( + "pki_dir" + ) + config_overrides["api_logfile"] = salt.config.DEFAULT_API_OPTS.get( + "api_logfile" + ) + config_overrides["api_pidfile"] = salt.config.DEFAULT_API_OPTS.get( + "api_pidfile" + ) + # verify files where set with correct owner/group + verify_files = [ + pathlib.Path("/var", "log", "salt"), + pathlib.Path("/etc", "salt", "master"), + pathlib.Path("/var", "cache", "salt", "master"), + ] + for _file in verify_files: + assert _file.owner() == "salt" + assert _file.group() == "salt" + if (platform.is_windows() or platform.is_darwin()) and install_salt.singlebin: start_timeout = 240 # For every minion started we have to accept it's key. @@ -324,6 +367,20 @@ def salt_master(salt_factories, install_salt, state_tree, pillar_tree): salt_pkg_install=install_salt, ) factory.after_terminate(pytest.helpers.remove_stale_master_key, factory) + if test_user: + # Salt factories calls salt.utils.verify.verify_env + # which sets root perms on /var/log/salt since we are running + # the test suite as root, but we want to run Salt master as salt + # We ensure those permissions where set by the package earlier + shutil.chown(pathlib.Path("/var", "log", "salt"), "salt", "salt") + # The engines_dirs is created in .nox path. We need to set correct perms + # for the user running the Salt Master + subprocess.run(["chown", "-R", "salt:salt", str(CODE_DIR.parent / ".nox")]) + file_roots = pathlib.Path("/srv/", "salt") + pillar_roots = pathlib.Path("/srv/", "pillar") + for _dir in [file_roots, pillar_roots]: + subprocess.run(["chown", "-R", "salt:salt", str(_dir)]) + with factory.started(start_timeout=start_timeout): yield factory @@ -364,6 +421,15 @@ def salt_minion(salt_factories, salt_master, install_salt): overrides=config_overrides, defaults=config_defaults, ) + # Salt factories calls salt.utils.verify.verify_env + # which sets root perms on /srv/salt and /srv/pillar since we are running + # the test suite as root, but we want to run Salt master as salt + if not platform.is_windows() and not platform.is_darwin(): + file_roots = pathlib.Path("/srv/", "salt") + pillar_roots = pathlib.Path("/srv/", "pillar") + for _dir in [file_roots, pillar_roots]: + subprocess.run(["chown", "-R", "salt:salt", str(_dir)]) + factory.after_terminate( pytest.helpers.remove_stale_minion_key, salt_master, factory.id ) @@ -393,10 +459,24 @@ def test_account(salt_call_cli): @pytest.fixture(scope="module") -def salt_api(salt_master, install_salt): +def extras_pypath(): + extras_dir = "extras-{}.{}".format(*sys.version_info) + if platform.is_windows(): + return pathlib.Path( + os.getenv("ProgramFiles"), "Salt Project", "Salt", extras_dir, "bin" + ) + elif platform.is_darwin(): + return pathlib.Path(f"/opt", "salt", extras_dir, "bin") + else: + return pathlib.Path(f"/opt", "saltstack", "salt", extras_dir, "bin") + + +@pytest.fixture(scope="module") +def salt_api(salt_master, install_salt, extras_pypath): """ start up and configure salt_api """ + shutil.rmtree(str(extras_pypath.parent), ignore_errors=True) start_timeout = None if platform.is_windows() and install_salt.singlebin: start_timeout = 240 diff --git a/pkg/tests/download/test_pkg_download.py b/pkg/tests/download/test_pkg_download.py index 367effcb3c2..bbe26df549f 100644 --- a/pkg/tests/download/test_pkg_download.py +++ b/pkg/tests/download/test_pkg_download.py @@ -103,6 +103,18 @@ def get_test_versions(): "os_codename": "jammy", "container_id": "ubuntu_22_04", }, + { + "image": "ghcr.io/saltstack/salt-ci-containers/photon:3", + "os_type": "photon", + "os_version": 3, + "container_id": "photon_3", + }, + { + "image": "ghcr.io/saltstack/salt-ci-containers/photon:4", + "os_type": "photon", + "os_version": 4, + "container_id": "photon_4", + }, ] for container in containers: test_versions.append( @@ -190,7 +202,7 @@ def pkg_container( container_setup_func = globals()[f"setup_{download_test_image.os_type}"] except KeyError: raise pytest.skip.Exception( - f"Unable to handle {pkg_container.os_type}. Skipping.", + f"Unable to handle {download_test_image.os_type}. Skipping.", _use_item_location=True, ) container.before_terminate(shutil.rmtree, str(downloads_path), ignore_errors=True) @@ -245,13 +257,16 @@ def root_url(salt_release): def get_salt_release(): salt_release = os.environ.get("SALT_RELEASE") + pkg_test_type = os.environ.get("PKG_TEST_TYPE", "install") if salt_release is None: - log.warning( - "Setting salt release to 3006.0rc2 which is probably not what you want." - ) + if pkg_test_type == "download-pkgs": + log.warning( + "Setting salt release to 3006.0rc2 which is probably not what you want." + ) salt_release = "3006.0rc2" - if packaging.version.parse(salt_release) < packaging.version.parse("3006.0rc1"): - log.warning(f"The salt release being tested, {salt_release!r} looks off.") + if pkg_test_type == "download-pkgs": + if packaging.version.parse(salt_release) < packaging.version.parse("3006.0rc1"): + log.warning(f"The salt release being tested, {salt_release!r} looks off.") return salt_release @@ -296,9 +311,11 @@ def setup_redhat_family( f"{repo_url_base}.repo", downloads_path / f"salt-{os_name}.repo" ) + clean_command = "all" if os_name == "photon" else "expire-cache" + install_dmesg = ("yum", "install", "-y", "util-linux") commands = [ ("mv", f"/downloads/{repo_file.name}", f"/etc/yum.repos.d/salt-{os_name}.repo"), - ("yum", "clean", "expire-cache"), + ("yum", "clean", clean_command), ( "yum", "install", @@ -311,6 +328,11 @@ def setup_redhat_family( "salt-api", ), ] + + # For some reason, the centosstream9 container doesn't have dmesg installed + if os_version == 9 and os_name == "redhat": + commands.insert(2, install_dmesg) + for cmd in commands: ret = container.run(*cmd) if ret.returncode != 0: @@ -380,6 +402,27 @@ def setup_fedora( ) +def setup_photon( + container, + os_version, + os_codename, + root_url, + salt_release, + downloads_path, + gpg_key_name, +): + setup_redhat_family( + container, + os_version, + os_codename, + root_url, + salt_release, + downloads_path, + "photon", + gpg_key_name, + ) + + def setup_debian_family( container, os_version, @@ -488,15 +531,8 @@ def setup_macos(root_url, salt_release, shell): if arch == "aarch64": arch = "arm64" - repo_type = os.environ.get("SALT_REPO_TYPE", "staging") if packaging.version.parse(salt_release) > packaging.version.parse("3005"): - if repo_type == "staging": - mac_pkg = f"salt-{salt_release}-py3-{arch}-unsigned.pkg" - else: - mac_pkg = f"salt-{salt_release}-py3-{arch}.pkg" - - # TODO: We still don't sign mac packages. Remove the line below when we do - mac_pkg = f"salt-{salt_release}-py3-{arch}-unsigned.pkg" + mac_pkg = f"salt-{salt_release}-py3-{arch}.pkg" mac_pkg_url = f"{root_url}/macos/minor/{salt_release}/{mac_pkg}" else: mac_pkg_url = f"{root_url}/macos/{salt_release}/{mac_pkg}" diff --git a/pkg/tests/integration/test_clean_zmq_teardown.py b/pkg/tests/integration/test_clean_zmq_teardown.py new file mode 100644 index 00000000000..d1dbe325ab2 --- /dev/null +++ b/pkg/tests/integration/test_clean_zmq_teardown.py @@ -0,0 +1,55 @@ +import logging +import pathlib +import shutil +import textwrap + +import pytest + +pytestmark = [ + pytest.mark.skip_on_windows, +] + +log = logging.getLogger(__name__) + + +def test_check_no_import_error(salt_call_cli, salt_master): + """ + Test that we don't have any errors on teardown of python when using a py-rendered sls file + This is a package test because the issue was not reproducible in our normal test suite + """ + init_sls = textwrap.dedent( + """#!py + + +def run(): + return { + "file_foobar": { + "file.managed": [ + { + "name": "/foobar" + }, + { + "template": "jinja" + }, + { + "context": { + "foobar": "baz", + } + }, + { + "source": "salt://breaks/foobar.jinja", + } + ] + } + } + """ + ) + base_tree = pathlib.Path(salt_master.config["file_roots"]["base"][0]) + breaks_tree = base_tree / "breaks" + breaks_tree.mkdir(exist_ok=True) + (breaks_tree / "init.sls").write_text(init_sls) + (breaks_tree / "foobar.jinja").write_text("{{ foobar }}") + output = salt_call_cli.run("state.apply", "breaks", "--output-diff", "test=true") + log.debug(output.stderr) + shutil.rmtree(str(breaks_tree), ignore_errors=True) + assert not output.stderr diff --git a/pkg/tests/integration/test_enabled_disabled.py b/pkg/tests/integration/test_enabled_disabled.py index 2bedb87d650..adb953a5dd5 100644 --- a/pkg/tests/integration/test_enabled_disabled.py +++ b/pkg/tests/integration/test_enabled_disabled.py @@ -14,7 +14,7 @@ def test_services(install_salt, salt_cli, salt_minion): if install_salt.distro_id in ("ubuntu", "debian"): services_enabled = ["salt-master", "salt-minion", "salt-syndic", "salt-api"] services_disabled = [] - elif install_salt.distro_id in ("centos", "redhat", "amzn", "fedora"): + elif install_salt.distro_id in ("centos", "redhat", "amzn", "fedora", "photon"): services_enabled = [] services_disabled = ["salt-master", "salt-minion", "salt-syndic", "salt-api"] elif platform.is_darwin(): diff --git a/pkg/tests/integration/test_pip.py b/pkg/tests/integration/test_pip.py index 29fa1a87bc6..ea9e6a81b84 100644 --- a/pkg/tests/integration/test_pip.py +++ b/pkg/tests/integration/test_pip.py @@ -1,5 +1,7 @@ +import json import os import pathlib +import shutil import subprocess import pytest @@ -17,10 +19,12 @@ def pypath(): @pytest.fixture(autouse=True) -def wipe_pydeps(pypath, install_salt): +def wipe_pydeps(install_salt, extras_pypath): try: yield finally: + # Note, uninstalling anything with an associated script will leave the script. + # This is due to a bug in pip. for dep in ["pep8", "PyGithub"]: subprocess.run( install_salt.binary_paths["pip"] + ["uninstall", "-y", dep], @@ -29,6 +33,7 @@ def wipe_pydeps(pypath, install_salt): check=False, universal_newlines=True, ) + shutil.rmtree(extras_pypath, ignore_errors=True) def test_pip_install(salt_call_cli): @@ -51,6 +56,49 @@ def test_pip_install(salt_call_cli): assert "The github execution module cannot be loaded" in use_lib.stderr +def test_pip_install_extras(install_salt, extras_pypath): + """ + Test salt-pip installs into the correct directory + """ + dep = "pep8" + extras_keyword = "extras" + if platform.is_windows(): + check_path = extras_pypath / f"{dep}.exe" + else: + check_path = extras_pypath / dep + + install_ret = subprocess.run( + install_salt.binary_paths["pip"] + ["install", dep], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + assert install_ret.returncode == 0 + + ret = subprocess.run( + install_salt.binary_paths["pip"] + ["list", "--format=json"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + assert ret.returncode == 0 + pkgs_installed = json.loads(ret.stdout.strip().decode()) + for pkg in pkgs_installed: + if pkg["name"] == dep: + break + else: + pytest.fail( + f"The {dep!r} package was not found installed. Packages Installed: {pkgs_installed}" + ) + + show_ret = subprocess.run( + install_salt.binary_paths["pip"] + ["show", dep], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + assert show_ret.returncode == 0 + assert extras_keyword in show_ret.stdout.decode() + assert check_path.exists() + + def demote(user_uid, user_gid): def result(): os.setgid(user_gid) @@ -60,18 +108,8 @@ def demote(user_uid, user_gid): @pytest.mark.skip_on_windows(reason="We can't easily demote users on Windows") -def test_pip_non_root(install_salt, test_account, pypath): - check_path = pypath / "pep8" - # Lets make sure pep8 is not currently installed - subprocess.run( - install_salt.binary_paths["pip"] + ["uninstall", "-y", "pep8"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - check=False, - universal_newlines=True, - ) - - assert not check_path.exists() +def test_pip_non_root(install_salt, test_account, extras_pypath): + check_path = extras_pypath / "pep8" # We should be able to issue a --help without being root ret = subprocess.run( install_salt.binary_paths["salt"] + ["--help"], @@ -84,21 +122,6 @@ def test_pip_non_root(install_salt, test_account, pypath): ) assert ret.returncode == 0, ret.stderr assert "Usage" in ret.stdout - assert not check_path.exists() - - # Try to pip install something, should fail - ret = subprocess.run( - install_salt.binary_paths["pip"] + ["install", "pep8"], - preexec_fn=demote(test_account.uid, test_account.gid), - env=test_account.env, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - check=False, - universal_newlines=True, - ) - assert ret.returncode == 1, ret.stderr - assert "Could not install packages due to an OSError" in ret.stderr - assert not check_path.exists() # Let tiamat-pip create the pypath directory for us ret = subprocess.run( diff --git a/pkg/tests/integration/test_salt_user.py b/pkg/tests/integration/test_salt_user.py new file mode 100644 index 00000000000..4e7ddfda0a0 --- /dev/null +++ b/pkg/tests/integration/test_salt_user.py @@ -0,0 +1,22 @@ +import psutil +import pytest +import yaml +from pytestskipmarkers.utils import platform + +pytestmark = [ + pytest.mark.skip_on_windows, +] + + +def test_salt_user_master(salt_master, install_salt): + """ + Test the correct user is running the Salt Master + """ + if platform.is_windows() or platform.is_darwin(): + pytest.skip("Package does not have user set. Not testing user") + match = False + for proc in psutil.Process(salt_master.pid).children(): + assert proc.username() == "salt" + match = True + + assert match diff --git a/pkg/tests/integration/test_systemd_config.py b/pkg/tests/integration/test_systemd_config.py index b57a018d1ab..81da09ef678 100644 --- a/pkg/tests/integration/test_systemd_config.py +++ b/pkg/tests/integration/test_systemd_config.py @@ -22,6 +22,8 @@ def test_system_config(salt_cli, salt_minion): "CentOS Linux-8", "CentOS Stream-9", "Fedora Linux-36", + "VMware Photon OS-3", + "VMware Photon OS-4", ): ret = subprocess.call( "systemctl show -p ${config} salt-minion.service", shell=True diff --git a/pkg/tests/integration/test_version.py b/pkg/tests/integration/test_version.py index 2b45ecbfd7a..d79ebcd8dfc 100644 --- a/pkg/tests/integration/test_version.py +++ b/pkg/tests/integration/test_version.py @@ -62,7 +62,11 @@ def test_compare_versions(version, binary, install_salt): ret = install_salt.proc.run(*install_salt.binary_paths[binary], "--version") ret.stdout.matcher.fnmatch_lines([f"*{version}*"]) else: - pytest.skip(f"Binary not available: {binary}") + if platform.is_windows(): + pytest.skip(f"Binary not available on windows: {binary}") + pytest.fail( + f"Platform is not Windows and yet the binary {binary!r} is not available" + ) @pytest.mark.skip_unless_on_darwin() diff --git a/pkg/tests/support/helpers.py b/pkg/tests/support/helpers.py index c51707d8ce0..90abf8b88e4 100644 --- a/pkg/tests/support/helpers.py +++ b/pkg/tests/support/helpers.py @@ -96,6 +96,7 @@ class SaltPkgInstall: minor: str = attr.ib(init=False) relenv: bool = attr.ib(default=True) file_ext: bool = attr.ib(default=None) + config_path: str = attr.ib(init=False) @proc.default def _default_proc(self): @@ -128,7 +129,7 @@ class SaltPkgInstall: @pkg_mngr.default def _default_pkg_mngr(self): - if self.distro_id in ("centos", "redhat", "amzn", "fedora"): + if self.distro_id in ("centos", "redhat", "amzn", "fedora", "photon"): return "yum" elif self.distro_id in ("ubuntu", "debian"): ret = self.proc.run("apt-get", "update") @@ -137,7 +138,7 @@ class SaltPkgInstall: @rm_pkg.default def _default_rm_pkg(self): - if self.distro_id in ("centos", "redhat", "amzn", "fedora"): + if self.distro_id in ("centos", "redhat", "amzn", "fedora", "photon"): return "remove" elif self.distro_id in ("ubuntu", "debian"): return "purge" @@ -152,7 +153,7 @@ class SaltPkgInstall: "salt-cloud", "salt-minion", ] - if self.distro_id in ("centos", "redhat", "amzn", "fedora"): + if self.distro_id in ("centos", "redhat", "amzn", "fedora", "photon"): salt_pkgs.append("salt") elif self.distro_id in ("ubuntu", "debian"): salt_pkgs.append("salt-common") @@ -171,6 +172,17 @@ class SaltPkgInstall: install_dir = pathlib.Path("/opt", "saltstack", "salt") return install_dir + @config_path.default + def _default_config_path(self): + """ + Default location for salt configurations + """ + if platform.is_windows(): + config_path = pathlib.Path("C://salt", "etc", "salt") + else: + config_path = pathlib.Path("/etc", "salt") + return config_path + @repo_data.default def _default_repo_data(self): """ @@ -640,7 +652,7 @@ class SaltPkgInstall: if self.classic: root_url = "py3/" - if self.distro_name in ["redhat", "centos", "amazon", "fedora"]: + if self.distro_name in ["redhat", "centos", "amazon", "fedora", "vmware"]: for fp in pathlib.Path("/etc", "yum.repos.d").glob("epel*"): fp.unlink() gpg_key = "SALTSTACK-GPG-KEY.pub" diff --git a/pkg/windows/msi/build_pkg.ps1 b/pkg/windows/msi/build_pkg.ps1 index f1b453f5143..897d60782e6 100644 --- a/pkg/windows/msi/build_pkg.ps1 +++ b/pkg/windows/msi/build_pkg.ps1 @@ -74,7 +74,7 @@ function VerifyOrDownload ($local_file, $URL, $SHA256) { #------------------------------------------------------------------------------- $WEBCACHE_DIR = "$env:TEMP\msi_build_cache_dir" -$DEPS_URL = "http://repo.saltproject.io/windows/dependencies" +$DEPS_URL = "https://repo.saltproject.io/windows/dependencies" $PROJECT_DIR = $(git rev-parse --show-toplevel) $BUILD_DIR = "$PROJECT_DIR\pkg\windows\build" $BUILDENV_DIR = "$PROJECT_DIR\pkg\windows\buildenv" diff --git a/requirements/darwin.txt b/requirements/darwin.txt index 8f157d3387f..be8a547ae8e 100644 --- a/requirements/darwin.txt +++ b/requirements/darwin.txt @@ -9,7 +9,6 @@ cryptography>=39.0.1 gitpython>=3.1.30; python_version >= '3.7' idna>=2.8 linode-python>=1.1.1 -mako>=1.0.7 pyasn1>=0.4.8 pycparser>=2.21 pyopenssl>=19.0.0 diff --git a/requirements/static/ci/cloud.in b/requirements/static/ci/cloud.in index 54477748df2..0d60c2d9a43 100644 --- a/requirements/static/ci/cloud.in +++ b/requirements/static/ci/cloud.in @@ -4,3 +4,5 @@ netaddr profitbricks pypsexec pywinrm +pyspnego==0.8.0 +smbprotocol==1.10.1 diff --git a/requirements/static/ci/py3.10/cloud.txt b/requirements/static/ci/py3.10/cloud.txt index eb373e8566a..61380ad366d 100644 --- a/requirements/static/ci/py3.10/cloud.txt +++ b/requirements/static/ci/py3.10/cloud.txt @@ -396,6 +396,7 @@ cryptography==39.0.2 # moto # paramiko # pyopenssl + # pyspnego # requests-ntlm # smbprotocol # vcert @@ -618,9 +619,7 @@ netaddr==0.7.19 # -r requirements/static/ci/cloud.in # junos-eznc ntlm-auth==1.3.0 - # via - # requests-ntlm - # smbprotocol + # via requests-ntlm oauthlib==3.2.2 # via requests-oauthlib oscrypto==1.2.1 @@ -657,7 +656,6 @@ pyasn1==0.4.8 # via # pyasn1-modules # rsa - # smbprotocol pycparser==2.21 ; python_version >= "3.9" # via # -r requirements/static/ci/common.in @@ -685,6 +683,10 @@ pyrsistent==0.18.0 # via jsonschema pyserial==3.5 # via junos-eznc +pyspnego==0.8.0 + # via + # -r requirements/static/ci/cloud.in + # smbprotocol pytest-custom-exit-code==0.3.0 # via -r requirements/pytest.txt pytest-helpers-namespace==2021.4.29 @@ -826,13 +828,14 @@ six==1.16.0 # pyvmomi # pywinrm # responses - # smbprotocol # transitions # vcert # virtualenv # websocket-client -smbprotocol==0.1.1 - # via pypsexec +smbprotocol==1.10.1 + # via + # -r requirements/static/ci/cloud.in + # pypsexec smmap==4.0.0 # via gitdb sqlparse==0.4.2 diff --git a/requirements/static/ci/py3.10/darwin.txt b/requirements/static/ci/py3.10/darwin.txt index 2971d403190..d3b43c46c38 100644 --- a/requirements/static/ci/py3.10/darwin.txt +++ b/requirements/static/ci/py3.10/darwin.txt @@ -495,9 +495,7 @@ lxml==4.9.1 # junos-eznc # ncclient mako==1.2.2 - # via - # -r requirements/darwin.txt - # -r requirements/static/ci/common.in + # via -r requirements/static/ci/common.in markupsafe==2.1.2 # via # -r requirements/base.txt diff --git a/requirements/static/ci/py3.10/pkgtests-windows.txt b/requirements/static/ci/py3.10/pkgtests-windows.txt index 2c2244b0032..2ba612f0a16 100644 --- a/requirements/static/ci/py3.10/pkgtests-windows.txt +++ b/requirements/static/ci/py3.10/pkgtests-windows.txt @@ -138,7 +138,7 @@ pywin32==305 # wmi pyyaml==6.0 # via -r requirements/base.txt -pyzmq==25.0.0 ; sys_platform == "win32" +pyzmq==25.0.2 ; sys_platform == "win32" # via # -r requirements/zeromq.txt # pytest-salt-factories diff --git a/requirements/static/ci/py3.10/pkgtests.txt b/requirements/static/ci/py3.10/pkgtests.txt index dc8987818b6..e5f6a8d0499 100644 --- a/requirements/static/ci/py3.10/pkgtests.txt +++ b/requirements/static/ci/py3.10/pkgtests.txt @@ -125,7 +125,7 @@ pytz==2022.7.1 # via tempora pyyaml==6.0 # via -r requirements/base.txt -pyzmq==25.0.0 ; python_version < "3.11" +pyzmq==25.0.2 ; python_version < "3.11" # via # -r requirements/zeromq.txt # pytest-salt-factories diff --git a/requirements/static/ci/py3.10/tools.txt b/requirements/static/ci/py3.10/tools.txt index 5b8e881d937..af55d67560f 100644 --- a/requirements/static/ci/py3.10/tools.txt +++ b/requirements/static/ci/py3.10/tools.txt @@ -41,7 +41,9 @@ python-tools-scripts==0.12.0 pyyaml==6.0 # via -r requirements/static/ci/tools.in requests==2.28.2 - # via python-tools-scripts + # via + # python-tools-scripts + # virustotal3 rich==12.5.1 # via python-tools-scripts s3transfer==0.5.2 @@ -54,3 +56,5 @@ urllib3==1.26.12 # via # botocore # requests +virustotal3==1.0.8 + # via -r requirements/static/ci/tools.in diff --git a/requirements/static/ci/py3.10/windows.txt b/requirements/static/ci/py3.10/windows.txt index a2427697092..610ddbd8363 100644 --- a/requirements/static/ci/py3.10/windows.txt +++ b/requirements/static/ci/py3.10/windows.txt @@ -165,9 +165,7 @@ looseversion==1.0.2 lxml==4.9.1 # via -r requirements/windows.txt mako==1.2.2 - # via - # -r requirements/static/ci/common.in - # -r requirements/windows.txt + # via -r requirements/static/ci/common.in markupsafe==2.1.1 # via # -r requirements/base.txt @@ -318,7 +316,7 @@ pyyaml==5.4.1 # clustershell # kubernetes # yamllint -pyzmq==25.0.0 ; sys_platform == "win32" +pyzmq==25.0.2 ; sys_platform == "win32" # via # -r requirements/zeromq.txt # pytest-salt-factories diff --git a/requirements/static/ci/py3.11/darwin.txt b/requirements/static/ci/py3.11/darwin.txt index 5e50cd66084..8ed823ee9d4 100644 --- a/requirements/static/ci/py3.11/darwin.txt +++ b/requirements/static/ci/py3.11/darwin.txt @@ -482,9 +482,7 @@ linode-python==1.1.1 looseversion==1.0.2 # via -r requirements/base.txt mako==1.2.2 - # via - # -r requirements/darwin.txt - # -r requirements/static/ci/common.in + # via -r requirements/static/ci/common.in markupsafe==2.1.2 # via # -r requirements/base.txt diff --git a/requirements/static/ci/py3.11/windows.txt b/requirements/static/ci/py3.11/windows.txt index 332002fd9bd..048cad62ebf 100644 --- a/requirements/static/ci/py3.11/windows.txt +++ b/requirements/static/ci/py3.11/windows.txt @@ -163,9 +163,7 @@ looseversion==1.0.2 lxml==4.9.1 # via -r requirements/windows.txt mako==1.2.2 - # via - # -r requirements/static/ci/common.in - # -r requirements/windows.txt + # via -r requirements/static/ci/common.in markupsafe==2.1.1 # via # -r requirements/base.txt @@ -316,7 +314,7 @@ pyyaml==5.4.1 # clustershell # kubernetes # yamllint -pyzmq==25.0.0 ; sys_platform == "win32" +pyzmq==25.0.2 ; sys_platform == "win32" # via # -r requirements/zeromq.txt # pytest-salt-factories diff --git a/requirements/static/ci/py3.7/cloud.txt b/requirements/static/ci/py3.7/cloud.txt index 33688ffb4d0..d618db32a8d 100644 --- a/requirements/static/ci/py3.7/cloud.txt +++ b/requirements/static/ci/py3.7/cloud.txt @@ -403,6 +403,7 @@ cryptography==39.0.2 # moto # paramiko # pyopenssl + # pyspnego # requests-ntlm # smbprotocol # vcert @@ -657,9 +658,7 @@ ntc-templates==2.3.2 # junos-eznc # netmiko ntlm-auth==1.3.0 - # via - # requests-ntlm - # smbprotocol + # via requests-ntlm oauthlib==3.2.2 # via requests-oauthlib oscrypto==1.2.1 @@ -700,7 +699,6 @@ pyasn1==0.4.8 # via # pyasn1-modules # rsa - # smbprotocol pycparser==2.19 # via cffi pycryptodomex==3.10.1 @@ -729,6 +727,10 @@ pyserial==3.5 # via # junos-eznc # netmiko +pyspnego==0.8.0 + # via + # -r requirements/static/ci/cloud.in + # smbprotocol pytest-custom-exit-code==0.3.0 # via -r requirements/pytest.txt pytest-helpers-namespace==2021.4.29 @@ -875,14 +877,15 @@ six==1.16.0 # pyvmomi # pywinrm # responses - # smbprotocol # textfsm # transitions # vcert # virtualenv # websocket-client -smbprotocol==0.1.1 - # via pypsexec +smbprotocol==1.10.1 + # via + # -r requirements/static/ci/cloud.in + # pypsexec smmap==4.0.0 # via gitdb sqlparse==0.4.2 diff --git a/requirements/static/ci/py3.7/windows.txt b/requirements/static/ci/py3.7/windows.txt index 2821b15bc03..4596f2f2a17 100644 --- a/requirements/static/ci/py3.7/windows.txt +++ b/requirements/static/ci/py3.7/windows.txt @@ -179,9 +179,7 @@ looseversion==1.0.2 lxml==4.9.1 # via -r requirements/windows.txt mako==1.2.2 - # via - # -r requirements/static/ci/common.in - # -r requirements/windows.txt + # via -r requirements/static/ci/common.in markupsafe==2.1.2 # via # -r requirements/base.txt @@ -332,7 +330,7 @@ pyyaml==5.4.1 # clustershell # kubernetes # yamllint -pyzmq==25.0.0 ; sys_platform == "win32" +pyzmq==25.0.2 ; sys_platform == "win32" # via # -r requirements/zeromq.txt # pytest-salt-factories diff --git a/requirements/static/ci/py3.8/cloud.txt b/requirements/static/ci/py3.8/cloud.txt index c19829c7a17..652f8d96710 100644 --- a/requirements/static/ci/py3.8/cloud.txt +++ b/requirements/static/ci/py3.8/cloud.txt @@ -401,6 +401,7 @@ cryptography==39.0.2 # moto # paramiko # pyopenssl + # pyspnego # requests-ntlm # smbprotocol # vcert @@ -646,9 +647,7 @@ ntc-templates==2.3.2 # junos-eznc # netmiko ntlm-auth==1.3.0 - # via - # requests-ntlm - # smbprotocol + # via requests-ntlm oauthlib==3.2.2 # via requests-oauthlib oscrypto==1.2.1 @@ -689,7 +688,6 @@ pyasn1==0.4.8 # via # pyasn1-modules # rsa - # smbprotocol pycparser==2.19 # via cffi pycryptodomex==3.10.1 @@ -718,6 +716,10 @@ pyserial==3.5 # via # junos-eznc # netmiko +pyspnego==0.8.0 + # via + # -r requirements/static/ci/cloud.in + # smbprotocol pytest-custom-exit-code==0.3.0 # via -r requirements/pytest.txt pytest-helpers-namespace==2021.4.29 @@ -864,14 +866,15 @@ six==1.16.0 # pyvmomi # pywinrm # responses - # smbprotocol # textfsm # transitions # vcert # virtualenv # websocket-client -smbprotocol==0.1.1 - # via pypsexec +smbprotocol==1.10.1 + # via + # -r requirements/static/ci/cloud.in + # pypsexec smmap==4.0.0 # via gitdb sqlparse==0.4.2 diff --git a/requirements/static/ci/py3.8/windows.txt b/requirements/static/ci/py3.8/windows.txt index 80082ee5443..12c6e3dfe4d 100644 --- a/requirements/static/ci/py3.8/windows.txt +++ b/requirements/static/ci/py3.8/windows.txt @@ -167,9 +167,7 @@ looseversion==1.0.2 lxml==4.9.1 # via -r requirements/windows.txt mako==1.2.2 - # via - # -r requirements/static/ci/common.in - # -r requirements/windows.txt + # via -r requirements/static/ci/common.in markupsafe==2.1.2 # via # -r requirements/base.txt @@ -320,7 +318,7 @@ pyyaml==5.4.1 # clustershell # kubernetes # yamllint -pyzmq==25.0.0 ; sys_platform == "win32" +pyzmq==25.0.2 ; sys_platform == "win32" # via # -r requirements/zeromq.txt # pytest-salt-factories diff --git a/requirements/static/ci/py3.9/cloud.txt b/requirements/static/ci/py3.9/cloud.txt index 08ad9cf6e03..befb44b1939 100644 --- a/requirements/static/ci/py3.9/cloud.txt +++ b/requirements/static/ci/py3.9/cloud.txt @@ -401,6 +401,7 @@ cryptography==39.0.2 # moto # paramiko # pyopenssl + # pyspnego # requests-ntlm # smbprotocol # vcert @@ -646,9 +647,7 @@ ntc-templates==2.3.2 # junos-eznc # netmiko ntlm-auth==1.3.0 - # via - # requests-ntlm - # smbprotocol + # via requests-ntlm oauthlib==3.2.2 # via requests-oauthlib oscrypto==1.2.1 @@ -689,7 +688,6 @@ pyasn1==0.4.8 # via # pyasn1-modules # rsa - # smbprotocol pycparser==2.21 ; python_version >= "3.9" # via # -r requirements/static/ci/common.in @@ -721,6 +719,10 @@ pyserial==3.5 # via # junos-eznc # netmiko +pyspnego==0.8.0 + # via + # -r requirements/static/ci/cloud.in + # smbprotocol pytest-custom-exit-code==0.3.0 # via -r requirements/pytest.txt pytest-helpers-namespace==2021.4.29 @@ -867,14 +869,15 @@ six==1.16.0 # pyvmomi # pywinrm # responses - # smbprotocol # textfsm # transitions # vcert # virtualenv # websocket-client -smbprotocol==0.1.1 - # via pypsexec +smbprotocol==1.10.1 + # via + # -r requirements/static/ci/cloud.in + # pypsexec smmap==4.0.0 # via gitdb sqlparse==0.4.2 diff --git a/requirements/static/ci/py3.9/darwin.txt b/requirements/static/ci/py3.9/darwin.txt index 4ae6044b837..50754ec41c0 100644 --- a/requirements/static/ci/py3.9/darwin.txt +++ b/requirements/static/ci/py3.9/darwin.txt @@ -509,9 +509,7 @@ lxml==4.9.1 # napalm # ncclient mako==1.2.2 - # via - # -r requirements/darwin.txt - # -r requirements/static/ci/common.in + # via -r requirements/static/ci/common.in markupsafe==2.1.2 # via # -r requirements/base.txt diff --git a/requirements/static/ci/py3.9/tools.txt b/requirements/static/ci/py3.9/tools.txt index 99126e4d992..149f2576546 100644 --- a/requirements/static/ci/py3.9/tools.txt +++ b/requirements/static/ci/py3.9/tools.txt @@ -41,7 +41,9 @@ python-tools-scripts==0.12.0 pyyaml==6.0 # via -r requirements/static/ci/tools.in requests==2.28.2 - # via python-tools-scripts + # via + # python-tools-scripts + # virustotal3 rich==12.5.1 # via python-tools-scripts s3transfer==0.5.2 @@ -54,3 +56,5 @@ urllib3==1.26.12 # via # botocore # requests +virustotal3==1.0.8 + # via -r requirements/static/ci/tools.in diff --git a/requirements/static/ci/py3.9/windows.txt b/requirements/static/ci/py3.9/windows.txt index dacf397da05..053437ca906 100644 --- a/requirements/static/ci/py3.9/windows.txt +++ b/requirements/static/ci/py3.9/windows.txt @@ -167,9 +167,7 @@ looseversion==1.0.2 lxml==4.9.1 # via -r requirements/windows.txt mako==1.2.2 - # via - # -r requirements/static/ci/common.in - # -r requirements/windows.txt + # via -r requirements/static/ci/common.in markupsafe==2.1.2 # via # -r requirements/base.txt @@ -321,7 +319,7 @@ pyyaml==5.4.1 # clustershell # kubernetes # yamllint -pyzmq==25.0.0 ; sys_platform == "win32" +pyzmq==25.0.2 ; sys_platform == "win32" # via # -r requirements/zeromq.txt # pytest-salt-factories diff --git a/requirements/static/ci/tools.in b/requirements/static/ci/tools.in index 519d59d17e6..7383f25a982 100644 --- a/requirements/static/ci/tools.in +++ b/requirements/static/ci/tools.in @@ -4,3 +4,4 @@ boto3 pyyaml jinja2 packaging +virustotal3 diff --git a/requirements/static/pkg/py3.10/darwin.txt b/requirements/static/pkg/py3.10/darwin.txt index 5f913ad9117..eafb49833a4 100644 --- a/requirements/static/pkg/py3.10/darwin.txt +++ b/requirements/static/pkg/py3.10/darwin.txt @@ -55,13 +55,10 @@ linode-python==1.1.1 # via -r requirements/darwin.txt looseversion==1.0.2 # via -r requirements/base.txt -mako==1.2.2 - # via -r requirements/darwin.txt markupsafe==2.1.2 # via # -r requirements/base.txt # jinja2 - # mako more-itertools==8.2.0 # via # cheroot diff --git a/requirements/static/pkg/py3.10/windows.txt b/requirements/static/pkg/py3.10/windows.txt index d205b3c28cb..6c8a45998a3 100644 --- a/requirements/static/pkg/py3.10/windows.txt +++ b/requirements/static/pkg/py3.10/windows.txt @@ -60,13 +60,10 @@ looseversion==1.0.2 # via -r requirements/base.txt lxml==4.9.1 # via -r requirements/windows.txt -mako==1.2.2 - # via -r requirements/windows.txt markupsafe==2.1.2 # via # -r requirements/base.txt # jinja2 - # mako more-itertools==8.2.0 # via # cheroot @@ -109,7 +106,7 @@ pywin32==305 # wmi pyyaml==5.4.1 # via -r requirements/base.txt -pyzmq==25.0.0 ; sys_platform == "win32" +pyzmq==25.0.2 ; sys_platform == "win32" # via -r requirements/zeromq.txt requests==2.25.1 # via diff --git a/requirements/static/pkg/py3.11/darwin.txt b/requirements/static/pkg/py3.11/darwin.txt index 3d69c020a14..0bbc204c682 100644 --- a/requirements/static/pkg/py3.11/darwin.txt +++ b/requirements/static/pkg/py3.11/darwin.txt @@ -55,13 +55,10 @@ linode-python==1.1.1 # via -r requirements/darwin.txt looseversion==1.0.2 # via -r requirements/base.txt -mako==1.2.2 - # via -r requirements/darwin.txt markupsafe==2.1.2 # via # -r requirements/base.txt # jinja2 - # mako more-itertools==8.2.0 # via # cheroot diff --git a/requirements/static/pkg/py3.11/windows.txt b/requirements/static/pkg/py3.11/windows.txt index 2233e876ad4..b6a308084a4 100644 --- a/requirements/static/pkg/py3.11/windows.txt +++ b/requirements/static/pkg/py3.11/windows.txt @@ -60,13 +60,10 @@ looseversion==1.0.2 # via -r requirements/base.txt lxml==4.9.1 # via -r requirements/windows.txt -mako==1.2.2 - # via -r requirements/windows.txt markupsafe==2.1.2 # via # -r requirements/base.txt # jinja2 - # mako more-itertools==8.2.0 # via # cheroot @@ -109,7 +106,7 @@ pywin32==305 # wmi pyyaml==5.4.1 # via -r requirements/base.txt -pyzmq==25.0.0 ; sys_platform == "win32" +pyzmq==25.0.2 ; sys_platform == "win32" # via -r requirements/zeromq.txt requests==2.25.1 # via diff --git a/requirements/static/pkg/py3.7/windows.txt b/requirements/static/pkg/py3.7/windows.txt index 88f06315e62..21965d5b388 100644 --- a/requirements/static/pkg/py3.7/windows.txt +++ b/requirements/static/pkg/py3.7/windows.txt @@ -38,9 +38,7 @@ idna==2.8 immutables==0.15 # via contextvars importlib-metadata==4.6.4 - # via - # -r requirements/windows.txt - # mako + # via -r requirements/windows.txt ioloop==0.1a0 # via -r requirements/windows.txt jaraco.classes==3.2.1 @@ -62,13 +60,10 @@ looseversion==1.0.2 # via -r requirements/base.txt lxml==4.9.1 # via -r requirements/windows.txt -mako==1.2.2 - # via -r requirements/windows.txt markupsafe==2.1.2 # via # -r requirements/base.txt # jinja2 - # mako more-itertools==8.2.0 # via # cheroot @@ -112,7 +107,7 @@ pywin32==305 # wmi pyyaml==5.4.1 # via -r requirements/base.txt -pyzmq==25.0.0 ; sys_platform == "win32" +pyzmq==25.0.2 ; sys_platform == "win32" # via -r requirements/zeromq.txt requests==2.25.1 # via diff --git a/requirements/static/pkg/py3.8/windows.txt b/requirements/static/pkg/py3.8/windows.txt index 1161bd30275..33734387c70 100644 --- a/requirements/static/pkg/py3.8/windows.txt +++ b/requirements/static/pkg/py3.8/windows.txt @@ -60,13 +60,10 @@ looseversion==1.0.2 # via -r requirements/base.txt lxml==4.9.1 # via -r requirements/windows.txt -mako==1.2.2 - # via -r requirements/windows.txt markupsafe==2.1.2 # via # -r requirements/base.txt # jinja2 - # mako more-itertools==8.2.0 # via # cheroot @@ -110,7 +107,7 @@ pywin32==305 # wmi pyyaml==5.4.1 # via -r requirements/base.txt -pyzmq==25.0.0 ; sys_platform == "win32" +pyzmq==25.0.2 ; sys_platform == "win32" # via -r requirements/zeromq.txt requests==2.25.1 # via diff --git a/requirements/static/pkg/py3.9/darwin.txt b/requirements/static/pkg/py3.9/darwin.txt index 7fa32216abe..978ce51a1d3 100644 --- a/requirements/static/pkg/py3.9/darwin.txt +++ b/requirements/static/pkg/py3.9/darwin.txt @@ -55,13 +55,10 @@ linode-python==1.1.1 # via -r requirements/darwin.txt looseversion==1.0.2 # via -r requirements/base.txt -mako==1.2.2 - # via -r requirements/darwin.txt markupsafe==2.1.2 # via # -r requirements/base.txt # jinja2 - # mako more-itertools==8.2.0 # via # cheroot diff --git a/requirements/static/pkg/py3.9/windows.txt b/requirements/static/pkg/py3.9/windows.txt index bac77f07e6d..cb76bdf0b3d 100644 --- a/requirements/static/pkg/py3.9/windows.txt +++ b/requirements/static/pkg/py3.9/windows.txt @@ -60,13 +60,10 @@ looseversion==1.0.2 # via -r requirements/base.txt lxml==4.9.1 # via -r requirements/windows.txt -mako==1.2.2 - # via -r requirements/windows.txt markupsafe==2.1.2 # via # -r requirements/base.txt # jinja2 - # mako more-itertools==8.2.0 # via # cheroot @@ -110,7 +107,7 @@ pywin32==305 # wmi pyyaml==5.4.1 # via -r requirements/base.txt -pyzmq==25.0.0 ; sys_platform == "win32" +pyzmq==25.0.2 ; sys_platform == "win32" # via -r requirements/zeromq.txt requests==2.25.1 # via diff --git a/requirements/windows.txt b/requirements/windows.txt index 6fd3f75cabd..dacdbd1279a 100644 --- a/requirements/windows.txt +++ b/requirements/windows.txt @@ -14,7 +14,6 @@ cryptography>=39.0.1 gitpython>=3.1.30; python_version >= '3.7' ioloop>=0.1a0 lxml>=4.6.3 -mako>=1.1.4 pyasn1>=0.4.8 pycparser>=2.21 pymssql>=2.2.1 diff --git a/requirements/zeromq.txt b/requirements/zeromq.txt index 3e75cdd7d73..60a528c17e0 100644 --- a/requirements/zeromq.txt +++ b/requirements/zeromq.txt @@ -3,4 +3,4 @@ pyzmq>=20.0.0 ; python_version < '3.11' pyzmq>=24.0.0 ; python_version >= '3.11' -pyzmq==25.0.0 ; sys_platform == "win32" +pyzmq==25.0.2 ; sys_platform == "win32" diff --git a/salt/__init__.py b/salt/__init__.py index 9c7eaffcdef..e06b8ad7127 100644 --- a/salt/__init__.py +++ b/salt/__init__.py @@ -12,7 +12,6 @@ if sys.version_info < (3,): ) sys.stderr.flush() - USE_VENDORED_TORNADO = True @@ -141,3 +140,9 @@ del __define_global_system_encoding_variable__ import salt._logging # isort:skip # pylint: enable=unused-import + + +# When we are running in a 'onedir' environment, setup the path for user +# installed packages. +if hasattr(sys, "RELENV"): + sys.path.insert(0, str(sys.RELENV / "extras-{}.{}".format(*sys.version_info))) diff --git a/salt/cli/daemons.py b/salt/cli/daemons.py index 864884e92a3..ecc05c919ef 100644 --- a/salt/cli/daemons.py +++ b/salt/cli/daemons.py @@ -563,7 +563,6 @@ class Syndic( verify_env( [ self.config["pki_dir"], - self.config["cachedir"], self.config["sock_dir"], self.config["extension_modules"], ], diff --git a/salt/client/mixins.py b/salt/client/mixins.py index 9cefe54cd64..7cdae88ae8a 100644 --- a/salt/client/mixins.py +++ b/salt/client/mixins.py @@ -246,6 +246,8 @@ class SyncClientMixin(ClientStateMixin): self.functions[fun], arglist, pub_data ) low = {"fun": fun, "arg": args, "kwarg": kwargs} + if "user" in pub_data: + low["__user__"] = pub_data["user"] return self.low(fun, low, print_event=print_event, full_return=full_return) @property diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py index 81e5b580bbe..88365a60994 100644 --- a/salt/client/ssh/__init__.py +++ b/salt/client/ssh/__init__.py @@ -1682,50 +1682,51 @@ def mod_data(fsclient): "returners", ] ret = {} - envs = fsclient.envs() - ver_base = "" - for env in envs: - files = fsclient.file_list(env) - for ref in sync_refs: - mods_data = {} - pref = "_{}".format(ref) - for fn_ in sorted(files): - if fn_.startswith(pref): - if fn_.endswith((".py", ".so", ".pyx")): - full = salt.utils.url.create(fn_) - mod_path = fsclient.cache_file(full, env) - if not os.path.isfile(mod_path): - continue - mods_data[os.path.basename(fn_)] = mod_path - chunk = salt.utils.hashutils.get_hash(mod_path) - ver_base += chunk - if mods_data: - if ref in ret: - ret[ref].update(mods_data) - else: - ret[ref] = mods_data - if not ret: - return {} + with fsclient: + envs = fsclient.envs() + ver_base = "" + for env in envs: + files = fsclient.file_list(env) + for ref in sync_refs: + mods_data = {} + pref = "_{}".format(ref) + for fn_ in sorted(files): + if fn_.startswith(pref): + if fn_.endswith((".py", ".so", ".pyx")): + full = salt.utils.url.create(fn_) + mod_path = fsclient.cache_file(full, env) + if not os.path.isfile(mod_path): + continue + mods_data[os.path.basename(fn_)] = mod_path + chunk = salt.utils.hashutils.get_hash(mod_path) + ver_base += chunk + if mods_data: + if ref in ret: + ret[ref].update(mods_data) + else: + ret[ref] = mods_data + if not ret: + return {} - ver_base = salt.utils.stringutils.to_bytes(ver_base) + ver_base = salt.utils.stringutils.to_bytes(ver_base) - ver = hashlib.sha1(ver_base).hexdigest() - ext_tar_path = os.path.join( - fsclient.opts["cachedir"], "ext_mods.{}.tgz".format(ver) - ) - mods = {"version": ver, "file": ext_tar_path} - if os.path.isfile(ext_tar_path): + ver = hashlib.sha1(ver_base).hexdigest() + ext_tar_path = os.path.join( + fsclient.opts["cachedir"], "ext_mods.{}.tgz".format(ver) + ) + mods = {"version": ver, "file": ext_tar_path} + if os.path.isfile(ext_tar_path): + return mods + tfp = tarfile.open(ext_tar_path, "w:gz") + verfile = os.path.join(fsclient.opts["cachedir"], "ext_mods.ver") + with salt.utils.files.fopen(verfile, "w+") as fp_: + fp_.write(ver) + tfp.add(verfile, "ext_version") + for ref in ret: + for fn_ in ret[ref]: + tfp.add(ret[ref][fn_], os.path.join(ref, fn_)) + tfp.close() return mods - tfp = tarfile.open(ext_tar_path, "w:gz") - verfile = os.path.join(fsclient.opts["cachedir"], "ext_mods.ver") - with salt.utils.files.fopen(verfile, "w+") as fp_: - fp_.write(ver) - tfp.add(verfile, "ext_version") - for ref in ret: - for fn_ in ret[ref]: - tfp.add(ret[ref][fn_], os.path.join(ref, fn_)) - tfp.close() - return mods def ssh_version(): diff --git a/salt/config/__init__.py b/salt/config/__init__.py index 58a3ff8584a..16326634749 100644 --- a/salt/config/__init__.py +++ b/salt/config/__init__.py @@ -987,6 +987,10 @@ VALID_OPTS = immutabletypes.freeze( "pass_gnupghome": str, # pass renderer: Set PASSWORD_STORE_DIR env for Pass "pass_dir": str, + # Maintenence process restart interval + "maintenance_interval": int, + # Fileserver process restart interval + "fileserver_interval": int, } ) @@ -1635,6 +1639,8 @@ DEFAULT_MASTER_OPTS = immutabletypes.freeze( "pass_gnupghome": "", "pass_dir": "", "netapi_enable_clients": [], + "maintenance_interval": 3600, + "fileserver_interval": 3600, } ) diff --git a/salt/fileclient.py b/salt/fileclient.py index 39e8d5dfbfb..fef5154a0be 100644 --- a/salt/fileclient.py +++ b/salt/fileclient.py @@ -1137,12 +1137,6 @@ class RemoteClient(Client): self.channel = salt.channel.client.ReqChannel.factory(self.opts) return self.channel - # pylint: disable=no-dunder-del - def __del__(self): - self.destroy() - - # pylint: enable=no-dunder-del - def destroy(self): if self._closing: return @@ -1466,6 +1460,12 @@ class RemoteClient(Client): load["tok"] = self.auth.gen_token(b"salt") return self.channel.send(load) + def __enter__(self): + return self + + def __exit__(self, *args): + self.destroy() + class FSClient(RemoteClient): """ diff --git a/salt/master.py b/salt/master.py index e6eab0103d9..9d2239bffbe 100644 --- a/salt/master.py +++ b/salt/master.py @@ -186,6 +186,7 @@ class Maintenance(salt.utils.process.SignalHandlingProcess): # Track key rotation intervals self.rotate = int(time.time()) # A serializer for general maint operations + self.restart_interval = int(self.opts["maintenance_interval"]) def _post_fork_init(self): """ @@ -243,21 +244,28 @@ class Maintenance(salt.utils.process.SignalHandlingProcess): # init things that need to be done after the process is forked self._post_fork_init() - # Make Start Times - last = int(time.time()) + # Start of process for maintenance process restart interval + start = time.time() + + # Unset last value will cause the interval items to run on the first + # loop iteration. This ensurs we always run them even if + # maintenance_interval happens to be less than loop_interval or + # git_update_interval + last = None + # update git_pillar on first loop last_git_pillar_update = 0 + now = int(time.time()) git_pillar_update_interval = self.opts.get("git_pillar_update_interval", 0) old_present = set() - while True: - now = int(time.time()) + while time.time() - start < self.restart_interval: log.trace("Running maintenance routines") - if (now - last) >= self.loop_interval: + if not last or (now - last) >= self.loop_interval: salt.daemons.masterapi.clean_old_jobs(self.opts) salt.daemons.masterapi.clean_expired_tokens(self.opts) salt.daemons.masterapi.clean_pub_auth(self.opts) - if (now - last_git_pillar_update) >= git_pillar_update_interval: + if not last or (now - last_git_pillar_update) >= git_pillar_update_interval: last_git_pillar_update = now self.handle_git_pillar() self.handle_schedule() @@ -266,6 +274,7 @@ class Maintenance(salt.utils.process.SignalHandlingProcess): self.handle_key_rotate(now) salt.utils.verify.check_max_open_files(self.opts) last = now + now = int(time.time()) time.sleep(self.loop_interval) def handle_key_cache(self): @@ -462,7 +471,7 @@ class FileserverUpdate(salt.utils.process.SignalHandlingProcess): ) @classmethod - def update(cls, interval, backends, timeout=300): + def update(cls, interval, backends, timeout): """ Threading target which handles all updates for a given wait interval """ @@ -503,7 +512,11 @@ class FileserverUpdate(salt.utils.process.SignalHandlingProcess): for interval in self.buckets: self.update_threads[interval] = threading.Thread( target=self.update, - args=(interval, self.buckets[interval]), + args=( + interval, + self.buckets[interval], + self.opts["fileserver_interval"], + ), ) self.update_threads[interval].start() diff --git a/salt/modules/chroot.py b/salt/modules/chroot.py index aa0fe768545..78c974cc196 100644 --- a/salt/modules/chroot.py +++ b/salt/modules/chroot.py @@ -242,13 +242,14 @@ def _create_and_execute_salt_state(root, chunks, file_refs, test, hash_type): """ # Create the tar containing the state pkg and relevant files. salt.client.ssh.wrapper.state._cleanup_slsmod_low_data(chunks) - trans_tar = salt.client.ssh.state.prep_trans_tar( - salt.fileclient.get_file_client(__opts__), - chunks, - file_refs, - __pillar__.value(), - root, - ) + with salt.fileclient.get_file_client(__opts__) as client: + trans_tar = salt.client.ssh.state.prep_trans_tar( + client, + chunks, + file_refs, + __pillar__.value(), + root, + ) trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, hash_type) ret = None @@ -314,6 +315,7 @@ def sls(root, mods, saltenv="base", test=None, exclude=None, **kwargs): # Clone the options data and apply some default values. May not be # needed, as this module just delegate opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) + st_ = salt.client.ssh.state.SSHHighState( opts, pillar, __salt__, salt.fileclient.get_file_client(__opts__) ) @@ -321,30 +323,31 @@ def sls(root, mods, saltenv="base", test=None, exclude=None, **kwargs): if isinstance(mods, str): mods = mods.split(",") - high_data, errors = st_.render_highstate({saltenv: mods}) - if exclude: - if isinstance(exclude, str): - exclude = exclude.split(",") - if "__exclude__" in high_data: - high_data["__exclude__"].extend(exclude) - else: - high_data["__exclude__"] = exclude + with st_: + high_data, errors = st_.render_highstate({saltenv: mods}) + if exclude: + if isinstance(exclude, str): + exclude = exclude.split(",") + if "__exclude__" in high_data: + high_data["__exclude__"].extend(exclude) + else: + high_data["__exclude__"] = exclude - high_data, ext_errors = st_.state.reconcile_extend(high_data) - errors += ext_errors - errors += st_.state.verify_high(high_data) - if errors: - return errors + high_data, ext_errors = st_.state.reconcile_extend(high_data) + errors += ext_errors + errors += st_.state.verify_high(high_data) + if errors: + return errors - high_data, req_in_errors = st_.state.requisite_in(high_data) - errors += req_in_errors - if errors: - return errors + high_data, req_in_errors = st_.state.requisite_in(high_data) + errors += req_in_errors + if errors: + return errors - high_data = st_.state.apply_exclude(high_data) + high_data = st_.state.apply_exclude(high_data) - # Compile and verify the raw chunks - chunks = st_.state.compile_high_data(high_data) + # Compile and verify the raw chunks + chunks = st_.state.compile_high_data(high_data) file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, salt.client.ssh.wrapper.state._merge_extra_filerefs( diff --git a/salt/modules/cp.py b/salt/modules/cp.py index 8daab8bb674..e9ac77434e4 100644 --- a/salt/modules/cp.py +++ b/salt/modules/cp.py @@ -157,26 +157,11 @@ def recv_chunked(dest, chunk, append=False, compressed=True, mode=None): pass -def _mk_client(): - """ - Create a file client and add it to the context. - - Each file client needs to correspond to a unique copy - of the opts dictionary, therefore it's hashed by the - id of the __opts__ dict - """ - if "cp.fileclient_{}".format(id(__opts__)) not in __context__: - __context__[ - "cp.fileclient_{}".format(id(__opts__)) - ] = salt.fileclient.get_file_client(__opts__) - - def _client(): """ Return a client, hashed by the list of masters """ - _mk_client() - return __context__["cp.fileclient_{}".format(id(__opts__))] + return salt.fileclient.get_file_client(__opts__) def _render_filenames(path, dest, saltenv, template, **kw): @@ -294,7 +279,8 @@ def get_file( if not hash_file(path, saltenv): return "" else: - return _client().get_file(path, dest, makedirs, saltenv, gzip) + with _client() as client: + return client.get_file(path, dest, makedirs, saltenv, gzip) def envs(): @@ -307,7 +293,8 @@ def envs(): salt '*' cp.envs """ - return _client().envs() + with _client() as client: + return client.envs() def get_template(path, dest, template="jinja", saltenv=None, makedirs=False, **kwargs): @@ -336,7 +323,8 @@ def get_template(path, dest, template="jinja", saltenv=None, makedirs=False, **k kwargs["grains"] = __grains__ if "opts" not in kwargs: kwargs["opts"] = __opts__ - return _client().get_template(path, dest, template, makedirs, saltenv, **kwargs) + with _client() as client: + return client.get_template(path, dest, template, makedirs, saltenv, **kwargs) def get_dir(path, dest, saltenv=None, template=None, gzip=None, **kwargs): @@ -359,7 +347,8 @@ def get_dir(path, dest, saltenv=None, template=None, gzip=None, **kwargs): (path, dest) = _render_filenames(path, dest, saltenv, template, **kwargs) - return _client().get_dir(path, dest, saltenv, gzip) + with _client() as client: + return client.get_dir(path, dest, saltenv, gzip) def get_url(path, dest="", saltenv=None, makedirs=False, source_hash=None): @@ -417,13 +406,16 @@ def get_url(path, dest="", saltenv=None, makedirs=False, source_hash=None): saltenv = __opts__["saltenv"] or "base" if isinstance(dest, str): - result = _client().get_url( - path, dest, makedirs, saltenv, source_hash=source_hash - ) + with _client() as client: + result = client.get_url( + path, dest, makedirs, saltenv, source_hash=source_hash + ) else: - result = _client().get_url( - path, None, makedirs, saltenv, no_cache=True, source_hash=source_hash - ) + + with _client() as client: + result = client.get_url( + path, None, makedirs, saltenv, no_cache=True, source_hash=source_hash + ) if not result: log.error( "Unable to fetch file %s from saltenv %s.", @@ -550,9 +542,14 @@ def cache_file(path, saltenv=None, source_hash=None, verify_ssl=True, use_etag=F if senv: saltenv = senv - result = _client().cache_file( - path, saltenv, source_hash=source_hash, verify_ssl=verify_ssl, use_etag=use_etag - ) + with _client() as client: + result = client.cache_file( + path, + saltenv, + source_hash=source_hash, + verify_ssl=verify_ssl, + use_etag=use_etag, + ) if not result and not use_etag: log.error("Unable to cache file '%s' from saltenv '%s'.", path, saltenv) if path_is_remote: @@ -587,7 +584,8 @@ def cache_dest(url, saltenv=None): """ if not saltenv: saltenv = __opts__["saltenv"] or "base" - return _client().cache_dest(url, saltenv) + with _client() as client: + return client.cache_dest(url, saltenv) def cache_files(paths, saltenv=None): @@ -631,7 +629,8 @@ def cache_files(paths, saltenv=None): """ if not saltenv: saltenv = __opts__["saltenv"] or "base" - return _client().cache_files(paths, saltenv) + with _client() as client: + return client.cache_files(paths, saltenv) def cache_dir( @@ -672,7 +671,8 @@ def cache_dir( """ if not saltenv: saltenv = __opts__["saltenv"] or "base" - return _client().cache_dir(path, saltenv, include_empty, include_pat, exclude_pat) + with _client() as client: + return client.cache_dir(path, saltenv, include_empty, include_pat, exclude_pat) def cache_master(saltenv=None): @@ -690,7 +690,8 @@ def cache_master(saltenv=None): """ if not saltenv: saltenv = __opts__["saltenv"] or "base" - return _client().cache_master(saltenv) + with _client() as client: + return client.cache_master(saltenv) def cache_local_file(path): @@ -717,7 +718,8 @@ def cache_local_file(path): return path_cached # The file hasn't been cached or has changed; cache it - return _client().cache_local_file(path) + with _client() as client: + return client.cache_local_file(path) def list_states(saltenv=None): @@ -735,7 +737,8 @@ def list_states(saltenv=None): """ if not saltenv: saltenv = __opts__["saltenv"] or "base" - return _client().list_states(saltenv) + with _client() as client: + return client.list_states(saltenv) def list_master(saltenv=None, prefix=""): @@ -753,7 +756,8 @@ def list_master(saltenv=None, prefix=""): """ if not saltenv: saltenv = __opts__["saltenv"] or "base" - return _client().file_list(saltenv, prefix) + with _client() as client: + return client.file_list(saltenv, prefix) def list_master_dirs(saltenv=None, prefix=""): @@ -771,7 +775,8 @@ def list_master_dirs(saltenv=None, prefix=""): """ if not saltenv: saltenv = __opts__["saltenv"] or "base" - return _client().dir_list(saltenv, prefix) + with _client() as client: + return client.dir_list(saltenv, prefix) def list_master_symlinks(saltenv=None, prefix=""): @@ -789,7 +794,8 @@ def list_master_symlinks(saltenv=None, prefix=""): """ if not saltenv: saltenv = __opts__["saltenv"] or "base" - return _client().symlink_list(saltenv, prefix) + with _client() as client: + return client.symlink_list(saltenv, prefix) def list_minion(saltenv=None): @@ -807,7 +813,8 @@ def list_minion(saltenv=None): """ if not saltenv: saltenv = __opts__["saltenv"] or "base" - return _client().file_local_list(saltenv) + with _client() as client: + return client.file_local_list(saltenv) def is_cached(path, saltenv=None): @@ -831,7 +838,8 @@ def is_cached(path, saltenv=None): if senv: saltenv = senv - return _client().is_cached(path, saltenv) + with _client() as client: + return client.is_cached(path, saltenv) def hash_file(path, saltenv=None): @@ -856,7 +864,8 @@ def hash_file(path, saltenv=None): if senv: saltenv = senv - return _client().hash_file(path, saltenv) + with _client() as client: + return client.hash_file(path, saltenv) def stat_file(path, saltenv=None, octal=True): @@ -881,7 +890,8 @@ def stat_file(path, saltenv=None, octal=True): if senv: saltenv = senv - stat = _client().hash_and_stat_file(path, saltenv)[1] + with _client() as client: + stat = client.hash_and_stat_file(path, saltenv)[1] if stat is None: return stat return salt.utils.files.st_mode_to_octal(stat[0]) if octal is True else stat[0] diff --git a/salt/modules/defaults.py b/salt/modules/defaults.py index 2164fed2290..c807337dc2c 100644 --- a/salt/modules/defaults.py +++ b/salt/modules/defaults.py @@ -25,8 +25,7 @@ def _mk_client(): """ Create a file client and add it to the context """ - if "cp.fileclient" not in __context__: - __context__["cp.fileclient"] = salt.fileclient.get_file_client(__opts__) + return salt.fileclient.get_file_client(__opts__) def _load(formula): @@ -38,13 +37,13 @@ def _load(formula): """ # Compute possibilities - _mk_client() paths = [] for ext in ("yaml", "json"): source_url = salt.utils.url.create(formula + "/defaults." + ext) paths.append(source_url) # Fetch files from master - defaults_files = __context__["cp.fileclient"].cache_files(paths) + with _mk_client() as client: + defaults_files = client.cache_files(paths) for file_ in defaults_files: if not file_: diff --git a/salt/modules/mac_xattr.py b/salt/modules/mac_xattr.py index f8d684e8e5b..e2bbf1c503a 100644 --- a/salt/modules/mac_xattr.py +++ b/salt/modules/mac_xattr.py @@ -110,6 +110,9 @@ def read(path, attribute, **kwargs): try: ret = salt.utils.mac_utils.execute_return_result(cmd) + except UnicodeDecodeError as exc: + # Mimic the builtin xattr tool by replacing undecodeable bytes. + return exc.object.decode(errors="replace") except CommandExecutionError as exc: if "No such file" in exc.strerror: raise CommandExecutionError("File not found: {}".format(path)) diff --git a/salt/modules/pip.py b/salt/modules/pip.py index b11be51163c..c4de0c29846 100644 --- a/salt/modules/pip.py +++ b/salt/modules/pip.py @@ -144,7 +144,7 @@ def _check_bundled(): """ Gather run-time information to indicate if we are running from source or bundled. """ - if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"): + if hasattr(sys, "RELENV"): return True return False @@ -157,7 +157,7 @@ def _get_pip_bin(bin_env): if not bin_env: if _check_bundled(): logger.debug("pip: Using pip from bundled app") - return [os.path.normpath(sys.executable), "pip"] + return [str(sys.RELENV / "salt-pip")] else: logger.debug("pip: Using pip from currently-running Python") return [os.path.normpath(sys.executable), "-m", "pip"] diff --git a/salt/modules/saltutil.py b/salt/modules/saltutil.py index 4642d5011bf..a692c3f34d4 100644 --- a/salt/modules/saltutil.py +++ b/salt/modules/saltutil.py @@ -1730,8 +1730,10 @@ def runner( arg = [] if kwarg is None: kwarg = {} + pub_data = {} jid = kwargs.pop("__orchestration_jid__", jid) saltenv = kwargs.pop("__env__", saltenv) + pub_data["user"] = kwargs.pop("__pub_user", "UNKNOWN") kwargs = salt.utils.args.clean_kwargs(**kwargs) if kwargs: kwarg.update(kwargs) @@ -1760,7 +1762,12 @@ def runner( ) return rclient.cmd( - name, arg=arg, kwarg=kwarg, print_event=False, full_return=full_return + name, + arg=arg, + pub_data=pub_data, + kwarg=kwarg, + print_event=False, + full_return=full_return, ) diff --git a/salt/renderers/mako.py b/salt/renderers/mako.py index c2c300c3800..01d413140ba 100644 --- a/salt/renderers/mako.py +++ b/salt/renderers/mako.py @@ -1,5 +1,13 @@ """ Mako Renderer for Salt + +This renderer requires the Mako library. + +To install Mako, do the following: + +.. code-block: bash + + salt-pip install mako """ diff --git a/salt/renderers/pyobjects.py b/salt/renderers/pyobjects.py index b65898d1bd5..ad56246396b 100644 --- a/salt/renderers/pyobjects.py +++ b/salt/renderers/pyobjects.py @@ -430,9 +430,6 @@ def render(template, saltenv="base", sls="", salt_data=True, **kwargs): if not salt_data: return _globals - # this will be used to fetch any import files - client = get_file_client(__opts__) - # process our sls imports # # we allow pyobjects users to use a special form of the import statement @@ -461,15 +458,18 @@ def render(template, saltenv="base", sls="", salt_data=True, **kwargs): # that we're importing everything imports = None - state_file = client.cache_file(import_file, saltenv) - if not state_file: - raise ImportError( - "Could not find the file '{}'".format(import_file) - ) + # this will be used to fetch any import files + # For example salt://test.sls + with get_file_client(__opts__) as client: + state_file = client.cache_file(import_file, saltenv) + if not state_file: + raise ImportError( + "Could not find the file '{}'".format(import_file) + ) - with salt.utils.files.fopen(state_file) as state_fh: - state_contents, state_globals = process_template(state_fh) - exec(state_contents, state_globals) + with salt.utils.files.fopen(state_file) as state_fh: + state_contents, state_globals = process_template(state_fh) + exec(state_contents, state_globals) # if no imports have been specified then we are being imported as: import salt://foo.sls # so we want to stick all of the locals from our state file into the template globals diff --git a/salt/runners/state.py b/salt/runners/state.py index 5642204ce99..44017c3792c 100644 --- a/salt/runners/state.py +++ b/salt/runners/state.py @@ -101,6 +101,16 @@ def orchestrate( salt-run state.orchestrate webserver pillar_enc=gpg pillar="$(cat somefile.json)" """ + + try: + orig_user = __opts__["user"] + __opts__["user"] = __user__ + log.debug( + f"changed opts user from original '{orig_user}' to global user '{__user__}'" + ) + except NameError: + log.debug("unable to find global user __user__") + if pillar is not None and not isinstance(pillar, dict): raise SaltInvocationError("Pillar data must be formatted as a dictionary") __opts__["file_client"] = "local" diff --git a/salt/scripts.py b/salt/scripts.py index 219bdfbca3e..07393373c9d 100644 --- a/salt/scripts.py +++ b/salt/scripts.py @@ -588,14 +588,37 @@ def salt_unity(): s_fun() +def _pip_args(args, target): + new_args = args[:] + target_in_args = False + for arg in args: + if "--target" in arg: + target_in_args = True + if "install" in args and not target_in_args: + new_args.append(f"--target={target}") + return new_args + + +def _pip_environment(env, extras): + new_env = env.copy() + if "PYTHONPATH" in env: + new_env["PYTHONPATH"] = f"{extras}{os.pathsep}{env['PYTHONPATH']}" + else: + new_env["PYTHONPATH"] = extras + return new_env + + def salt_pip(): """ Proxy to current python's pip """ + extras = str(sys.RELENV / "extras-{}.{}".format(*sys.version_info)) + env = _pip_environment(os.environ.copy(), extras) + args = _pip_args(sys.argv[1:], extras) command = [ sys.executable, "-m", "pip", - ] + sys.argv[1:] - ret = subprocess.run(command, shell=False, check=False) + ] + _pip_args(sys.argv[1:], extras) + ret = subprocess.run(command, shell=False, check=False, env=env) sys.exit(ret.returncode) diff --git a/salt/state.py b/salt/state.py index 2f6252161d9..868be2749e9 100644 --- a/salt/state.py +++ b/salt/state.py @@ -84,6 +84,7 @@ STATE_RUNTIME_KEYWORDS = frozenset( "fun", "state", "check_cmd", + "cmd_opts_exclude", "failhard", "onlyif", "unless", @@ -972,10 +973,18 @@ class State: "timeout", "success_retcodes", ) + if "cmd_opts_exclude" in low_data: + if not isinstance(low_data["cmd_opts_exclude"], list): + cmd_opts_exclude = [low_data["cmd_opts_exclude"]] + else: + cmd_opts_exclude = low_data["cmd_opts_exclude"] + else: + cmd_opts_exclude = [] for run_cmd_arg in POSSIBLE_CMD_ARGS: - cmd_opts[run_cmd_arg] = low_data.get(run_cmd_arg) + if run_cmd_arg not in cmd_opts_exclude: + cmd_opts[run_cmd_arg] = low_data.get(run_cmd_arg) - if "shell" in low_data: + if "shell" in low_data and "shell" not in cmd_opts_exclude: cmd_opts["shell"] = low_data["shell"] elif "shell" in self.opts["grains"]: cmd_opts["shell"] = self.opts["grains"].get("shell") @@ -2293,6 +2302,7 @@ class State: initial_ret={"full": state_func_name}, expected_extra_kws=STATE_INTERNAL_KEYWORDS, ) + inject_globals = { # Pass a copy of the running dictionary, the low state chunks and # the current state dictionaries. @@ -2302,6 +2312,7 @@ class State: "__running__": immutabletypes.freeze(running) if running else {}, "__instance_id__": self.instance_id, "__lowstate__": immutabletypes.freeze(chunks) if chunks else {}, + "__user__": self.opts.get("user", "UNKNOWN"), } if "__env__" in low: diff --git a/salt/states/ansiblegate.py b/salt/states/ansiblegate.py index 4de7fb096d8..7fd4deb6c2a 100644 --- a/salt/states/ansiblegate.py +++ b/salt/states/ansiblegate.py @@ -171,7 +171,8 @@ def playbooks(name, rundir=None, git_repo=None, git_kwargs=None, ansible_kwargs= } if git_repo: if not isinstance(rundir, str) or not os.path.isdir(rundir): - rundir = _client()._extrn_path(git_repo, "base") + with _client() as client: + rundir = client._extrn_path(git_repo, "base") log.trace("rundir set to %s", rundir) if not isinstance(git_kwargs, dict): log.debug("Setting git_kwargs to empty dict: %s", git_kwargs) diff --git a/salt/states/saltmod.py b/salt/states/saltmod.py index 7ae8dae37a0..7b908c155e9 100644 --- a/salt/states/saltmod.py +++ b/salt/states/saltmod.py @@ -125,7 +125,7 @@ def state( subset=None, orchestration_jid=None, failhard=None, - **kwargs + **kwargs, ): """ Invoke a state run on a given target @@ -454,7 +454,7 @@ def function( batch=None, subset=None, failhard=None, - **kwargs + **kwargs, ): # pylint: disable=unused-argument """ Execute a single module function on a remote minion via salt or salt-ssh @@ -780,6 +780,14 @@ def runner(name, **kwargs): log.debug("Unable to fire args event due to missing __orchestration_jid__") jid = None + try: + kwargs["__pub_user"] = __user__ + log.debug( + f"added __pub_user to kwargs using dunder user '{__user__}', kwargs '{kwargs}'" + ) + except NameError: + log.warning("unable to find user for fire args event due to missing __user__") + if __opts__.get("test", False): ret = { "name": name, @@ -899,7 +907,7 @@ def parallel_runners(name, runners, **kwargs): # pylint: disable=unused-argumen __orchestration_jid__=jid, __env__=__env__, full_return=True, - **(runner_config.get("kwarg", {})) + **(runner_config.get("kwarg", {})), ) try: diff --git a/salt/transport/zeromq.py b/salt/transport/zeromq.py index f83cb1a390c..3ec7f7726c4 100644 --- a/salt/transport/zeromq.py +++ b/salt/transport/zeromq.py @@ -330,6 +330,8 @@ class RequestServer(salt.transport.base.DaemonizedRequestServer): self.clients.bind(self.uri) log.info("ReqServer workers %s", self.w_uri) self.workers.bind(self.w_uri) + if self.opts.get("ipc_mode", "") != "tcp": + os.chmod(os.path.join(self.opts["sock_dir"], "workers.ipc"), 0o600) while True: if self.clients.closed or self.workers.closed: @@ -416,6 +418,10 @@ class RequestServer(salt.transport.base.DaemonizedRequestServer): ) log.info("Worker binding to socket %s", self.w_uri) self._socket.connect(self.w_uri) + if self.opts.get("ipc_mode", "") != "tcp" and os.path.isfile( + os.path.join(self.opts["sock_dir"], "workers.ipc") + ): + os.chmod(os.path.join(self.opts["sock_dir"], "workers.ipc"), 0o600) self.stream = zmq.eventloop.zmqstream.ZMQStream(self._socket, io_loop=io_loop) self.message_handler = message_handler self.stream.on_recv_stream(self.handle_message) @@ -539,14 +545,9 @@ class AsyncReqMessageClient: self.socket = None self.stream = None if self.context.closed is False: + # This hangs if closing the stream causes an import error self.context.term() - # pylint: disable=W1701 - def __del__(self): - self.close() - - # pylint: enable=W1701 - def _init_socket(self): if hasattr(self, "stream"): self.stream.close() # pylint: disable=E0203 diff --git a/salt/utils/event.py b/salt/utils/event.py index be3caaa0da3..a07ad513b1c 100644 --- a/salt/utils/event.py +++ b/salt/utils/event.py @@ -1212,7 +1212,7 @@ class EventPublisher(salt.utils.process.SignalHandlingProcess): ): os.chmod( # nosec os.path.join(self.opts["sock_dir"], "master_event_pub.ipc"), - 0o666, + 0o660, ) atexit.register(self.close) diff --git a/salt/utils/extmods.py b/salt/utils/extmods.py index c3574436b6c..af04825e7e6 100644 --- a/salt/utils/extmods.py +++ b/salt/utils/extmods.py @@ -75,58 +75,58 @@ def sync(opts, form, saltenv=None, extmod_whitelist=None, extmod_blacklist=None) "Cannot create cache module directory %s. Check permissions.", mod_dir, ) - fileclient = salt.fileclient.get_file_client(opts) - for sub_env in saltenv: - log.info("Syncing %s for environment '%s'", form, sub_env) - cache = [] - log.info("Loading cache from %s, for %s", source, sub_env) - # Grab only the desired files (.py, .pyx, .so) - cache.extend( - fileclient.cache_dir( - source, - sub_env, - include_empty=False, - include_pat=r"E@\.(pyx?|so|zip)$", - exclude_pat=None, + with salt.fileclient.get_file_client(opts) as fileclient: + for sub_env in saltenv: + log.info("Syncing %s for environment '%s'", form, sub_env) + cache = [] + log.info("Loading cache from %s, for %s", source, sub_env) + # Grab only the desired files (.py, .pyx, .so) + cache.extend( + fileclient.cache_dir( + source, + sub_env, + include_empty=False, + include_pat=r"E@\.(pyx?|so|zip)$", + exclude_pat=None, + ) ) - ) - local_cache_dir = os.path.join( - opts["cachedir"], "files", sub_env, "_{}".format(form) - ) - log.debug("Local cache dir: '%s'", local_cache_dir) - for fn_ in cache: - relpath = os.path.relpath(fn_, local_cache_dir) - relname = os.path.splitext(relpath)[0].replace(os.sep, ".") - if ( - extmod_whitelist - and form in extmod_whitelist - and relname not in extmod_whitelist[form] - ): - continue - if ( - extmod_blacklist - and form in extmod_blacklist - and relname in extmod_blacklist[form] - ): - continue - remote.add(relpath) - dest = os.path.join(mod_dir, relpath) - log.info("Copying '%s' to '%s'", fn_, dest) - if os.path.isfile(dest): - # The file is present, if the sum differs replace it - hash_type = opts.get("hash_type", "md5") - src_digest = salt.utils.hashutils.get_hash(fn_, hash_type) - dst_digest = salt.utils.hashutils.get_hash(dest, hash_type) - if src_digest != dst_digest: - # The downloaded file differs, replace! + local_cache_dir = os.path.join( + opts["cachedir"], "files", sub_env, "_{}".format(form) + ) + log.debug("Local cache dir: '%s'", local_cache_dir) + for fn_ in cache: + relpath = os.path.relpath(fn_, local_cache_dir) + relname = os.path.splitext(relpath)[0].replace(os.sep, ".") + if ( + extmod_whitelist + and form in extmod_whitelist + and relname not in extmod_whitelist[form] + ): + continue + if ( + extmod_blacklist + and form in extmod_blacklist + and relname in extmod_blacklist[form] + ): + continue + remote.add(relpath) + dest = os.path.join(mod_dir, relpath) + log.info("Copying '%s' to '%s'", fn_, dest) + if os.path.isfile(dest): + # The file is present, if the sum differs replace it + hash_type = opts.get("hash_type", "md5") + src_digest = salt.utils.hashutils.get_hash(fn_, hash_type) + dst_digest = salt.utils.hashutils.get_hash(dest, hash_type) + if src_digest != dst_digest: + # The downloaded file differs, replace! + shutil.copyfile(fn_, dest) + ret.append("{}.{}".format(form, relname)) + else: + dest_dir = os.path.dirname(dest) + if not os.path.isdir(dest_dir): + os.makedirs(dest_dir) shutil.copyfile(fn_, dest) ret.append("{}.{}".format(form, relname)) - else: - dest_dir = os.path.dirname(dest) - if not os.path.isdir(dest_dir): - os.makedirs(dest_dir) - shutil.copyfile(fn_, dest) - ret.append("{}.{}".format(form, relname)) touched = bool(ret) if opts["clean_dynamic_modules"] is True: diff --git a/salt/utils/templates.py b/salt/utils/templates.py index 2c2f1aa58f0..4947b820a36 100644 --- a/salt/utils/templates.py +++ b/salt/utils/templates.py @@ -515,6 +515,10 @@ def render_jinja_tmpl(tmplstr, context, tmplpath=None): raise SaltRenderError( "Jinja error: {}{}".format(exc, out), line, tmplstr, trace=tracestr ) + finally: + if loader and hasattr(loader, "_file_client"): + if hasattr(loader._file_client, "destroy"): + loader._file_client.destroy() # Workaround a bug in Jinja that removes the final newline # (https://github.com/mitsuhiko/jinja2/issues/75) @@ -564,6 +568,10 @@ def render_mako_tmpl(tmplstr, context, tmplpath=None): ).render(**context) except Exception: # pylint: disable=broad-except raise SaltRenderError(mako.exceptions.text_error_template().render()) + finally: + if lookup and hasattr(lookup, "_file_client"): + if hasattr(lookup._file_client, "destroy"): + lookup._file_client.destroy() def render_wempy_tmpl(tmplstr, context, tmplpath=None): diff --git a/salt/version.py b/salt/version.py index 67719bd0201..43cb5f86f75 100644 --- a/salt/version.py +++ b/salt/version.py @@ -1,6 +1,7 @@ """ Set up the version of Salt """ +import argparse import operator import os import platform @@ -77,7 +78,7 @@ class SaltVersionsInfo(type): ALUMINIUM = SaltVersion("Aluminium" , info=3003, released=True) SILICON = SaltVersion("Silicon" , info=3004, released=True) PHOSPHORUS = SaltVersion("Phosphorus" , info=3005, released=True) - SULFUR = SaltVersion("Sulfur" , info=(3006, 0)) + SULFUR = SaltVersion("Sulfur" , info=(3006, 0), released=True) CHLORINE = SaltVersion("Chlorine" , info=(3007, 0)) ARGON = SaltVersion("Argon" , info=(3008, 0)) POTASSIUM = SaltVersion("Potassium" , info=(3009, 0)) @@ -921,5 +922,20 @@ def versions_report(include_salt_cloud=False, include_extensions=True): yield from info +def _parser(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--next-release", help="Return the next release", action="store_true" + ) + # When pip installing we pass in other args to this script. + # This allows us to catch those args but not use them + parser.add_argument("unknown", nargs=argparse.REMAINDER) + return parser.parse_args() + + if __name__ == "__main__": - print(__version__) + args = _parser() + if args.next_release: + print(__saltstack_version__.next_release()) + else: + print(__version__) diff --git a/setup.py b/setup.py index de473b1feb4..a6f5fef0a68 100755 --- a/setup.py +++ b/setup.py @@ -5,10 +5,10 @@ The setup script for salt # pylint: disable=file-perms,resource-leakage import setuptools # isort:skip - import distutils.dist import glob import os +import subprocess import sys import warnings from datetime import datetime @@ -170,8 +170,9 @@ if os.path.exists(SALT_VERSION_HARDCODED): with open(SALT_VERSION_HARDCODED, encoding="utf-8") as rfh: SALT_VERSION = rfh.read().strip() else: - exec(compile(open(SALT_VERSION_MODULE).read(), SALT_VERSION_MODULE, "exec")) - SALT_VERSION = str(__saltstack_version__) # pylint: disable=undefined-variable + SALT_VERSION = ( + subprocess.check_output([sys.executable, SALT_VERSION_MODULE]).decode().strip() + ) # pylint: enable=W0122 diff --git a/tests/conftest.py b/tests/conftest.py index 6f387e95d74..a7777c2cea6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -167,6 +167,46 @@ def pytest_addoption(parser): "may be insecure! Default: False" ), ) + test_selection_group.addoption( + "--no-fast", + "--no-fast-tests", + dest="fast", + action="store_false", + default=True, + help="Don't run salt-fast tests. Default: %(default)s", + ) + test_selection_group.addoption( + "--run-slow", + "--slow", + "--slow-tests", + dest="slow", + action="store_true", + default=False, + help="Run slow tests. Default: %(default)s", + ) + test_selection_group.addoption( + "--core", + "--core-tests", + dest="core", + action="store_true", + default=False, + help=( + "Run salt-core tests. These tests test the engine of salt! " + "Default: %(default)s" + ), + ) + test_selection_group.addoption( + "--flaky", + "--flaky-jail", + dest="flaky", + action="store_true", + default=False, + help=( + "Run salt-flaky jail tests. These tests are in jail for being flaky! " + "One day they will be made not flaky." + "Default: %(default)s" + ), + ) test_selection_group.addoption( "--proxy", "--proxy-tests", @@ -175,12 +215,6 @@ def pytest_addoption(parser): default=False, help="Run proxy tests (DEPRECATED)", ) - test_selection_group.addoption( - "--run-slow", - action="store_true", - default=False, - help="Run slow tests.", - ) output_options_group = parser.getgroup("Output Options") output_options_group.addoption( @@ -269,6 +303,16 @@ def pytest_configure(config): "slow_test: Mark test as being slow. These tests are skipped by default unless" " `--run-slow` is passed", ) + config.addinivalue_line( + "markers", + "core_test: Mark test as being core. These tests are skipped by default unless" + " `--core-tests` is passed", + ) + config.addinivalue_line( + "markers", + "flaky_jail: Mark test as being jlaky. These tests are skipped by default unless" + " `--flaky-jail` is passed", + ) config.addinivalue_line( "markers", "async_timeout: Timeout, in seconds, for asynchronous test functions(`async def`)", @@ -534,10 +578,34 @@ def pytest_runtest_setup(item): item._skipped_by_mark = True pytest.skip(PRE_PYTEST_SKIP_REASON) + if item.get_closest_marker("core_test"): + if not item.config.getoption("--core-tests"): + raise pytest.skip.Exception( + "Core tests are disabled, pass '--core-tests' to enable them.", + _use_item_location=True, + ) if item.get_closest_marker("slow_test"): - if item.config.getoption("--run-slow") is False: - item._skipped_by_mark = True - pytest.skip("Slow tests are disabled!") + if not item.config.getoption("--slow-tests"): + raise pytest.skip.Exception( + "Slow tests are disabled, pass '--run-slow' to enable them.", + _use_item_location=True, + ) + if item.get_closest_marker("flaky_jail"): + if not item.config.getoption("--flaky-jail"): + raise pytest.skip.Exception( + "flaky jail tests are disabled, pass '--flaky-jail' to enable them.", + _use_item_location=True, + ) + if ( + not item.get_closest_marker("slow_test") + and not item.get_closest_marker("core_test") + and not item.get_closest_marker("flaky_jail") + ): + if not item.config.getoption("--no-fast-tests"): + raise pytest.skip.Exception( + "Fast tests are disabled, dont pass '--no-fast-tests' to enable them.", + _use_item_location=True, + ) requires_sshd_server_marker = item.get_closest_marker("requires_sshd_server") if requires_sshd_server_marker is not None: diff --git a/tests/integration/modules/test_chocolatey.py b/tests/integration/modules/test_chocolatey.py index 102a3716b6b..188e5446f48 100644 --- a/tests/integration/modules/test_chocolatey.py +++ b/tests/integration/modules/test_chocolatey.py @@ -9,6 +9,7 @@ from tests.support.sminion import create_sminion @pytest.mark.skip_unless_on_windows @pytest.mark.windows_whitelisted @pytest.mark.destructive_test +@pytest.mark.slow_test class ChocolateyModuleTest(ModuleCase): """ Validate Chocolatey module diff --git a/tests/integration/modules/test_cp.py b/tests/integration/modules/test_cp.py index ad7538b4ba8..cd3e4c2f5ad 100644 --- a/tests/integration/modules/test_cp.py +++ b/tests/integration/modules/test_cp.py @@ -234,9 +234,9 @@ class CPModuleTest(ModuleCase): self.run_function("cp.get_url", ["https://repo.saltproject.io/index.html", tgt]) with salt.utils.files.fopen(tgt, "r") as instructions: data = salt.utils.stringutils.to_unicode(instructions.read()) - self.assertIn("Bootstrap", data) - self.assertIn("Debian", data) - self.assertIn("Windows", data) + self.assertIn("Salt Project", data) + self.assertIn("Package", data) + self.assertIn("Repo", data) self.assertNotIn("AYBABTU", data) @pytest.mark.slow_test @@ -250,9 +250,9 @@ class CPModuleTest(ModuleCase): with salt.utils.files.fopen(ret, "r") as instructions: data = salt.utils.stringutils.to_unicode(instructions.read()) - self.assertIn("Bootstrap", data) - self.assertIn("Debian", data) - self.assertIn("Windows", data) + self.assertIn("Salt Project", data) + self.assertIn("Package", data) + self.assertIn("Repo", data) self.assertNotIn("AYBABTU", data) @pytest.mark.slow_test @@ -273,9 +273,9 @@ class CPModuleTest(ModuleCase): time.sleep(sleep) if ret.find("HTTP 599") != -1: raise Exception("https://repo.saltproject.io/index.html returned 599 error") - self.assertIn("Bootstrap", ret) - self.assertIn("Debian", ret) - self.assertIn("Windows", ret) + self.assertIn("Salt Project", ret) + self.assertIn("Package", ret) + self.assertIn("Repo", ret) self.assertNotIn("AYBABTU", ret) @pytest.mark.slow_test @@ -346,9 +346,9 @@ class CPModuleTest(ModuleCase): """ src = "https://repo.saltproject.io/index.html" ret = self.run_function("cp.get_file_str", [src]) - self.assertIn("Bootstrap", ret) - self.assertIn("Debian", ret) - self.assertIn("Windows", ret) + self.assertIn("Salt Project", ret) + self.assertIn("Package", ret) + self.assertIn("Repo", ret) self.assertNotIn("AYBABTU", ret) @pytest.mark.slow_test diff --git a/tests/integration/modules/test_linux_shadow.py b/tests/integration/modules/test_linux_shadow.py index 73a18a8dc81..aaea75d8e45 100644 --- a/tests/integration/modules/test_linux_shadow.py +++ b/tests/integration/modules/test_linux_shadow.py @@ -15,6 +15,7 @@ from tests.support.case import ModuleCase @pytest.mark.skip_if_not_root @pytest.mark.skip_unless_on_linux +@pytest.mark.slow_test class ShadowModuleTest(ModuleCase): """ Validate the linux shadow system module diff --git a/tests/integration/modules/test_mac_power.py b/tests/integration/modules/test_mac_power.py index cf63d0ae97d..e8aa0f535f3 100644 --- a/tests/integration/modules/test_mac_power.py +++ b/tests/integration/modules/test_mac_power.py @@ -11,6 +11,7 @@ from tests.support.case import ModuleCase @pytest.mark.skip_unless_on_darwin @pytest.mark.skip_if_binaries_missing("systemsetup") @pytest.mark.skip_if_not_root +@pytest.mark.slow_test class MacPowerModuleTest(ModuleCase): """ Validate the mac_power module diff --git a/tests/integration/modules/test_mac_system.py b/tests/integration/modules/test_mac_system.py index 10aee4a88ea..bf590f82c78 100644 --- a/tests/integration/modules/test_mac_system.py +++ b/tests/integration/modules/test_mac_system.py @@ -21,6 +21,7 @@ SET_SUBNET_NAME = random_string("RS-", lowercase=False) @pytest.mark.usefixtures("salt_sub_minion") @pytest.mark.skip_if_not_root @pytest.mark.skip_if_binaries_missing("systemsetup") +@pytest.mark.slow_test class MacSystemModuleTest(ModuleCase): """ Validate the mac_system module diff --git a/tests/integration/modules/test_mac_timezone.py b/tests/integration/modules/test_mac_timezone.py index f0905843360..c424710a410 100644 --- a/tests/integration/modules/test_mac_timezone.py +++ b/tests/integration/modules/test_mac_timezone.py @@ -20,6 +20,7 @@ from tests.support.case import ModuleCase @pytest.mark.skip_unless_on_darwin @pytest.mark.skip_if_binaries_missing("systemsetup") @pytest.mark.skip_if_not_root +@pytest.mark.slow_test class MacTimezoneModuleTest(ModuleCase): """ Validate the mac_timezone module diff --git a/tests/integration/modules/test_status.py b/tests/integration/modules/test_status.py index b11f1d9e767..73ce4817e82 100644 --- a/tests/integration/modules/test_status.py +++ b/tests/integration/modules/test_status.py @@ -14,6 +14,7 @@ class StatusModuleTest(ModuleCase): @pytest.mark.skip_on_windows @pytest.mark.flaky(max_runs=4) + @pytest.mark.slow_test def test_status_pid(self): """ status.pid diff --git a/tests/integration/modules/test_win_ntp.py b/tests/integration/modules/test_win_ntp.py index 1e4053edb8e..1c52eb9ece2 100644 --- a/tests/integration/modules/test_win_ntp.py +++ b/tests/integration/modules/test_win_ntp.py @@ -6,6 +6,7 @@ from tests.support.case import ModuleCase @pytest.mark.flaky(max_runs=4) @pytest.mark.skip_unless_on_windows @pytest.mark.windows_whitelisted +@pytest.mark.slow_test class NTPTest(ModuleCase): """ Validate windows ntp module diff --git a/tests/integration/ssh/test_state.py b/tests/integration/ssh/test_state.py index 4f4d2bf8a51..a9fd3e7f2d3 100644 --- a/tests/integration/ssh/test_state.py +++ b/tests/integration/ssh/test_state.py @@ -17,6 +17,7 @@ SSH_SLS_FILE = "/tmp/salt_test_file" log = logging.getLogger(__name__) +@pytest.mark.slow_test class SSHStateTest(SSHCase): """ testing the state system with salt-ssh diff --git a/tests/integration/states/test_lxd.py b/tests/integration/states/test_lxd.py index 7aee81f96cd..34a5efcf161 100644 --- a/tests/integration/states/test_lxd.py +++ b/tests/integration/states/test_lxd.py @@ -13,6 +13,7 @@ from tests.support.mixins import SaltReturnAssertsMixin @pytest.mark.skipif(salt.modules.lxd.HAS_PYLXD is False, reason="pylxd not installed") @pytest.mark.skip_if_binaries_missing("lxd", reason="LXD not installed") @pytest.mark.skip_if_binaries_missing("lxc", reason="LXC not installed") +@pytest.mark.slow_test class LxdTestCase(ModuleCase, SaltReturnAssertsMixin): @pytest.mark.flaky(max_runs=4) def test_01__init_lxd(self): diff --git a/tests/integration/states/test_lxd_container.py b/tests/integration/states/test_lxd_container.py index 4ee92d33fef..a7060562a90 100644 --- a/tests/integration/states/test_lxd_container.py +++ b/tests/integration/states/test_lxd_container.py @@ -13,6 +13,7 @@ from tests.support.mixins import SaltReturnAssertsMixin @pytest.mark.skipif(salt.modules.lxd.HAS_PYLXD is False, reason="pylxd not installed") @pytest.mark.skip_if_binaries_missing("lxd", reason="LXD not installed") @pytest.mark.skip_if_binaries_missing("lxc", reason="LXC not installed") +@pytest.mark.slow_test class LxdContainerTestCase(ModuleCase, SaltReturnAssertsMixin): def setUp(self): self.run_state( diff --git a/tests/pytests/functional/cache/test_consul.py b/tests/pytests/functional/cache/test_consul.py index 1156b7aab24..3a38e495a93 100644 --- a/tests/pytests/functional/cache/test_consul.py +++ b/tests/pytests/functional/cache/test_consul.py @@ -67,5 +67,6 @@ def cache(minion_opts, consul_container): return cache +@pytest.mark.slow_test def test_caching(subtests, cache): run_common_cache_tests(subtests, cache) diff --git a/tests/pytests/functional/channel/test_server.py b/tests/pytests/functional/channel/test_server.py index d92a55bf68f..bdf96679b78 100644 --- a/tests/pytests/functional/channel/test_server.py +++ b/tests/pytests/functional/channel/test_server.py @@ -4,7 +4,9 @@ import multiprocessing import os import pathlib import shutil +import stat import time +from pathlib import Path import pytest from pytestshellutils.utils import ports @@ -162,6 +164,12 @@ def test_pub_server_channel( log.info("TEST - Req Server handle payload %r", payload) req_server_channel.post_fork(handle_payload, io_loop=io_loop) + if master_config["transport"] == "zeromq": + p = Path(str(master_config["sock_dir"])) / "workers.ipc" + mode = os.lstat(p).st_mode + assert bool(os.lstat(p).st_mode & stat.S_IRUSR) + assert not bool(os.lstat(p).st_mode & stat.S_IRGRP) + assert not bool(os.lstat(p).st_mode & stat.S_IROTH) pub_channel = salt.channel.client.AsyncPubChannel.factory(minion_config) received = [] diff --git a/tests/pytests/functional/modules/state/requisites/test_listen.py b/tests/pytests/functional/modules/state/requisites/test_listen.py index 03210adc6b8..c3104155acd 100644 --- a/tests/pytests/functional/modules/state/requisites/test_listen.py +++ b/tests/pytests/functional/modules/state/requisites/test_listen.py @@ -2,6 +2,7 @@ import pytest pytestmark = [ pytest.mark.windows_whitelisted, + pytest.mark.core_test, ] diff --git a/tests/pytests/functional/modules/state/requisites/test_mixed.py b/tests/pytests/functional/modules/state/requisites/test_mixed.py index 256bb4bea14..622e73b986e 100644 --- a/tests/pytests/functional/modules/state/requisites/test_mixed.py +++ b/tests/pytests/functional/modules/state/requisites/test_mixed.py @@ -4,6 +4,7 @@ from . import normalize_ret pytestmark = [ pytest.mark.windows_whitelisted, + pytest.mark.core_test, ] diff --git a/tests/pytests/functional/modules/state/requisites/test_onchanges.py b/tests/pytests/functional/modules/state/requisites/test_onchanges.py index b1b1f76c561..5c3f0c3e390 100644 --- a/tests/pytests/functional/modules/state/requisites/test_onchanges.py +++ b/tests/pytests/functional/modules/state/requisites/test_onchanges.py @@ -4,6 +4,7 @@ from . import normalize_ret pytestmark = [ pytest.mark.windows_whitelisted, + pytest.mark.core_test, ] diff --git a/tests/pytests/functional/modules/state/requisites/test_onfail.py b/tests/pytests/functional/modules/state/requisites/test_onfail.py index ad5e89bbeac..35a509e48ab 100644 --- a/tests/pytests/functional/modules/state/requisites/test_onfail.py +++ b/tests/pytests/functional/modules/state/requisites/test_onfail.py @@ -4,6 +4,7 @@ from . import normalize_ret pytestmark = [ pytest.mark.windows_whitelisted, + pytest.mark.core_test, ] diff --git a/tests/pytests/functional/modules/state/requisites/test_onlyif.py b/tests/pytests/functional/modules/state/requisites/test_onlyif.py index eb7af07e38a..7e85fbe9513 100644 --- a/tests/pytests/functional/modules/state/requisites/test_onlyif.py +++ b/tests/pytests/functional/modules/state/requisites/test_onlyif.py @@ -2,6 +2,7 @@ import pytest pytestmark = [ pytest.mark.windows_whitelisted, + pytest.mark.core_test, ] diff --git a/tests/pytests/functional/modules/state/requisites/test_prereq.py b/tests/pytests/functional/modules/state/requisites/test_prereq.py index 85850eef228..546df6f9909 100644 --- a/tests/pytests/functional/modules/state/requisites/test_prereq.py +++ b/tests/pytests/functional/modules/state/requisites/test_prereq.py @@ -4,6 +4,7 @@ from . import normalize_ret pytestmark = [ pytest.mark.windows_whitelisted, + pytest.mark.core_test, ] diff --git a/tests/pytests/functional/modules/state/requisites/test_require.py b/tests/pytests/functional/modules/state/requisites/test_require.py index 1d1b3d1c411..2fa84704519 100644 --- a/tests/pytests/functional/modules/state/requisites/test_require.py +++ b/tests/pytests/functional/modules/state/requisites/test_require.py @@ -6,6 +6,7 @@ from . import normalize_ret pytestmark = [ pytest.mark.windows_whitelisted, + pytest.mark.core_test, ] diff --git a/tests/pytests/functional/modules/state/requisites/test_unless.py b/tests/pytests/functional/modules/state/requisites/test_unless.py index 613ca18c416..237163da40c 100644 --- a/tests/pytests/functional/modules/state/requisites/test_unless.py +++ b/tests/pytests/functional/modules/state/requisites/test_unless.py @@ -2,6 +2,7 @@ import pytest pytestmark = [ pytest.mark.windows_whitelisted, + pytest.mark.core_test, ] diff --git a/tests/pytests/functional/modules/state/requisites/test_use.py b/tests/pytests/functional/modules/state/requisites/test_use.py index 6dba56f0698..0f4c5293423 100644 --- a/tests/pytests/functional/modules/state/requisites/test_use.py +++ b/tests/pytests/functional/modules/state/requisites/test_use.py @@ -2,6 +2,7 @@ import pytest pytestmark = [ pytest.mark.windows_whitelisted, + pytest.mark.core_test, ] diff --git a/tests/pytests/functional/modules/state/requisites/test_watch.py b/tests/pytests/functional/modules/state/requisites/test_watch.py index 9eff2c10b6d..15eb9e8aa53 100644 --- a/tests/pytests/functional/modules/state/requisites/test_watch.py +++ b/tests/pytests/functional/modules/state/requisites/test_watch.py @@ -6,6 +6,7 @@ from . import normalize_ret pytestmark = [ pytest.mark.windows_whitelisted, + pytest.mark.core_test, ] diff --git a/tests/pytests/functional/modules/state/test_jinja_renderer.py b/tests/pytests/functional/modules/state/test_jinja_renderer.py index dbd7b923266..a2902032723 100644 --- a/tests/pytests/functional/modules/state/test_jinja_renderer.py +++ b/tests/pytests/functional/modules/state/test_jinja_renderer.py @@ -2,6 +2,7 @@ import pytest pytestmark = [ pytest.mark.windows_whitelisted, + pytest.mark.core_test, ] diff --git a/tests/pytests/functional/modules/state/test_mako_renderer.py b/tests/pytests/functional/modules/state/test_mako_renderer.py new file mode 100644 index 00000000000..83a11df751c --- /dev/null +++ b/tests/pytests/functional/modules/state/test_mako_renderer.py @@ -0,0 +1,23 @@ +import pytest + +pytestmark = [ + pytest.mark.windows_whitelisted, +] + + +def test_mako_renderer(state, state_tree): + """ + Test mako renderer when running state.sls + """ + sls_contents = """ + #!mako|yaml + %for a in [1,2,3]: + echo ${a}: + cmd.run + %endfor + """ + with pytest.helpers.temp_file("issue-55124.sls", sls_contents, state_tree): + ret = state.sls("issue-55124") + for state_return in ret: + assert state_return.result is True + assert "echo" in state_return.id diff --git a/tests/pytests/functional/modules/state/test_pyobjects_renderer.py b/tests/pytests/functional/modules/state/test_pyobjects_renderer.py new file mode 100644 index 00000000000..a1afa06b65b --- /dev/null +++ b/tests/pytests/functional/modules/state/test_pyobjects_renderer.py @@ -0,0 +1,37 @@ +import pytest + +pytestmark = [ + pytest.mark.windows_whitelisted, +] + + +def test_pyobjects_renderer(state, state_tree, tmp_path): + """ + Test pyobjects renderer when running state.sls + """ + file_path = str(tmp_path).replace("\\", "/") + sls1_contents = f""" + #!pyobjects + import pathlib + import salt://test_pyobjects2.sls + test_file = pathlib.Path("{file_path}", "test") + File.managed(str(test_file)) + """ + sls2_contents = f""" + #!pyobjects + import pathlib + test_file = pathlib.Path("{file_path}", "test2") + File.managed(str(test_file)) + """ + + with pytest.helpers.temp_file( + "test_pyobjects.sls", sls1_contents, state_tree + ) as state1: + with pytest.helpers.temp_file( + "test_pyobjects2.sls", sls2_contents, state_tree + ) as state2: + ret = state.sls("test_pyobjects") + assert not ret.errors + for state_return in ret: + assert state_return.result is True + assert str(tmp_path) in state_return.name diff --git a/tests/pytests/functional/modules/state/test_state.py b/tests/pytests/functional/modules/state/test_state.py index 3b88bfaeadc..7640afaa882 100644 --- a/tests/pytests/functional/modules/state/test_state.py +++ b/tests/pytests/functional/modules/state/test_state.py @@ -18,6 +18,7 @@ log = logging.getLogger(__name__) pytestmark = [ pytest.mark.windows_whitelisted, + pytest.mark.core_test, ] @@ -1009,3 +1010,31 @@ def test_issue_62264_requisite_not_found(state, state_tree): for state_return in ret: assert state_return.result is True assert "The following requisites were not found" not in state_return.comment + + +def test_state_sls_defaults(state, state_tree): + """ """ + json_contents = """ + { + "users": { + "root": 1 + } + } + """ + sls_contents = """ + {% set test = salt['defaults.get']('core:users:root') %} + + echo {{ test }}: + cmd.run + """ + state_id = "cmd_|-echo 1_|-echo 1_|-run" + core_dir = state_tree / "core" + with pytest.helpers.temp_file( + core_dir / "defaults.json", json_contents, state_tree + ): + with pytest.helpers.temp_file(core_dir / "test.sls", sls_contents, state_tree): + ret = state.sls("core.test") + assert state_id in ret + for state_return in ret: + assert state_return.result is True + assert "echo 1" in state_return.comment diff --git a/tests/pytests/functional/modules/test_ansiblegate.py b/tests/pytests/functional/modules/test_ansiblegate.py index 08dc32e3689..0c51b622709 100644 --- a/tests/pytests/functional/modules/test_ansiblegate.py +++ b/tests/pytests/functional/modules/test_ansiblegate.py @@ -9,6 +9,7 @@ pytestmark = [ check_all=True, reason="ansible is not installed", ), + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/modules/test_aptpkg.py b/tests/pytests/functional/modules/test_aptpkg.py index 45b748d8949..5bc8209f4c7 100644 --- a/tests/pytests/functional/modules/test_aptpkg.py +++ b/tests/pytests/functional/modules/test_aptpkg.py @@ -17,6 +17,7 @@ from tests.support.mock import Mock, patch pytestmark = [ pytest.mark.skip_if_binaries_missing("apt-cache", "grep"), + pytest.mark.slow_test, ] KEY_FILES = ( diff --git a/tests/pytests/functional/modules/test_defaults.py b/tests/pytests/functional/modules/test_defaults.py new file mode 100644 index 00000000000..ce4a57753a1 --- /dev/null +++ b/tests/pytests/functional/modules/test_defaults.py @@ -0,0 +1,40 @@ +import pytest + +pytestmark = [pytest.mark.skip_unless_on_linux] + + +@pytest.fixture(scope="module") +def defaults(modules): + return modules.defaults + + +def test_defaults_get(defaults, state_tree, caplog): + """ + test defaults.get + """ + + json_contents = """ + { + "users": { + "root": 1 + } + } + """ + path = state_tree / "core" + with pytest.helpers.temp_file("defaults.json", json_contents, path): + assert defaults.get("core:users:root") == 1 + + +def test_defaults_merge(defaults): + """ + test defaults.merge + """ + assert defaults.merge({"a": "b"}, {"d": "e"}) == {"a": "b", "d": "e"} + + +def test_defaults_deepcopy(defaults): + """ + test defaults.deepcopy + """ + test_dict = {"1": "one"} + assert defaults.deepcopy(test_dict) == test_dict diff --git a/tests/pytests/functional/modules/test_etcd_mod.py b/tests/pytests/functional/modules/test_etcd_mod.py index e7e6a586ac9..e1e1b552df2 100644 --- a/tests/pytests/functional/modules/test_etcd_mod.py +++ b/tests/pytests/functional/modules/test_etcd_mod.py @@ -14,6 +14,7 @@ log = logging.getLogger(__name__) pytestmark = [ pytest.mark.skip_if_binaries_missing("docker", "dockerd", check_all=False), + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/modules/test_pip.py b/tests/pytests/functional/modules/test_pip.py index 5c67fa3f562..9b87735b68f 100644 --- a/tests/pytests/functional/modules/test_pip.py +++ b/tests/pytests/functional/modules/test_pip.py @@ -21,6 +21,7 @@ from tests.support.helpers import VirtualEnv ), ) @pytest.mark.requires_network +@pytest.mark.slow_test def test_list_available_packages(modules, pip_version, tmp_path): with VirtualEnv(venv_dir=tmp_path, pip_requirement=pip_version) as virtualenv: virtualenv.install("-U", pip_version) diff --git a/tests/pytests/functional/modules/test_saltutil.py b/tests/pytests/functional/modules/test_saltutil.py index ca61f70143a..f9e72a9f73e 100644 --- a/tests/pytests/functional/modules/test_saltutil.py +++ b/tests/pytests/functional/modules/test_saltutil.py @@ -47,6 +47,7 @@ def get_top(configure_mocks): yield get_top +@pytest.mark.slow_test def test__get_top_file_envs(modules, get_top, destroy): """ Ensure we cleanup objects created by saltutil._get_top_file_envs #60449 diff --git a/tests/pytests/functional/modules/test_system.py b/tests/pytests/functional/modules/test_system.py index 0249ba71269..2dabaaebfad 100644 --- a/tests/pytests/functional/modules/test_system.py +++ b/tests/pytests/functional/modules/test_system.py @@ -9,7 +9,10 @@ import pytest import salt.utils.files -pytestmark = [pytest.mark.skip_unless_on_linux] +pytestmark = [ + pytest.mark.skip_unless_on_linux, + pytest.mark.slow_test, +] log = logging.getLogger(__name__) diff --git a/tests/pytests/functional/modules/test_win_certutil.py b/tests/pytests/functional/modules/test_win_certutil.py index ca2e2a219cb..2e8a7984cae 100644 --- a/tests/pytests/functional/modules/test_win_certutil.py +++ b/tests/pytests/functional/modules/test_win_certutil.py @@ -10,6 +10,7 @@ import salt.utils.files pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/modules/test_win_dsc.py b/tests/pytests/functional/modules/test_win_dsc.py index ab1b2f8a061..76255968631 100644 --- a/tests/pytests/functional/modules/test_win_dsc.py +++ b/tests/pytests/functional/modules/test_win_dsc.py @@ -10,6 +10,7 @@ import salt.exceptions pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/modules/test_win_shortcut.py b/tests/pytests/functional/modules/test_win_shortcut.py index 1afa0217bc7..292f439536b 100644 --- a/tests/pytests/functional/modules/test_win_shortcut.py +++ b/tests/pytests/functional/modules/test_win_shortcut.py @@ -21,6 +21,7 @@ pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, pytest.mark.skipif(not HAS_WIN32, reason="Requires Win32 libraries"), + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/modules/win_lgpo/test_audit_settings_module.py b/tests/pytests/functional/modules/win_lgpo/test_audit_settings_module.py index 3aa1afdb652..2830c7a7d27 100644 --- a/tests/pytests/functional/modules/win_lgpo/test_audit_settings_module.py +++ b/tests/pytests/functional/modules/win_lgpo/test_audit_settings_module.py @@ -6,6 +6,7 @@ pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, pytest.mark.destructive_test, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/modules/win_lgpo/test_get_policy.py b/tests/pytests/functional/modules/win_lgpo/test_get_policy.py index 58651f28c52..ef91a3198fb 100644 --- a/tests/pytests/functional/modules/win_lgpo/test_get_policy.py +++ b/tests/pytests/functional/modules/win_lgpo/test_get_policy.py @@ -3,6 +3,7 @@ import pytest pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/modules/win_lgpo/test_get_policy_info.py b/tests/pytests/functional/modules/win_lgpo/test_get_policy_info.py index 76ce483f1d3..09de8845f23 100644 --- a/tests/pytests/functional/modules/win_lgpo/test_get_policy_info.py +++ b/tests/pytests/functional/modules/win_lgpo/test_get_policy_info.py @@ -10,6 +10,7 @@ from packaging import version pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/modules/win_lgpo/test_registry_policy.py b/tests/pytests/functional/modules/win_lgpo/test_registry_policy.py index 543bcc9c945..8337c90b4db 100644 --- a/tests/pytests/functional/modules/win_lgpo/test_registry_policy.py +++ b/tests/pytests/functional/modules/win_lgpo/test_registry_policy.py @@ -6,6 +6,7 @@ pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, pytest.mark.destructive_test, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/states/file/test__check_directory_win.py b/tests/pytests/functional/states/file/test__check_directory_win.py index 1ce94d06425..6568be82304 100644 --- a/tests/pytests/functional/states/file/test__check_directory_win.py +++ b/tests/pytests/functional/states/file/test__check_directory_win.py @@ -6,6 +6,7 @@ import salt.utils.win_dacl as win_dacl pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/states/file/test_comment.py b/tests/pytests/functional/states/file/test_comment.py index 5b439b02298..377e6b1b0e6 100644 --- a/tests/pytests/functional/states/file/test_comment.py +++ b/tests/pytests/functional/states/file/test_comment.py @@ -10,6 +10,7 @@ from tests.support.helpers import dedent pytestmark = [ pytest.mark.windows_whitelisted, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/states/file/test_directory_win.py b/tests/pytests/functional/states/file/test_directory_win.py index 0b622be6ff0..f8a58dc4fd0 100644 --- a/tests/pytests/functional/states/file/test_directory_win.py +++ b/tests/pytests/functional/states/file/test_directory_win.py @@ -16,6 +16,7 @@ except NameError: pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/states/file/test_pruned.py b/tests/pytests/functional/states/file/test_pruned.py index 101fa76d2cc..80d4f94b6c2 100644 --- a/tests/pytests/functional/states/file/test_pruned.py +++ b/tests/pytests/functional/states/file/test_pruned.py @@ -2,6 +2,7 @@ import pytest pytestmark = [ pytest.mark.windows_whitelisted, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/states/file/test_rename.py b/tests/pytests/functional/states/file/test_rename.py index ffffb76ec8a..db293d16277 100644 --- a/tests/pytests/functional/states/file/test_rename.py +++ b/tests/pytests/functional/states/file/test_rename.py @@ -9,6 +9,7 @@ import salt.utils.path pytestmark = [ pytest.mark.windows_whitelisted, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/states/pkgrepo/test_debian.py b/tests/pytests/functional/states/pkgrepo/test_debian.py index adbea008951..d025643aa4c 100644 --- a/tests/pytests/functional/states/pkgrepo/test_debian.py +++ b/tests/pytests/functional/states/pkgrepo/test_debian.py @@ -21,6 +21,7 @@ log = logging.getLogger(__name__) pytestmark = [ pytest.mark.destructive_test, pytest.mark.skip_if_not_root, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/states/test_archive.py b/tests/pytests/functional/states/test_archive.py index b3bb6c0fc9a..6cdb3f5552a 100644 --- a/tests/pytests/functional/states/test_archive.py +++ b/tests/pytests/functional/states/test_archive.py @@ -113,6 +113,7 @@ def web_root(tmp_path_factory): shutil.rmtree(str(_web_root), ignore_errors=True) +@pytest.mark.slow_test def test_archive_extracted_web_source_etag_operation( modules, states, free_port, web_root, minion_opts ): diff --git a/tests/pytests/functional/states/test_etcd_mod.py b/tests/pytests/functional/states/test_etcd_mod.py index ede8debd173..5a862b4c7bc 100644 --- a/tests/pytests/functional/states/test_etcd_mod.py +++ b/tests/pytests/functional/states/test_etcd_mod.py @@ -13,6 +13,7 @@ log = logging.getLogger(__name__) pytestmark = [ pytest.mark.skip_if_binaries_missing("docker", "dockerd", check_all=False), + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/states/test_file.py b/tests/pytests/functional/states/test_file.py index a3ad275e141..cea0552f365 100644 --- a/tests/pytests/functional/states/test_file.py +++ b/tests/pytests/functional/states/test_file.py @@ -113,6 +113,7 @@ def web_root(tmp_path_factory): shutil.rmtree(str(_web_root), ignore_errors=True) +@pytest.mark.slow_test def test_file_managed_web_source_etag_operation( states, free_port, web_root, minion_opts ): diff --git a/tests/pytests/functional/states/test_module.py b/tests/pytests/functional/states/test_module.py index bf2410ab529..b9afb4f0926 100644 --- a/tests/pytests/functional/states/test_module.py +++ b/tests/pytests/functional/states/test_module.py @@ -7,7 +7,7 @@ from tests.support.helpers import dedent log = logging.getLogger(__name__) -@pytest.mark.slow_test +@pytest.mark.core_test def test_issue_58763(tmp_path, modules, state_tree, caplog): venv_dir = tmp_path / "issue-2028-pip-installed" @@ -39,7 +39,7 @@ def test_issue_58763(tmp_path, modules, state_tree, caplog): assert "Using new style module.run syntax: run_new" in caplog.messages -@pytest.mark.slow_test +@pytest.mark.core_test def test_issue_58763_a(tmp_path, modules, state_tree, caplog): venv_dir = tmp_path / "issue-2028-pip-installed" @@ -65,7 +65,7 @@ def test_issue_58763_a(tmp_path, modules, state_tree, caplog): ) -@pytest.mark.slow_test +@pytest.mark.core_test def test_issue_58763_b(tmp_path, modules, state_tree, caplog): venv_dir = tmp_path / "issue-2028-pip-installed" @@ -87,7 +87,7 @@ def test_issue_58763_b(tmp_path, modules, state_tree, caplog): assert "Detected legacy module.run syntax: test.ping" in caplog.messages -@pytest.mark.slow_test +@pytest.mark.core_test def test_issue_62988_a(tmp_path, modules, state_tree, caplog): venv_dir = tmp_path / "issue-2028-pip-installed" @@ -117,7 +117,7 @@ def test_issue_62988_a(tmp_path, modules, state_tree, caplog): assert "Using new style module.run syntax: run_new" in caplog.messages -@pytest.mark.slow_test +@pytest.mark.core_test def test_issue_62988_b(tmp_path, modules, state_tree, caplog): venv_dir = tmp_path / "issue-2028-pip-installed" diff --git a/tests/pytests/functional/states/test_pkg.py b/tests/pytests/functional/states/test_pkg.py index 80df3b7b725..0e82dc608ba 100644 --- a/tests/pytests/functional/states/test_pkg.py +++ b/tests/pytests/functional/states/test_pkg.py @@ -174,6 +174,7 @@ def latest_version(ctx, modules): @pytest.mark.requires_salt_modules("pkg.version") @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_001_installed(modules, states, PKG_TARGETS): """ This is a destructive test as it installs and then removes a package @@ -194,6 +195,7 @@ def test_pkg_001_installed(modules, states, PKG_TARGETS): @pytest.mark.usefixtures("VERSION_SPEC_SUPPORTED") @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_002_installed_with_version(PKG_TARGETS, states, latest_version): """ This is a destructive test as it installs and then removes a package @@ -213,6 +215,7 @@ def test_pkg_002_installed_with_version(PKG_TARGETS, states, latest_version): @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_003_installed_multipkg(PKG_TARGETS, modules, states): """ This is a destructive test as it installs and then removes two packages @@ -236,6 +239,7 @@ def test_pkg_003_installed_multipkg(PKG_TARGETS, modules, states): @pytest.mark.usefixtures("VERSION_SPEC_SUPPORTED") @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_004_installed_multipkg_with_version(PKG_TARGETS, latest_version, states): """ This is a destructive test as it installs and then removes two packages @@ -259,6 +263,7 @@ def test_pkg_004_installed_multipkg_with_version(PKG_TARGETS, latest_version, st @pytest.mark.requires_salt_modules("pkg.version") @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_005_installed_32bit(PKG_32_TARGETS, modules, states): """ This is a destructive test as it installs and then removes a package @@ -283,6 +288,7 @@ def test_pkg_005_installed_32bit(PKG_32_TARGETS, modules, states): @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_006_installed_32bit_with_version(PKG_32_TARGETS, latest_version, states): """ This is a destructive test as it installs and then removes a package @@ -307,6 +313,7 @@ def test_pkg_006_installed_32bit_with_version(PKG_32_TARGETS, latest_version, st @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_007_with_dot_in_pkgname(PKG_DOT_TARGETS, latest_version, states): """ This tests for the regression found in the following issue: @@ -329,6 +336,7 @@ def test_pkg_007_with_dot_in_pkgname(PKG_DOT_TARGETS, latest_version, states): @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_008_epoch_in_version(PKG_EPOCH_TARGETS, latest_version, states): """ This tests for the regression found in the following issue: @@ -455,6 +463,7 @@ def test_pkg_011_latest_only_upgrade( @pytest.mark.usefixtures("WILDCARDS_SUPPORTED") @pytest.mark.requires_salt_modules("pkg.version") @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_012_installed_with_wildcard_version(PKG_TARGETS, states, modules): """ This is a destructive test as it installs and then removes a package @@ -502,6 +511,7 @@ def test_pkg_012_installed_with_wildcard_version(PKG_TARGETS, states, modules): @pytest.mark.requires_salt_modules("pkg.version", "pkg.latest_version") @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_013_installed_with_comparison_operator( grains, PKG_TARGETS, states, modules ): @@ -540,6 +550,7 @@ def test_pkg_013_installed_with_comparison_operator( @pytest.mark.requires_salt_modules("pkg.version") @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_014_installed_missing_release(grains, PKG_TARGETS, states, modules): """ Tests that a version number missing the release portion still resolves @@ -572,6 +583,7 @@ def test_pkg_014_installed_missing_release(grains, PKG_TARGETS, states, modules) "pkg.hold", "pkg.unhold", "pkg.version", "pkg.list_pkgs" ) @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_015_installed_held(grains, modules, states, PKG_TARGETS): """ Tests that a package can be held even when the package is already installed. @@ -649,6 +661,7 @@ def test_pkg_015_installed_held(grains, modules, states, PKG_TARGETS): @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_016_conditionally_ignore_epoch(PKG_EPOCH_TARGETS, latest_version, states): """ See @@ -753,6 +766,7 @@ def test_pkg_017_installed_held_equals_false(grains, modules, states, PKG_TARGET @pytest.mark.requires_salt_modules("pkg.version") @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_cap_001_installed(PKG_CAP_TARGETS, modules, states): """ This is a destructive test as it installs and then removes a package @@ -788,6 +802,7 @@ def test_pkg_cap_001_installed(PKG_CAP_TARGETS, modules, states): @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_cap_002_already_installed(PKG_CAP_TARGETS, modules, states): """ This is a destructive test as it installs and then removes a package @@ -829,6 +844,7 @@ def test_pkg_cap_002_already_installed(PKG_CAP_TARGETS, modules, states): @pytest.mark.usefixtures("VERSION_SPEC_SUPPORTED") @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed") +@pytest.mark.slow_test def test_pkg_cap_003_installed_multipkg_with_version( PKG_CAP_TARGETS, PKG_TARGETS, @@ -891,6 +907,7 @@ def test_pkg_cap_003_installed_multipkg_with_version( @pytest.mark.requires_salt_modules("pkg.version") @pytest.mark.requires_salt_states("pkg.latest", "pkg.removed") +@pytest.mark.slow_test def test_pkg_cap_004_latest(PKG_CAP_TARGETS, modules, states): """ This tests pkg.latest with a package that has no epoch (or a zero @@ -930,6 +947,7 @@ def test_pkg_cap_004_latest(PKG_CAP_TARGETS, modules, states): @pytest.mark.requires_salt_modules("pkg.version") @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed", "pkg.downloaded") +@pytest.mark.slow_test def test_pkg_cap_005_downloaded(PKG_CAP_TARGETS, modules, states): """ This is a destructive test as it installs and then removes a package @@ -963,6 +981,7 @@ def test_pkg_cap_005_downloaded(PKG_CAP_TARGETS, modules, states): @pytest.mark.requires_salt_modules("pkg.version") @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed", "pkg.uptodate") +@pytest.mark.slow_test def test_pkg_cap_006_uptodate(PKG_CAP_TARGETS, modules, states): """ This is a destructive test as it installs and then removes a package diff --git a/tests/pytests/functional/states/test_user.py b/tests/pytests/functional/states/test_user.py index ba2d01c0143..09d34da168a 100644 --- a/tests/pytests/functional/states/test_user.py +++ b/tests/pytests/functional/states/test_user.py @@ -76,6 +76,7 @@ def existing_account(): yield _account +@pytest.mark.slow_test def test_user_absent(states): """ Test user.absent with a non existing account diff --git a/tests/pytests/functional/states/test_zookeeper.py b/tests/pytests/functional/states/test_zookeeper.py index d33f7e47eab..e735fdd1cf0 100644 --- a/tests/pytests/functional/states/test_zookeeper.py +++ b/tests/pytests/functional/states/test_zookeeper.py @@ -15,6 +15,7 @@ log = logging.getLogger(__name__) pytestmark = [ pytest.mark.slow_test, pytest.mark.skip_if_binaries_missing("dockerd"), + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/states/win_lgpo/test_admx_policy.py b/tests/pytests/functional/states/win_lgpo/test_admx_policy.py index b8a40261bd0..bb2edcbcd2c 100644 --- a/tests/pytests/functional/states/win_lgpo/test_admx_policy.py +++ b/tests/pytests/functional/states/win_lgpo/test_admx_policy.py @@ -15,6 +15,7 @@ pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, pytest.mark.destructive_test, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/states/win_lgpo/test_adv_audit_settings_state.py b/tests/pytests/functional/states/win_lgpo/test_adv_audit_settings_state.py index 9129d82ed67..5a0600bba57 100644 --- a/tests/pytests/functional/states/win_lgpo/test_adv_audit_settings_state.py +++ b/tests/pytests/functional/states/win_lgpo/test_adv_audit_settings_state.py @@ -8,6 +8,7 @@ pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, pytest.mark.destructive_test, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/states/win_lgpo/test_audit_settings_state.py b/tests/pytests/functional/states/win_lgpo/test_audit_settings_state.py index 400c99f03b7..6f45461618d 100644 --- a/tests/pytests/functional/states/win_lgpo/test_audit_settings_state.py +++ b/tests/pytests/functional/states/win_lgpo/test_audit_settings_state.py @@ -10,6 +10,7 @@ pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, pytest.mark.destructive_test, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/states/win_lgpo/test_rights_assignment.py b/tests/pytests/functional/states/win_lgpo/test_rights_assignment.py index f7cc1300d82..9dded5a0744 100644 --- a/tests/pytests/functional/states/win_lgpo/test_rights_assignment.py +++ b/tests/pytests/functional/states/win_lgpo/test_rights_assignment.py @@ -9,6 +9,7 @@ pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, pytest.mark.destructive_test, + pytest.mark.slow_test, ] diff --git a/tests/pytests/functional/transport/server/test_req_channel.py b/tests/pytests/functional/transport/server/test_req_channel.py index eed86f21c68..4a74802a0d0 100644 --- a/tests/pytests/functional/transport/server/test_req_channel.py +++ b/tests/pytests/functional/transport/server/test_req_channel.py @@ -23,7 +23,8 @@ log = logging.getLogger(__name__) pytestmark = [ pytest.mark.skip_on_spawning_platform( reason="These tests are currently broken on spawning platforms. Need to be rewritten.", - ) + ), + pytest.mark.slow_test, ] diff --git a/tests/pytests/integration/cli/conftest.py b/tests/pytests/integration/cli/conftest.py index 48554dda4d8..1f87f17e58a 100644 --- a/tests/pytests/integration/cli/conftest.py +++ b/tests/pytests/integration/cli/conftest.py @@ -2,6 +2,7 @@ import pytest @pytest.fixture(scope="package") +@pytest.mark.core_test def salt_eauth_account(salt_eauth_account_factory): with salt_eauth_account_factory as account: yield account diff --git a/tests/pytests/integration/cli/test_batch.py b/tests/pytests/integration/cli/test_batch.py index 81175f62a46..70d66d99598 100644 --- a/tests/pytests/integration/cli/test_batch.py +++ b/tests/pytests/integration/cli/test_batch.py @@ -8,7 +8,7 @@ import salt.utils.platform pytestmark = [ pytest.mark.windows_whitelisted, - # pytest.mark.slow_test, + pytest.mark.core_test, ] diff --git a/tests/pytests/integration/cli/test_matcher.py b/tests/pytests/integration/cli/test_matcher.py index f64d5b9014a..6b3b21bbaa6 100644 --- a/tests/pytests/integration/cli/test_matcher.py +++ b/tests/pytests/integration/cli/test_matcher.py @@ -5,7 +5,7 @@ import pytest import salt.defaults.exitcodes pytestmark = [ - pytest.mark.slow_test, + pytest.mark.core_test, pytest.mark.windows_whitelisted, ] diff --git a/tests/pytests/integration/cli/test_salt.py b/tests/pytests/integration/cli/test_salt.py index 2f9ff0e541e..b9ddc6f23f1 100644 --- a/tests/pytests/integration/cli/test_salt.py +++ b/tests/pytests/integration/cli/test_salt.py @@ -19,7 +19,7 @@ import salt.utils.path log = logging.getLogger(__name__) pytestmark = [ - pytest.mark.slow_test, + pytest.mark.core_test, pytest.mark.windows_whitelisted, ] diff --git a/tests/pytests/integration/cli/test_salt_auth.py b/tests/pytests/integration/cli/test_salt_auth.py index 53cc92e6abc..adaf235ae21 100644 --- a/tests/pytests/integration/cli/test_salt_auth.py +++ b/tests/pytests/integration/cli/test_salt_auth.py @@ -5,7 +5,7 @@ import pytest log = logging.getLogger(__name__) pytestmark = [ - pytest.mark.slow_test, + pytest.mark.core_test, pytest.mark.skip_if_not_root, pytest.mark.destructive_test, pytest.mark.skip_on_windows, diff --git a/tests/pytests/integration/cli/test_salt_call.py b/tests/pytests/integration/cli/test_salt_call.py index b663372ec59..6aa6730ec5c 100644 --- a/tests/pytests/integration/cli/test_salt_call.py +++ b/tests/pytests/integration/cli/test_salt_call.py @@ -15,7 +15,7 @@ import salt.utils.yaml from tests.support.helpers import PRE_PYTEST_SKIP, PRE_PYTEST_SKIP_REASON pytestmark = [ - pytest.mark.slow_test, + pytest.mark.core_test, pytest.mark.windows_whitelisted, ] diff --git a/tests/pytests/integration/cli/test_salt_cp.py b/tests/pytests/integration/cli/test_salt_cp.py index ebc6afc9233..db4a1519d66 100644 --- a/tests/pytests/integration/cli/test_salt_cp.py +++ b/tests/pytests/integration/cli/test_salt_cp.py @@ -34,6 +34,7 @@ def dest_testfile(): @pytest.mark.slow_test @pytest.mark.windows_whitelisted +@pytest.mark.core_test def test_cp_testfile(salt_minion, salt_cp_cli, source_testfile, dest_testfile): """ test salt-cp diff --git a/tests/pytests/integration/cli/test_salt_deltaproxy.py b/tests/pytests/integration/cli/test_salt_deltaproxy.py index c047ffecbcf..85c7aeb7dcc 100644 --- a/tests/pytests/integration/cli/test_salt_deltaproxy.py +++ b/tests/pytests/integration/cli/test_salt_deltaproxy.py @@ -18,7 +18,8 @@ log = logging.getLogger(__name__) pytestmark = [ pytest.mark.skip_on_spawning_platform( reason="Deltaproxy minions do not currently work on spawning platforms.", - ) + ), + pytest.mark.core_test, ] diff --git a/tests/pytests/integration/cli/test_salt_key.py b/tests/pytests/integration/cli/test_salt_key.py index c4bd5cce16b..2e16cd3a96e 100644 --- a/tests/pytests/integration/cli/test_salt_key.py +++ b/tests/pytests/integration/cli/test_salt_key.py @@ -12,7 +12,7 @@ import salt.utils.pycrypto import salt.utils.yaml pytestmark = [ - pytest.mark.slow_test, + pytest.mark.core_test, pytest.mark.windows_whitelisted, ] diff --git a/tests/pytests/integration/cli/test_salt_master.py b/tests/pytests/integration/cli/test_salt_master.py index 6db26d0fdae..555a7f1d97f 100644 --- a/tests/pytests/integration/cli/test_salt_master.py +++ b/tests/pytests/integration/cli/test_salt_master.py @@ -8,7 +8,7 @@ import salt.defaults.exitcodes from tests.support.helpers import PRE_PYTEST_SKIP_REASON pytestmark = [ - pytest.mark.slow_test, + pytest.mark.core_test, pytest.mark.windows_whitelisted, ] diff --git a/tests/pytests/integration/cli/test_salt_minion.py b/tests/pytests/integration/cli/test_salt_minion.py index 8cb73916d2f..c0d60134746 100644 --- a/tests/pytests/integration/cli/test_salt_minion.py +++ b/tests/pytests/integration/cli/test_salt_minion.py @@ -9,7 +9,7 @@ import salt.defaults.exitcodes from tests.support.helpers import PRE_PYTEST_SKIP_REASON pytestmark = [ - pytest.mark.slow_test, + pytest.mark.core_test, pytest.mark.windows_whitelisted, ] diff --git a/tests/pytests/integration/cli/test_salt_proxy.py b/tests/pytests/integration/cli/test_salt_proxy.py index 69d8547c114..fbf39e30438 100644 --- a/tests/pytests/integration/cli/test_salt_proxy.py +++ b/tests/pytests/integration/cli/test_salt_proxy.py @@ -25,7 +25,7 @@ def proxy_minion_id(salt_master): pytest.helpers.remove_stale_minion_key(salt_master, _proxy_minion_id) -@pytest.mark.slow_test +@pytest.mark.core_test def test_exit_status_no_proxyid(salt_master, proxy_minion_id): """ Ensure correct exit status when --proxyid argument is missing. @@ -42,6 +42,7 @@ def test_exit_status_no_proxyid(salt_master, proxy_minion_id): @pytest.mark.skip_on_windows(reason="Windows does not do user checks") +@pytest.mark.core_test def test_exit_status_unknown_user(salt_master, proxy_minion_id): """ Ensure correct exit status when the proxy is configured to run as an @@ -57,7 +58,7 @@ def test_exit_status_unknown_user(salt_master, proxy_minion_id): assert "The user is not available." in exc.value.process_result.stderr -@pytest.mark.slow_test +@pytest.mark.core_test def test_exit_status_unknown_argument(salt_master, proxy_minion_id): """ Ensure correct exit status when an unknown argument is passed to diff --git a/tests/pytests/integration/cli/test_salt_run.py b/tests/pytests/integration/cli/test_salt_run.py index 7581927a3a6..9a051f55d92 100644 --- a/tests/pytests/integration/cli/test_salt_run.py +++ b/tests/pytests/integration/cli/test_salt_run.py @@ -9,7 +9,7 @@ import salt.utils.pycrypto import salt.utils.yaml pytestmark = [ - pytest.mark.slow_test, + pytest.mark.core_test, pytest.mark.windows_whitelisted, ] diff --git a/tests/pytests/integration/cli/test_salt_syndic.py b/tests/pytests/integration/cli/test_salt_syndic.py index 349a5aacf6e..c547df2c2eb 100644 --- a/tests/pytests/integration/cli/test_salt_syndic.py +++ b/tests/pytests/integration/cli/test_salt_syndic.py @@ -10,7 +10,7 @@ import salt.defaults.exitcodes from tests.support.helpers import PRE_PYTEST_SKIP, PRE_PYTEST_SKIP_REASON pytestmark = [ - pytest.mark.slow_test, + pytest.mark.core_test, pytest.mark.windows_whitelisted, ] diff --git a/tests/pytests/integration/cli/test_syndic_eauth.py b/tests/pytests/integration/cli/test_syndic_eauth.py index 1577acf7b7d..57e9c0a467a 100644 --- a/tests/pytests/integration/cli/test_syndic_eauth.py +++ b/tests/pytests/integration/cli/test_syndic_eauth.py @@ -8,6 +8,11 @@ import pytest docker = pytest.importorskip("docker") +pytestmark = [ + pytest.mark.core_test, +] + + def json_output_to_dict(output): """ Convert ``salt ... --out=json`` Syndic return to a dictionary. Since the diff --git a/tests/pytests/integration/daemons/test_masterapi.py b/tests/pytests/integration/daemons/test_masterapi.py index d95d3781f7f..da4c9698a32 100644 --- a/tests/pytests/integration/daemons/test_masterapi.py +++ b/tests/pytests/integration/daemons/test_masterapi.py @@ -12,7 +12,9 @@ import salt.utils.files import salt.utils.stringutils from tests.support.runtests import RUNTIME_VARS -pytestmark = [pytest.mark.slow_test] +pytestmark = [ + pytest.mark.slow_test, +] @pytest.fixture diff --git a/tests/pytests/integration/modules/test_beacons.py b/tests/pytests/integration/modules/test_beacons.py index c15485cb76a..131ebe5eb47 100644 --- a/tests/pytests/integration/modules/test_beacons.py +++ b/tests/pytests/integration/modules/test_beacons.py @@ -10,7 +10,7 @@ import pytest from tests.support.helpers import PRE_PYTEST_SKIP_OR_NOT pytestmark = [ - pytest.mark.slow_test, + pytest.mark.core_test, pytest.mark.windows_whitelisted, ] diff --git a/tests/pytests/integration/modules/test_useradd.py b/tests/pytests/integration/modules/test_useradd.py index 5dd32efe8e0..6b180d89df6 100644 --- a/tests/pytests/integration/modules/test_useradd.py +++ b/tests/pytests/integration/modules/test_useradd.py @@ -7,6 +7,7 @@ from saltfactories.utils import random_string pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.slow_test, ] diff --git a/tests/pytests/integration/proxy/test_deltaproxy.py b/tests/pytests/integration/proxy/test_deltaproxy.py index 4ea69e0b8a5..48f23b18d68 100644 --- a/tests/pytests/integration/proxy/test_deltaproxy.py +++ b/tests/pytests/integration/proxy/test_deltaproxy.py @@ -10,7 +10,8 @@ log = logging.getLogger(__name__) pytestmark = [ pytest.mark.skip_on_spawning_platform( reason="Deltaproxy minions do not currently work on spawning platforms.", - ) + ), + pytest.mark.slow_test, ] diff --git a/tests/pytests/integration/proxy/test_simple.py b/tests/pytests/integration/proxy/test_simple.py index c1c0cada47c..f3d26834ef9 100644 --- a/tests/pytests/integration/proxy/test_simple.py +++ b/tests/pytests/integration/proxy/test_simple.py @@ -8,6 +8,7 @@ import pytest log = logging.getLogger(__name__) +@pytest.mark.core_test def test_can_it_ping(salt_cli, salt_proxy): """ Ensure the proxy can ping @@ -16,6 +17,7 @@ def test_can_it_ping(salt_cli, salt_proxy): assert ret.data is True +@pytest.mark.slow_test def test_list_pkgs(salt_cli, salt_proxy): """ Package test 1, really just tests that the virtual function capability diff --git a/tests/pytests/integration/runners/state/orchestrate/test_events.py b/tests/pytests/integration/runners/state/orchestrate/test_events.py index 4a4b7eb6f64..3604d1c4c65 100644 --- a/tests/pytests/integration/runners/state/orchestrate/test_events.py +++ b/tests/pytests/integration/runners/state/orchestrate/test_events.py @@ -4,16 +4,93 @@ Tests for orchestration events import concurrent.futures import functools import json +import logging import time +import attr import pytest +from saltfactories.utils import random_string import salt.utils.jid import salt.utils.platform +import salt.utils.pycrypto -pytestmark = [ - pytest.mark.slow_test, -] +log = logging.getLogger(__name__) + + +@attr.s(kw_only=True, slots=True) +class TestMasterAccount: + username = attr.ib() + password = attr.ib() + _delete_account = attr.ib(init=False, repr=False, default=False) + + @username.default + def _default_username(self): + return random_string("account-", uppercase=False) + + @password.default + def _default_password(self): + return random_string("pwd-", size=8) + + def __enter__(self): + return self + + def __exit__(self, *args): + pass + + +@pytest.fixture(scope="session") +def salt_auth_account_m_factory(): + return TestMasterAccount(username="saltdev-auth-m") + + +@pytest.fixture(scope="module") +def salt_auth_account_m(salt_auth_account_m_factory): + with salt_auth_account_m_factory as account: + yield account + + +@pytest.fixture(scope="module") +def runner_master_config(salt_auth_account_m): + return { + "external_auth": { + "pam": {salt_auth_account_m.username: [{"*": [".*"]}, "@runner", "@wheel"]} + } + } + + +@pytest.fixture(scope="module") +def runner_salt_master(salt_factories, runner_master_config): + factory = salt_factories.salt_master_daemon( + "runner-master", defaults=runner_master_config + ) + with factory.started(): + yield factory + + +@pytest.fixture(scope="module") +def runner_salt_run_cli(runner_salt_master): + return runner_salt_master.salt_run_cli() + + +@pytest.fixture(scope="module") +def runner_salt_call_cli(runner_salt_minion): + return runner_salt_minion.salt_call_cli() + + +@pytest.fixture(scope="module") +def runner_add_user(runner_salt_run_cli, salt_auth_account_m): + ## create user on master to use + ret = runner_salt_run_cli.run("salt.cmd", "user.add", salt_auth_account_m.username) + assert ret.returncode == 0 + + yield + + ## remove user on master + ret = runner_salt_run_cli.run( + "salt.cmd", "user.delete", salt_auth_account_m.username + ) + assert ret.returncode == 0 def test_state_event(salt_run_cli, salt_cli, salt_minion): @@ -335,3 +412,106 @@ def test_orchestration_onchanges_and_prereq( # After the file was created, running again in test mode should have # shown no changes. assert not state_data["changes"] + + +@pytest.mark.slow_test +@pytest.mark.skip_if_not_root +@pytest.mark.skip_on_windows +@pytest.mark.skip_on_darwin +def test_unknown_in_runner_event( + runner_salt_run_cli, + runner_salt_master, + salt_minion, + salt_auth_account_m, + runner_add_user, + event_listener, +): + """ + Test to confirm that the ret event for the orchestration contains the + jid for the jobs spawned. + """ + file_roots_base_dir = runner_salt_master.config["file_roots"]["base"][0] + test_top_file_contents = """ + base: + '{minion_id}': + - {file_roots} + """.format( + minion_id=salt_minion.id, file_roots=file_roots_base_dir + ) + test_init_state_contents = """ + always-passes-with-any-kwarg: + test.nop: + - name: foo + - something: else + - foo: bar + always-passes: + test.succeed_without_changes: + - name: foo + always-changes-and-succeeds: + test.succeed_with_changes: + - name: foo + {{slspath}}: + test.nop + """ + test_orch_contents = """ + test_highstate: + salt.state: + - tgt: {minion_id} + - highstate: True + test_runner_metasyntetic: + salt.runner: + - name: test.metasyntactic + - locality: us + """.format( + minion_id=salt_minion.id + ) + with runner_salt_master.state_tree.base.temp_file( + "top.sls", test_top_file_contents + ), runner_salt_master.state_tree.base.temp_file( + "init.sls", test_init_state_contents + ), runner_salt_master.state_tree.base.temp_file( + "orch.sls", test_orch_contents + ): + ret = runner_salt_run_cli.run( + "salt.cmd", "shadow.gen_password", salt_auth_account_m.password + ) + assert ret.returncode == 0 + + gen_pwd = ret.stdout + ret = runner_salt_run_cli.run( + "salt.cmd", "shadow.set_password", salt_auth_account_m.username, gen_pwd + ) + assert ret.returncode == 0 + + jid = salt.utils.jid.gen_jid(runner_salt_master.config) + start_time = time.time() + + ret = runner_salt_run_cli.run( + "--jid", + jid, + "-a", + "pam", + "--username", + salt_auth_account_m.username, + "--password", + salt_auth_account_m.password, + "state.orchestrate", + "orch", + ) + assert not ret.stdout.startswith("Authentication failure") + + expected_new_event_tag = "salt/run/*/new" + event_pattern = (runner_salt_master.id, expected_new_event_tag) + found_events = event_listener.get_events([event_pattern], after_time=start_time) + + for event in found_events: + if event.data["fun"] == "runner.test.metasyntactic": + assert event.data["user"] == salt_auth_account_m.username + + expected_ret_event_tag = "salt/run/*/ret" + event_pattern = (runner_salt_master.id, expected_ret_event_tag) + found_events = event_listener.get_events([event_pattern], after_time=start_time) + + for event in found_events: + if event.data["fun"] == "runner.test.metasyntactic": + assert event.data["user"] == salt_auth_account_m.username diff --git a/tests/pytests/integration/states/test_file.py b/tests/pytests/integration/states/test_file.py index 9115818bf7e..01e9da69902 100644 --- a/tests/pytests/integration/states/test_file.py +++ b/tests/pytests/integration/states/test_file.py @@ -1278,3 +1278,32 @@ def test_issue_62611( state_run = next(iter(ret.data.values())) assert state_run["name"] == "echo MEEP MOOP" assert state_run["result"] is True + + +def test_contents_file(salt_master, salt_call_cli, tmp_path): + """ + test calling file.managed multiple times + with salt-call + """ + target_path = tmp_path / "add-contents-file.txt" + sls_name = "file-contents" + sls_contents = """ + add_contents_file_sls: + file.managed: + - name: {} + - contents: 1234 + """.format( + target_path + ) + sls_tempfile = salt_master.state_tree.base.temp_file( + "{}.sls".format(sls_name), sls_contents + ) + with sls_tempfile: + for i in range(1, 4): + ret = salt_call_cli.run("state.sls", sls_name) + assert ret.returncode == 0 + assert ret.data + state_run = next(iter(ret.data.values())) + assert state_run["result"] is True + # Check to make sure the file was created + assert target_path.is_file() diff --git a/tests/pytests/scenarios/failover/multimaster/test_failover_master.py b/tests/pytests/scenarios/failover/multimaster/test_failover_master.py index d811372f4a8..6efecfb8334 100644 --- a/tests/pytests/scenarios/failover/multimaster/test_failover_master.py +++ b/tests/pytests/scenarios/failover/multimaster/test_failover_master.py @@ -6,7 +6,7 @@ import time import pytest pytestmark = [ - pytest.mark.slow_test, + pytest.mark.core_test, pytest.mark.skip_on_freebsd(reason="Processes are not properly killed on FreeBSD"), ] diff --git a/tests/pytests/scenarios/multimaster/test_multimaster.py b/tests/pytests/scenarios/multimaster/test_multimaster.py index 9b239ad4009..8f8c8cf9055 100644 --- a/tests/pytests/scenarios/multimaster/test_multimaster.py +++ b/tests/pytests/scenarios/multimaster/test_multimaster.py @@ -9,7 +9,7 @@ log = logging.getLogger(__name__) ECHO_STR = "The FitnessGram Pacer Test is a multistage aerobic capacity test" pytestmark = [ - pytest.mark.slow_test, + pytest.mark.core_test, ] diff --git a/tests/pytests/scenarios/multimaster/test_offline_master.py b/tests/pytests/scenarios/multimaster/test_offline_master.py index d5995803e51..fe8f6d28bf0 100644 --- a/tests/pytests/scenarios/multimaster/test_offline_master.py +++ b/tests/pytests/scenarios/multimaster/test_offline_master.py @@ -3,7 +3,7 @@ import time import pytest pytestmark = [ - pytest.mark.slow_test, + pytest.mark.core_test, ] diff --git a/tests/pytests/scenarios/performance/conftest.py b/tests/pytests/scenarios/performance/conftest.py index d12451b123a..40f8cf60acf 100644 --- a/tests/pytests/scenarios/performance/conftest.py +++ b/tests/pytests/scenarios/performance/conftest.py @@ -60,7 +60,10 @@ def host_docker_network_ip_address(network): ipam_pools=[{"subnet": network_subnet, "gateway": network_gateway}], ) assert isinstance(ret, dict), ret - assert ret["result"], "Failed to create docker network: {}".format(ret) + try: + assert ret["result"] + except AssertionError: + pytest.skip("Failed to create docker network: {}".format(ret)) yield network_gateway finally: sminion.states.docker_network.absent(network_name) diff --git a/tests/pytests/scenarios/performance/test_performance.py b/tests/pytests/scenarios/performance/test_performance.py index 8f3fa0ac988..85b92ed986e 100644 --- a/tests/pytests/scenarios/performance/test_performance.py +++ b/tests/pytests/scenarios/performance/test_performance.py @@ -42,6 +42,11 @@ def prev_version(): return str(SaltVersionsInfo.previous_release().info[0]) +@pytest.fixture +def curr_version(): + return str(SaltVersionsInfo.current_release().info[0]) + + @pytest.fixture def prev_master_id(): return random_string("master-performance-prev-", uppercase=False) @@ -190,7 +195,6 @@ def curr_master( salt_factories, host_docker_network_ip_address, network, - prev_version, docker_client, curr_master_id, ): @@ -220,7 +224,7 @@ def curr_master( defaults=config_defaults, overrides=config_overrides, factory_class=ContainerMaster, - image="ghcr.io/saltstack/salt-ci-containers/salt:{}".format(prev_version), + image="ghcr.io/saltstack/salt-ci-containers/salt:current", base_script_args=["--log-level=debug"], container_run_kwargs={ "network": network, @@ -270,7 +274,6 @@ def curr_minion( curr_minion_id, curr_master, docker_client, - prev_version, host_docker_network_ip_address, network, curr_master_id, @@ -286,7 +289,7 @@ def curr_minion( factory_class=ContainerMinion, # SaltMinion kwargs name=curr_minion_id, - image="ghcr.io/saltstack/salt-ci-containers/salt:{}".format(prev_version), + image="ghcr.io/saltstack/salt-ci-containers/salt:current", docker_client=docker_client, start_timeout=120, pull_before_start=False, @@ -329,7 +332,7 @@ def _wait_for_stdout(expected, func, *args, timeout=120, **kwargs): time.sleep(1) else: pytest.skip( - f"Skipping test, one or more daemons failed to start: {expected} NOT FOUND IN {ret}" + f"Skipping test, one or more daemons failed to start: {expected} not found in {ret}" ) @@ -349,6 +352,7 @@ def test_performance( curr_minion, prev_sls, curr_sls, + curr_version, ): # Copy all of the needed files to both master file roots directories subdir = random_string("performance-") @@ -376,7 +380,9 @@ def test_performance( ) # Wait for the new master and minion to start - _wait_for_stdout("3005", curr_master.run, *curr_salt_run_cli.cmdline("--version")) + _wait_for_stdout( + curr_version, curr_master.run, *curr_salt_run_cli.cmdline("--version") + ) curr_key_cmd = [ comp for comp in curr_salt_key_cli.cmdline("-Ay") @@ -384,7 +390,7 @@ def test_performance( ] _wait_for_stdout(curr_minion.id, curr_master.run, *curr_key_cmd) _wait_for_stdout( - "Salt: {}".format("3005"), + "Salt: {}".format(curr_version), curr_master.run, *curr_salt_cli.cmdline("test.versions", minion_tgt=curr_minion.id), ) @@ -409,7 +415,10 @@ def test_performance( break else: return duration - pytest.skip("Something went wrong with the states, skipping.") + pytest.skip("Something went wrong with the states, skipping.") + + prev_duration = 0 + curr_duration = 0 for _ in range(applies): prev_state_ret = prev_master.run( @@ -417,7 +426,7 @@ def test_performance( "state.apply", f"{subdir}.{prev_sls}", minion_tgt=prev_minion.id ) ) - prev_duration = _gather_durations(prev_state_ret, prev_minion.id) + prev_duration += _gather_durations(prev_state_ret, prev_minion.id) for _ in range(applies): curr_state_ret = curr_master.run( @@ -425,7 +434,7 @@ def test_performance( "state.apply", f"{subdir}.{curr_sls}", minion_tgt=curr_minion.id ) ) - curr_duration = _gather_durations(curr_state_ret, curr_minion.id) + curr_duration += _gather_durations(curr_state_ret, curr_minion.id) # We account for network slowness, etc... here. # There is a hard balance here as far as a threshold. diff --git a/tests/pytests/scenarios/setup/test_install.py b/tests/pytests/scenarios/setup/test_install.py index ba14c760058..9c506b56cab 100644 --- a/tests/pytests/scenarios/setup/test_install.py +++ b/tests/pytests/scenarios/setup/test_install.py @@ -3,12 +3,14 @@ Tests for building and installing salt """ import json import logging +import os import pathlib import re import sys import pytest +import salt.utils.files import salt.utils.path import salt.utils.platform import salt.version @@ -17,7 +19,7 @@ from salt.modules.virtualenv_mod import KNOWN_BINARY_NAMES log = logging.getLogger(__name__) pytestmark = [ - pytest.mark.slow_test, + pytest.mark.core_test, pytest.mark.windows_whitelisted, pytest.mark.skip_initial_onedir_failure, pytest.mark.skip_if_binaries_missing(*KNOWN_BINARY_NAMES, check_all=False), @@ -457,3 +459,38 @@ def test_setup_install(virtualenv, cache_dir, use_static_requirements, src_dir): installed_salt_path = installed_salt_path[0] / "salt" salt_generated_version_file_path = installed_salt_path / "_version.txt" assert salt_generated_version_file_path.is_file() + + +def test_salt_install_args( + virtualenv, cache_dir, use_static_requirements, src_dir, tmp_path +): + """ + test building with `install` command with --salt-* + args. For example, --salt-config-dir and --salt-cache-dir. + """ + cache_dir = tmp_path / "cache_dir" + config_dir = tmp_path / "config_dir" + # Let's create the testing virtualenv + with virtualenv as venv: + venv.run(venv.venv_python, "setup.py", "clean", cwd=src_dir) + env = os.environ.copy() + env["GENERATE_SALT_SYSPATHS"] = "True" + ret = venv.run( + venv.venv_python, + "setup.py", + "--salt-config-dir", + str(config_dir), + "--salt-cache-dir", + str(cache_dir), + "install", + cwd=src_dir, + env=env, + ) + assert ret.returncode == 0 + syspath = pathlib.Path(src_dir, "build", "lib", "salt", "_syspaths.py") + assert syspath.exists() + with salt.utils.files.fopen(syspath) as fp: + data = fp.read() + assert str(cache_dir) in data + assert str(config_dir) in data + venv.run(venv.venv_python, "setup.py", "clean", cwd=src_dir) diff --git a/tests/pytests/scenarios/setup/test_man.py b/tests/pytests/scenarios/setup/test_man.py index aafb55f8160..28f0d6285a3 100644 --- a/tests/pytests/scenarios/setup/test_man.py +++ b/tests/pytests/scenarios/setup/test_man.py @@ -11,7 +11,7 @@ import salt.utils.platform from salt.modules.virtualenv_mod import KNOWN_BINARY_NAMES pytestmark = [ - pytest.mark.slow_test, + pytest.mark.core_test, pytest.mark.skip_on_windows, pytest.mark.skip_on_aix, pytest.mark.skip_initial_onedir_failure, diff --git a/tests/pytests/unit/client/ssh/test_ssh.py b/tests/pytests/unit/client/ssh/test_ssh.py index 9eb3899fab5..2be96ab195e 100644 --- a/tests/pytests/unit/client/ssh/test_ssh.py +++ b/tests/pytests/unit/client/ssh/test_ssh.py @@ -7,6 +7,7 @@ from tests.support.mock import MagicMock, patch pytestmark = [ pytest.mark.skip_if_binaries_missing("ssh", "ssh-keygen", check_all=True), + pytest.mark.slow_test, ] diff --git a/tests/pytests/unit/daemons/masterapi/test_local_funcs.py b/tests/pytests/unit/daemons/masterapi/test_local_funcs.py index cc4e7255b13..3c439f49477 100644 --- a/tests/pytests/unit/daemons/masterapi/test_local_funcs.py +++ b/tests/pytests/unit/daemons/masterapi/test_local_funcs.py @@ -5,7 +5,9 @@ import salt.daemons.masterapi as masterapi import salt.utils.platform from tests.support.mock import MagicMock, patch -pytestmark = [pytest.mark.slow_test] +pytestmark = [ + pytest.mark.slow_test, +] @pytest.fixture diff --git a/tests/pytests/unit/daemons/masterapi/test_remote_funcs.py b/tests/pytests/unit/daemons/masterapi/test_remote_funcs.py index 3a18f10e20d..8151dcaf006 100644 --- a/tests/pytests/unit/daemons/masterapi/test_remote_funcs.py +++ b/tests/pytests/unit/daemons/masterapi/test_remote_funcs.py @@ -5,7 +5,9 @@ import salt.daemons.masterapi as masterapi import salt.utils.platform from tests.support.mock import MagicMock, patch -pytestmark = [pytest.mark.slow_test] +pytestmark = [ + pytest.mark.slow_test, +] class FakeCache: diff --git a/tests/pytests/unit/modules/test_boto_dynamodb.py b/tests/pytests/unit/modules/test_boto_dynamodb.py new file mode 100644 index 00000000000..f5b983e13f0 --- /dev/null +++ b/tests/pytests/unit/modules/test_boto_dynamodb.py @@ -0,0 +1,92 @@ +""" + Test cases for salt.modules.boto_dynamodb +""" + + +import pytest + +import salt.modules.boto_dynamodb as boto_dynamodb +from tests.support.mock import MagicMock, patch + + +@pytest.fixture +def configure_loader_modules(): + return {boto_dynamodb: {"__opts__": {}, "__utils__": {}}} + + +@pytest.fixture +def arn(): + return "arn:aws:dynamodb:us-east-1:012345678901:table/my-table" + + +@pytest.fixture +def tags(): + return {"foo": "bar", "hello": "world"} + + +@pytest.fixture +def tags_as_list(): + return [{"Key": "foo", "Value": "bar"}, {"Key": "hello", "Value": "world"}] + + +class DummyConn: + def __init__(self, tags_as_list): + self.list_tags_of_resource = MagicMock( + return_value={"Tags": tags_as_list, "NextToken": None} + ) + self.tag_resource = MagicMock(return_value=True) + self.untag_resource = MagicMock(return_value=True) + + +def test_list_tags_of_resource(arn, tags, tags_as_list): + """ + Test that the correct API call is made and correct return format is + returned. + """ + conn = DummyConn(tags_as_list) + utils = {"boto3.get_connection": MagicMock(return_value=conn)} + with patch.dict(boto_dynamodb.__utils__, utils): + ret = boto_dynamodb.list_tags_of_resource(resource_arn=arn) + + assert ret == tags, ret + conn.list_tags_of_resource.assert_called_once_with(ResourceArn=arn, NextToken="") + + +def test_tag_resource(arn, tags, tags_as_list): + """ + Test that the correct API call is made and correct return format is + returned. + """ + conn = DummyConn(tags_as_list) + utils = {"boto3.get_connection": MagicMock(return_value=conn)} + with patch.dict(boto_dynamodb.__utils__, utils): + ret = boto_dynamodb.tag_resource(resource_arn=arn, tags=tags) + + assert ret is True, ret + # Account for differing dict iteration order among Python versions by + # being more explicit in asserts. + assert len(conn.tag_resource.mock_calls) == 1 + call = conn.tag_resource.mock_calls[0] + # No positional args + assert not call.args + # Make sure there aren't any additional kwargs beyond what we expect + assert len(call.kwargs) == 2 + assert call.kwargs["ResourceArn"] == arn + # Make sure there aren't any additional tags beyond what we expect + assert len(call.kwargs["Tags"]) == 2 + for tag_dict in tags_as_list: + assert tag_dict in call.kwargs["Tags"] + + +def test_untag_resource(arn, tags, tags_as_list): + """ + Test that the correct API call is made and correct return format is + returned. + """ + conn = DummyConn(tags_as_list) + utils = {"boto3.get_connection": MagicMock(return_value=conn)} + with patch.dict(boto_dynamodb.__utils__, utils): + ret = boto_dynamodb.untag_resource(resource_arn=arn, tag_keys=sorted(tags)) + + assert ret is True, ret + conn.untag_resource.assert_called_once_with(ResourceArn=arn, TagKeys=sorted(tags)) diff --git a/tests/pytests/unit/modules/test_cassandra_cql.py b/tests/pytests/unit/modules/test_cassandra_cql.py index e9a1a271d1d..6b39d2f0cc4 100644 --- a/tests/pytests/unit/modules/test_cassandra_cql.py +++ b/tests/pytests/unit/modules/test_cassandra_cql.py @@ -15,6 +15,11 @@ from tests.support.mock import MagicMock, patch log = logging.getLogger(__name__) +pytestmark = pytest.mark.skipif( + not cassandra_cql.HAS_DRIVER, reason="Cassandra CQL driver not loaded" +) + + @pytest.fixture def configure_loader_modules(): return {cassandra_cql: {}} diff --git a/tests/pytests/unit/modules/test_drbd.py b/tests/pytests/unit/modules/test_drbd.py new file mode 100644 index 00000000000..ce9625c2d0c --- /dev/null +++ b/tests/pytests/unit/modules/test_drbd.py @@ -0,0 +1,186 @@ +""" + :codeauthor: Jayesh Kariya + + Test cases for salt.modules.drbd +""" + + +import pytest + +import salt.modules.drbd as drbd +from tests.support.mock import MagicMock, patch + + +@pytest.fixture +def configure_loader_modules(): + return {drbd: {}} + + +# 'overview' function tests: 1 + + +def test_overview(): + """ + Test if it shows status of the DRBD devices + """ + ret = { + "connection state": "True", + "device": "Stack", + "fs": "None", + "local disk state": "UpToDate", + "local role": "master", + "minor number": "Salt", + "mountpoint": "True", + "partner disk state": "UpToDate", + "partner role": "minion", + "percent": "888", + "remains": "666", + "total size": "50", + "used": "50", + } + mock = MagicMock( + return_value=( + "Salt:Stack True master/minion UpToDate/UpToDate True None 50 50 666 888" + ) + ) + with patch.dict(drbd.__salt__, {"cmd.run": mock}): + assert drbd.overview() == ret + + ret = { + "connection state": "True", + "device": "Stack", + "local disk state": "UpToDate", + "local role": "master", + "minor number": "Salt", + "partner disk state": "partner", + "partner role": "minion", + "synched": "5050", + "synchronisation: ": "syncbar", + } + mock = MagicMock( + return_value=( + "Salt:Stack True master/minion UpToDate/partner syncbar None 50 50" + ) + ) + with patch.dict(drbd.__salt__, {"cmd.run": mock}): + assert drbd.overview() == ret + + +def test_status(): + """ + Test if it shows status of the DRBD resources via drbdadm + """ + ret = [ + { + "local role": "Primary", + "local volumes": [{"disk": "UpToDate"}], + "peer nodes": [ + { + "peer volumes": [ + { + "done": "96.47", + "peer-disk": "Inconsistent", + "replication": "SyncSource", + } + ], + "peernode name": "opensuse-node2", + "role": "Secondary", + } + ], + "resource name": "single", + } + ] + + mock = MagicMock( + return_value=""" +single role:Primary + disk:UpToDate + opensuse-node2 role:Secondary + replication:SyncSource peer-disk:Inconsistent done:96.47 +""" + ) + + with patch.dict(drbd.__salt__, {"cmd.run": mock}): + assert drbd.status() == ret + + ret = [ + { + "local role": "Primary", + "local volumes": [ + {"disk": "UpToDate", "volume": "0"}, + {"disk": "UpToDate", "volume": "1"}, + ], + "peer nodes": [ + { + "peer volumes": [ + {"peer-disk": "UpToDate", "volume": "0"}, + {"peer-disk": "UpToDate", "volume": "1"}, + ], + "peernode name": "node2", + "role": "Secondary", + }, + { + "peer volumes": [ + {"peer-disk": "UpToDate", "volume": "0"}, + {"peer-disk": "UpToDate", "volume": "1"}, + ], + "peernode name": "node3", + "role": "Secondary", + }, + ], + "resource name": "res", + }, + { + "local role": "Primary", + "local volumes": [ + {"disk": "UpToDate", "volume": "0"}, + {"disk": "UpToDate", "volume": "1"}, + ], + "peer nodes": [ + { + "peer volumes": [ + {"peer-disk": "UpToDate", "volume": "0"}, + {"peer-disk": "UpToDate", "volume": "1"}, + ], + "peernode name": "node2", + "role": "Secondary", + }, + { + "peer volumes": [ + {"peer-disk": "UpToDate", "volume": "0"}, + {"peer-disk": "UpToDate", "volume": "1"}, + ], + "peernode name": "node3", + "role": "Secondary", + }, + ], + "resource name": "test", + }, + ] + + mock = MagicMock( + return_value=""" +res role:Primary + volume:0 disk:UpToDate + volume:1 disk:UpToDate + node2 role:Secondary + volume:0 peer-disk:UpToDate + volume:1 peer-disk:UpToDate + node3 role:Secondary + volume:0 peer-disk:UpToDate + volume:1 peer-disk:UpToDate + +test role:Primary + volume:0 disk:UpToDate + volume:1 disk:UpToDate + node2 role:Secondary + volume:0 peer-disk:UpToDate + volume:1 peer-disk:UpToDate + node3 role:Secondary + volume:0 peer-disk:UpToDate + volume:1 peer-disk:UpToDate + +""" + ) + with patch.dict(drbd.__salt__, {"cmd.run": mock}): + assert drbd.status() == ret diff --git a/tests/pytests/unit/modules/test_gpg.py b/tests/pytests/unit/modules/test_gpg.py index 52e26bdffad..697f53c6541 100644 --- a/tests/pytests/unit/modules/test_gpg.py +++ b/tests/pytests/unit/modules/test_gpg.py @@ -22,6 +22,7 @@ pytest.importorskip("gnupg") pytestmark = [ pytest.mark.skip_unless_on_linux, pytest.mark.requires_random_entropy, + pytest.mark.slow_test, ] log = logging.getLogger(__name__) diff --git a/tests/pytests/unit/modules/test_hashutil.py b/tests/pytests/unit/modules/test_hashutil.py new file mode 100644 index 00000000000..d8f2195c174 --- /dev/null +++ b/tests/pytests/unit/modules/test_hashutil.py @@ -0,0 +1,85 @@ +""" + Test cases for salt.modules.hashutil +""" + + +import pytest + +import salt.modules.hashutil as hashutil + + +@pytest.fixture +def the_string(): + return "get salted" + + +@pytest.fixture +def the_string_base64(): + return "Z2V0IHNhbHRlZA==\n" + + +@pytest.fixture +def the_string_md5(): + return "2aacf29e92feaf528fb738bcf9d647ac" + + +@pytest.fixture +def the_string_sha256(): + return "d49859ccbc854fa68d800b5734efc70d72383e6479d545468bc300263164ff33" + + +@pytest.fixture +def the_string_sha512(): + return "a8c174a7941c64a068e686812a2fafd7624c840fde800f5965fbeca675f2f6e37061ffe41e17728c919bdea290eab7a21e13c04ae71661955a87f2e0e04bb045" + + +@pytest.fixture +def the_string_hmac(): + return "eBWf9bstXg+NiP5AOwppB5HMvZiYMPzEM9W5YMm/AmQ=" + + +@pytest.fixture +def the_string_hmac_compute(): + return "78159ff5bb2d5e0f8d88fe403b0a690791ccbd989830fcc433d5b960c9bf0264" + + +@pytest.fixture +def the_string_github(): + return "sha1=b06aa56bdf4935eec82c4e53e83ed03f03fdb32d" + + +@pytest.fixture +def configure_loader_modules(): + return {hashutil: {}} + + +def test_base64_encodestring(the_string, the_string_base64): + assert hashutil.base64_encodestring(the_string) == the_string_base64 + + +def test_base64_decodestring(the_string, the_string_base64): + assert hashutil.base64_decodestring(the_string_base64) == the_string + + +def test_md5_digest(the_string, the_string_md5): + assert hashutil.md5_digest(the_string) == the_string_md5 + + +def test_sha256_digest(the_string, the_string_sha256): + assert hashutil.sha256_digest(the_string) == the_string_sha256 + + +def test_sha512_digest(the_string, the_string_sha512): + assert hashutil.sha512_digest(the_string) == the_string_sha512 + + +def test_hmac_signature(the_string, the_string_hmac): + assert hashutil.hmac_signature(the_string, "shared secret", the_string_hmac) + + +def test_hmac_compute(the_string, the_string_hmac_compute): + assert hashutil.hmac_compute(the_string, "shared secret") + + +def test_github_signature(the_string, the_string_github): + assert hashutil.github_signature(the_string, "shared secret", the_string_github) diff --git a/tests/pytests/unit/modules/test_mac_xattr.py b/tests/pytests/unit/modules/test_mac_xattr.py index c5816877e72..feacf2eed09 100644 --- a/tests/pytests/unit/modules/test_mac_xattr.py +++ b/tests/pytests/unit/modules/test_mac_xattr.py @@ -74,6 +74,19 @@ def test_read_missing(): pytest.raises(CommandExecutionError, xattr.read, "/path/to/file", "attribute") +def test_read_not_decodeable(): + """ + Test reading an attribute which returns non-UTF-8 bytes + """ + with patch( + "salt.utils.mac_utils.execute_return_result", + MagicMock( + side_effect=UnicodeDecodeError("UTF-8", b"\xd1expected results", 0, 1, "") + ), + ): + assert xattr.read("/path/to/file", "com.attr") == "�expected results" + + def test_write(): """ Test writing a specific attribute to a file diff --git a/tests/pytests/unit/modules/test_pip.py b/tests/pytests/unit/modules/test_pip.py index d3565ec07ae..b7ad1ea3fd2 100644 --- a/tests/pytests/unit/modules/test_pip.py +++ b/tests/pytests/unit/modules/test_pip.py @@ -79,7 +79,15 @@ def test__pip_bin_env_no_bin_env(): assert ret is None -def test_install_frozen_app(): +@pytest.fixture +def python_binary(): + binary = [sys.executable, "-m", "pip"] + if hasattr(sys, "RELENV"): + binary = [str(sys.RELENV / "salt-pip")] + return binary + + +def test_install_frozen_app(python_binary): pkg = "pep8" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch("sys.frozen", True, create=True): @@ -87,8 +95,7 @@ def test_install_frozen_app(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg) expected = [ - sys.executable, - "pip", + *python_binary, "install", pkg, ] @@ -101,7 +108,7 @@ def test_install_frozen_app(): ) -def test_install_source_app(): +def test_install_source_app(python_binary): pkg = "pep8" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch("sys.frozen", False, create=True): @@ -109,9 +116,7 @@ def test_install_source_app(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", pkg, ] @@ -124,14 +129,12 @@ def test_install_source_app(): ) -def test_fix4361(): +def test_fix4361(python_binary): mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(requirements="requirements.txt") expected_cmd = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", "--requirement", "requirements.txt", @@ -155,13 +158,13 @@ def test_install_editable_without_egg_fails(): ) -def test_install_multiple_editable(): +def test_install_multiple_editable(python_binary): editables = [ "git+https://github.com/saltstack/istr.git@v1.0.1#egg=iStr", "git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting", ] - expected = [sys.executable, "-m", "pip", "install"] + expected = [*python_binary, "install"] for item in editables: expected.extend(["--editable", item]) @@ -190,14 +193,14 @@ def test_install_multiple_editable(): ) -def test_install_multiple_pkgs_and_editables(): +def test_install_multiple_pkgs_and_editables(python_binary): pkgs = ["pep8", "salt"] editables = [ "git+https://github.com/saltstack/istr.git@v1.0.1#egg=iStr", "git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting", ] - expected = [sys.executable, "-m", "pip", "install"] + expected = [*python_binary, "install"] expected.extend(pkgs) for item in editables: expected.extend(["--editable", item]) @@ -231,9 +234,7 @@ def test_install_multiple_pkgs_and_editables(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkgs=pkgs[0], editable=editables[0]) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", pkgs[0], "--editable", @@ -248,7 +249,7 @@ def test_install_multiple_pkgs_and_editables(): ) -def test_issue5940_install_multiple_pip_mirrors(): +def test_issue5940_install_multiple_pip_mirrors(python_binary): """ test multiple pip mirrors. This test only works with pip < 7.0.0 """ @@ -259,7 +260,7 @@ def test_issue5940_install_multiple_pip_mirrors(): "http://pypi.crate.io", ] - expected = [sys.executable, "-m", "pip", "install", "--use-mirrors"] + expected = [*python_binary, "install", "--use-mirrors"] for item in mirrors: expected.extend(["--mirrors", item]) expected.append("pep8") @@ -289,9 +290,7 @@ def test_issue5940_install_multiple_pip_mirrors(): ) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", "--use-mirrors", "--mirrors", @@ -312,7 +311,7 @@ def test_issue5940_install_multiple_pip_mirrors(): ) -def test_install_with_multiple_find_links(): +def test_install_with_multiple_find_links(python_binary): find_links = [ "http://g.pypi.python.org", "http://c.pypi.python.org", @@ -320,7 +319,7 @@ def test_install_with_multiple_find_links(): ] pkg = "pep8" - expected = [sys.executable, "-m", "pip", "install"] + expected = [*python_binary, "install"] for item in find_links: expected.extend(["--find-links", item]) expected.append(pkg) @@ -362,9 +361,7 @@ def test_install_with_multiple_find_links(): ) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", "--find-links", find_links[0], @@ -422,16 +419,14 @@ def test_install_failed_cached_requirements(): assert "my_test_reqs" in ret["comment"] -def test_install_cached_requirements_used(): +def test_install_cached_requirements_used(python_binary): with patch("salt.modules.pip._get_cached_requirements") as get_cached_requirements: get_cached_requirements.return_value = "my_cached_reqs" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(requirements="salt://requirements.txt") expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", "--requirement", "my_cached_reqs", @@ -479,7 +474,7 @@ def test_install_venv(): ) -def test_install_log_argument_in_resulting_command(): +def test_install_log_argument_in_resulting_command(python_binary): with patch("os.access") as mock_path: pkg = "pep8" log_path = "/tmp/pip-install.log" @@ -487,9 +482,7 @@ def test_install_log_argument_in_resulting_command(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, log=log_path) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", "--log", log_path, @@ -515,10 +508,10 @@ def test_non_writeable_log(): pytest.raises(IOError, pip.install, pkg, log=log_path) -def test_install_timeout_argument_in_resulting_command(): +def test_install_timeout_argument_in_resulting_command(python_binary): # Passing an int pkg = "pep8" - expected = [sys.executable, "-m", "pip", "install", "--timeout"] + expected = [*python_binary, "install", "--timeout"] mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, timeout=10) @@ -548,16 +541,14 @@ def test_install_timeout_argument_in_resulting_command(): pytest.raises(ValueError, pip.install, pkg, timeout="a") -def test_install_index_url_argument_in_resulting_command(): +def test_install_index_url_argument_in_resulting_command(python_binary): pkg = "pep8" index_url = "http://foo.tld" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, index_url=index_url) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", "--index-url", index_url, @@ -572,16 +563,14 @@ def test_install_index_url_argument_in_resulting_command(): ) -def test_install_extra_index_url_argument_in_resulting_command(): +def test_install_extra_index_url_argument_in_resulting_command(python_binary): pkg = "pep8" extra_index_url = "http://foo.tld" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, extra_index_url=extra_index_url) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", "--extra-index-url", extra_index_url, @@ -596,12 +585,12 @@ def test_install_extra_index_url_argument_in_resulting_command(): ) -def test_install_no_index_argument_in_resulting_command(): +def test_install_no_index_argument_in_resulting_command(python_binary): pkg = "pep8" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, no_index=True) - expected = [sys.executable, "-m", "pip", "install", "--no-index", pkg] + expected = [*python_binary, "install", "--no-index", pkg] mock.assert_called_with( expected, saltenv="base", @@ -611,13 +600,13 @@ def test_install_no_index_argument_in_resulting_command(): ) -def test_install_build_argument_in_resulting_command(): +def test_install_build_argument_in_resulting_command(python_binary): pkg = "pep8" build = "/tmp/foo" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, build=build) - expected = [sys.executable, "-m", "pip", "install", "--build", build, pkg] + expected = [*python_binary, "install", "--build", build, pkg] mock.assert_called_with( expected, saltenv="base", @@ -627,13 +616,13 @@ def test_install_build_argument_in_resulting_command(): ) -def test_install_target_argument_in_resulting_command(): +def test_install_target_argument_in_resulting_command(python_binary): pkg = "pep8" target = "/tmp/foo" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, target=target) - expected = [sys.executable, "-m", "pip", "install", "--target", target, pkg] + expected = [*python_binary, "install", "--target", target, pkg] mock.assert_called_with( expected, saltenv="base", @@ -643,16 +632,14 @@ def test_install_target_argument_in_resulting_command(): ) -def test_install_download_argument_in_resulting_command(): +def test_install_download_argument_in_resulting_command(python_binary): pkg = "pep8" download = "/tmp/foo" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, download=download) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", "--download", download, @@ -667,12 +654,12 @@ def test_install_download_argument_in_resulting_command(): ) -def test_install_no_download_argument_in_resulting_command(): +def test_install_no_download_argument_in_resulting_command(python_binary): pkg = "pep8" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, no_download=True) - expected = [sys.executable, "-m", "pip", "install", "--no-download", pkg] + expected = [*python_binary, "install", "--no-download", pkg] mock.assert_called_with( expected, saltenv="base", @@ -682,7 +669,7 @@ def test_install_no_download_argument_in_resulting_command(): ) -def test_install_download_cache_dir_arguments_in_resulting_command(): +def test_install_download_cache_dir_arguments_in_resulting_command(python_binary): pkg = "pep8" cache_dir_arg_mapping = { "1.5.6": "--download-cache", @@ -697,9 +684,7 @@ def test_install_download_cache_dir_arguments_in_resulting_command(): # test `download_cache` kwarg pip.install(pkg, download_cache="/tmp/foo") expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", cmd_arg, download_cache, @@ -724,13 +709,13 @@ def test_install_download_cache_dir_arguments_in_resulting_command(): ) -def test_install_source_argument_in_resulting_command(): +def test_install_source_argument_in_resulting_command(python_binary): pkg = "pep8" source = "/tmp/foo" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, source=source) - expected = [sys.executable, "-m", "pip", "install", "--source", source, pkg] + expected = [*python_binary, "install", "--source", source, pkg] mock.assert_called_with( expected, saltenv="base", @@ -740,16 +725,14 @@ def test_install_source_argument_in_resulting_command(): ) -def test_install_exists_action_argument_in_resulting_command(): +def test_install_exists_action_argument_in_resulting_command(python_binary): pkg = "pep8" for action in ("s", "i", "w", "b"): mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, exists_action=action) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", "--exists-action", action, @@ -769,11 +752,11 @@ def test_install_exists_action_argument_in_resulting_command(): pytest.raises(CommandExecutionError, pip.install, pkg, exists_action="d") -def test_install_install_options_argument_in_resulting_command(): +def test_install_install_options_argument_in_resulting_command(python_binary): install_options = ["--exec-prefix=/foo/bar", "--install-scripts=/foo/bar/bin"] pkg = "pep8" - expected = [sys.executable, "-m", "pip", "install"] + expected = [*python_binary, "install"] for item in install_options: expected.extend(["--install-option", item]) expected.append(pkg) @@ -807,9 +790,7 @@ def test_install_install_options_argument_in_resulting_command(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, install_options=install_options[0]) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", "--install-option", install_options[0], @@ -824,11 +805,11 @@ def test_install_install_options_argument_in_resulting_command(): ) -def test_install_global_options_argument_in_resulting_command(): +def test_install_global_options_argument_in_resulting_command(python_binary): global_options = ["--quiet", "--no-user-cfg"] pkg = "pep8" - expected = [sys.executable, "-m", "pip", "install"] + expected = [*python_binary, "install"] for item in global_options: expected.extend(["--global-option", item]) expected.append(pkg) @@ -862,9 +843,7 @@ def test_install_global_options_argument_in_resulting_command(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, global_options=global_options[0]) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", "--global-option", global_options[0], @@ -879,12 +858,12 @@ def test_install_global_options_argument_in_resulting_command(): ) -def test_install_upgrade_argument_in_resulting_command(): +def test_install_upgrade_argument_in_resulting_command(python_binary): pkg = "pep8" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, upgrade=True) - expected = [sys.executable, "-m", "pip", "install", "--upgrade", pkg] + expected = [*python_binary, "install", "--upgrade", pkg] mock.assert_called_with( expected, saltenv="base", @@ -894,15 +873,13 @@ def test_install_upgrade_argument_in_resulting_command(): ) -def test_install_force_reinstall_argument_in_resulting_command(): +def test_install_force_reinstall_argument_in_resulting_command(python_binary): pkg = "pep8" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, force_reinstall=True) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", "--force-reinstall", pkg, @@ -916,15 +893,13 @@ def test_install_force_reinstall_argument_in_resulting_command(): ) -def test_install_ignore_installed_argument_in_resulting_command(): +def test_install_ignore_installed_argument_in_resulting_command(python_binary): pkg = "pep8" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, ignore_installed=True) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", "--ignore-installed", pkg, @@ -938,12 +913,12 @@ def test_install_ignore_installed_argument_in_resulting_command(): ) -def test_install_no_deps_argument_in_resulting_command(): +def test_install_no_deps_argument_in_resulting_command(python_binary): pkg = "pep8" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, no_deps=True) - expected = [sys.executable, "-m", "pip", "install", "--no-deps", pkg] + expected = [*python_binary, "install", "--no-deps", pkg] mock.assert_called_with( expected, saltenv="base", @@ -953,12 +928,12 @@ def test_install_no_deps_argument_in_resulting_command(): ) -def test_install_no_install_argument_in_resulting_command(): +def test_install_no_install_argument_in_resulting_command(python_binary): pkg = "pep8" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, no_install=True) - expected = [sys.executable, "-m", "pip", "install", "--no-install", pkg] + expected = [*python_binary, "install", "--no-install", pkg] mock.assert_called_with( expected, saltenv="base", @@ -968,13 +943,13 @@ def test_install_no_install_argument_in_resulting_command(): ) -def test_install_proxy_argument_in_resulting_command(): +def test_install_proxy_argument_in_resulting_command(python_binary): pkg = "pep8" proxy = "salt-user:salt-passwd@salt-proxy:3128" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(pkg, proxy=proxy) - expected = [sys.executable, "-m", "pip", "install", "--proxy", proxy, pkg] + expected = [*python_binary, "install", "--proxy", proxy, pkg] mock.assert_called_with( expected, saltenv="base", @@ -984,7 +959,7 @@ def test_install_proxy_argument_in_resulting_command(): ) -def test_install_proxy_false_argument_in_resulting_command(): +def test_install_proxy_false_argument_in_resulting_command(python_binary): """ Checking that there is no proxy set if proxy arg is set to False even if the global proxy is set. @@ -1001,7 +976,7 @@ def test_install_proxy_false_argument_in_resulting_command(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): with patch.dict(pip.__opts__, config_mock): pip.install(pkg, proxy=proxy) - expected = [sys.executable, "-m", "pip", "install", pkg] + expected = [*python_binary, "install", pkg] mock.assert_called_with( expected, saltenv="base", @@ -1011,7 +986,7 @@ def test_install_proxy_false_argument_in_resulting_command(): ) -def test_install_global_proxy_in_resulting_command(): +def test_install_global_proxy_in_resulting_command(python_binary): """ Checking that there is proxy set if global proxy is set. """ @@ -1028,9 +1003,7 @@ def test_install_global_proxy_in_resulting_command(): with patch.dict(pip.__opts__, config_mock): pip.install(pkg) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", "--proxy", proxy, @@ -1045,13 +1018,13 @@ def test_install_global_proxy_in_resulting_command(): ) -def test_install_multiple_requirements_arguments_in_resulting_command(): +def test_install_multiple_requirements_arguments_in_resulting_command(python_binary): with patch("salt.modules.pip._get_cached_requirements") as get_cached_requirements: cached_reqs = ["my_cached_reqs-1", "my_cached_reqs-2"] get_cached_requirements.side_effect = cached_reqs requirements = ["salt://requirements-1.txt", "salt://requirements-2.txt"] - expected = [sys.executable, "-m", "pip", "install"] + expected = [*python_binary, "install"] for item in cached_reqs: expected.extend(["--requirement", item]) @@ -1086,9 +1059,7 @@ def test_install_multiple_requirements_arguments_in_resulting_command(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.install(requirements=requirements[0]) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", "--requirement", cached_reqs[0], @@ -1102,7 +1073,7 @@ def test_install_multiple_requirements_arguments_in_resulting_command(): ) -def test_install_extra_args_arguments_in_resulting_command(): +def test_install_extra_args_arguments_in_resulting_command(python_binary): pkg = "pep8" mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): @@ -1110,9 +1081,7 @@ def test_install_extra_args_arguments_in_resulting_command(): pkg, extra_args=[{"--latest-pip-kwarg": "param"}, "--latest-pip-arg"] ) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "install", pkg, "--latest-pip-kwarg", @@ -1148,13 +1117,13 @@ def test_install_extra_args_arguments_recursion_error(): ) -def test_uninstall_multiple_requirements_arguments_in_resulting_command(): +def test_uninstall_multiple_requirements_arguments_in_resulting_command(python_binary): with patch("salt.modules.pip._get_cached_requirements") as get_cached_requirements: cached_reqs = ["my_cached_reqs-1", "my_cached_reqs-2"] get_cached_requirements.side_effect = cached_reqs requirements = ["salt://requirements-1.txt", "salt://requirements-2.txt"] - expected = [sys.executable, "-m", "pip", "uninstall", "-y"] + expected = [*python_binary, "uninstall", "-y"] for item in cached_reqs: expected.extend(["--requirement", item]) @@ -1191,9 +1160,7 @@ def test_uninstall_multiple_requirements_arguments_in_resulting_command(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.uninstall(requirements=requirements[0]) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "uninstall", "-y", "--requirement", @@ -1209,7 +1176,7 @@ def test_uninstall_multiple_requirements_arguments_in_resulting_command(): ) -def test_uninstall_global_proxy_in_resulting_command(): +def test_uninstall_global_proxy_in_resulting_command(python_binary): """ Checking that there is proxy set if global proxy is set. """ @@ -1226,9 +1193,7 @@ def test_uninstall_global_proxy_in_resulting_command(): with patch.dict(pip.__opts__, config_mock): pip.uninstall(pkg) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "uninstall", "-y", "--proxy", @@ -1245,7 +1210,7 @@ def test_uninstall_global_proxy_in_resulting_command(): ) -def test_uninstall_proxy_false_argument_in_resulting_command(): +def test_uninstall_proxy_false_argument_in_resulting_command(python_binary): """ Checking that there is no proxy set if proxy arg is set to False even if the global proxy is set. @@ -1262,7 +1227,7 @@ def test_uninstall_proxy_false_argument_in_resulting_command(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): with patch.dict(pip.__opts__, config_mock): pip.uninstall(pkg, proxy=proxy) - expected = [sys.executable, "-m", "pip", "uninstall", "-y", pkg] + expected = [*python_binary, "uninstall", "-y", pkg] mock.assert_called_with( expected, saltenv="base", @@ -1273,7 +1238,7 @@ def test_uninstall_proxy_false_argument_in_resulting_command(): ) -def test_uninstall_log_argument_in_resulting_command(): +def test_uninstall_log_argument_in_resulting_command(python_binary): pkg = "pep8" log_path = "/tmp/pip-install.log" @@ -1281,9 +1246,7 @@ def test_uninstall_log_argument_in_resulting_command(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): pip.uninstall(pkg, log=log_path) expected = [ - sys.executable, - "-m", - "pip", + *python_binary, "uninstall", "-y", "--log", @@ -1307,9 +1270,9 @@ def test_uninstall_log_argument_in_resulting_command(): pytest.raises(IOError, pip.uninstall, pkg, log=log_path) -def test_uninstall_timeout_argument_in_resulting_command(): +def test_uninstall_timeout_argument_in_resulting_command(python_binary): pkg = "pep8" - expected = [sys.executable, "-m", "pip", "uninstall", "-y", "--timeout"] + expected = [*python_binary, "uninstall", "-y", "--timeout"] # Passing an int mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) with patch.dict(pip.__salt__, {"cmd.run_all": mock}): @@ -1342,8 +1305,8 @@ def test_uninstall_timeout_argument_in_resulting_command(): pytest.raises(ValueError, pip.uninstall, pkg, timeout="a") -def test_freeze_command(): - expected = [sys.executable, "-m", "pip", "freeze"] +def test_freeze_command(python_binary): + expected = [*python_binary, "freeze"] eggs = [ "M2Crypto==0.21.1", "-e git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8#egg=SaltTesting-dev", @@ -1389,7 +1352,7 @@ def test_freeze_command(): ) -def test_freeze_command_with_all(): +def test_freeze_command_with_all(python_binary): eggs = [ "M2Crypto==0.21.1", "-e git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8#egg=SaltTesting-dev", @@ -1403,7 +1366,7 @@ def test_freeze_command_with_all(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): with patch("salt.modules.pip.version", MagicMock(return_value="9.0.1")): ret = pip.freeze() - expected = [sys.executable, "-m", "pip", "freeze", "--all"] + expected = [*python_binary, "freeze", "--all"] mock.assert_called_with( expected, cwd=None, @@ -1423,7 +1386,7 @@ def test_freeze_command_with_all(): ) -def test_list_freeze_parse_command(): +def test_list_freeze_parse_command(python_binary): eggs = [ "M2Crypto==0.21.1", "-e git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8#egg=SaltTesting-dev", @@ -1436,7 +1399,7 @@ def test_list_freeze_parse_command(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): with patch("salt.modules.pip.version", MagicMock(return_value=mock_version)): ret = pip.list_freeze_parse() - expected = [sys.executable, "-m", "pip", "freeze"] + expected = [*python_binary, "freeze"] mock.assert_called_with( expected, cwd=None, @@ -1463,7 +1426,7 @@ def test_list_freeze_parse_command(): ) -def test_list_freeze_parse_command_with_all(): +def test_list_freeze_parse_command_with_all(python_binary): eggs = [ "M2Crypto==0.21.1", "-e git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8#egg=SaltTesting-dev", @@ -1481,7 +1444,7 @@ def test_list_freeze_parse_command_with_all(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): with patch("salt.modules.pip.version", MagicMock(return_value=mock_version)): ret = pip.list_freeze_parse() - expected = [sys.executable, "-m", "pip", "freeze", "--all"] + expected = [*python_binary, "freeze", "--all"] mock.assert_called_with( expected, cwd=None, @@ -1509,7 +1472,7 @@ def test_list_freeze_parse_command_with_all(): ) -def test_list_freeze_parse_command_with_prefix(): +def test_list_freeze_parse_command_with_prefix(python_binary): eggs = [ "M2Crypto==0.21.1", "-e git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8#egg=SaltTesting-dev", @@ -1521,7 +1484,7 @@ def test_list_freeze_parse_command_with_prefix(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): with patch("salt.modules.pip.version", MagicMock(return_value="6.1.1")): ret = pip.list_freeze_parse(prefix="bb") - expected = [sys.executable, "-m", "pip", "freeze"] + expected = [*python_binary, "freeze"] mock.assert_called_with( expected, cwd=None, @@ -1532,7 +1495,7 @@ def test_list_freeze_parse_command_with_prefix(): assert ret == {"bbfreeze-loader": "1.1.0", "bbfreeze": "1.1.0"} -def test_list_upgrades_legacy(): +def test_list_upgrades_legacy(python_binary): eggs = [ "apache-libcloud (Current: 1.1.0 Latest: 2.2.1 [wheel])", "appdirs (Current: 1.4.1 Latest: 1.4.3 [wheel])", @@ -1543,7 +1506,7 @@ def test_list_upgrades_legacy(): with patch("salt.modules.pip.version", MagicMock(return_value="6.1.1")): ret = pip.list_upgrades() mock.assert_called_with( - [sys.executable, "-m", "pip", "list", "--outdated"], + [*python_binary, "list", "--outdated"], cwd=None, runas=None, ) @@ -1554,7 +1517,7 @@ def test_list_upgrades_legacy(): } -def test_list_upgrades_gt9(): +def test_list_upgrades_gt9(python_binary): eggs = """[{"latest_filetype": "wheel", "version": "1.1.0", "name": "apache-libcloud", "latest_version": "2.2.1"}, {"latest_filetype": "wheel", "version": "1.4.1", "name": "appdirs", "latest_version": "1.4.3"}, {"latest_filetype": "sdist", "version": "1.11.63", "name": "awscli", "latest_version": "1.12.1"} @@ -1565,9 +1528,7 @@ def test_list_upgrades_gt9(): ret = pip.list_upgrades() mock.assert_called_with( [ - sys.executable, - "-m", - "pip", + *python_binary, "list", "--outdated", "--format=json", @@ -1582,7 +1543,7 @@ def test_list_upgrades_gt9(): } -def test_is_installed_true(): +def test_is_installed_true(python_binary): eggs = [ "M2Crypto==0.21.1", "-e git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8#egg=SaltTesting-dev", @@ -1595,7 +1556,7 @@ def test_is_installed_true(): with patch("salt.modules.pip.version", MagicMock(return_value="6.1.1")): ret = pip.is_installed(pkgname="bbfreeze") mock.assert_called_with( - [sys.executable, "-m", "pip", "freeze"], + [*python_binary, "freeze"], cwd=None, runas=None, python_shell=False, @@ -1604,7 +1565,7 @@ def test_is_installed_true(): assert ret -def test_is_installed_false(): +def test_is_installed_false(python_binary): eggs = [ "M2Crypto==0.21.1", "-e git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8#egg=SaltTesting-dev", @@ -1617,7 +1578,7 @@ def test_is_installed_false(): with patch("salt.modules.pip.version", MagicMock(return_value="6.1.1")): ret = pip.is_installed(pkgname="notexist") mock.assert_called_with( - [sys.executable, "-m", "pip", "freeze"], + [*python_binary, "freeze"], cwd=None, runas=None, python_shell=False, @@ -1626,7 +1587,7 @@ def test_is_installed_false(): assert not ret -def test_install_pre_argument_in_resulting_command(): +def test_install_pre_argument_in_resulting_command(python_binary): pkg = "pep8" # Lower than 1.4 versions don't end up with `--pre` in the resulting output mock = MagicMock( @@ -1638,7 +1599,7 @@ def test_install_pre_argument_in_resulting_command(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): with patch("salt.modules.pip.version", MagicMock(return_value="1.3")): pip.install(pkg, pre_releases=True) - expected = [sys.executable, "-m", "pip", "install", pkg] + expected = [*python_binary, "install", pkg] mock.assert_called_with( expected, saltenv="base", @@ -1777,7 +1738,7 @@ def test_when_version_is_called_with_a_user_it_should_be_passed_to_undelying_run ) -def test_install_target_from_VENV_PIP_TARGET_in_resulting_command(): +def test_install_target_from_VENV_PIP_TARGET_in_resulting_command(python_binary): pkg = "pep8" target = "/tmp/foo" target_env = "/tmp/bar" @@ -1788,7 +1749,7 @@ def test_install_target_from_VENV_PIP_TARGET_in_resulting_command(): os, "environ", environment ): pip.install(pkg) - expected = [sys.executable, "-m", "pip", "install", "--target", target_env, pkg] + expected = [*python_binary, "install", "--target", target_env, pkg] mock.assert_called_with( expected, saltenv="base", @@ -1798,7 +1759,7 @@ def test_install_target_from_VENV_PIP_TARGET_in_resulting_command(): ) mock.reset_mock() pip.install(pkg, target=target) - expected = [sys.executable, "-m", "pip", "install", "--target", target, pkg] + expected = [*python_binary, "install", "--target", target, pkg] mock.assert_called_with( expected, saltenv="base", @@ -1808,7 +1769,7 @@ def test_install_target_from_VENV_PIP_TARGET_in_resulting_command(): ) -def test_list(): +def test_list(python_binary): json_out = dedent( """ [ @@ -1853,7 +1814,7 @@ def test_list(): with patch.dict(pip.__salt__, {"cmd.run_all": mock}): with patch("salt.modules.pip.version", MagicMock(return_value=mock_version)): ret = pip.list_() - expected = [sys.executable, "-m", "pip", "list", "--format=json"] + expected = [*python_binary, "list", "--format=json"] mock.assert_called_with( expected, cwd=None, diff --git a/tests/pytests/unit/modules/test_status.py b/tests/pytests/unit/modules/test_status.py index 9b3bcb82bef..e0bb270df66 100644 --- a/tests/pytests/unit/modules/test_status.py +++ b/tests/pytests/unit/modules/test_status.py @@ -1,8 +1,16 @@ +""" + Test cases for salt.modules.status +""" + + +import os + import pytest import salt.modules.status as status +import salt.utils.platform from salt.exceptions import CommandExecutionError -from tests.support.mock import MagicMock, Mock, patch +from tests.support.mock import MagicMock, Mock, mock_open, patch @pytest.fixture @@ -73,3 +81,402 @@ def test_custom(): with patch.dict(status.__salt__, {"config.dot_vals": mock2}): with patch.dict(status.__salt__, {"status.uptime": mock}): assert status.custom() == {"day": "UNKNOWN"} + + +def _set_up_test_uptime(): + """ + Define common mock data for status.uptime tests + """ + + class MockData: + """ + Store mock data + """ + + m = MockData() + m.now = 1477004312 + m.ut = 1540154.00 + m.idle = 3047777.32 + m.ret = { + "users": 3, + "seconds": 1540154, + "since_t": 1475464158, + "days": 17, + "since_iso": "2016-10-03T03:09:18", + "time": "19:49", + } + + return m + + +def _set_up_test_uptime_sunos(): + """ + Define common mock data for cmd.run_all for status.uptime on SunOS + """ + + class MockData: + """ + Store mock data + """ + + m = MockData() + m.ret = { + "retcode": 0, + "stdout": "unix:0:system_misc:boot_time 1475464158", + } + + return m + + +def test_uptime_linux(): + """ + Test modules.status.uptime function for Linux + """ + m = _set_up_test_uptime() + + with patch.multiple( + salt.utils.platform, + is_linux=MagicMock(return_value=True), + is_sunos=MagicMock(return_value=False), + is_darwin=MagicMock(return_value=False), + is_freebsd=MagicMock(return_value=False), + is_openbsd=MagicMock(return_value=False), + is_netbsd=MagicMock(return_value=False), + ), patch("salt.utils.path.which", MagicMock(return_value=True)), patch.dict( + status.__salt__, + {"cmd.run": MagicMock(return_value=os.linesep.join(["1", "2", "3"]))}, + ), patch( + "time.time", MagicMock(return_value=m.now) + ), patch( + "os.path.exists", MagicMock(return_value=True) + ): + proc_uptime = salt.utils.stringutils.to_str("{} {}".format(m.ut, m.idle)) + + with patch("salt.utils.files.fopen", mock_open(read_data=proc_uptime)): + ret = status.uptime() + assert ret == m.ret + with patch("os.path.exists", MagicMock(return_value=False)): + with pytest.raises(CommandExecutionError): + status.uptime() + + +def test_uptime_sunos(): + """ + Test modules.status.uptime function for SunOS + """ + m = _set_up_test_uptime() + m2 = _set_up_test_uptime_sunos() + with patch.multiple( + salt.utils.platform, + is_linux=MagicMock(return_value=False), + is_sunos=MagicMock(return_value=True), + is_darwin=MagicMock(return_value=False), + is_freebsd=MagicMock(return_value=False), + is_openbsd=MagicMock(return_value=False), + is_netbsd=MagicMock(return_value=False), + ), patch("salt.utils.path.which", MagicMock(return_value=True)), patch.dict( + status.__salt__, + { + "cmd.run": MagicMock(return_value=os.linesep.join(["1", "2", "3"])), + "cmd.run_all": MagicMock(return_value=m2.ret), + }, + ), patch( + "time.time", MagicMock(return_value=m.now) + ): + ret = status.uptime() + assert ret == m.ret + + +def test_uptime_macos(): + """ + Test modules.status.uptime function for macOS + """ + m = _set_up_test_uptime() + + kern_boottime = ( + "{{ sec = {0}, usec = {1:0<6} }} Mon Oct 03 03:09:18.23 2016".format( + *str(m.now - m.ut).split(".") + ) + ) + with patch.multiple( + salt.utils.platform, + is_linux=MagicMock(return_value=False), + is_sunos=MagicMock(return_value=False), + is_darwin=MagicMock(return_value=True), + is_freebsd=MagicMock(return_value=False), + is_openbsd=MagicMock(return_value=False), + is_netbsd=MagicMock(return_value=False), + ), patch("salt.utils.path.which", MagicMock(return_value=True)), patch.dict( + status.__salt__, + { + "cmd.run": MagicMock(return_value=os.linesep.join(["1", "2", "3"])), + "sysctl.get": MagicMock(return_value=kern_boottime), + }, + ), patch( + "time.time", MagicMock(return_value=m.now) + ): + + ret = status.uptime() + assert ret == m.ret + + with patch.dict(status.__salt__, {"sysctl.get": MagicMock(return_value="")}): + with pytest.raises(CommandExecutionError): + status.uptime() + + +def test_uptime_return_success_not_supported(): + """ + Test modules.status.uptime function for other platforms + """ + with patch.multiple( + salt.utils.platform, + is_linux=MagicMock(return_value=False), + is_sunos=MagicMock(return_value=False), + is_darwin=MagicMock(return_value=False), + is_freebsd=MagicMock(return_value=False), + is_openbsd=MagicMock(return_value=False), + is_netbsd=MagicMock(return_value=False), + ): + exc_mock = MagicMock(side_effect=CommandExecutionError) + with pytest.raises(CommandExecutionError): + with patch.dict(status.__salt__, {"cmd.run": exc_mock}): + status.uptime() + + +def _set_up_test_cpustats_openbsd(): + """ + Define mock data for status.cpustats on OpenBSD + """ + + class MockData: + """ + Store mock data + """ + + m = MockData() + m.ret = { + "0": { + "User": "0.0%", + "Nice": "0.0%", + "System": "4.5%", + "Interrupt": "0.5%", + "Idle": "95.0%", + } + } + + return m + + +def test_cpustats_openbsd(): + """ + Test modules.status.cpustats function for OpenBSD + """ + m = _set_up_test_cpustats_openbsd() + + systat = ( + "\n\n 1 users Load 0.20 0.07 0.05 salt.localdomain" + " 09:42:42\nCPU User Nice System " + " Interrupt Idle\n0 0.0% 0.0% " + " 4.5% 0.5% 95.0%\n" + ) + + with patch.multiple( + salt.utils.platform, + is_linux=MagicMock(return_value=False), + is_sunos=MagicMock(return_value=False), + is_darwin=MagicMock(return_value=False), + is_freebsd=MagicMock(return_value=False), + is_openbsd=MagicMock(return_value=True), + is_netbsd=MagicMock(return_value=False), + ), patch("salt.utils.path.which", MagicMock(return_value=True)), patch.dict( + status.__grains__, {"kernel": "OpenBSD"} + ), patch.dict( + status.__salt__, {"cmd.run": MagicMock(return_value=systat)} + ): + ret = status.cpustats() + assert ret == m.ret + + +def _set_up_test_cpuinfo_bsd(): + class MockData: + """ + Store mock data + """ + + m = MockData() + m.ret = { + "hw.model": "Intel(R) Core(TM) i5-7287U CPU @ 3.30GHz", + "hw.ncpu": "4", + } + + return m + + +def test_cpuinfo_freebsd(): + m = _set_up_test_cpuinfo_bsd() + sysctl = "hw.model:Intel(R) Core(TM) i5-7287U CPU @ 3.30GHz\nhw.ncpu:4" + + with patch.dict(status.__grains__, {"kernel": "FreeBSD"}): + with patch.dict(status.__salt__, {"cmd.run": MagicMock(return_value=sysctl)}): + ret = status.cpuinfo() + assert ret == m.ret + + +def test_cpuinfo_openbsd(): + m = _set_up_test_cpuinfo_bsd() + sysctl = "hw.model=Intel(R) Core(TM) i5-7287U CPU @ 3.30GHz\nhw.ncpu=4" + + for bsd in ["NetBSD", "OpenBSD"]: + with patch.dict(status.__grains__, {"kernel": bsd}): + with patch.dict( + status.__salt__, {"cmd.run": MagicMock(return_value=sysctl)} + ): + ret = status.cpuinfo() + assert ret == m.ret + + +def _set_up_test_meminfo_openbsd(): + class MockData: + """ + Store mock data + """ + + m = MockData() + m.ret = { + "active virtual pages": "355M", + "free list size": "305M", + "page faults": "845", + "pages reclaimed": "1", + "pages paged in": "2", + "pages paged out": "3", + "pages freed": "4", + "pages scanned": "5", + } + + return m + + +def test_meminfo_openbsd(): + m = _set_up_test_meminfo_openbsd() + vmstat = ( + " procs memory page disks traps " + " cpu\n r s avm fre flt re pi po fr sr cd0 sd0 int sys " + " cs us sy id\n 2 103 355M 305M 845 1 2 3 4 5 0 1 21 " + " 682 86 1 1 98" + ) + + with patch.dict(status.__grains__, {"kernel": "OpenBSD"}): + with patch.dict(status.__salt__, {"cmd.run": MagicMock(return_value=vmstat)}): + ret = status.meminfo() + assert ret == m.ret + + +def _set_up_test_w_linux(): + """ + Define mock data for status.w on Linux + """ + + class MockData: + """ + Store mock data + """ + + m = MockData() + m.ret = [ + { + "idle": "0s", + "jcpu": "0.24s", + "login": "13:42", + "pcpu": "0.16s", + "tty": "pts/1", + "user": "root", + "what": "nmap -sV 10.2.2.2", + } + ] + + return m + + +def _set_up_test_w_bsd(): + """ + Define mock data for status.w on Linux + """ + + class MockData: + """ + Store mock data + """ + + m = MockData() + m.ret = [ + { + "idle": "0", + "from": "10.2.2.1", + "login": "1:42PM", + "tty": "p1", + "user": "root", + "what": "nmap -sV 10.2.2.2", + } + ] + + return m + + +def test_w_linux(): + m = _set_up_test_w_linux() + w_output = "root pts/1 13:42 0s 0.24s 0.16s nmap -sV 10.2.2.2" + + with patch.dict(status.__grains__, {"kernel": "Linux"}): + with patch.dict(status.__salt__, {"cmd.run": MagicMock(return_value=w_output)}): + ret = status.w() + assert ret == m.ret + + +def test_w_bsd(): + m = _set_up_test_w_bsd() + w_output = "root p1 10.2.2.1 1:42PM 0 nmap -sV 10.2.2.2" + + for bsd in ["Darwin", "FreeBSD", "OpenBSD"]: + with patch.dict(status.__grains__, {"kernel": bsd}): + with patch.dict( + status.__salt__, {"cmd.run": MagicMock(return_value=w_output)} + ): + ret = status.w() + assert ret == m.ret + + +def _set_up_test_status_pid_linux(): + class MockData: + """ + Store mock data + """ + + m = MockData() + m.ret = "2701\n7539\n7540\n7542\n7623" + return m + + +def test_status_pid_linux(): + m = _set_up_test_status_pid_linux() + ps = ( + "UID PID PPID C STIME TTY TIME CMD\nroot 360 2 0 Jun08 ?" + " 00:00:00 [jbd2/dm-0-8]\nroot 947 2 0 Jun08 ? 00:00:00 " + " [jbd2/dm-1-8]\nroot 949 2 0 Jun08 ? 00:00:09 " + " [jbd2/dm-3-8]\nroot 951 2 0 Jun08 ? 00:00:00 " + " [jbd2/dm-4-8]\nroot 2701 1 0 Jun08 ? 00:00:28 /usr/sbin/httpd" + " -k start\napache 7539 2701 0 04:40 ? 00:00:04 /usr/sbin/httpd -k" + " start\napache 7540 2701 0 04:40 ? 00:00:02 /usr/sbin/httpd -k" + " start\napache 7542 2701 0 04:40 ? 00:01:46 /usr/sbin/httpd -k" + " start\napache 7623 2701 0 04:40 ? 00:02:41 /usr/sbin/httpd -k" + " start\nroot 1564 1 0 Jun11 ? 00:07:19 /usr/bin/python3" + " /usr/bin/salt-minion -d\nroot 6674 1564 0 19:53 ? 00:00:00 " + " /usr/bin/python3 /usr/bin/salt-call status.pid httpd -l debug" + ) + + with patch.dict(status.__grains__, {"ps": "ps -efHww"}): + with patch.dict( + status.__salt__, {"cmd.run_stdout": MagicMock(return_value=ps)} + ): + with patch.object(os, "getpid", return_value="6674"): + ret = status.pid("httpd") + assert ret == m.ret diff --git a/tests/pytests/unit/modules/test_win_iis.py b/tests/pytests/unit/modules/test_win_iis.py new file mode 100644 index 00000000000..f5e37724d24 --- /dev/null +++ b/tests/pytests/unit/modules/test_win_iis.py @@ -0,0 +1,928 @@ +""" + Test cases for salt.modules.win_iis +""" + + +import pytest + +import salt.modules.win_iis as win_iis +import salt.utils.json +from salt.exceptions import SaltInvocationError +from tests.support.mock import MagicMock, call, patch + + +@pytest.fixture +def configure_loader_modules(): + return {win_iis: {}} + + +@pytest.fixture +def app_list(): + return { + "testApp": { + "apppool": "MyTestPool", + "path": "/testApp", + "preload": False, + "protocols": ["http"], + "sourcepath": r"C:\inetpub\apps\testApp", + } + } + + +@pytest.fixture +def apppol_list(): + return {"MyTestPool": {"applications": ["MyTestSite"], "state": "Started"}} + + +@pytest.fixture +def binding_list(): + return { + "*:80:": { + "certificatehash": None, + "certificatestorename": None, + "hostheader": None, + "ipaddress": "*", + "port": 80, + "protocol": "http", + "sslflags": 0, + }, + "*:443:mytestsite.local": { + "certificatehash": "9988776655443322111000AAABBBCCCDDDEEEFFF", + "certificatestorename": "My", + "hostheader": "mytestsite.local", + "ipaddress": "*", + "port": 443, + "protocol": "https", + "sslflags": 0, + }, + } + + +@pytest.fixture +def site_list(binding_list): + return { + "MyTestSite": { + "apppool": "MyTestPool", + "bindings": binding_list, + "id": 1, + "sourcepath": r"C:\inetpub\wwwroot", + "state": "Started", + } + } + + +@pytest.fixture +def vdir_list(): + return {"TestVdir": {"sourcepath": r"C:\inetpub\vdirs\TestVdir"}} + + +@pytest.fixture +def nested_vdir_list(): + return {"Test/Nested/Vdir": {"sourcepath": r"C:\inetpub\vdirs\NestedTestVdir"}} + + +@pytest.fixture +def list_apps_srvmgr(): + return { + "retcode": 0, + "stdout": salt.utils.json.dumps( + [ + { + "applicationPool": "MyTestPool", + "name": "testApp", + "path": "/testApp", + "PhysicalPath": r"C:\inetpub\apps\testApp", + "preloadEnabled": False, + "protocols": "http", + } + ] + ), + } + + +@pytest.fixture +def list_apppools_srvmgr(): + return { + "retcode": 0, + "stdout": salt.utils.json.dumps( + [ + { + "name": "MyTestPool", + "state": "Started", + "Applications": {"value": ["MyTestSite"], "Count": 1}, + } + ] + ), + } + + +@pytest.fixture +def list_vdirs_srvmgr(): + return { + "retcode": 0, + "stdout": salt.utils.json.dumps( + [{"name": "TestVdir", "physicalPath": r"C:\inetpub\vdirs\TestVdir"}] + ), + } + + +@pytest.fixture +def list_more_vdirs_srvmgr(): + return { + "retcode": 0, + "stdout": salt.utils.json.dumps( + [ + {"name": "TestVdir", "physicalPath": r"C:\inetpub\vdirs\TestVdir"}, + { + "name": "Test/Nested/Vdir", + "physicalPath": r"C:\inetpub\vdirs\NestedTestVdir", + }, + ] + ), + } + + +@pytest.fixture +def container_setting(): + return { + "retcode": 0, + "stdout": salt.utils.json.dumps([{"managedPipelineMode": "Integrated"}]), + } + + +@pytest.fixture +def cert_binding_info(): + return "*:443:mytestsite.local" + + +def test_create_apppool(): + """ + Test - Create an IIS application pool. + """ + with patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ), patch( + "salt.modules.win_iis.list_apppools", MagicMock(return_value=dict()) + ), patch.dict( + win_iis.__salt__ + ): + assert win_iis.create_apppool("MyTestPool") + + +def test_list_apppools(apppol_list, list_apppools_srvmgr): + """ + Test - List all configured IIS application pools. + """ + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value=list_apppools_srvmgr) + ): + assert win_iis.list_apppools() == apppol_list + + +def test_remove_apppool(): + """ + Test - Remove an IIS application pool. + """ + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ), patch( + "salt.modules.win_iis.list_apppools", + MagicMock( + return_value={"MyTestPool": {"applications": list(), "state": "Started"}} + ), + ): + assert win_iis.remove_apppool("MyTestPool") + + +def test_restart_apppool(): + """ + Test - Restart an IIS application pool. + """ + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ): + assert win_iis.restart_apppool("MyTestPool") + + +def test_create_site(): + """ + Test - Create a basic website in IIS. + """ + kwargs = { + "name": "MyTestSite", + "sourcepath": r"C:\inetpub\wwwroot", + "apppool": "MyTestPool", + "hostheader": "mytestsite.local", + "ipaddress": "*", + "port": 80, + "protocol": "http", + } + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ), patch("salt.modules.win_iis.list_sites", MagicMock(return_value=dict())), patch( + "salt.modules.win_iis.list_apppools", MagicMock(return_value=dict()) + ): + assert win_iis.create_site(**kwargs) + + +def test_create_site_failed(): + """ + Test - Create a basic website in IIS using invalid data. + """ + kwargs = { + "name": "MyTestSite", + "sourcepath": r"C:\inetpub\wwwroot", + "apppool": "MyTestPool", + "hostheader": "mytestsite.local", + "ipaddress": "*", + "port": 80, + "protocol": "invalid-protocol-name", + } + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ), patch("salt.modules.win_iis.list_sites", MagicMock(return_value=dict())), patch( + "salt.modules.win_iis.list_apppools", MagicMock(return_value=dict()) + ): + pytest.raises(SaltInvocationError, win_iis.create_site, **kwargs) + + +def test_remove_site(site_list): + """ + Test - Delete a website from IIS. + """ + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ), patch("salt.modules.win_iis.list_sites", MagicMock(return_value=site_list)): + assert win_iis.remove_site("MyTestSite") + + +def test_create_app(app_list): + """ + Test - Create an IIS application. + """ + kwargs = { + "name": "testApp", + "site": "MyTestSite", + "sourcepath": r"C:\inetpub\apps\testApp", + "apppool": "MyTestPool", + } + with patch.dict(win_iis.__salt__), patch( + "os.path.isdir", MagicMock(return_value=True) + ), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ), patch( + "salt.modules.win_iis.list_apps", MagicMock(return_value=app_list) + ): + assert win_iis.create_app(**kwargs) + + +def test_list_apps(app_list, list_apps_srvmgr): + """ + Test - Get all configured IIS applications for the specified site. + """ + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value=list_apps_srvmgr) + ): + assert win_iis.list_apps("MyTestSite") == app_list + + +def test_remove_app(app_list): + """ + Test - Remove an IIS application. + """ + kwargs = {"name": "otherApp", "site": "MyTestSite"} + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ), patch("salt.modules.win_iis.list_apps", MagicMock(return_value=app_list)): + assert win_iis.remove_app(**kwargs) + + +def test_create_binding(binding_list): + """ + Test - Create an IIS binding. + """ + kwargs = { + "site": "MyTestSite", + "hostheader": "", + "ipaddress": "*", + "port": 80, + "protocol": "http", + "sslflags": 0, + } + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ), patch( + "salt.modules.win_iis.list_bindings", MagicMock(return_value=binding_list) + ): + assert win_iis.create_binding(**kwargs) + + +def test_create_binding_failed(binding_list): + """ + Test - Create an IIS binding using invalid data. + """ + kwargs = { + "site": "MyTestSite", + "hostheader": "", + "ipaddress": "*", + "port": 80, + "protocol": "invalid-protocol-name", + "sslflags": 999, + } + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ), patch( + "salt.modules.win_iis.list_bindings", MagicMock(return_value=binding_list) + ): + pytest.raises(SaltInvocationError, win_iis.create_binding, **kwargs) + + +def test_list_bindings(binding_list, site_list): + """ + Test - Get all configured IIS bindings for the specified site. + """ + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis.list_sites", MagicMock(return_value=site_list) + ): + assert win_iis.list_bindings("MyTestSite") == binding_list + + +def test_remove_binding(binding_list): + """ + Test - Remove an IIS binding. + """ + kwargs = { + "site": "MyTestSite", + "hostheader": "myothertestsite.local", + "ipaddress": "*", + "port": 443, + } + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ), patch( + "salt.modules.win_iis.list_bindings", MagicMock(return_value=binding_list) + ): + assert win_iis.remove_binding(**kwargs) + + +def test_create_vdir(vdir_list): + """ + Test - Create an IIS virtual directory. + """ + kwargs = { + "name": "TestVdir", + "site": "MyTestSite", + "sourcepath": r"C:\inetpub\vdirs\TestVdir", + } + with patch.dict(win_iis.__salt__), patch( + "os.path.isdir", MagicMock(return_value=True) + ), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ), patch( + "salt.modules.win_iis.list_vdirs", MagicMock(return_value=vdir_list) + ): + assert win_iis.create_vdir(**kwargs) + + +def test_list_vdirs(list_vdirs_srvmgr): + """ + Test - Get configured IIS virtual directories. + """ + vdirs = {"TestVdir": {"sourcepath": r"C:\inetpub\vdirs\TestVdir"}} + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value=list_vdirs_srvmgr) + ): + assert win_iis.list_vdirs("MyTestSite") == vdirs + + +def test_remove_vdir(vdir_list): + """ + Test - Remove an IIS virtual directory. + """ + kwargs = {"name": "TestOtherVdir", "site": "MyTestSite"} + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ), patch("salt.modules.win_iis.list_vdirs", MagicMock(return_value=vdir_list)): + assert win_iis.remove_vdir(**kwargs) + + +def test_create_nested_vdir(nested_vdir_list): + """ + Test - Create a nested IIS virtual directory. + """ + kwargs = { + "name": "Test/Nested/Vdir", + "site": "MyTestSite", + "sourcepath": r"C:\inetpub\vdirs\NestedTestVdir", + } + with patch.dict(win_iis.__salt__), patch( + "os.path.isdir", MagicMock(return_value=True) + ), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ), patch( + "salt.modules.win_iis.list_vdirs", MagicMock(return_value=nested_vdir_list) + ): + assert win_iis.create_vdir(**kwargs) + + +def test_list_nested_vdirs(list_more_vdirs_srvmgr): + """ + Test - Get configured IIS virtual directories. + """ + vdirs = { + "TestVdir": {"sourcepath": r"C:\inetpub\vdirs\TestVdir"}, + "Test/Nested/Vdir": {"sourcepath": r"C:\inetpub\vdirs\NestedTestVdir"}, + } + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", + MagicMock(return_value=list_more_vdirs_srvmgr), + ): + assert win_iis.list_vdirs("MyTestSite") == vdirs + + +def test_create_cert_binding(binding_list, cert_binding_info): + """ + Test - Assign a certificate to an IIS binding. + """ + kwargs = { + "name": "9988776655443322111000AAABBBCCCDDDEEEFFF", + "site": "MyTestSite", + "hostheader": "mytestsite.local", + "ipaddress": "*", + "port": 443, + } + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._list_certs", + MagicMock(return_value={"9988776655443322111000AAABBBCCCDDDEEEFFF": None}), + ), patch( + "salt.modules.win_iis._srvmgr", + MagicMock(return_value={"retcode": 0, "stdout": 10}), + ), patch( + "salt.utils.json.loads", + MagicMock(return_value=[{"MajorVersion": 10, "MinorVersion": 0}]), + ), patch( + "salt.modules.win_iis.list_bindings", MagicMock(return_value=binding_list) + ), patch( + "salt.modules.win_iis.list_cert_bindings", + MagicMock(return_value={cert_binding_info: binding_list[cert_binding_info]}), + ): + assert win_iis.create_cert_binding(**kwargs) + + +def test_list_cert_bindings(binding_list, site_list): + """ + Test - List certificate bindings for an IIS site. + """ + key = "*:443:mytestsite.local" + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis.list_sites", MagicMock(return_value=site_list) + ): + assert win_iis.list_cert_bindings("MyTestSite") == {key: binding_list[key]} + + +def test_remove_cert_binding(binding_list, cert_binding_info): + """ + Test - Remove a certificate from an IIS binding. + """ + kwargs = { + "name": "FFFEEEDDDCCCBBBAAA0001112233445566778899", + "site": "MyOtherTestSite", + "hostheader": "myothertestsite.local", + "ipaddress": "*", + "port": 443, + } + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ), patch( + "salt.modules.win_iis.list_cert_bindings", + MagicMock(return_value={cert_binding_info: binding_list[cert_binding_info]}), + ): + assert win_iis.remove_cert_binding(**kwargs) + + +def test_get_container_setting(container_setting): + """ + Test - Get the value of the setting for the IIS container. + """ + kwargs = { + "name": "MyTestSite", + "container": "AppPools", + "settings": ["managedPipelineMode"], + } + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value=container_setting) + ): + assert win_iis.get_container_setting(**kwargs) == { + "managedPipelineMode": "Integrated" + } + + +def test_set_container_setting(): + """ + Test - Set the value of the setting for an IIS container. + """ + kwargs = { + "name": "MyTestSite", + "container": "AppPools", + "settings": {"managedPipelineMode": "Integrated"}, + } + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) + ), patch( + "salt.modules.win_iis.get_container_setting", + MagicMock(return_value={"managedPipelineMode": "Integrated"}), + ): + assert win_iis.set_container_setting(**kwargs) + + +def test__collection_match_to_index(): + bad_match = {"key_0": "value"} + first_match = {"key_1": "value"} + second_match = {"key_2": "value"} + collection = [first_match, second_match] + settings = [{"name": "enabled", "value": collection}] + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis.get_webconfiguration_settings", + MagicMock(return_value=settings), + ): + ret = win_iis._collection_match_to_index( + "pspath", "colfilter", "name", bad_match + ) + assert ret == -1 + ret = win_iis._collection_match_to_index( + "pspath", "colfilter", "name", first_match + ) + assert ret == 0 + ret = win_iis._collection_match_to_index( + "pspath", "colfilter", "name", second_match + ) + assert ret == 1 + + +def test__prepare_settings(): + simple_setting = {"name": "value", "filter": "value"} + collection_setting = {"name": "Collection[{yaml:\n\tdata}]", "filter": "value"} + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._collection_match_to_index", MagicMock(return_value=0) + ): + ret = win_iis._prepare_settings( + "pspath", + [ + simple_setting, + collection_setting, + {"invalid": "setting"}, + {"name": "filter-less_setting"}, + ], + ) + assert ret == [simple_setting, collection_setting] + + +@patch("salt.modules.win_iis.log") +def test_get_webconfiguration_settings_empty(mock_log): + ret = win_iis.get_webconfiguration_settings("name", settings=[]) + mock_log.warning.assert_called_once_with("No settings provided") + assert ret == {} + + +def test_get_webconfiguration_settings(): + # Setup + name = "IIS" + collection_setting = {"name": "Collection[{yaml:\n\tdata}]", "filter": "value"} + filter_setting = { + "name": "enabled", + "filter": ( + "system.webServer / security / authentication / anonymousAuthentication" + ), + } + settings = [collection_setting, filter_setting] + + ps_cmd = [ + "$Settings = New-Object System.Collections.ArrayList;", + ] + for setting in settings: + ps_cmd.extend( + [ + "$Property = Get-WebConfigurationProperty -PSPath '{}'".format(name), + "-Name '{name}' -Filter '{filter}' -ErrorAction Stop;".format( + filter=setting["filter"], name=setting["name"] + ), + "if (([String]::IsNullOrEmpty($Property) -eq $False) -and", + "($Property.GetType()).Name -eq 'ConfigurationAttribute') {", + "$Property = $Property | Select-Object", + "-ExpandProperty Value };", + "$Settings.add(@{{filter='{filter}';name='{name}';value=[String]" + " $Property}})| Out-Null;".format( + filter=setting["filter"], name=setting["name"] + ), + "$Property = $Null;", + ] + ) + ps_cmd.append("$Settings") + + # Execute + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._prepare_settings", MagicMock(return_value=settings) + ), patch( + "salt.modules.win_iis._srvmgr", + MagicMock(return_value={"retcode": 0, "stdout": "{}"}), + ): + ret = win_iis.get_webconfiguration_settings(name, settings=settings) + + # Verify + win_iis._srvmgr.assert_called_with(cmd=ps_cmd, return_json=True) + assert ret == {} + + +@patch("salt.modules.win_iis.log") +def test_set_webconfiguration_settings_empty(mock_log): + ret = win_iis.set_webconfiguration_settings("name", settings=[]) + mock_log.warning.assert_called_once_with("No settings provided") + assert ret is False + + +@patch("salt.modules.win_iis.log") +def test_set_webconfiguration_settings_no_changes(mock_log): + # Setup + name = "IIS" + setting = { + "name": "Collection[{yaml:\n\tdata}]", + "filter": ( + "system.webServer / security / authentication / anonymousAuthentication" + ), + "value": [], + } + settings = [setting] + + # Execute + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._prepare_settings", MagicMock(return_value=settings) + ), patch( + "salt.modules.win_iis._srvmgr", + MagicMock(return_value={"retcode": 0, "stdout": "{}"}), + ), patch( + "salt.modules.win_iis.get_webconfiguration_settings", + MagicMock(return_value=settings), + ): + ret = win_iis.set_webconfiguration_settings(name, settings=settings) + + # Verify + mock_log.debug.assert_called_with( + "Settings already contain the provided values." + ) + assert ret is True + + +@patch("salt.modules.win_iis.log") +def test_set_webconfiguration_settings_failed(mock_log): + # Setup + name = "IIS" + setting = { + "name": "Collection[{yaml:\n\tdata}]", + "filter": ( + "system.webServer / security / authentication / anonymousAuthentication" + ), + "value": [], + } + settings = [setting] + + # Execute + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._prepare_settings", MagicMock(return_value=settings) + ), patch( + "salt.modules.win_iis._srvmgr", + MagicMock(return_value={"retcode": 0, "stdout": "{}"}), + ), patch( + "salt.modules.win_iis.get_webconfiguration_settings", + MagicMock(side_effect=[[], [{"value": "unexpected_change!"}]]), + ): + + ret = win_iis.set_webconfiguration_settings(name, settings=settings) + + # Verify + assert ret is False + mock_log.error.assert_called_with("Failed to change settings: %s", settings) + + +@patch("salt.modules.win_iis.log") +def test_set_webconfiguration_settings(mock_log): + # Setup + name = "IIS" + setting = { + "name": "Collection[{yaml:\n\tdata}]", + "filter": ( + "system.webServer / security / authentication / anonymousAuthentication" + ), + "value": [], + } + settings = [setting] + + # Execute + with patch.dict(win_iis.__salt__), patch( + "salt.modules.win_iis._prepare_settings", MagicMock(return_value=settings) + ), patch( + "salt.modules.win_iis._srvmgr", + MagicMock(return_value={"retcode": 0, "stdout": "{}"}), + ), patch( + "salt.modules.win_iis.get_webconfiguration_settings", + MagicMock(side_effect=[[], settings]), + ): + ret = win_iis.set_webconfiguration_settings(name, settings=settings) + + # Verify + assert ret is True + mock_log.debug.assert_called_with( + "Settings configured successfully: %s", settings + ) + + +def test_get_webconfiguration_settings_no_settings(): + assert win_iis.get_webconfiguration_settings("salt", {}) == {} + + +def test_get_webconfiguration_settings_pass(): + settings = [ + { + "name": "enabled", + "filter": ( + "system.webServer/security/authentication/anonymousAuthentication" + ), + } + ] + + ps_cmd_validate = [ + "Get-WebConfigurationProperty", + "-PSPath", + "'salt'", + "-Filter", + "'system.webServer/security/authentication/anonymousAuthentication'", + "-Name", + "'enabled'", + "-ErrorAction", + "Stop", + "|", + "Out-Null;", + ] + + ps_cmd = [ + "$Settings = New-Object System.Collections.ArrayList;", + "$Property = Get-WebConfigurationProperty -PSPath 'salt'", + "-Name 'enabled' -Filter" + " 'system.webServer/security/authentication/anonymousAuthentication'" + " -ErrorAction Stop;", + "if (([String]::IsNullOrEmpty($Property) -eq $False) -and", + "($Property.GetType()).Name -eq 'ConfigurationAttribute') {", + "$Property = $Property | Select-Object", + "-ExpandProperty Value };", + "$Settings.add(@{filter='system.webServer/security/authentication/anonymousAuthentication';name='enabled';value=[String]" + " $Property})| Out-Null;", + "$Property = $Null;", + "$Settings", + ] + + func_ret = {"name": "enabled", "value": True} + with patch.object( + win_iis, "_srvmgr", return_value={"retcode": 0, "stdout": "json data"} + ) as _srvmgr: + with patch.object( + win_iis.salt.utils.json, "loads", return_value=func_ret + ) as loads: + ret = win_iis.get_webconfiguration_settings("salt", settings) + + assert _srvmgr.call_count == 2 + assert _srvmgr.mock_calls[0] == call(cmd=ps_cmd_validate, return_json=True) + assert _srvmgr.mock_calls[1] == call(cmd=ps_cmd, return_json=True) + + loads.assert_called_once_with("json data", strict=False) + assert func_ret == ret + + +def test_set_webconfiguration_settings_no_settings(): + assert win_iis.set_webconfiguration_settings("salt", {}) is False + + +def test_set_webconfiguration_settings_pass(): + settings = [ + { + "name": "enabled", + "filter": ( + "system.webServer/security/authentication/anonymousAuthentication" + ), + "value": False, + } + ] + + current_settings = [ + { + "name": "enabled", + "filter": ( + "system.webServer/security/authentication/anonymousAuthentication" + ), + "value": True, + } + ] + + new_settings = [ + { + "name": "enabled", + "filter": ( + "system.webServer/security/authentication/anonymousAuthentication" + ), + "value": False, + } + ] + + ps_cmd = [ + "Set-WebConfigurationProperty", + "-PSPath", + "'salt'", + "-Filter", + "'system.webServer/security/authentication/anonymousAuthentication'", + "-Name", + "'enabled'", + "-Value", + "'False';", + ] + + with patch.object( + win_iis, + "get_webconfiguration_settings", + side_effect=[current_settings, new_settings], + ) as get_webconfiguration_settings: + with patch.object(win_iis, "_srvmgr", return_value={"retcode": 0}) as _srvmgr: + ret = win_iis.set_webconfiguration_settings("salt", settings) + + assert get_webconfiguration_settings.call_count == 2 + assert get_webconfiguration_settings.mock_calls[0] == call( + name="salt", settings=settings + ) + assert get_webconfiguration_settings.mock_calls[1] == call( + name="salt", settings=settings + ) + + _srvmgr.assert_called_once_with(ps_cmd) + + assert ret + + +def test_set_webconfiguration_settings_fail(): + settings = [ + { + "name": "enabled", + "filter": ( + "system.webServer/security/authentication/anonymousAuthentication" + ), + "value": False, + } + ] + + current_settings = [ + { + "name": "enabled", + "filter": ( + "system.webServer/security/authentication/anonymousAuthentication" + ), + "value": True, + } + ] + + new_settings = [ + { + "name": "enabled", + "filter": ( + "system.webServer/security/authentication/anonymousAuthentication" + ), + "value": True, + } + ] + + ps_cmd = [ + "Set-WebConfigurationProperty", + "-PSPath", + "'salt'", + "-Filter", + "'system.webServer/security/authentication/anonymousAuthentication'", + "-Name", + "'enabled'", + "-Value", + "'False';", + ] + + with patch.object( + win_iis, + "get_webconfiguration_settings", + side_effect=[current_settings, new_settings], + ) as get_webconfiguration_settings: + with patch.object(win_iis, "_srvmgr", return_value={"retcode": 0}) as _srvmgr: + ret = win_iis.set_webconfiguration_settings("salt", settings) + + assert get_webconfiguration_settings.call_count == 2 + assert get_webconfiguration_settings.mock_calls[0] == call( + name="salt", settings=settings + ) + assert get_webconfiguration_settings.mock_calls[1] == call( + name="salt", settings=settings + ) + + _srvmgr.assert_called_once_with(ps_cmd) + + assert not ret diff --git a/tests/pytests/unit/modules/test_win_ip.py b/tests/pytests/unit/modules/test_win_ip.py new file mode 100644 index 00000000000..38eb6b1ac5f --- /dev/null +++ b/tests/pytests/unit/modules/test_win_ip.py @@ -0,0 +1,396 @@ +""" + :codeauthor: Jayesh Kariya + + Test cases for salt.modules.win_ip +""" + +import pytest + +import salt.modules.win_ip as win_ip +from salt.exceptions import CommandExecutionError, SaltInvocationError +from tests.support.mock import MagicMock, call, patch + + +@pytest.fixture +def configure_loader_modules(): + return {win_ip: {}} + + +@pytest.fixture +def ethernet_config(): + return ( + 'Configuration for interface "Ethernet"\n' + "DHCP enabled: Yes\n" + "IP Address: 1.2.3.74\n" + "Subnet Prefix: 1.2.3.0/24 (mask 255.255.255.0)\n" + "Default Gateway: 1.2.3.1\n" + "Gateway Metric: 0\n" + "InterfaceMetric: 20\n" + "DNS servers configured through DHCP: 1.2.3.4\n" + "Register with which suffix: Primary only\n" + "WINS servers configured through DHCP: None\n" + ) + + +@pytest.fixture +def ethernet_enable(): + return "Ethernet\nType: Dedicated\nAdministrative state: Enabled\nConnect state: Connected" + + +# 'raw_interface_configs' function tests: 1 + + +def test_raw_interface_configs(ethernet_config): + """ + Test if it return raw configs for all interfaces. + """ + mock_cmd = MagicMock(return_value=ethernet_config) + with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): + assert win_ip.raw_interface_configs() == ethernet_config + + +# 'get_all_interfaces' function tests: 1 + + +def test_get_all_interfaces(ethernet_config): + """ + Test if it return configs for all interfaces. + """ + ret = { + "Ethernet": { + "DHCP enabled": "Yes", + "DNS servers configured through DHCP": ["1.2.3.4"], + "Default Gateway": "1.2.3.1", + "Gateway Metric": "0", + "InterfaceMetric": "20", + "Register with which suffix": "Primary only", + "WINS servers configured through DHCP": ["None"], + "ip_addrs": [ + { + "IP Address": "1.2.3.74", + "Netmask": "255.255.255.0", + "Subnet": "1.2.3.0/24", + } + ], + } + } + + mock_cmd = MagicMock(return_value=ethernet_config) + with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): + assert win_ip.get_all_interfaces() == ret + + +# 'get_interface' function tests: 1 + + +def test_get_interface(ethernet_config): + """ + Test if it return the configuration of a network interface. + """ + ret = { + "DHCP enabled": "Yes", + "DNS servers configured through DHCP": ["1.2.3.4"], + "Default Gateway": "1.2.3.1", + "Gateway Metric": "0", + "InterfaceMetric": "20", + "Register with which suffix": "Primary only", + "WINS servers configured through DHCP": ["None"], + "ip_addrs": [ + { + "IP Address": "1.2.3.74", + "Netmask": "255.255.255.0", + "Subnet": "1.2.3.0/24", + } + ], + } + + mock_cmd = MagicMock(return_value=ethernet_config) + with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): + assert win_ip.get_interface("Ethernet") == ret + + +# 'is_enabled' function tests: 1 + + +def test_is_enabled(ethernet_enable): + """ + Test if it returns `True` if interface is enabled, otherwise `False`. + """ + mock_cmd = MagicMock(side_effect=[ethernet_enable, ""]) + with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): + assert win_ip.is_enabled("Ethernet") + pytest.raises(CommandExecutionError, win_ip.is_enabled, "Ethernet") + + +# 'is_disabled' function tests: 1 + + +def test_is_disabled(ethernet_enable): + """ + Test if it returns `True` if interface is disabled, otherwise `False`. + """ + mock_cmd = MagicMock(return_value=ethernet_enable) + with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): + assert not win_ip.is_disabled("Ethernet") + + +# 'enable' function tests: 1 + + +def test_enable(): + """ + Test if it enable an interface. + """ + # Test with enabled interface + with patch.object(win_ip, "is_enabled", return_value=True): + assert win_ip.enable("Ethernet") + + mock_cmd = MagicMock() + with patch.object(win_ip, "is_enabled", side_effect=[False, True]), patch.dict( + win_ip.__salt__, {"cmd.run": mock_cmd} + ): + assert win_ip.enable("Ethernet") + + mock_cmd.called_once_with( + [ + "netsh", + "interface", + "set", + "interface", + "name=Ethernet", + "admin=ENABLED", + ], + python_shell=False, + ) + + +# 'disable' function tests: 1 + + +def test_disable(): + """ + Test if it disable an interface. + """ + with patch.object(win_ip, "is_disabled", return_value=True): + assert win_ip.disable("Ethernet") + + mock_cmd = MagicMock() + with patch.object(win_ip, "is_disabled", side_effect=[False, True]), patch.dict( + win_ip.__salt__, {"cmd.run": mock_cmd} + ): + assert win_ip.disable("Ethernet") + + mock_cmd.called_once_with( + [ + "netsh", + "interface", + "set", + "interface", + "name=Ethernet", + "admin=DISABLED", + ], + python_shell=False, + ) + + +# 'get_subnet_length' function tests: 1 + + +def test_get_subnet_length(): + """ + Test if it disable an interface. + """ + assert win_ip.get_subnet_length("255.255.255.0") == 24 + pytest.raises(SaltInvocationError, win_ip.get_subnet_length, "255.255.0") + + +# 'set_static_ip' function tests: 1 + + +@pytest.mark.slow_test +def test_set_static_ip(ethernet_config): + """ + Test if it set static IP configuration on a Windows NIC. + """ + pytest.raises( + SaltInvocationError, + win_ip.set_static_ip, + "Local Area Connection", + "10.1.2/24", + ) + + mock_cmd = MagicMock(return_value=ethernet_config) + mock_all = MagicMock(return_value={"retcode": 1, "stderr": "Error"}) + with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd, "cmd.run_all": mock_all}): + pytest.raises( + CommandExecutionError, + win_ip.set_static_ip, + "Ethernet", + "1.2.3.74/24", + append=True, + ) + pytest.raises( + CommandExecutionError, win_ip.set_static_ip, "Ethernet", "1.2.3.74/24" + ) + + mock_all = MagicMock(return_value={"retcode": 0}) + with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd, "cmd.run_all": mock_all}): + assert win_ip.set_static_ip("Local Area Connection", "1.2.3.74/24") == {} + assert win_ip.set_static_ip("Ethernet", "1.2.3.74/24") == { + "Address Info": { + "IP Address": "1.2.3.74", + "Netmask": "255.255.255.0", + "Subnet": "1.2.3.0/24", + } + } + + +# 'set_dhcp_ip' function tests: 1 + + +def test_set_dhcp_ip(ethernet_config): + """ + Test if it set Windows NIC to get IP from DHCP. + """ + mock_cmd = MagicMock(return_value=ethernet_config) + with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): + assert win_ip.set_dhcp_ip("Ethernet") == { + "DHCP enabled": "Yes", + "Interface": "Ethernet", + } + + +# 'set_static_dns' function tests: 1 + + +def test_set_static_dns(): + """ + Test if it set static DNS configuration on a Windows NIC. + """ + mock_cmd = MagicMock() + with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): + assert win_ip.set_static_dns("Ethernet", "192.168.1.252", "192.168.1.253") == { + "DNS Server": ("192.168.1.252", "192.168.1.253"), + "Interface": "Ethernet", + } + mock_cmd.assert_has_calls( + [ + call( + [ + "netsh", + "interface", + "ip", + "set", + "dns", + "name=Ethernet", + "source=static", + "address=192.168.1.252", + "register=primary", + ], + python_shell=False, + ), + call( + [ + "netsh", + "interface", + "ip", + "add", + "dns", + "name=Ethernet", + "address=192.168.1.253", + "index=2", + ], + python_shell=False, + ), + ] + ) + + +def test_set_static_dns_clear(): + """ + Test if it set static DNS configuration on a Windows NIC. + """ + mock_cmd = MagicMock() + with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): + assert win_ip.set_static_dns("Ethernet", []) == { + "DNS Server": [], + "Interface": "Ethernet", + } + mock_cmd.assert_called_once_with( + [ + "netsh", + "interface", + "ip", + "set", + "dns", + "name=Ethernet", + "source=static", + "address=none", + ], + python_shell=False, + ) + + +def test_set_static_dns_no_action(): + """ + Test if it set static DNS configuration on a Windows NIC. + """ + # Test passing nothing + assert win_ip.set_static_dns("Ethernet") == { + "DNS Server": "No Changes", + "Interface": "Ethernet", + } + # Test passing None + assert win_ip.set_static_dns("Ethernet", None) == { + "DNS Server": "No Changes", + "Interface": "Ethernet", + } + + # Test passing string None + assert win_ip.set_static_dns("Ethernet", "None") == { + "DNS Server": "No Changes", + "Interface": "Ethernet", + } + + +# 'set_dhcp_dns' function tests: 1 + + +def test_set_dhcp_dns(ethernet_config): + """ + Test if it set DNS source to DHCP on Windows. + """ + mock_cmd = MagicMock(return_value=ethernet_config) + with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): + assert win_ip.set_dhcp_dns("Ethernet") == { + "DNS Server": "DHCP", + "Interface": "Ethernet", + } + + +# 'set_dhcp_all' function tests: 1 + + +def test_set_dhcp_all(ethernet_config): + """ + Test if it set both IP Address and DNS to DHCP. + """ + mock_cmd = MagicMock(return_value=ethernet_config) + with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): + assert win_ip.set_dhcp_all("Ethernet") == { + "Interface": "Ethernet", + "DNS Server": "DHCP", + "DHCP enabled": "Yes", + } + + +# 'get_default_gateway' function tests: 1 + + +def test_get_default_gateway(ethernet_config): + """ + Test if it set DNS source to DHCP on Windows. + """ + mock_cmd = MagicMock(return_value=ethernet_config) + with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): + assert win_ip.get_default_gateway() == "1.2.3.1" diff --git a/tests/pytests/unit/modules/test_win_licence.py b/tests/pytests/unit/modules/test_win_licence.py new file mode 100644 index 00000000000..2948be088f0 --- /dev/null +++ b/tests/pytests/unit/modules/test_win_licence.py @@ -0,0 +1,102 @@ +""" + Test cases for salt.modules.win_licence +""" + + +import pytest + +import salt.modules.win_license as win_license +from tests.support.mock import MagicMock, patch + + +@pytest.fixture +def configure_loader_modules(): + return {win_license: {}} + + +def test_installed(): + """ + Test to see if the given license key is installed + """ + mock = MagicMock(return_value="Partial Product Key: ABCDE") + with patch.dict(win_license.__salt__, {"cmd.run": mock}): + out = win_license.installed("AAAAA-AAAAA-AAAAA-AAAA-AAAAA-ABCDE") + mock.assert_called_once_with(r"cscript C:\Windows\System32\slmgr.vbs /dli") + assert out + + +def test_installed_diff(): + """ + Test to see if the given license key is installed when the key is different + """ + mock = MagicMock(return_value="Partial Product Key: 12345") + with patch.dict(win_license.__salt__, {"cmd.run": mock}): + out = win_license.installed("AAAAA-AAAAA-AAAAA-AAAA-AAAAA-ABCDE") + mock.assert_called_once_with(r"cscript C:\Windows\System32\slmgr.vbs /dli") + assert not out + + +def test_install(): + """ + Test installing the given product key + """ + mock = MagicMock() + with patch.dict(win_license.__salt__, {"cmd.run": mock}): + win_license.install("AAAAA-AAAAA-AAAAA-AAAA-AAAAA-ABCDE") + mock.assert_called_once_with( + r"cscript C:\Windows\System32\slmgr.vbs /ipk " + "AAAAA-AAAAA-AAAAA-AAAA-AAAAA-ABCDE" + ) + + +def test_uninstall(): + """ + Test uninstalling the given product key + """ + mock = MagicMock() + with patch.dict(win_license.__salt__, {"cmd.run": mock}): + win_license.uninstall() + mock.assert_called_once_with(r"cscript C:\Windows\System32\slmgr.vbs /upk") + + +def test_activate(): + """ + Test activating the current product key + """ + mock = MagicMock() + with patch.dict(win_license.__salt__, {"cmd.run": mock}): + win_license.activate() + mock.assert_called_once_with(r"cscript C:\Windows\System32\slmgr.vbs /ato") + + +def test_licensed(): + """ + Test checking if the minion is licensed + """ + mock = MagicMock(return_value="License Status: Licensed") + with patch.dict(win_license.__salt__, {"cmd.run": mock}): + win_license.licensed() + mock.assert_called_once_with(r"cscript C:\Windows\System32\slmgr.vbs /dli") + + +def test_info(): + """ + Test getting the info about the current license key + """ + expected = { + "description": "Prof", + "licensed": True, + "name": "Win7", + "partial_key": "12345", + } + + mock = MagicMock( + return_value=( + "Name: Win7\r\nDescription: Prof\r\nPartial Product Key: 12345\r\n" + "License Status: Licensed" + ) + ) + with patch.dict(win_license.__salt__, {"cmd.run": mock}): + out = win_license.info() + mock.assert_called_once_with(r"cscript C:\Windows\System32\slmgr.vbs /dli") + assert out == expected diff --git a/tests/pytests/unit/modules/test_win_pki.py b/tests/pytests/unit/modules/test_win_pki.py new file mode 100644 index 00000000000..128fb14f820 --- /dev/null +++ b/tests/pytests/unit/modules/test_win_pki.py @@ -0,0 +1,184 @@ +""" + Test cases for salt.modules.win_pki +""" + + +import pytest + +import salt.modules.win_pki as win_pki +from tests.support.mock import MagicMock, patch + + +@pytest.fixture +def configure_loader_modules(): + return {win_pki: {}} + + +@pytest.fixture +def cert_path(): + return r"C:\certs\testdomain.local.cer" + + +@pytest.fixture +def thumbprint(): + return "9988776655443322111000AAABBBCCCDDDEEEFFF" + + +@pytest.fixture +def certs(thumbprint): + return { + thumbprint: { + "dnsnames": ["testdomain.local"], + "serialnumber": "0123456789AABBCCDD", + "subject": "CN=testdomain.local, OU=testou, O=testorg, S=California, C=US", + "thumbprint": thumbprint, + "version": 3, + } + } + + +@pytest.fixture +def stores(): + return { + "CurrentUser": [ + "AuthRoot", + "CA", + "ClientAuthIssuer", + "Disallowed", + "MSIEHistoryJournal", + "My", + "Root", + "SmartCardRoot", + "Trust", + "TrustedPeople", + "TrustedPublisher", + "UserDS", + ], + "LocalMachine": [ + "AuthRoot", + "CA", + "ClientAuthIssuer", + "Disallowed", + "My", + "Remote Desktop", + "Root", + "SmartCardRoot", + "Trust", + "TrustedDevices", + "TrustedPeople", + "TrustedPublisher", + "WebHosting", + ], + } + + +@pytest.fixture +def json_certs(): + return [ + { + "DnsNameList": [ + {"Punycode": "testdomain.local", "Unicode": "testdomain.local"} + ], + "SerialNumber": "0123456789AABBCCDD", + "Subject": "CN=testdomain.local, OU=testou, O=testorg, S=California, C=US", + "Thumbprint": "9988776655443322111000AAABBBCCCDDDEEEFFF", + "Version": 3, + } + ] + + +@pytest.fixture +def json_stores(stores): + return [ + {"LocationName": "CurrentUser", "StoreNames": stores["CurrentUser"]}, + {"LocationName": "LocalMachine", "StoreNames": stores["LocalMachine"]}, + ] + + +def test_get_stores(stores, json_stores): + """ + Test - Get the certificate location contexts and their corresponding stores. + """ + with patch.dict(win_pki.__salt__), patch( + "salt.modules.win_pki._cmd_run", MagicMock(return_value=json_stores) + ): + assert win_pki.get_stores() == stores + + +def test_get_certs(certs, json_certs): + """ + Test - Get the available certificates in the given store. + """ + with patch.dict(win_pki.__salt__), patch( + "salt.modules.win_pki._cmd_run", MagicMock(return_value=json_certs) + ), patch("salt.modules.win_pki._validate_cert_path", MagicMock(return_value=None)): + assert win_pki.get_certs() == certs + + +def test_get_cert_file(cert_path, thumbprint, certs, json_certs): + """ + Test - Get the details of the certificate file. + """ + kwargs = {"name": cert_path} + with patch.dict(win_pki.__salt__), patch( + "os.path.isfile", MagicMock(return_value=True) + ), patch("salt.modules.win_pki._cmd_run", MagicMock(return_value=json_certs)): + assert win_pki.get_cert_file(**kwargs) == certs[thumbprint] + + +def test_import_cert(cert_path, thumbprint, certs, json_certs): + """ + Test - Import the certificate file into the given certificate store. + """ + kwargs = {"name": cert_path} + mock_value = MagicMock(return_value=cert_path) + with patch.dict(win_pki.__salt__, {"cp.cache_file": mock_value}), patch( + "salt.modules.win_pki._cmd_run", MagicMock(return_value=json_certs) + ), patch( + "salt.modules.win_pki._validate_cert_path", MagicMock(return_value=None) + ), patch( + "salt.modules.win_pki.get_cert_file", + MagicMock(return_value=certs[thumbprint]), + ), patch( + "salt.modules.win_pki.get_certs", MagicMock(return_value=certs) + ): + assert win_pki.import_cert(**kwargs) + + +def test_export_cert(cert_path, thumbprint): + """ + Test - Export the certificate to a file from the given certificate store. + """ + kwargs = {"name": cert_path, "thumbprint": thumbprint} + with patch.dict(win_pki.__salt__), patch( + "salt.modules.win_pki._cmd_run", MagicMock(return_value="True") + ), patch( + "salt.modules.win_pki._validate_cert_format", MagicMock(return_value=None) + ), patch( + "salt.modules.win_pki._validate_cert_path", MagicMock(return_value=None) + ): + assert win_pki.export_cert(**kwargs) + + +def test_test_cert(thumbprint): + """ + Test - Check the certificate for validity. + """ + with patch.dict(win_pki.__salt__), patch( + "salt.modules.win_pki._cmd_run", MagicMock(return_value="True") + ), patch("salt.modules.win_pki._validate_cert_path", MagicMock(return_value=None)): + assert win_pki.test_cert(thumbprint=thumbprint) + + +def test_remove_cert(thumbprint, certs): + """ + Test - Remove the certificate from the given certificate store. + """ + with patch.dict(win_pki.__salt__), patch( + "salt.modules.win_pki._cmd_run", MagicMock(return_value=None) + ), patch( + "salt.modules.win_pki._validate_cert_path", MagicMock(return_value=None) + ), patch( + "salt.modules.win_pki.get_certs", MagicMock(return_value=certs) + ): + assert win_pki.remove_cert(thumbprint=thumbprint[::-1]) diff --git a/tests/pytests/unit/modules/test_win_powercfg.py b/tests/pytests/unit/modules/test_win_powercfg.py new file mode 100644 index 00000000000..e1cd9426a4c --- /dev/null +++ b/tests/pytests/unit/modules/test_win_powercfg.py @@ -0,0 +1,284 @@ +""" + Test cases for salt.modules.win_powercfg +""" + + +import pytest + +import salt.modules.win_powercfg as powercfg +from tests.support.mock import MagicMock, call, patch + + +@pytest.fixture +def configure_loader_modules(): + return {powercfg: {"__grains__": {"osrelease": 8}}} + + +@pytest.fixture +def query_output(): + return """Subgroup GUID: 238c9fa8-0aad-41ed-83f4-97be242c8f20 (Hibernate) + GUID Alias: SUB_SLEEP + Power Setting GUID: 29f6c1db-86da-48c5-9fdb-f2b67b1f44da (Hibernate after) + GUID Alias: HIBERNATEIDLE + Minimum Possible Setting: 0x00000000 + Maximum Possible Setting: 0xffffffff + Possible Settings increment: 0x00000001 + Possible Settings units: Seconds + Current AC Power Setting Index: 0x00000708 + Current DC Power Setting Index: 0x00000384""" + + +def test_set_monitor_timeout(query_output): + """ + Test to make sure we can set the monitor timeout value + """ + mock = MagicMock(return_value=0) + mock.side_effect = [ + "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", + query_output, + ] + + mock_retcode = MagicMock(return_value=0) + + with patch.dict(powercfg.__salt__, {"cmd.run": mock}): + with patch.dict(powercfg.__salt__, {"cmd.retcode": mock_retcode}): + powercfg.set_monitor_timeout(0, "dc") + mock.assert_called_once_with( + "powercfg /getactivescheme", python_shell=False + ) + mock_retcode.assert_called_once_with( + "powercfg /setdcvalueindex 381b4222-f694-41f0-9685-ff5bb260df2e" + " SUB_VIDEO VIDEOIDLE 0", + python_shell=False, + ) + + +def test_set_disk_timeout(query_output): + """ + Test to make sure we can set the disk timeout value + """ + mock = MagicMock() + mock.side_effect = [ + "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", + query_output, + ] + + mock_retcode = MagicMock(return_value=0) + + with patch.dict(powercfg.__salt__, {"cmd.run": mock}): + with patch.dict(powercfg.__salt__, {"cmd.retcode": mock_retcode}): + powercfg.set_disk_timeout(0, "dc") + mock.assert_called_once_with( + "powercfg /getactivescheme", python_shell=False + ) + mock_retcode.assert_called_once_with( + "powercfg /setdcvalueindex 381b4222-f694-41f0-9685-ff5bb260df2e" + " SUB_DISK DISKIDLE 0", + python_shell=False, + ) + + +def test_set_standby_timeout(query_output): + """ + Test to make sure we can set the standby timeout value + """ + mock = MagicMock(return_value=0) + mock.side_effect = [ + "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", + query_output, + ] + + mock_retcode = MagicMock(return_value=0) + + with patch.dict(powercfg.__salt__, {"cmd.run": mock}): + with patch.dict(powercfg.__salt__, {"cmd.retcode": mock_retcode}): + powercfg.set_standby_timeout(0, "dc") + mock.assert_called_once_with( + "powercfg /getactivescheme", python_shell=False + ) + mock_retcode.assert_called_once_with( + "powercfg /setdcvalueindex 381b4222-f694-41f0-9685-ff5bb260df2e" + " SUB_SLEEP STANDBYIDLE 0", + python_shell=False, + ) + + +def test_set_hibernate_timeout(query_output): + """ + Test to make sure we can set the hibernate timeout value + """ + mock = MagicMock(return_value=0) + mock.side_effect = [ + "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", + query_output, + ] + + mock_retcode = MagicMock(return_value=0) + + with patch.dict(powercfg.__salt__, {"cmd.run": mock}): + with patch.dict(powercfg.__salt__, {"cmd.retcode": mock_retcode}): + powercfg.set_hibernate_timeout(0, "dc") + mock.assert_called_once_with( + "powercfg /getactivescheme", python_shell=False + ) + mock_retcode.assert_called_once_with( + "powercfg /setdcvalueindex 381b4222-f694-41f0-9685-ff5bb260df2e" + " SUB_SLEEP HIBERNATEIDLE 0", + python_shell=False, + ) + + +def test_get_monitor_timeout(query_output): + """ + Test to make sure we can get the monitor timeout value + """ + mock = MagicMock() + mock.side_effect = [ + "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", + query_output, + ] + + with patch.dict(powercfg.__salt__, {"cmd.run": mock}): + ret = powercfg.get_monitor_timeout() + calls = [ + call("powercfg /getactivescheme", python_shell=False), + call( + "powercfg /q 381b4222-f694-41f0-9685-ff5bb260df2e SUB_VIDEO" + " VIDEOIDLE", + python_shell=False, + ), + ] + mock.assert_has_calls(calls) + + assert {"ac": 30, "dc": 15} == ret + + +def test_get_disk_timeout(query_output): + """ + Test to make sure we can get the disk timeout value + """ + mock = MagicMock() + mock.side_effect = [ + "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", + query_output, + ] + + with patch.dict(powercfg.__salt__, {"cmd.run": mock}): + ret = powercfg.get_disk_timeout() + calls = [ + call("powercfg /getactivescheme", python_shell=False), + call( + "powercfg /q 381b4222-f694-41f0-9685-ff5bb260df2e SUB_DISK" " DISKIDLE", + python_shell=False, + ), + ] + mock.assert_has_calls(calls) + + assert {"ac": 30, "dc": 15} == ret + + +def test_get_standby_timeout(query_output): + """ + Test to make sure we can get the standby timeout value + """ + mock = MagicMock() + mock.side_effect = [ + "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", + query_output, + ] + + with patch.dict(powercfg.__salt__, {"cmd.run": mock}): + ret = powercfg.get_standby_timeout() + calls = [ + call("powercfg /getactivescheme", python_shell=False), + call( + "powercfg /q 381b4222-f694-41f0-9685-ff5bb260df2e SUB_SLEEP" + " STANDBYIDLE", + python_shell=False, + ), + ] + mock.assert_has_calls(calls) + + assert {"ac": 30, "dc": 15} == ret + + +def test_get_hibernate_timeout(query_output): + """ + Test to make sure we can get the hibernate timeout value + """ + mock = MagicMock() + mock.side_effect = [ + "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", + query_output, + ] + + with patch.dict(powercfg.__salt__, {"cmd.run": mock}): + ret = powercfg.get_hibernate_timeout() + calls = [ + call("powercfg /getactivescheme", python_shell=False), + call( + "powercfg /q 381b4222-f694-41f0-9685-ff5bb260df2e SUB_SLEEP" + " HIBERNATEIDLE", + python_shell=False, + ), + ] + mock.assert_has_calls(calls) + + assert {"ac": 30, "dc": 15} == ret + + +def test_windows_7(query_output): + """ + Test to make sure we can get the hibernate timeout value on windows 7 + """ + mock = MagicMock() + mock.side_effect = [ + "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", + query_output, + ] + + with patch.dict(powercfg.__salt__, {"cmd.run": mock}): + with patch.dict(powercfg.__grains__, {"osrelease": "7"}): + ret = powercfg.get_hibernate_timeout() + calls = [ + call("powercfg /getactivescheme", python_shell=False), + call( + "powercfg /q 381b4222-f694-41f0-9685-ff5bb260df2e SUB_SLEEP", + python_shell=False, + ), + ] + mock.assert_has_calls(calls) + + assert {"ac": 30, "dc": 15} == ret + + +def test_set_hibernate_timeout_scheme(query_output): + """ + Test to make sure we can set the hibernate timeout value + """ + mock = MagicMock(return_value=0) + mock.side_effect = [query_output] + + with patch.dict(powercfg.__salt__, {"cmd.retcode": mock}): + powercfg.set_hibernate_timeout(0, "dc", scheme="SCHEME_MIN") + mock.assert_called_once_with( + "powercfg /setdcvalueindex SCHEME_MIN SUB_SLEEP HIBERNATEIDLE 0", + python_shell=False, + ) + + +def test_get_hibernate_timeout_scheme(query_output): + """ + Test to make sure we can get the hibernate timeout value with a + specified scheme + """ + mock = MagicMock() + mock.side_effect = [query_output] + + with patch.dict(powercfg.__salt__, {"cmd.run": mock}): + ret = powercfg.get_hibernate_timeout(scheme="SCHEME_MIN") + mock.assert_called_once_with( + "powercfg /q SCHEME_MIN SUB_SLEEP HIBERNATEIDLE", python_shell=False + ) + + assert {"ac": 30, "dc": 15} == ret diff --git a/tests/unit/modules/test_win_psget.py b/tests/pytests/unit/modules/test_win_psget.py similarity index 61% rename from tests/unit/modules/test_win_psget.py rename to tests/pytests/unit/modules/test_win_psget.py index 49ce2550c65..af7737b121f 100644 --- a/tests/unit/modules/test_win_psget.py +++ b/tests/pytests/unit/modules/test_win_psget.py @@ -1,9 +1,22 @@ -import salt.modules.win_psget as win_psget -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase +""" + Test cases for salt.modules.win_psget +""" -BOOTSTRAP_PS_STR = """ + +import pytest + +import salt.modules.win_psget as win_psget +from tests.support.mock import MagicMock, patch + + +@pytest.fixture +def configure_loader_modules(): + return {win_psget: {}} + + +@pytest.fixture +def bootstrap_ps_str(): + return """ NuGet @@ -18,7 +31,10 @@ BOOTSTRAP_PS_STR = """ """ -AVAIL_MODULES_PS_STR = """ + +@pytest.fixture +def avail_modules_ps_str(): + return """ ActOnCmdlets @@ -39,37 +55,30 @@ AVAIL_MODULES_PS_STR = """ """ -class WinPsgetCase(TestCase, LoaderModuleMockMixin): - """ - Test cases for salt.modules.win_psget - """ +def test_bootstrap(bootstrap_ps_str): + mock_read_ok = MagicMock( + return_value={ + "pid": 78, + "retcode": 0, + "stderr": "", + "stdout": bootstrap_ps_str, + } + ) - def setup_loader_modules(self): - return {win_psget: {}} + with patch.dict(win_psget.__salt__, {"cmd.run_all": mock_read_ok}): + assert "NuGet" in win_psget.bootstrap() - def test_bootstrap(self): - mock_read_ok = MagicMock( - return_value={ - "pid": 78, - "retcode": 0, - "stderr": "", - "stdout": BOOTSTRAP_PS_STR, - } - ) - with patch.dict(win_psget.__salt__, {"cmd.run_all": mock_read_ok}): - self.assertTrue("NuGet" in win_psget.bootstrap()) +def test_avail_modules(avail_modules_ps_str): + mock_read_ok = MagicMock( + return_value={ + "pid": 78, + "retcode": 0, + "stderr": "", + "stdout": avail_modules_ps_str, + } + ) - def test_avail_modules(self): - mock_read_ok = MagicMock( - return_value={ - "pid": 78, - "retcode": 0, - "stderr": "", - "stdout": AVAIL_MODULES_PS_STR, - } - ) - - with patch.dict(win_psget.__salt__, {"cmd.run_all": mock_read_ok}): - self.assertTrue("DHCPMigration" in win_psget.avail_modules(False)) - self.assertTrue("DHCPMigration" in win_psget.avail_modules(True)) + with patch.dict(win_psget.__salt__, {"cmd.run_all": mock_read_ok}): + assert "DHCPMigration" in win_psget.avail_modules(False) + assert "DHCPMigration" in win_psget.avail_modules(True) diff --git a/tests/pytests/unit/modules/test_win_shadow.py b/tests/pytests/unit/modules/test_win_shadow.py new file mode 100644 index 00000000000..bccb67fe9da --- /dev/null +++ b/tests/pytests/unit/modules/test_win_shadow.py @@ -0,0 +1,50 @@ +""" + :codeauthor: Jayesh Kariya + + Test cases for salt.modules.win_shadow +""" + + +import pytest + +import salt.modules.win_shadow as win_shadow +from tests.support.mock import MagicMock, patch + + +@pytest.fixture +def configure_loader_modules(): + return {win_shadow: {"__salt__": {"user.update": MagicMock(return_value=True)}}} + + +def test_info(): + """ + Test if it return information for the specified user + """ + mock_user_info = MagicMock( + return_value={"name": "SALT", "password_changed": "", "expiration_date": ""} + ) + with patch.dict(win_shadow.__salt__, {"user.info": mock_user_info}): + assert win_shadow.info("SALT") == { + "name": "SALT", + "passwd": "Unavailable", + "lstchg": "", + "min": "", + "max": "", + "warn": "", + "inact": "", + "expire": "", + } + + +def test_set_password(): + """ + Test if it set the password for a named user. + """ + mock_cmd = MagicMock(return_value={"retcode": False}) + mock_user_info = MagicMock( + return_value={"name": "SALT", "password_changed": "", "expiration_date": ""} + ) + with patch.dict( + win_shadow.__salt__, {"cmd.run_all": mock_cmd, "user.info": mock_user_info} + ): + assert win_shadow.set_password("root", "mysecretpassword") diff --git a/tests/pytests/unit/modules/test_win_snmp.py b/tests/pytests/unit/modules/test_win_snmp.py new file mode 100644 index 00000000000..339f834e0d8 --- /dev/null +++ b/tests/pytests/unit/modules/test_win_snmp.py @@ -0,0 +1,114 @@ +""" + Test cases for salt.modules.win_snmp +""" + + +import pytest + +import salt.modules.win_snmp as win_snmp +from salt.exceptions import CommandExecutionError +from tests.support.mock import MagicMock, patch + + +@pytest.fixture +def community_names(): + return {"TestCommunity": "Read Create"} + + +@pytest.fixture +def configure_loader_modules(): + return {win_snmp: {}} + + +def test_get_agent_service_types(): + """ + Test - Get the sysServices types that can be configured. + """ + assert isinstance(win_snmp.get_agent_service_types(), list) + + +def test_get_permission_types(): + """ + Test - Get the permission types that can be configured for communities. + """ + assert isinstance(win_snmp.get_permission_types(), list) + + +def test_get_auth_traps_enabled(): + """ + Test - Determine whether the host is configured to send authentication traps. + """ + mock_value = MagicMock(return_value={"vdata": 1}) + with patch.dict(win_snmp.__utils__, {"reg.read_value": mock_value}): + assert win_snmp.get_auth_traps_enabled() + + +def test_set_auth_traps_enabled(): + """ + Test - Manage the sending of authentication traps. + """ + mock_value = MagicMock(return_value=True) + kwargs = {"status": True} + with patch.dict(win_snmp.__utils__, {"reg.set_value": mock_value}), patch( + "salt.modules.win_snmp.get_auth_traps_enabled", MagicMock(return_value=True) + ): + assert win_snmp.set_auth_traps_enabled(**kwargs) + + +def test_get_community_names(community_names): + """ + Test - Get the current accepted SNMP community names and their permissions. + """ + mock_ret = MagicMock(return_value=[{"vdata": 16, "vname": "TestCommunity"}]) + mock_false = MagicMock(return_value=False) + with patch.dict( + win_snmp.__utils__, + {"reg.list_values": mock_ret, "reg.key_exists": mock_false}, + ): + assert win_snmp.get_community_names() == community_names + + +def test_get_community_names_gpo(): + """ + Test - Get the current accepted SNMP community names and their permissions. + """ + mock_ret = MagicMock(return_value=[{"vdata": "TestCommunity", "vname": 1}]) + mock_false = MagicMock(return_value=True) + with patch.dict( + win_snmp.__utils__, + {"reg.list_values": mock_ret, "reg.key_exists": mock_false}, + ): + assert win_snmp.get_community_names() == {"TestCommunity": "Managed by GPO"} + + +def test_set_community_names(community_names): + """ + Test - Manage the SNMP accepted community names and their permissions. + """ + mock_true = MagicMock(return_value=True) + kwargs = {"communities": community_names} + mock_false = MagicMock(return_value=False) + with patch.dict( + win_snmp.__utils__, + {"reg.set_value": mock_true, "reg.key_exists": mock_false}, + ), patch( + "salt.modules.win_snmp.get_community_names", + MagicMock(return_value=community_names), + ): + assert win_snmp.set_community_names(**kwargs) + + +def test_set_community_names_gpo(community_names): + """ + Test - Manage the SNMP accepted community names and their permissions. + """ + mock_true = MagicMock(return_value=True) + kwargs = {"communities": community_names} + with patch.dict( + win_snmp.__utils__, + {"reg.set_value": mock_true, "reg.key_exists": mock_true}, + ), patch( + "salt.modules.win_snmp.get_community_names", + MagicMock(return_value=community_names), + ): + pytest.raises(CommandExecutionError, win_snmp.set_community_names, **kwargs) diff --git a/tests/pytests/unit/modules/test_zfs.py b/tests/pytests/unit/modules/test_zfs.py index 93f8087df9a..a9d8a3016ec 100644 --- a/tests/pytests/unit/modules/test_zfs.py +++ b/tests/pytests/unit/modules/test_zfs.py @@ -18,6 +18,10 @@ from salt.utils.odict import OrderedDict from tests.support.mock import MagicMock, patch from tests.support.zfs import ZFSMockData +pytestmark = [ + pytest.mark.slow_test, +] + @pytest.fixture def utils_patch(): diff --git a/tests/pytests/unit/modules/test_zpool.py b/tests/pytests/unit/modules/test_zpool.py index c4b8fd072e8..48fcf9e272c 100644 --- a/tests/pytests/unit/modules/test_zpool.py +++ b/tests/pytests/unit/modules/test_zpool.py @@ -19,6 +19,10 @@ from salt.utils.odict import OrderedDict from tests.support.mock import MagicMock, patch from tests.support.zfs import ZFSMockData +pytestmark = [ + pytest.mark.slow_test, +] + @pytest.fixture def utils_patch(): diff --git a/tests/pytests/unit/modules/win_lgpo/test_admx_policies.py b/tests/pytests/unit/modules/win_lgpo/test_admx_policies.py index b78e8059cf9..9297426decf 100644 --- a/tests/pytests/unit/modules/win_lgpo/test_admx_policies.py +++ b/tests/pytests/unit/modules/win_lgpo/test_admx_policies.py @@ -23,6 +23,7 @@ log = logging.getLogger(__name__) pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.slow_test, ] diff --git a/tests/pytests/unit/modules/win_lgpo/test_adv_audit_settings.py b/tests/pytests/unit/modules/win_lgpo/test_adv_audit_settings.py index 8ff4796d415..c31641ec1d8 100644 --- a/tests/pytests/unit/modules/win_lgpo/test_adv_audit_settings.py +++ b/tests/pytests/unit/modules/win_lgpo/test_adv_audit_settings.py @@ -9,6 +9,7 @@ pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, pytest.mark.destructive_test, + pytest.mark.slow_test, ] diff --git a/tests/pytests/unit/modules/win_lgpo/test_defined_policies.py b/tests/pytests/unit/modules/win_lgpo/test_defined_policies.py index 06e91666775..9acfc0f141c 100644 --- a/tests/pytests/unit/modules/win_lgpo/test_defined_policies.py +++ b/tests/pytests/unit/modules/win_lgpo/test_defined_policies.py @@ -10,6 +10,7 @@ import salt.utils.win_reg as win_reg pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.slow_test, ] diff --git a/tests/pytests/unit/modules/win_lgpo/test_mechanisms.py b/tests/pytests/unit/modules/win_lgpo/test_mechanisms.py index f0c8497497b..b9d659acb5f 100644 --- a/tests/pytests/unit/modules/win_lgpo/test_mechanisms.py +++ b/tests/pytests/unit/modules/win_lgpo/test_mechanisms.py @@ -16,6 +16,7 @@ from tests.support.mock import patch pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.slow_test, ] diff --git a/tests/pytests/unit/modules/win_lgpo/test_point_print_enabled.py b/tests/pytests/unit/modules/win_lgpo/test_point_print_enabled.py index 258a7a49049..88b1c05b4e7 100644 --- a/tests/pytests/unit/modules/win_lgpo/test_point_print_enabled.py +++ b/tests/pytests/unit/modules/win_lgpo/test_point_print_enabled.py @@ -13,6 +13,7 @@ import salt.utils.win_reg as win_reg pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.slow_test, ] diff --git a/tests/pytests/unit/modules/win_lgpo/test_point_print_nc.py b/tests/pytests/unit/modules/win_lgpo/test_point_print_nc.py index edfec83b3e8..174ca38fb50 100644 --- a/tests/pytests/unit/modules/win_lgpo/test_point_print_nc.py +++ b/tests/pytests/unit/modules/win_lgpo/test_point_print_nc.py @@ -20,6 +20,7 @@ import salt.utils.win_reg as win_reg pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.slow_test, ] diff --git a/tests/pytests/unit/modules/win_lgpo/test_policy_info.py b/tests/pytests/unit/modules/win_lgpo/test_policy_info.py index 6ecb434a5bc..b728ab3de89 100644 --- a/tests/pytests/unit/modules/win_lgpo/test_policy_info.py +++ b/tests/pytests/unit/modules/win_lgpo/test_policy_info.py @@ -9,6 +9,7 @@ import salt.modules.win_lgpo as win_lgpo pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.slow_test, ] diff --git a/tests/pytests/unit/modules/win_lgpo/test_policy_info_functions.py b/tests/pytests/unit/modules/win_lgpo/test_policy_info_functions.py index 37125644955..bedacc237fb 100644 --- a/tests/pytests/unit/modules/win_lgpo/test_policy_info_functions.py +++ b/tests/pytests/unit/modules/win_lgpo/test_policy_info_functions.py @@ -9,6 +9,7 @@ from tests.support.mock import MagicMock, Mock, patch pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.slow_test, ] diff --git a/tests/pytests/unit/modules/win_lgpo/test_policy_resources.py b/tests/pytests/unit/modules/win_lgpo/test_policy_resources.py index 0c91de7ae19..b7a6618f47e 100644 --- a/tests/pytests/unit/modules/win_lgpo/test_policy_resources.py +++ b/tests/pytests/unit/modules/win_lgpo/test_policy_resources.py @@ -13,6 +13,7 @@ import salt.utils.win_reg as win_reg pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, + pytest.mark.slow_test, ] diff --git a/tests/pytests/unit/modules/win_lgpo/test_secedit_policy.py b/tests/pytests/unit/modules/win_lgpo/test_secedit_policy.py index d797878b799..6a0d2c027c5 100644 --- a/tests/pytests/unit/modules/win_lgpo/test_secedit_policy.py +++ b/tests/pytests/unit/modules/win_lgpo/test_secedit_policy.py @@ -12,6 +12,7 @@ pytestmark = [ pytest.mark.windows_whitelisted, pytest.mark.skip_unless_on_windows, pytest.mark.destructive_test, + pytest.mark.slow_test, ] diff --git a/tests/pytests/unit/state/test_global_state_conditions.py b/tests/pytests/unit/state/test_global_state_conditions.py index e7d812f6b68..a866e60aa24 100644 --- a/tests/pytests/unit/state/test_global_state_conditions.py +++ b/tests/pytests/unit/state/test_global_state_conditions.py @@ -8,6 +8,11 @@ import salt.state log = logging.getLogger(__name__) +pytestmark = [ + pytest.mark.core_test, +] + + @pytest.fixture def minion_config(minion_opts): minion_opts["file_client"] = "local" diff --git a/tests/pytests/unit/state/test_multi_env_highstate.py b/tests/pytests/unit/state/test_multi_env_highstate.py index d1ae83fabc2..f270a31a187 100644 --- a/tests/pytests/unit/state/test_multi_env_highstate.py +++ b/tests/pytests/unit/state/test_multi_env_highstate.py @@ -15,6 +15,11 @@ import salt.utils.platform log = logging.getLogger(__name__) +pytestmark = [ + pytest.mark.core_test, +] + + @pytest.fixture def root_dir(tmp_path): return str(tmp_path / "root_dir") diff --git a/tests/pytests/unit/state/test_state_compiler.py b/tests/pytests/unit/state/test_state_compiler.py index 3ef63b8ad29..bc96dc9e173 100644 --- a/tests/pytests/unit/state/test_state_compiler.py +++ b/tests/pytests/unit/state/test_state_compiler.py @@ -17,6 +17,11 @@ from tests.support.mock import MagicMock, patch log = logging.getLogger(__name__) +pytestmark = [ + pytest.mark.core_test, +] + + def test_format_log_non_ascii_character(): """ Tests running a non-ascii character through the state.format_log @@ -1038,3 +1043,50 @@ def test_mod_aggregate(minion_opts): # Ensure pkgs were aggregated assert low_ret["pkgs"] == ["figlet", "sl"] + + +def test_verify_onlyif_cmd_opts_exclude(minion_opts): + """ + Verify cmd.run state arguments are properly excluded from cmd.retcode + when passed. + """ + low_data = { + "onlyif": "somecommand", + "cmd_opts_exclude": ["shell"], + "cwd": "acwd", + "root": "aroot", + "env": [{"akey": "avalue"}], + "prepend_path": "apath", + "umask": "0700", + "success_retcodes": 1, + "timeout": 5, + "runas": "doesntexist", + "name": "echo something", + "shell": "/bin/dash", + "state": "cmd", + "__id__": "this is just a test", + "fun": "run", + "__env__": "base", + "__sls__": "sometest", + "order": 10000, + } + + with patch("salt.state.State._gather_pillar"): + state_obj = salt.state.State(minion_opts) + mock = MagicMock() + with patch.dict(state_obj.functions, {"cmd.retcode": mock}): + # The mock handles the exception, but the runas dict is being passed as it would actually be + return_result = state_obj._run_check(low_data) + mock.assert_called_once_with( + "somecommand", + ignore_retcode=True, + python_shell=True, + cwd="acwd", + root="aroot", + runas="doesntexist", + env=[{"akey": "avalue"}], + prepend_path="apath", + umask="0700", + timeout=5, + success_retcodes=1, + ) diff --git a/tests/pytests/unit/state/test_state_format_slots.py b/tests/pytests/unit/state/test_state_format_slots.py index 4fb6f0f915d..1254994f34b 100644 --- a/tests/pytests/unit/state/test_state_format_slots.py +++ b/tests/pytests/unit/state/test_state_format_slots.py @@ -15,6 +15,11 @@ from tests.support.mock import MagicMock, patch log = logging.getLogger(__name__) +pytestmark = [ + pytest.mark.core_test, +] + + @pytest.fixture def state_obj(minion_opts): with patch("salt.state.State._gather_pillar"): diff --git a/tests/pytests/unit/state/test_state_highstate.py b/tests/pytests/unit/state/test_state_highstate.py index 83529d98b0c..5278c4a4b72 100644 --- a/tests/pytests/unit/state/test_state_highstate.py +++ b/tests/pytests/unit/state/test_state_highstate.py @@ -13,6 +13,11 @@ from salt.utils.odict import OrderedDict log = logging.getLogger(__name__) +pytestmark = [ + pytest.mark.core_test, +] + + @pytest.fixture def root_dir(tmp_path): return tmp_path / "root_dir" diff --git a/tests/pytests/unit/state/test_state_options.py b/tests/pytests/unit/state/test_state_options.py index ccba8d291ff..7639567b044 100644 --- a/tests/pytests/unit/state/test_state_options.py +++ b/tests/pytests/unit/state/test_state_options.py @@ -4,6 +4,10 @@ import pytest import salt.state +pytestmark = [ + pytest.mark.core_test, +] + @pytest.fixture def master_opts(master_opts): diff --git a/tests/pytests/unit/state/test_state_returns.py b/tests/pytests/unit/state/test_state_returns.py index 1a3253fbb8e..65799dfeb01 100644 --- a/tests/pytests/unit/state/test_state_returns.py +++ b/tests/pytests/unit/state/test_state_returns.py @@ -11,6 +11,11 @@ from salt.utils.decorators import state as statedecorators log = logging.getLogger(__name__) +pytestmark = [ + pytest.mark.core_test, +] + + def test_state_output_check_changes_is_dict(): """ Test that changes key contains a dictionary. diff --git a/tests/pytests/unit/state/test_sub_state_returns.py b/tests/pytests/unit/state/test_sub_state_returns.py index d979f08a3eb..1428d0d92f2 100644 --- a/tests/pytests/unit/state/test_sub_state_returns.py +++ b/tests/pytests/unit/state/test_sub_state_returns.py @@ -11,6 +11,11 @@ from salt.utils.decorators import state as statedecorators log = logging.getLogger(__name__) +pytestmark = [ + pytest.mark.core_test, +] + + def test_sub_state_output_check_changes_is_dict(): """ Test that changes key contains a dictionary. diff --git a/tests/pytests/unit/states/test_boto_cloudwatch_event.py b/tests/pytests/unit/states/test_boto_cloudwatch_event.py index 1aa6a04e543..2974947e60e 100644 --- a/tests/pytests/unit/states/test_boto_cloudwatch_event.py +++ b/tests/pytests/unit/states/test_boto_cloudwatch_event.py @@ -15,6 +15,11 @@ botocore = pytest.importorskip("botocore", "1.4.41") log = logging.getLogger(__name__) +pytestmark = [ + pytest.mark.slow_test, +] + + class GlobalConfig: region = "us-east-1" access_key = "GKTADJGHEIQSXMKKRBJ08H" diff --git a/tests/pytests/unit/states/test_boto_elasticache.py b/tests/pytests/unit/states/test_boto_elasticache.py index 6dbe211d771..3692577834c 100644 --- a/tests/pytests/unit/states/test_boto_elasticache.py +++ b/tests/pytests/unit/states/test_boto_elasticache.py @@ -7,6 +7,10 @@ import pytest import salt.states.boto_elasticache as boto_elasticache from tests.support.mock import MagicMock, patch +pytestmark = [ + pytest.mark.slow_test, +] + @pytest.fixture def configure_loader_modules(): diff --git a/tests/pytests/unit/states/test_boto_iot.py b/tests/pytests/unit/states/test_boto_iot.py index 233ed12dac7..594cd9982bb 100644 --- a/tests/pytests/unit/states/test_boto_iot.py +++ b/tests/pytests/unit/states/test_boto_iot.py @@ -16,6 +16,11 @@ botocore = pytest.importorskip("botocore", "1.4.41") log = logging.getLogger(__name__) +pytestmark = [ + pytest.mark.slow_test, +] + + class GlobalConfig: region = "us-east-1" access_key = "GKTADJGHEIQSXMKKRBJ08H" diff --git a/tests/pytests/unit/states/test_boto_lambda.py b/tests/pytests/unit/states/test_boto_lambda.py index f8885a8491e..400af9b23c8 100644 --- a/tests/pytests/unit/states/test_boto_lambda.py +++ b/tests/pytests/unit/states/test_boto_lambda.py @@ -20,6 +20,11 @@ botocore = pytest.importorskip("botocore", "1.5.2") log = logging.getLogger(__name__) +pytestmark = [ + pytest.mark.slow_test, +] + + class GlobalConfig: region = "us-east-1" access_key = "GKTADJGHEIQSXMKKRBJ08H" diff --git a/tests/pytests/unit/states/test_helm.py b/tests/pytests/unit/states/test_helm.py new file mode 100644 index 00000000000..d7d78432e17 --- /dev/null +++ b/tests/pytests/unit/states/test_helm.py @@ -0,0 +1,275 @@ +""" + Test cases for salt.modules.helm +""" + + +import pytest + +import salt.states.helm as helm +from tests.support.mock import MagicMock, patch + + +@pytest.fixture +def configure_loader_modules(): + return {helm: {}} + + +def test_repo_managed_import_failed_repo_manage(): + ret = { + "name": "state_id", + "changes": {}, + "result": False, + "comment": "'helm.repo_manage' modules not available on this minion.", + } + assert helm.repo_managed("state_id") == ret + + +def test_repo_managed_import_failed_repo_update(): + mock_helm_modules = {"helm.repo_manage": MagicMock(return_value=True)} + with patch.dict(helm.__salt__, mock_helm_modules): + ret = { + "name": "state_id", + "changes": {}, + "result": False, + "comment": "'helm.repo_update' modules not available on this minion.", + } + assert helm.repo_managed("state_id") == ret + + +def test_repo_managed_is_testing(): + mock_helm_modules = { + "helm.repo_manage": MagicMock(return_value=True), + "helm.repo_update": MagicMock(return_value=True), + } + with patch.dict(helm.__salt__, mock_helm_modules): + mock__opts__ = {"test": MagicMock(return_value=True)} + with patch.dict(helm.__opts__, mock__opts__): + ret = { + "name": "state_id", + "result": None, + "comment": "Helm repo would have been managed.", + "changes": {}, + } + assert helm.repo_managed("state_id") == ret + + +def test_repo_managed_success(): + result_changes = {"added": True, "removed": True, "failed": False} + mock_helm_modules = { + "helm.repo_manage": MagicMock(return_value=result_changes), + "helm.repo_update": MagicMock(return_value=True), + } + with patch.dict(helm.__salt__, mock_helm_modules): + ret = { + "name": "state_id", + "result": True, + "comment": "Repositories were added or removed.", + "changes": result_changes, + } + assert helm.repo_managed("state_id") == ret + + +def test_repo_managed_success_with_update(): + result_changes = {"added": True, "removed": True, "failed": False} + mock_helm_modules = { + "helm.repo_manage": MagicMock(return_value=result_changes), + "helm.repo_update": MagicMock(return_value=True), + } + result_wanted = result_changes + result_wanted.update({"repo_update": True}) + with patch.dict(helm.__salt__, mock_helm_modules): + ret = { + "name": "state_id", + "result": True, + "comment": "Repositories were added or removed.", + "changes": result_wanted, + } + assert helm.repo_managed("state_id") == ret + + +def test_repo_managed_failed(): + result_changes = {"added": True, "removed": True, "failed": True} + mock_helm_modules = { + "helm.repo_manage": MagicMock(return_value=result_changes), + "helm.repo_update": MagicMock(return_value=True), + } + with patch.dict(helm.__salt__, mock_helm_modules): + ret = { + "name": "state_id", + "result": False, + "comment": "Failed to add or remove some repositories.", + "changes": result_changes, + } + assert helm.repo_managed("state_id") == ret + + +def test_repo_updated_import_failed(): + ret = { + "name": "state_id", + "changes": {}, + "result": False, + "comment": "'helm.repo_update' modules not available on this minion.", + } + assert helm.repo_updated("state_id") == ret + + +def test_repo_updated_is_testing(): + mock_helm_modules = {"helm.repo_update": MagicMock(return_value=True)} + with patch.dict(helm.__salt__, mock_helm_modules): + mock__opts__ = {"test": MagicMock(return_value=True)} + with patch.dict(helm.__opts__, mock__opts__): + ret = { + "name": "state_id", + "result": None, + "comment": "Helm repo would have been updated.", + "changes": {}, + } + assert helm.repo_updated("state_id") == ret + + +def test_repo_updated_success(): + mock_helm_modules = {"helm.repo_update": MagicMock(return_value=True)} + with patch.dict(helm.__salt__, mock_helm_modules): + ret = { + "name": "state_id", + "result": True, + "comment": "Helm repo is updated.", + "changes": {}, + } + assert helm.repo_updated("state_id") == ret + + +def test_repo_updated_failed(): + mock_helm_modules = {"helm.repo_update": MagicMock(return_value=False)} + with patch.dict(helm.__salt__, mock_helm_modules): + ret = { + "name": "state_id", + "result": False, + "comment": "Failed to sync some repositories.", + "changes": False, + } + assert helm.repo_updated("state_id") == ret + + +def test_release_present_import_failed_helm_status(): + ret = { + "name": "state_id", + "changes": {}, + "result": False, + "comment": "'helm.status' modules not available on this minion.", + } + assert helm.release_present("state_id", "mychart") == ret + + +def test_release_present_import_failed_helm_install(): + mock_helm_modules = {"helm.status": MagicMock(return_value=True)} + with patch.dict(helm.__salt__, mock_helm_modules): + ret = { + "name": "state_id", + "changes": {}, + "result": False, + "comment": "'helm.install' modules not available on this minion.", + } + assert helm.release_present("state_id", "mychart") == ret + + +def test_release_present_import_failed_helm_upgrade(): + mock_helm_modules = { + "helm.status": MagicMock(return_value=True), + "helm.install": MagicMock(return_value=True), + } + with patch.dict(helm.__salt__, mock_helm_modules): + ret = { + "name": "state_id", + "changes": {}, + "result": False, + "comment": "'helm.upgrade' modules not available on this minion.", + } + assert helm.release_present("state_id", "mychart") == ret + + +def test_release_present_is_testing(): + mock_helm_modules = { + "helm.status": MagicMock(return_value=True), + "helm.install": MagicMock(return_value=True), + "helm.upgrade": MagicMock(return_value=True), + } + with patch.dict(helm.__salt__, mock_helm_modules): + mock__opts__ = {"test": MagicMock(return_value=True)} + with patch.dict(helm.__opts__, mock__opts__): + ret = { + "name": "state_id", + "result": None, + "comment": "Helm release would have been installed or updated.", + "changes": {}, + } + assert helm.release_present("state_id", "mychart") == ret + + +def test_release_absent_import_failed_helm_uninstall(): + ret = { + "name": "state_id", + "changes": {}, + "result": False, + "comment": "'helm.uninstall' modules not available on this minion.", + } + assert helm.release_absent("state_id") == ret + + +def test_release_absent_import_failed_helm_status(): + mock_helm_modules = {"helm.uninstall": MagicMock(return_value=True)} + with patch.dict(helm.__salt__, mock_helm_modules): + ret = { + "name": "state_id", + "changes": {}, + "result": False, + "comment": "'helm.status' modules not available on this minion.", + } + assert helm.release_absent("state_id") == ret + + +def test_release_absent_is_testing(): + mock_helm_modules = { + "helm.status": MagicMock(return_value=True), + "helm.uninstall": MagicMock(return_value=True), + } + with patch.dict(helm.__salt__, mock_helm_modules): + mock__opts__ = {"test": MagicMock(return_value=True)} + with patch.dict(helm.__opts__, mock__opts__): + ret = { + "name": "state_id", + "result": None, + "comment": "Helm release would have been uninstalled.", + "changes": {}, + } + assert helm.release_absent("state_id") == ret + + +def test_release_absent_success(): + mock_helm_modules = { + "helm.status": MagicMock(return_value={}), + "helm.uninstall": MagicMock(return_value=True), + } + with patch.dict(helm.__salt__, mock_helm_modules): + ret = { + "name": "state_id", + "result": True, + "comment": "Helm release state_id is absent.", + "changes": {"absent": "state_id"}, + } + assert helm.release_absent("state_id") == ret + + +def test_release_absent_error(): + mock_helm_modules = { + "helm.status": MagicMock(return_value={}), + "helm.uninstall": MagicMock(return_value="error"), + } + with patch.dict(helm.__salt__, mock_helm_modules): + ret = { + "name": "state_id", + "result": False, + "comment": "error", + "changes": {}, + } + assert helm.release_absent("state_id") == ret diff --git a/tests/pytests/unit/states/test_hg.py b/tests/pytests/unit/states/test_hg.py new file mode 100644 index 00000000000..1c50ba4b97a --- /dev/null +++ b/tests/pytests/unit/states/test_hg.py @@ -0,0 +1,140 @@ +""" + :codeauthor: Rahul Handay + + Test cases for salt.modules.hg +""" + +import os + +import pytest + +import salt.states.hg as hg +from tests.support.mock import MagicMock, patch + + +@pytest.fixture +def configure_loader_modules(): + return {hg: {}} + + +def test_latest(): + """ + Test to Make sure the repository is cloned to + the given directory and is up to date + """ + ret = {"changes": {}, "comment": "", "name": "salt", "result": True} + mock = MagicMock(return_value=True) + with patch.object(hg, "_fail", mock): + assert hg.latest("salt") + + mock = MagicMock(side_effect=[False, True, False, False, False, False]) + with patch.object(os.path, "isdir", mock): + mock = MagicMock(return_value=True) + with patch.object(hg, "_handle_existing", mock): + assert hg.latest("salt", target="c:\\salt") + + with patch.dict(hg.__opts__, {"test": True}): + mock = MagicMock(return_value=True) + with patch.object(hg, "_neutral_test", mock): + assert hg.latest("salt", target="c:\\salt") + + with patch.dict(hg.__opts__, {"test": False}): + mock = MagicMock(return_value=True) + with patch.object(hg, "_clone_repo", mock): + assert hg.latest("salt", target="c:\\salt") == ret + + +def test_latest_update_changes(): + """ + Test to make sure we don't update even if we have changes + """ + ret = {"changes": {}, "comment": "", "name": "salt", "result": True} + revision_mock = MagicMock(return_value="abcdef") + pull_mock = MagicMock(return_value="Blah.") + update_mock = MagicMock() + + with patch.dict( + hg.__salt__, + { + "hg.revision": revision_mock, + "hg.pull": pull_mock, + "hg.update": update_mock, + }, + ): + mock = MagicMock(side_effect=[True, True]) + with patch.object(os.path, "isdir", mock): + mock = MagicMock(return_value=True) + with patch.dict(hg.__opts__, {"test": False}): + with patch.object(hg, "_clone_repo", mock): + assert hg.latest("salt", target="c:\\salt", update_head=True) == ret + assert update_mock.called + + +def test_latest_no_update_changes(): + """ + Test to make sure we don't update even if we have changes + """ + ret = { + "changes": {}, + "comment": ( + "Update is probably required but update_head=False so we will skip" + " updating." + ), + "name": "salt", + "result": True, + } + revision_mock = MagicMock(return_value="abcdef") + pull_mock = MagicMock(return_value="Blah.") + update_mock = MagicMock() + + with patch.dict( + hg.__salt__, + { + "hg.revision": revision_mock, + "hg.pull": pull_mock, + "hg.update": update_mock, + }, + ): + mock = MagicMock(side_effect=[True, True]) + with patch.object(os.path, "isdir", mock): + mock = MagicMock(return_value=True) + with patch.dict(hg.__opts__, {"test": False}): + with patch.object(hg, "_clone_repo", mock): + assert ( + hg.latest("salt", target="c:\\salt", update_head=False) == ret + ) + assert not update_mock.called + + +def test_latest_no_update_no_changes(): + """ + Test to Make sure the repository is cloned to + the given directory and is up to date + """ + ret = { + "changes": {}, + "comment": "No changes found and update_head=False so will skip updating.", + "name": "salt", + "result": True, + } + revision_mock = MagicMock(return_value="abcdef") + pull_mock = MagicMock(return_value="Blah no changes found.") + update_mock = MagicMock() + + with patch.dict( + hg.__salt__, + { + "hg.revision": revision_mock, + "hg.pull": pull_mock, + "hg.update": update_mock, + }, + ): + mock = MagicMock(side_effect=[True, True]) + with patch.object(os.path, "isdir", mock): + mock = MagicMock(return_value=True) + with patch.dict(hg.__opts__, {"test": False}): + with patch.object(hg, "_clone_repo", mock): + assert ( + hg.latest("salt", target="c:\\salt", update_head=False) == ret + ) + assert not update_mock.called diff --git a/tests/pytests/unit/states/test_ini_manage.py b/tests/pytests/unit/states/test_ini_manage.py index 009e006f240..9f0217b5b40 100644 --- a/tests/pytests/unit/states/test_ini_manage.py +++ b/tests/pytests/unit/states/test_ini_manage.py @@ -1,3 +1,8 @@ +""" + Test cases for salt.states.ini_manage +""" + + import copy import os @@ -6,7 +11,7 @@ import pytest import salt.modules.ini_manage as mod_ini_manage import salt.states.ini_manage as ini_manage from salt.utils.odict import OrderedDict -from tests.support.mock import patch +from tests.support.mock import MagicMock, patch @pytest.fixture @@ -104,3 +109,84 @@ def test_options_present_true_file(tmp_path, sections): assert os.path.exists(name) assert mod_ini_manage.get_ini(name) == sections + + +def test_options_absent(): + """ + Test to verify options absent in file. + """ + name = "salt" + + ret = {"name": name, "result": None, "comment": "", "changes": {}} + + with patch.dict(ini_manage.__opts__, {"test": True}): + comt = "No changes detected." + ret.update({"comment": comt, "result": True}) + assert ini_manage.options_absent(name) == ret + + with patch.dict(ini_manage.__opts__, {"test": False}): + comt = "No anomaly detected" + ret.update({"comment": comt, "result": True}) + assert ini_manage.options_absent(name) == ret + sections = {"Tables": ["key2", "key3"]} + changes = {"Tables": {"key2": "2", "key3": "3"}} + with patch.dict( + ini_manage.__salt__, + {"ini.remove_option": MagicMock(side_effect=["2", "3"])}, + ): + with patch.dict(ini_manage.__opts__, {"test": False}): + comt = "Changes take effect" + ret.update({"comment": comt, "result": True, "changes": changes}) + assert ini_manage.options_absent(name, sections) == ret + + +def test_sections_present(): + """ + Test to verify sections present in file. + """ + name = "salt" + + ret = {"name": name, "result": None, "comment": "", "changes": {}} + + with patch.dict(ini_manage.__opts__, {"test": True}): + with patch.dict( + ini_manage.__salt__, {"ini.get_ini": MagicMock(return_value=None)} + ): + comt = "No changes detected." + ret.update({"comment": comt, "result": True}) + assert ini_manage.sections_present(name) == ret + + changes = { + "first": "who is on", + "second": "what is on", + "third": "I don't know", + } + with patch.dict( + ini_manage.__salt__, {"ini.set_option": MagicMock(return_value=changes)} + ): + with patch.dict(ini_manage.__opts__, {"test": False}): + comt = "Changes take effect" + ret.update({"comment": comt, "result": True, "changes": changes}) + assert ini_manage.sections_present(name) == ret + + +def test_sections_absent(): + """ + Test to verify sections absent in file. + """ + name = "salt" + + ret = {"name": name, "result": None, "comment": "", "changes": {}} + + with patch.dict(ini_manage.__opts__, {"test": True}): + with patch.dict( + ini_manage.__salt__, {"ini.get_ini": MagicMock(return_value=None)} + ): + comt = "No changes detected." + ret.update({"comment": comt, "result": True}) + assert ini_manage.sections_absent(name) == ret + + with patch.dict(ini_manage.__opts__, {"test": False}): + comt = "No anomaly detected" + ret.update({"comment": comt, "result": True}) + assert ini_manage.sections_absent(name) == ret diff --git a/tests/pytests/unit/states/test_ipmi.py b/tests/pytests/unit/states/test_ipmi.py new file mode 100644 index 00000000000..a1c00345a7c --- /dev/null +++ b/tests/pytests/unit/states/test_ipmi.py @@ -0,0 +1,166 @@ +""" + :codeauthor: Jayesh Kariya + + Test cases for salt.states.ipmi +""" + +import pytest + +import salt.states.ipmi as ipmi +from tests.support.mock import MagicMock, patch + + +@pytest.fixture +def configure_loader_modules(): + return {ipmi: {}} + + +def test_boot_device(): + """ + Test to request power state change. + """ + name = "salt" + + ret = {"name": name, "result": True, "comment": "", "changes": {}} + + mock = MagicMock(return_value=name) + with patch.dict( + ipmi.__salt__, {"ipmi.get_bootdev": mock, "ipmi.set_bootdev": mock} + ): + comt = "system already in this state" + ret.update({"comment": comt}) + assert ipmi.boot_device(name) == ret + + with patch.dict(ipmi.__opts__, {"test": False}): + comt = "changed boot device" + ret.update( + { + "name": "default", + "comment": comt, + "result": True, + "changes": {"new": "default", "old": "salt"}, + } + ) + assert ipmi.boot_device() == ret + + with patch.dict(ipmi.__opts__, {"test": True}): + comt = "would change boot device" + ret.update({"comment": comt, "result": None}) + assert ipmi.boot_device() == ret + + +def test_power(): + """ + Test to request power state change + """ + ret = {"name": "power_on", "result": True, "comment": "", "changes": {}} + + mock = MagicMock(return_value="on") + with patch.dict(ipmi.__salt__, {"ipmi.get_power": mock, "ipmi.set_power": mock}): + comt = "system already in this state" + ret.update({"comment": comt}) + assert ipmi.power() == ret + + with patch.dict(ipmi.__opts__, {"test": False}): + comt = "changed system power" + ret.update( + { + "name": "off", + "comment": comt, + "result": True, + "changes": {"new": "off", "old": "on"}, + } + ) + assert ipmi.power("off") == ret + + with patch.dict(ipmi.__opts__, {"test": True}): + comt = "would power: off system" + ret.update({"comment": comt, "result": None}) + assert ipmi.power("off") == ret + + +def test_user_present(): + """ + Test to ensure IPMI user and user privileges. + """ + name = "salt" + + ret = {"name": name, "result": True, "comment": "", "changes": {}} + + mock_ret = { + "access": { + "callback": False, + "link_auth": True, + "ipmi_msg": True, + "privilege_level": "administrator", + } + } + mock = MagicMock(return_value=mock_ret) + mock_bool = MagicMock(side_effect=[True, False, False, False]) + with patch.dict( + ipmi.__salt__, + { + "ipmi.get_user": mock, + "ipmi.set_user_password": mock_bool, + "ipmi.ensure_user": mock_bool, + }, + ): + comt = "user already present" + ret.update({"comment": comt}) + assert ipmi.user_present(name, 5, "salt@123") == ret + + with patch.dict(ipmi.__opts__, {"test": True}): + comt = "would (re)create user" + ret.update( + { + "comment": comt, + "result": None, + "changes": {"new": "salt", "old": mock_ret}, + } + ) + assert ipmi.user_present(name, 5, "pw@123") == ret + + with patch.dict(ipmi.__opts__, {"test": False}): + comt = "(re)created user" + ret.update( + { + "comment": comt, + "result": True, + "changes": {"new": mock_ret, "old": mock_ret}, + } + ) + assert ipmi.user_present(name, 5, "pw@123") == ret + + +def test_user_absent(): + """ + Test to delete all user (uid) records having the matching name. + """ + name = "salt" + + ret = {"name": name, "result": True, "comment": "", "changes": {}} + + mock = MagicMock(side_effect=[[], [5], [5]]) + mock_bool = MagicMock(return_value=True) + with patch.dict( + ipmi.__salt__, {"ipmi.get_name_uids": mock, "ipmi.delete_user": mock_bool} + ): + comt = "user already absent" + ret.update({"comment": comt}) + assert ipmi.user_absent(name) == ret + + with patch.dict(ipmi.__opts__, {"test": True}): + comt = "would delete user(s)" + ret.update({"comment": comt, "result": None, "changes": {"delete": [5]}}) + assert ipmi.user_absent(name) == ret + + with patch.dict(ipmi.__opts__, {"test": False}): + comt = "user(s) removed" + ret.update( + { + "comment": comt, + "result": False, + "changes": {"new": "None", "old": [5]}, + } + ) + assert ipmi.user_absent(name) == ret diff --git a/tests/pytests/unit/states/test_kapacitor.py b/tests/pytests/unit/states/test_kapacitor.py new file mode 100644 index 00000000000..df748455541 --- /dev/null +++ b/tests/pytests/unit/states/test_kapacitor.py @@ -0,0 +1,135 @@ +""" + Test cases for salt.states.kapacitor +""" + + +import pytest + +import salt.states.kapacitor as kapacitor +from tests.support.mock import Mock, mock_open, patch + + +@pytest.fixture +def configure_loader_modules(): + return {kapacitor: {"__opts__": {"test": False}, "__env__": "test"}} + + +def _present( + name="testname", + tick_script="/tmp/script.tick", + task_type="stream", + database="testdb", + retention_policy="default", + dbrps=None, + enable=True, + task=None, + define_result=True, + enable_result=True, + disable_result=True, + script="testscript", +): + """ + Run a "kapacitor.present" state after setting up mocks, and return the + state return value as well as the mocks to make assertions. + """ + get_mock = Mock(return_value=task) + + if isinstance(define_result, bool): + define_result = {"success": define_result} + define_mock = Mock(return_value=define_result) + + if isinstance(enable_result, bool): + enable_result = {"success": enable_result} + enable_mock = Mock(return_value=enable_result) + + if isinstance(disable_result, bool): + disable_result = {"success": disable_result} + disable_mock = Mock(return_value=disable_result) + + with patch.dict( + kapacitor.__salt__, + { + "kapacitor.get_task": get_mock, + "kapacitor.define_task": define_mock, + "kapacitor.enable_task": enable_mock, + "kapacitor.disable_task": disable_mock, + }, + ): + with patch("salt.utils.files.fopen", mock_open(read_data=script)) as open_mock: + retval = kapacitor.task_present( + name, + tick_script, + task_type=task_type, + database=database, + retention_policy=retention_policy, + enable=enable, + dbrps=dbrps, + ) + + return retval, get_mock, define_mock, enable_mock, disable_mock + + +def _task( + script="testscript", enabled=True, task_type="stream", db="testdb", rp="default" +): + return { + "script": script, + "enabled": enabled, + "type": task_type, + "dbrps": [{"db": db, "rp": rp}], + } + + +def test_task_present_new_task(): + ret, get_mock, define_mock, enable_mock, _ = _present(dbrps=["testdb2.default_rp"]) + get_mock.assert_called_once_with("testname") + define_mock.assert_called_once_with( + "testname", + "/tmp/script.tick", + database="testdb", + retention_policy="default", + task_type="stream", + dbrps=["testdb2.default_rp", "testdb.default"], + ) + enable_mock.assert_called_once_with("testname") + assert "TICKscript diff" in ret["changes"] + assert "enabled" in ret["changes"] + assert ret["changes"]["enabled"]["new"] is True + + +def test_task_present_existing_task_updated_script(): + ret, get_mock, define_mock, enable_mock, _ = _present( + task=_task(script="oldscript") + ) + get_mock.assert_called_once_with("testname") + define_mock.assert_called_once_with( + "testname", + "/tmp/script.tick", + database="testdb", + retention_policy="default", + task_type="stream", + dbrps=["testdb.default"], + ) + assert enable_mock.called is False + assert "TICKscript diff" in ret["changes"] + assert "enabled" not in ret["changes"] + + +def test_task_present_existing_task_not_enabled(): + ret, get_mock, define_mock, enable_mock, _ = _present(task=_task(enabled=False)) + get_mock.assert_called_once_with("testname") + assert define_mock.called is False + enable_mock.assert_called_once_with("testname") + assert "diff" not in ret["changes"] + assert "enabled" in ret["changes"] + assert ret["changes"]["enabled"]["new"] is True + + +def test_task_present_disable_existing_task(): + ret, get_mock, define_mock, _, disable_mock = _present(task=_task(), enable=False) + get_mock.assert_called_once_with("testname") + assert define_mock.called is False + disable_mock.assert_called_once_with("testname") + assert "diff" not in ret["changes"] + assert "enabled" in ret["changes"] + assert ret["changes"]["enabled"]["new"] is False diff --git a/tests/pytests/unit/states/test_kernelpkg.py b/tests/pytests/unit/states/test_kernelpkg.py new file mode 100644 index 00000000000..22b3cbf2db0 --- /dev/null +++ b/tests/pytests/unit/states/test_kernelpkg.py @@ -0,0 +1,153 @@ +""" + Test cases for salt.states.kernelpkg +""" + + +import pytest + +import salt.states.kernelpkg as kernelpkg +from tests.support.mock import MagicMock, patch + + +@pytest.fixture +def kernel_list(): + return ["4.4.0-70-generic", "4.4.0-71-generic", "4.5.1-14-generic"] + + +@pytest.fixture +def state_name(): + return "kernelpkg-test" + + +@pytest.fixture +def configure_loader_modules(): + return { + kernelpkg: { + "__salt__": { + "system.reboot": MagicMock(return_value=None), + "kernelpkg.upgrade": MagicMock( + return_value={ + "upgrades": {"kernel": {"old": "1.0.0", "new": "2.0.0"}} + } + ), + "kernelpkg.active": MagicMock(return_value=0), + "kernelpkg.latest_installed": MagicMock(return_value=0), + } + } + } + + +def test_latest_installed_with_changes(kernel_list, state_name): + """ + Test - latest_installed when an upgrade is available + """ + installed = MagicMock(return_value=kernel_list[:-1]) + upgrade = MagicMock(return_value=kernel_list[-1]) + with patch.dict(kernelpkg.__salt__, {"kernelpkg.list_installed": installed}): + with patch.dict(kernelpkg.__salt__, {"kernelpkg.latest_available": upgrade}): + with patch.dict(kernelpkg.__opts__, {"test": False}): + kernelpkg.__salt__["kernelpkg.upgrade"].reset_mock() + ret = kernelpkg.latest_installed(name=state_name) + assert ret["name"] == state_name + assert ret["result"] + assert isinstance(ret["changes"], dict) + assert isinstance(ret["comment"], str) + kernelpkg.__salt__["kernelpkg.upgrade"].assert_called_once() + + with patch.dict(kernelpkg.__opts__, {"test": True}): + kernelpkg.__salt__["kernelpkg.upgrade"].reset_mock() + ret = kernelpkg.latest_installed(name=state_name) + assert ret["name"] == state_name + assert ret["result"] is None + assert ret["changes"] == {} + assert isinstance(ret["comment"], str) + kernelpkg.__salt__["kernelpkg.upgrade"].assert_not_called() + + +def test_latest_installed_at_latest(kernel_list, state_name): + """ + Test - latest_installed when no upgrade is available + """ + installed = MagicMock(return_value=kernel_list) + upgrade = MagicMock(return_value=kernel_list[-1]) + with patch.dict(kernelpkg.__salt__, {"kernelpkg.list_installed": installed}): + with patch.dict(kernelpkg.__salt__, {"kernelpkg.latest_available": upgrade}): + with patch.dict(kernelpkg.__opts__, {"test": False}): + ret = kernelpkg.latest_installed(name=state_name) + assert ret["name"] == state_name + assert ret["result"] + assert ret["changes"] == {} + assert isinstance(ret["comment"], str) + kernelpkg.__salt__["kernelpkg.upgrade"].assert_not_called() + + with patch.dict(kernelpkg.__opts__, {"test": True}): + ret = kernelpkg.latest_installed(name=state_name) + assert ret["name"] == state_name + assert ret["result"] + assert ret["changes"] == {} + assert isinstance(ret["comment"], str) + kernelpkg.__salt__["kernelpkg.upgrade"].assert_not_called() + + +def test_latest_active_with_changes(state_name): + """ + Test - latest_active when a new kernel is available + """ + reboot = MagicMock(return_value=True) + latest = MagicMock(return_value=1) + with patch.dict( + kernelpkg.__salt__, + {"kernelpkg.needs_reboot": reboot, "kernelpkg.latest_installed": latest}, + ), patch.dict(kernelpkg.__opts__, {"test": False}): + kernelpkg.__salt__["system.reboot"].reset_mock() + ret = kernelpkg.latest_active(name=state_name) + assert ret["name"] == state_name + assert ret["result"] + assert isinstance(ret["changes"], dict) + assert isinstance(ret["comment"], str) + kernelpkg.__salt__["system.reboot"].assert_called_once() + + with patch.dict(kernelpkg.__opts__, {"test": True}): + kernelpkg.__salt__["system.reboot"].reset_mock() + ret = kernelpkg.latest_active(name=state_name) + assert ret["name"] == state_name + assert ret["result"] is None + assert ret["changes"] == {"kernel": {"new": 1, "old": 0}} + assert isinstance(ret["comment"], str) + kernelpkg.__salt__["system.reboot"].assert_not_called() + + +def test_latest_active_at_latest(state_name): + """ + Test - latest_active when the newest kernel is already active + """ + reboot = MagicMock(return_value=False) + with patch.dict(kernelpkg.__salt__, {"kernelpkg.needs_reboot": reboot}): + with patch.dict(kernelpkg.__opts__, {"test": False}): + kernelpkg.__salt__["system.reboot"].reset_mock() + ret = kernelpkg.latest_active(name=state_name) + assert ret["name"] == state_name + assert ret["result"] + assert ret["changes"] == {} + assert isinstance(ret["comment"], str) + kernelpkg.__salt__["system.reboot"].assert_not_called() + + with patch.dict(kernelpkg.__opts__, {"test": True}): + kernelpkg.__salt__["system.reboot"].reset_mock() + ret = kernelpkg.latest_active(name=state_name) + assert ret["name"] == state_name + assert ret["result"] + assert ret["changes"] == {} + assert isinstance(ret["comment"], str) + kernelpkg.__salt__["system.reboot"].assert_not_called() + + +def test_latest_wait(state_name): + """ + Test - latest_wait static results + """ + ret = kernelpkg.latest_wait(name=state_name) + assert ret["name"] == state_name + assert ret["result"] + assert ret["changes"] == {} + assert isinstance(ret["comment"], str) diff --git a/tests/pytests/unit/states/test_keystone.py b/tests/pytests/unit/states/test_keystone.py new file mode 100644 index 00000000000..d0461180433 --- /dev/null +++ b/tests/pytests/unit/states/test_keystone.py @@ -0,0 +1,397 @@ +""" + :codeauthor: Jayesh Kariya + + Test cases for salt.states.keystone +""" + +import pytest + +import salt.states.keystone as keystone +from tests.support.mock import MagicMock, patch + + +@pytest.fixture +def configure_loader_modules(): + return {keystone: {}} + + +def test_user_present(): + """ + Test to ensure that the keystone user is present + with the specified properties. + """ + name = "nova" + password = "$up3rn0v4" + email = "nova@domain.com" + tenant = "demo" + + ret = {"name": name, "result": False, "changes": {}, "comment": ""} + + mock_f = MagicMock(return_value=False) + mock_lst = MagicMock(return_value=["Error"]) + with patch.dict(keystone.__salt__, {"keystone.tenant_get": mock_lst}): + comt = 'Tenant / project "{}" does not exist'.format(tenant) + ret.update({"comment": comt}) + assert keystone.user_present(name, password, email, tenant) == ret + + mock_dict = MagicMock( + side_effect=[ + {name: {"email": "a@a.com"}}, + {name: {"email": email, "enabled": False}}, + {name: {"email": email, "enabled": True}}, + {name: {"email": email, "enabled": True}}, + {"Error": "error"}, + {"Error": "error"}, + ] + ) + mock_l = MagicMock(return_value={tenant: {"id": "abc"}}) + with patch.dict( + keystone.__salt__, + { + "keystone.user_get": mock_dict, + "keystone.tenant_get": mock_l, + "keystone.user_verify_password": mock_f, + "keystone.user_create": mock_f, + }, + ): + with patch.dict(keystone.__opts__, {"test": True}): + comt = 'User "{}" will be updated'.format(name) + ret.update( + { + "comment": comt, + "result": None, + "changes": { + "Email": "Will be updated", + "Enabled": "Will be True", + "Password": "Will be updated", + }, + } + ) + assert keystone.user_present(name, password, email) == ret + + ret.update( + { + "comment": comt, + "result": None, + "changes": { + "Enabled": "Will be True", + "Password": "Will be updated", + }, + } + ) + assert keystone.user_present(name, password, email) == ret + + ret.update( + { + "comment": comt, + "result": None, + "changes": { + "Tenant": 'Will be added to "demo" tenant', + "Password": "Will be updated", + }, + } + ) + assert keystone.user_present(name, password, email, tenant) == ret + + ret.update( + { + "comment": comt, + "result": None, + "changes": {"Password": "Will be updated"}, + } + ) + assert keystone.user_present(name, password, email) == ret + + comt = 'Keystone user "nova" will be added' + ret.update( + { + "comment": comt, + "result": None, + "changes": {"User": "Will be created"}, + } + ) + assert keystone.user_present(name, password, email) == ret + + with patch.dict(keystone.__opts__, {"test": False}): + comt = "Keystone user {} has been added".format(name) + ret.update( + {"comment": comt, "result": True, "changes": {"User": "Created"}} + ) + assert keystone.user_present(name, password, email) == ret + + +def test_user_absent(): + """ + Test to ensure that the keystone user is absent. + """ + name = "nova" + + ret = { + "name": name, + "changes": {}, + "result": True, + "comment": 'User "{}" is already absent'.format(name), + } + + mock_lst = MagicMock(side_effect=[["Error"], []]) + with patch.dict(keystone.__salt__, {"keystone.user_get": mock_lst}): + assert keystone.user_absent(name) == ret + + with patch.dict(keystone.__opts__, {"test": True}): + comt = 'User "{}" will be deleted'.format(name) + ret.update({"comment": comt, "result": None}) + assert keystone.user_absent(name) == ret + + +def test_tenant_present(): + """ + Test to ensures that the keystone tenant exists + """ + name = "nova" + description = "OpenStack Compute Service" + + ret = { + "name": name, + "changes": {}, + "result": True, + "comment": 'Tenant / project "{}" already exists'.format(name), + } + + mock_dict = MagicMock( + side_effect=[ + {name: {"description": "desc"}}, + {name: {"description": description, "enabled": False}}, + {"Error": "error"}, + {"Error": "error"}, + ] + ) + mock_t = MagicMock(return_value=True) + with patch.dict( + keystone.__salt__, + {"keystone.tenant_get": mock_dict, "keystone.tenant_create": mock_t}, + ): + with patch.dict(keystone.__opts__, {"test": True}): + comt = 'Tenant / project "{}" will be updated'.format(name) + ret.update( + { + "comment": comt, + "result": None, + "changes": {"Description": "Will be updated"}, + } + ) + assert keystone.tenant_present(name) == ret + + comt = 'Tenant / project "{}" will be updated'.format(name) + ret.update( + { + "comment": comt, + "result": None, + "changes": {"Enabled": "Will be True"}, + } + ) + assert keystone.tenant_present(name, description) == ret + + comt = 'Tenant / project "{}" will be added'.format(name) + ret.update( + { + "comment": comt, + "result": None, + "changes": {"Tenant": "Will be created"}, + } + ) + assert keystone.tenant_present(name) == ret + + with patch.dict(keystone.__opts__, {"test": False}): + comt = 'Tenant / project "{}" has been added'.format(name) + ret.update( + {"comment": comt, "result": True, "changes": {"Tenant": "Created"}} + ) + assert keystone.tenant_present(name) == ret + + +def test_tenant_absent(): + """ + Test to ensure that the keystone tenant is absent. + """ + name = "nova" + + ret = { + "name": name, + "changes": {}, + "result": True, + "comment": 'Tenant / project "{}" is already absent'.format(name), + } + + mock_lst = MagicMock(side_effect=[["Error"], []]) + with patch.dict(keystone.__salt__, {"keystone.tenant_get": mock_lst}): + assert keystone.tenant_absent(name) == ret + + with patch.dict(keystone.__opts__, {"test": True}): + comt = 'Tenant / project "{}" will be deleted'.format(name) + ret.update({"comment": comt, "result": None}) + assert keystone.tenant_absent(name) == ret + + +def test_role_present(): + """ + Test to ensures that the keystone role exists + """ + name = "nova" + + ret = { + "name": name, + "changes": {}, + "result": True, + "comment": 'Role "{}" already exists'.format(name), + } + + mock_lst = MagicMock(side_effect=[[], ["Error"]]) + with patch.dict(keystone.__salt__, {"keystone.role_get": mock_lst}): + assert keystone.role_present(name) == ret + + with patch.dict(keystone.__opts__, {"test": True}): + comt = 'Role "{}" will be added'.format(name) + ret.update({"comment": comt, "result": None}) + assert keystone.role_present(name) == ret + + +def test_role_absent(): + """ + Test to ensure that the keystone role is absent. + """ + name = "nova" + + ret = { + "name": name, + "changes": {}, + "result": True, + "comment": 'Role "{}" is already absent'.format(name), + } + + mock_lst = MagicMock(side_effect=[["Error"], []]) + with patch.dict(keystone.__salt__, {"keystone.role_get": mock_lst}): + assert keystone.role_absent(name) == ret + + with patch.dict(keystone.__opts__, {"test": True}): + comt = 'Role "{}" will be deleted'.format(name) + ret.update({"comment": comt, "result": None}) + assert keystone.role_absent(name) == ret + + +def test_service_present(): + """ + Test to ensure service present in Keystone catalog + """ + name = "nova" + service_type = "compute" + + ret = { + "name": name, + "changes": {}, + "result": True, + "comment": 'Service "{}" already exists'.format(name), + } + + mock_lst = MagicMock(side_effect=[[], ["Error"]]) + with patch.dict(keystone.__salt__, {"keystone.service_get": mock_lst}): + assert keystone.service_present(name, service_type) == ret + + with patch.dict(keystone.__opts__, {"test": True}): + comt = 'Service "{}" will be added'.format(name) + ret.update({"comment": comt, "result": None}) + assert keystone.service_present(name, service_type) == ret + + +def test_service_absent(): + """ + Test to ensure that the service doesn't exist in Keystone catalog + """ + name = "nova" + + ret = { + "name": name, + "changes": {}, + "result": True, + "comment": 'Service "{}" is already absent'.format(name), + } + + mock_lst = MagicMock(side_effect=[["Error"], []]) + with patch.dict(keystone.__salt__, {"keystone.service_get": mock_lst}): + assert keystone.service_absent(name) == ret + + with patch.dict(keystone.__opts__, {"test": True}): + comt = 'Service "{}" will be deleted'.format(name) + ret.update({"comment": comt, "result": None}) + assert keystone.service_absent(name) == ret + + +def test_endpoint_present(): + """ + Test to ensure the specified endpoints exists for service + """ + name = "nova" + region = "RegionOne" + + ret = {"name": name, "changes": {}, "result": True, "comment": ""} + + endpoint = { + "adminurl": None, + "region": None, + "internalurl": None, + "publicurl": None, + "id": 1, + "service_id": None, + } + + mock_lst = MagicMock( + side_effect=[endpoint, ["Error"], {"id": 1, "service_id": None}, []] + ) + mock = MagicMock(return_value=True) + with patch.dict( + keystone.__salt__, + {"keystone.endpoint_get": mock_lst, "keystone.endpoint_create": mock}, + ): + + comt = 'Endpoint for service "{}" already exists'.format(name) + ret.update({"comment": comt, "result": True, "changes": {}}) + assert keystone.endpoint_present(name) == ret + + with patch.dict(keystone.__opts__, {"test": True}): + comt = 'Endpoint for service "{}" will be added'.format(name) + ret.update( + { + "comment": comt, + "result": None, + "changes": {"Endpoint": "Will be created"}, + } + ) + assert keystone.endpoint_present(name) == ret + + comt = 'Endpoint for service "{}" already exists'.format(name) + ret.update({"comment": comt, "result": True, "changes": {}}) + assert keystone.endpoint_present(name) == ret + + with patch.dict(keystone.__opts__, {"test": False}): + comt = 'Endpoint for service "{}" has been added'.format(name) + ret.update({"comment": comt, "result": True, "changes": True}) + assert keystone.endpoint_present(name) == ret + + +def test_endpoint_absent(): + """ + Test to ensure that the endpoint for a service doesn't + exist in Keystone catalog + """ + name = "nova" + region = "RegionOne" + comment = 'Endpoint for service "{}" is already absent'.format(name) + ret = {"name": name, "changes": {}, "result": True, "comment": comment} + + mock_lst = MagicMock(side_effect=[[], ["Error"]]) + with patch.dict(keystone.__salt__, {"keystone.endpoint_get": mock_lst}): + assert keystone.endpoint_absent(name, region) == ret + + with patch.dict(keystone.__opts__, {"test": True}): + comt = 'Endpoint for service "{}" will be deleted'.format(name) + ret.update({"comment": comt, "result": None}) + assert keystone.endpoint_absent(name, region) == ret diff --git a/tests/pytests/unit/states/test_keystore.py b/tests/pytests/unit/states/test_keystore.py new file mode 100644 index 00000000000..8e6bfdabf25 --- /dev/null +++ b/tests/pytests/unit/states/test_keystore.py @@ -0,0 +1,497 @@ +""" + Test cases for salt.states.keystore +""" + +import pytest + +import salt.states.keystore as keystore +from tests.support.mock import MagicMock, patch + + +@pytest.fixture +def configure_loader_modules(): + return {keystore: {"__opts__": {"test": False}}} + + +def test_cert_already_present(): + """ + Test for existing value_present + """ + + cert_return = [ + { + "valid_until": "August 21 2017", + "sha1": "07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D5".encode( + __salt_system_encoding__ + ), + "valid_start": "August 22 2012", + "type": "TrustedCertEntry", + "alias": "stringhost", + "expired": True, + } + ] + x509_return = { + "Not After": "2017-08-21 05:26:54", + "Subject Hash": "97:95:14:4F", + "Serial Number": "0D:FA", + "SHA1 Finger Print": ( + "07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D5".encode( + __salt_system_encoding__ + ) + ), + "SHA-256 Finger Print": "5F:0F:B5:16:65:81:AA:E6:4A:10:1C:15:83:B1:BE:BE:74:E8:14:A9:1E:7A:8A:14:BA:1E:83:5D:78:F6:E9:E7".encode( + __salt_system_encoding__ + ), + "MD5 Finger Print": "80:E6:17:AF:78:D8:E4:B8:FB:5F:41:3A:27:1D:CC:F2".encode( + __salt_system_encoding__ + ), + "Version": 1, + "Key Size": 512, + "Public Key": ( + "-----BEGIN PUBLIC" + " KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJv8ZpB5hEK7qxP9K3v43hUS5fGT4waK\ne7ix4Z4mu5UBv+cw7WSFAt0Vaag0sAbsPzU8Hhsrj/qPABvfB8asUwcCAwEAAQ==\n-----END" + " PUBLIC KEY-----\n" + ), + "Issuer": { + "C": "JP", + "organizationName": "Frank4DD", + "CN": "Frank4DD Web CA", + "SP": "Tokyo", + "L": "Chuo-ku", + "emailAddress": "support@frank4dd.com", + "OU": "WebCert Support", + }, + "Issuer Hash": "92:DA:45:6B", + "Not Before": "2012-08-22 05:26:54", + "Subject": { + "C": "JP", + "SP": "Tokyo", + "organizationName": "Frank4DD", + "CN": "www.example.com", + }, + } + + name = "keystore.jks" + passphrase = "changeit" + entries = [ + { + "alias": "stringhost", + "certificate": """-----BEGIN CERTIFICATE----- + MIICEjCCAXsCAg36MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG + A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE + MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl + YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw + ODIyMDUyNjU0WhcNMTcwODIxMDUyNjU0WjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE + CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs + ZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAm/xmkHmEQrurE/0re/jeFRLl + 8ZPjBop7uLHhnia7lQG/5zDtZIUC3RVpqDSwBuw/NTweGyuP+o8AG98HxqxTBwID + AQABMA0GCSqGSIb3DQEBBQUAA4GBABS2TLuBeTPmcaTaUW/LCB2NYOy8GMdzR1mx + 8iBIu2H6/E2tiY3RIevV2OW61qY2/XRQg7YPxx3ffeUugX9F4J/iPnnu1zAxxyBy + 2VguKv4SWjRFoRkIfIlHX0qVviMhSlNy2ioFLy7JcPZb+v3ftDGywUqcBiVDoea0 + Hn+GmxZA\n-----END CERTIFICATE-----""", + } + ] + + state_return = { + "name": name, + "changes": {}, + "result": True, + "comment": "No changes made.\n", + } + + # with patch.dict(keystore.__opts__, {'test': False}): + with patch("os.path.exists", return_value=True): + with patch.dict( + keystore.__salt__, + { + "keystore.list": MagicMock(return_value=cert_return), + "x509.read_certificate": MagicMock(return_value=x509_return), + }, + ): + assert keystore.managed(name, passphrase, entries) == state_return + + with patch("os.path.exists", return_value=True): + with patch.dict(keystore.__opts__, {"test": True}): + with patch.dict( + keystore.__salt__, + { + "keystore.list": MagicMock(return_value=cert_return), + "x509.read_certificate": MagicMock(return_value=x509_return), + }, + ): + assert keystore.managed(name, passphrase, entries) == state_return + + +def test_cert_update(): + """ + Test for existing value_present + """ + + cert_return = [ + { + "valid_until": "August 21 2017", + "sha1": "07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D5".encode( + __salt_system_encoding__ + ), + "valid_start": "August 22 2012", + "type": "TrustedCertEntry", + "alias": "stringhost", + "expired": True, + } + ] + x509_return = { + "Not After": "2017-08-21 05:26:54", + "Subject Hash": "97:95:14:4F", + "Serial Number": "0D:FA", + "SHA1 Finger Print": ( + "07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D6".encode( + __salt_system_encoding__ + ) + ), + "SHA-256 Finger Print": "5F:0F:B5:16:65:81:AA:E6:4A:10:1C:15:83:B1:BE:BE:74:E8:14:A9:1E:7A:8A:14:BA:1E:83:5D:78:F6:E9:E7", + "MD5 Finger Print": "80:E6:17:AF:78:D8:E4:B8:FB:5F:41:3A:27:1D:CC:F2", + "Version": 1, + "Key Size": 512, + "Public Key": ( + "-----BEGIN PUBLIC" + " KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJv8ZpB5hEK7qxP9K3v43hUS5fGT4waK\ne7ix4Z4mu5UBv+cw7WSFAt0Vaag0sAbsPzU8Hhsrj/qPABvfB8asUwcCAwEAAQ==\n-----END" + " PUBLIC KEY-----\n" + ), + "Issuer": { + "C": "JP", + "organizationName": "Frank4DD", + "CN": "Frank4DD Web CA", + "SP": "Tokyo", + "L": "Chuo-ku", + "emailAddress": "support@frank4dd.com", + "OU": "WebCert Support", + }, + "Issuer Hash": "92:DA:45:6B", + "Not Before": "2012-08-22 05:26:54", + "Subject": { + "C": "JP", + "SP": "Tokyo", + "organizationName": "Frank4DD", + "CN": "www.example.com", + }, + } + + name = "keystore.jks" + passphrase = "changeit" + entries = [ + { + "alias": "stringhost", + "certificate": """-----BEGIN CERTIFICATE----- + MIICEjCCAXsCAg36MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG + A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE + MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl + YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw + ODIyMDUyNjU0WhcNMTcwODIxMDUyNjU0WjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE + CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs + ZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAm/xmkHmEQrurE/0re/jeFRLl + 8ZPjBop7uLHhnia7lQG/5zDtZIUC3RVpqDSwBuw/NTweGyuP+o8AG98HxqxTBwID + AQABMA0GCSqGSIb3DQEBBQUAA4GBABS2TLuBeTPmcaTaUW/LCB2NYOy8GMdzR1mx + 8iBIu2H6/E2tiY3RIevV2OW61qY2/XRQg7YPxx3ffeUugX9F4J/iPnnu1zAxxyBy + 2VguKv4SWjRFoRkIfIlHX0qVviMhSlNy2ioFLy7JcPZb+v3ftDGywUqcBiVDoea0 + Hn+GmxZA\n-----END CERTIFICATE-----""", + } + ] + + test_return = { + "name": name, + "changes": {}, + "result": None, + "comment": "Alias stringhost would have been updated\n", + } + state_return = { + "name": name, + "changes": {"stringhost": "Updated"}, + "result": True, + "comment": "Alias stringhost updated.\n", + } + + with patch.dict(keystore.__opts__, {"test": True}): + with patch("os.path.exists", return_value=True): + with patch.dict( + keystore.__salt__, + { + "keystore.list": MagicMock(return_value=cert_return), + "x509.read_certificate": MagicMock(return_value=x509_return), + }, + ): + assert keystore.managed(name, passphrase, entries) == test_return + + with patch("os.path.exists", return_value=True): + with patch.dict( + keystore.__salt__, + { + "keystore.list": MagicMock(return_value=cert_return), + "x509.read_certificate": MagicMock(return_value=x509_return), + "keystore.remove": MagicMock(return_value=True), + "keystore.add": MagicMock(return_value=True), + }, + ): + assert keystore.managed(name, passphrase, entries) == state_return + + +def test_cert_update_no_sha1_fingerprint_in_x509(): + """ + Test for existing value_present + """ + + cert_return = [ + { + "valid_until": "August 21 2017", + "sha1": "07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D5".encode( + __salt_system_encoding__ + ), + "valid_start": "August 22 2012", + "type": "TrustedCertEntry", + "alias": "stringhost", + "expired": True, + } + ] + sha1_return = b"07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D5" + x509_return = { + "Not After": "2017-08-21 05:26:54", + "Subject Hash": "97:95:14:4F", + "Serial Number": "0D:FA", + "SHA-256 Finger Print": "5F:0F:B5:16:65:81:AA:E6:4A:10:1C:15:83:B1:BE:BE:74:E8:14:A9:1E:7A:8A:14:BA:1E:83:5D:78:F6:E9:E7", + "MD5 Finger Print": "80:E6:17:AF:78:D8:E4:B8:FB:5F:41:3A:27:1D:CC:F2", + "Version": 1, + "Key Size": 512, + "Public Key": ( + "-----BEGIN PUBLIC" + " KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJv8ZpB5hEK7qxP9K3v43hUS5fGT4waK\ne7ix4Z4mu5UBv+cw7WSFAt0Vaag0sAbsPzU8Hhsrj/qPABvfB8asUwcCAwEAAQ==\n-----END" + " PUBLIC KEY-----\n" + ), + "Issuer": { + "C": "JP", + "organizationName": "Frank4DD", + "CN": "Frank4DD Web CA", + "SP": "Tokyo", + "L": "Chuo-ku", + "emailAddress": "support@frank4dd.com", + "OU": "WebCert Support", + }, + "Issuer Hash": "92:DA:45:6B", + "Not Before": "2012-08-22 05:26:54", + "Subject": { + "C": "JP", + "SP": "Tokyo", + "organizationName": "Frank4DD", + "CN": "www.example.com", + }, + } + + name = "keystore.jks" + passphrase = "changeit" + entries = [ + { + "alias": "stringhost", + "certificate": """-----BEGIN CERTIFICATE----- + MIICEjCCAXsCAg36MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG + A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE + MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl + YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw + ODIyMDUyNjU0WhcNMTcwODIxMDUyNjU0WjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE + CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs + ZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAm/xmkHmEQrurE/0re/jeFRLl + 8ZPjBop7uLHhnia7lQG/5zDtZIUC3RVpqDSwBuw/NTweGyuP+o8AG98HxqxTBwID + AQABMA0GCSqGSIb3DQEBBQUAA4GBABS2TLuBeTPmcaTaUW/LCB2NYOy8GMdzR1mx + 8iBIu2H6/E2tiY3RIevV2OW61qY2/XRQg7YPxx3ffeUugX9F4J/iPnnu1zAxxyBy + 2VguKv4SWjRFoRkIfIlHX0qVviMhSlNy2ioFLy7JcPZb+v3ftDGywUqcBiVDoea0 + Hn+GmxZA\n-----END CERTIFICATE-----""", + } + ] + + test_return = { + "name": name, + "changes": {}, + "result": True, + "comment": "No changes made.\n", + } + with patch("os.path.exists", return_value=True): + with patch.dict(keystore.__opts__, {"test": True}): + with patch.dict( + keystore.__salt__, + { + "keystore.list": MagicMock(return_value=cert_return), + "x509.read_certificate": MagicMock(return_value=x509_return), + "keystore.get_sha1": MagicMock(return_value=sha1_return), + }, + ): + assert keystore.managed(name, passphrase, entries) == test_return + + +def test_new_file(): + """ + Test for existing value_present + """ + name = "keystore.jks" + passphrase = "changeit" + entries = [ + { + "alias": "stringhost", + "certificate": """-----BEGIN CERTIFICATE----- + MIICEjCCAXsCAg36MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG + A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE + MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl + YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw + ODIyMDUyNjU0WhcNMTcwODIxMDUyNjU0WjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE + CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs + ZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAm/xmkHmEQrurE/0re/jeFRLl + 8ZPjBop7uLHhnia7lQG/5zDtZIUC3RVpqDSwBuw/NTweGyuP+o8AG98HxqxTBwID + AQABMA0GCSqGSIb3DQEBBQUAA4GBABS2TLuBeTPmcaTaUW/LCB2NYOy8GMdzR1mx + 8iBIu2H6/E2tiY3RIevV2OW61qY2/XRQg7YPxx3ffeUugX9F4J/iPnnu1zAxxyBy + 2VguKv4SWjRFoRkIfIlHX0qVviMhSlNy2ioFLy7JcPZb+v3ftDGywUqcBiVDoea0 + Hn+GmxZA\n-----END CERTIFICATE-----""", + } + ] + + test_return = { + "name": name, + "changes": {}, + "result": None, + "comment": "Alias stringhost would have been added\n", + } + state_return = { + "name": name, + "changes": {"stringhost": "Added"}, + "result": True, + "comment": "Alias stringhost added.\n", + } + + with patch.dict(keystore.__opts__, {"test": True}): + assert keystore.managed(name, passphrase, entries) == test_return + + with patch("os.path.exists", return_value=False): + with patch.dict( + keystore.__salt__, + { + "keystore.remove": MagicMock(return_value=True), + "keystore.add": MagicMock(return_value=True), + }, + ): + assert keystore.managed(name, passphrase, entries) == state_return + + +def test_force_remove(): + """ + Test for existing value_present + """ + + cert_return = [ + { + "valid_until": "August 21 2017", + "sha1": "07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D5".encode( + __salt_system_encoding__ + ), + "valid_start": "August 22 2012", + "type": "TrustedCertEntry", + "alias": "oldhost", + "expired": True, + } + ] + x509_return = { + "Not After": "2017-08-21 05:26:54", + "Subject Hash": "97:95:14:4F", + "Serial Number": "0D:FA", + "SHA1 Finger Print": ( + "07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D6".encode( + __salt_system_encoding__ + ) + ), + "SHA-256 Finger Print": "5F:0F:B5:16:65:81:AA:E6:4A:10:1C:15:83:B1:BE:BE:74:E8:14:A9:1E:7A:8A:14:BA:1E:83:5D:78:F6:E9:E7", + "MD5 Finger Print": "80:E6:17:AF:78:D8:E4:B8:FB:5F:41:3A:27:1D:CC:F2", + "Version": 1, + "Key Size": 512, + "Public Key": ( + "-----BEGIN PUBLIC" + " KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJv8ZpB5hEK7qxP9K3v43hUS5fGT4waK\ne7ix4Z4mu5UBv+cw7WSFAt0Vaag0sAbsPzU8Hhsrj/qPABvfB8asUwcCAwEAAQ==\n-----END" + " PUBLIC KEY-----\n" + ), + "Issuer": { + "C": "JP", + "organizationName": "Frank4DD", + "CN": "Frank4DD Web CA", + "SP": "Tokyo", + "L": "Chuo-ku", + "emailAddress": "support@frank4dd.com", + "OU": "WebCert Support", + }, + "Issuer Hash": "92:DA:45:6B", + "Not Before": "2012-08-22 05:26:54", + "Subject": { + "C": "JP", + "SP": "Tokyo", + "organizationName": "Frank4DD", + "CN": "www.example.com", + }, + } + + name = "keystore.jks" + passphrase = "changeit" + entries = [ + { + "alias": "stringhost", + "certificate": """-----BEGIN CERTIFICATE----- + MIICEjCCAXsCAg36MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG + A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE + MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl + YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw + ODIyMDUyNjU0WhcNMTcwODIxMDUyNjU0WjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE + CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs + ZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAm/xmkHmEQrurE/0re/jeFRLl + 8ZPjBop7uLHhnia7lQG/5zDtZIUC3RVpqDSwBuw/NTweGyuP+o8AG98HxqxTBwID + AQABMA0GCSqGSIb3DQEBBQUAA4GBABS2TLuBeTPmcaTaUW/LCB2NYOy8GMdzR1mx + 8iBIu2H6/E2tiY3RIevV2OW61qY2/XRQg7YPxx3ffeUugX9F4J/iPnnu1zAxxyBy + 2VguKv4SWjRFoRkIfIlHX0qVviMhSlNy2ioFLy7JcPZb+v3ftDGywUqcBiVDoea0 + Hn+GmxZA\n-----END CERTIFICATE-----""", + } + ] + + test_return = { + "name": name, + "changes": {}, + "result": None, + "comment": ( + "Alias stringhost would have been updated\nAlias oldhost would have" + " been removed" + ), + } + state_return = { + "name": name, + "changes": {"oldhost": "Removed", "stringhost": "Updated"}, + "result": True, + "comment": "Alias stringhost updated.\nAlias oldhost removed.\n", + } + + with patch.dict(keystore.__opts__, {"test": True}): + with patch("os.path.exists", return_value=True): + with patch.dict( + keystore.__salt__, + { + "keystore.list": MagicMock(return_value=cert_return), + "x509.read_certificate": MagicMock(return_value=x509_return), + }, + ): + assert ( + keystore.managed(name, passphrase, entries, force_remove=True) + == test_return + ) + + with patch("os.path.exists", return_value=True): + with patch.dict( + keystore.__salt__, + { + "keystore.list": MagicMock(return_value=cert_return), + "x509.read_certificate": MagicMock(return_value=x509_return), + "keystore.remove": MagicMock(return_value=True), + "keystore.add": MagicMock(return_value=True), + }, + ): + assert ( + keystore.managed(name, passphrase, entries, force_remove=True) + == state_return + ) diff --git a/tests/pytests/unit/states/test_net_napalm_yang.py b/tests/pytests/unit/states/test_net_napalm_yang.py new file mode 100644 index 00000000000..99c99e06a7f --- /dev/null +++ b/tests/pytests/unit/states/test_net_napalm_yang.py @@ -0,0 +1,55 @@ +""" + :codeauthor: Anthony Shaw + + Test cases for salt.states.net_napalm_yang +""" + +import pytest + +import salt.states.net_napalm_yang as netyang +from tests.support.mock import MagicMock, patch + + +@pytest.fixture +def configure_loader_modules(): + return {netyang: {}} + + +def test_managed(): + ret = {"changes": {}, "comment": "Loaded.", "name": "test", "result": False} + parse = MagicMock(return_value="abcdef") + temp_file = MagicMock(return_value="") + compliance_report = MagicMock(return_value={"complies": False}) + load_config = MagicMock(return_value={"comment": "Loaded."}) + file_remove = MagicMock() + + with patch("salt.utils.files.fopen"): + with patch.dict( + netyang.__salt__, + { + "temp.file": temp_file, + "napalm_yang.parse": parse, + "napalm_yang.load_config": load_config, + "napalm_yang.compliance_report": compliance_report, + "file.remove": file_remove, + }, + ): + with patch.dict(netyang.__opts__, {"test": False}): + assert netyang.managed("test", "test", models=("model1",)) == ret + assert parse.called + assert temp_file.called + assert compliance_report.called + assert load_config.called + assert file_remove.called + + +def test_configured(): + ret = {"changes": {}, "comment": "Loaded.", "name": "test", "result": False} + load_config = MagicMock(return_value={"comment": "Loaded."}) + + with patch("salt.utils.files.fopen"): + with patch.dict(netyang.__salt__, {"napalm_yang.load_config": load_config}): + with patch.dict(netyang.__opts__, {"test": False}): + assert netyang.configured("test", "test", models=("model1",)) == ret + + assert load_config.called diff --git a/tests/pytests/unit/states/test_zfs.py b/tests/pytests/unit/states/test_zfs.py index 1c25a4c0e99..ce622cf7951 100644 --- a/tests/pytests/unit/states/test_zfs.py +++ b/tests/pytests/unit/states/test_zfs.py @@ -18,6 +18,10 @@ from salt.utils.odict import OrderedDict from tests.support.mock import MagicMock, patch from tests.support.zfs import ZFSMockData +pytestmark = [ + pytest.mark.slow_test, +] + @pytest.fixture def utils_patch(): diff --git a/tests/pytests/unit/states/test_zpool.py b/tests/pytests/unit/states/test_zpool.py index af14b900f0b..62afec60bea 100644 --- a/tests/pytests/unit/states/test_zpool.py +++ b/tests/pytests/unit/states/test_zpool.py @@ -18,6 +18,10 @@ from salt.utils.odict import OrderedDict from tests.support.mock import MagicMock, patch from tests.support.zfs import ZFSMockData +pytestmark = [ + pytest.mark.slow_test, +] + @pytest.fixture def utils_patch(): diff --git a/tests/pytests/unit/test_fileclient.py b/tests/pytests/unit/test_fileclient.py new file mode 100644 index 00000000000..20d16baa734 --- /dev/null +++ b/tests/pytests/unit/test_fileclient.py @@ -0,0 +1,48 @@ +import salt.fileclient +from tests.support.mock import patch + + +class MockReqChannel: + def factory(self, opts): + return self + + def close(self): + return True + + def send(self, load): + return self + + +def test_fileclient_context_manager_closes(temp_salt_minion, temp_salt_master): + """ + ensure fileclient channel closes + when used with a context manager + """ + opts = temp_salt_minion.config.copy() + opts.update( + { + "id": "root", + "transport": "zeromq", + "auth_tries": 1, + "auth_timeout": 5, + "master_ip": "127.0.0.1", + "master_port": temp_salt_master.config["ret_port"], + "master_uri": "tcp://127.0.0.1:{}".format( + temp_salt_master.config["ret_port"] + ), + } + ) + master_uri = "tcp://{master_ip}:{master_port}".format( + master_ip="localhost", master_port=opts["master_port"] + ) + mock_reqchannel = MockReqChannel() + patch_reqchannel = patch.object( + salt.channel.client, "ReqChannel", return_value=mock_reqchannel + ) + with patch_reqchannel: + with salt.fileclient.get_file_client(opts) as client: + client.master_opts() + assert not client._closing + + assert client._closing + assert client.channel.close.called diff --git a/tests/pytests/unit/test_master.py b/tests/pytests/unit/test_master.py index 14e137f4983..cd11d217c79 100644 --- a/tests/pytests/unit/test_master.py +++ b/tests/pytests/unit/test_master.py @@ -21,7 +21,39 @@ def encrypted_requests(tmp_path): ) +def test_maintenance_duration(): + """ + Validate Maintenance process duration. + """ + opts = { + "loop_interval": 10, + "maintenance_interval": 1, + "cachedir": "/tmp", + "sock_dir": "/tmp", + "maintenance_niceness": 1, + "key_cache": "sched", + "conf_file": "", + "master_job_cache": "", + "pki_dir": "/tmp", + "eauth_tokens": "", + } + mp = salt.master.Maintenance(opts) + with patch("salt.utils.verify.check_max_open_files") as check_files, patch.object( + mp, "handle_key_cache" + ) as handle_key_cache, patch("salt.daemons") as salt_daemons, patch.object( + mp, "handle_git_pillar" + ) as handle_git_pillar: + mp.run() + assert salt_daemons.masterapi.clean_old_jobs.called + assert salt_daemons.masterapi.clean_expired_tokens.called + assert salt_daemons.masterapi.clean_pub_auth.called + assert handle_git_pillar.called + + def test_fileserver_duration(): + """ + Validate Fileserver process duration. + """ with patch("salt.master.FileserverUpdate._do_update") as update: start = time.time() salt.master.FileserverUpdate.update(1, {}, 1) diff --git a/tests/pytests/unit/test_scripts.py b/tests/pytests/unit/test_scripts.py new file mode 100644 index 00000000000..a636275e0de --- /dev/null +++ b/tests/pytests/unit/test_scripts.py @@ -0,0 +1,80 @@ +import pytest + +from salt.scripts import _pip_args, _pip_environment + + +def test_pip_environment_no_pypath(): + """ + We add PYTHONPATH to environemnt when it doesn't already exist. + """ + extras = "/tmp/footest" + env = {"HOME": "/home/dwoz"} + pipenv = _pip_environment(env, extras) + assert "PYTHONPATH" not in env + assert "PYTHONPATH" in pipenv + assert pipenv["PYTHONPATH"] == "/tmp/footest" + + +@pytest.mark.skip_on_windows(reason="Specific to *nix systems") +def test_pip_environment_pypath_nix(): + """ + We update PYTHONPATH in environemnt when it's already set. + """ + extras = "/tmp/footest" + env = { + "HOME": "/home/dwoz", + "PYTHONPATH": "/usr/local/lib/python3.10/site-packages", + } + assert "PYTHONPATH" in env + pipenv = _pip_environment(env, extras) + assert env["PYTHONPATH"] == "/usr/local/lib/python3.10/site-packages" + assert "PYTHONPATH" in pipenv + assert ( + pipenv["PYTHONPATH"] == "/tmp/footest:/usr/local/lib/python3.10/site-packages" + ) + + +@pytest.mark.skip_unless_on_windows(reason="Specific to win32 systems") +def test_pip_environment_pypath_win(): + """ + We update PYTHONPATH in environemnt when it's already set. + """ + extras = "/tmp/footest" + env = { + "HOME": "/home/dwoz", + "PYTHONPATH": "/usr/local/lib/python3.10/site-packages", + } + assert "PYTHONPATH" in env + pipenv = _pip_environment(env, extras) + assert env["PYTHONPATH"] == "/usr/local/lib/python3.10/site-packages" + assert "PYTHONPATH" in pipenv + assert ( + pipenv["PYTHONPATH"] == "/tmp/footest;/usr/local/lib/python3.10/site-packages" + ) + + +def test_pip_args_not_installing(): + extras = "/tmp/footest" + args = ["list"] + pargs = _pip_args(args, extras) + assert pargs is not args + assert args == ["list"] + assert pargs == ["list"] + + +def test_pip_args_installing_without_target(): + extras = "/tmp/footest" + args = ["install"] + pargs = _pip_args(args, extras) + assert pargs is not args + assert args == ["install"] + assert pargs == ["install", "--target=/tmp/footest"] + + +def test_pip_args_installing_with_target(): + extras = "/tmp/footest" + args = ["install", "--target=/tmp/bartest"] + pargs = _pip_args(args, extras) + assert pargs is not args + assert args == ["install", "--target=/tmp/bartest"] + assert pargs == ["install", "--target=/tmp/bartest"] diff --git a/tests/pytests/unit/transport/test_ipc.py b/tests/pytests/unit/transport/test_ipc.py index 8f41f9d723a..5a687836161 100644 --- a/tests/pytests/unit/transport/test_ipc.py +++ b/tests/pytests/unit/transport/test_ipc.py @@ -6,6 +6,10 @@ import salt.transport.ipc import salt.utils.asynchronous import salt.utils.platform +pytestmark = [ + pytest.mark.core_test, +] + def test_ipc_connect_in_async_methods(): "The connect method is in IPCMessageSubscriber's async_methods property" diff --git a/tests/pytests/unit/transport/test_tcp.py b/tests/pytests/unit/transport/test_tcp.py index e56468526f6..bcfb71f5590 100644 --- a/tests/pytests/unit/transport/test_tcp.py +++ b/tests/pytests/unit/transport/test_tcp.py @@ -12,6 +12,10 @@ import salt.ext.tornado import salt.transport.tcp from tests.support.mock import MagicMock, PropertyMock, patch +pytestmark = [ + pytest.mark.core_test, +] + @pytest.fixture def fake_keys(): diff --git a/tests/pytests/unit/transport/test_zeromq.py b/tests/pytests/unit/transport/test_zeromq.py index 6a4f177d1d9..10bb4917b83 100644 --- a/tests/pytests/unit/transport/test_zeromq.py +++ b/tests/pytests/unit/transport/test_zeromq.py @@ -40,6 +40,12 @@ except ImportError: log = logging.getLogger(__name__) + +pytestmark = [ + pytest.mark.core_test, +] + + MASTER_PRIV_KEY = """ -----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAoAsMPt+4kuIG6vKyw9r3+OuZrVBee/2vDdVetW+Js5dTlgrJ diff --git a/tests/pytests/unit/utils/event/test_event.py b/tests/pytests/unit/utils/event/test_event.py index 5ab3d7ffbcf..e289e72dad0 100644 --- a/tests/pytests/unit/utils/event/test_event.py +++ b/tests/pytests/unit/utils/event/test_event.py @@ -1,5 +1,8 @@ import hashlib +import os +import stat import time +from pathlib import Path import pytest import zmq.eventloop.ioloop @@ -327,3 +330,13 @@ def test_connect_pull_should_error_log_on_other_errors(error): assert not isinstance( call.args[1], salt.ext.tornado.iostream.StreamClosedError ) + + +@pytest.mark.slow_test +def test_master_pub_permissions(sock_dir): + with eventpublisher_process(str(sock_dir)): + p = Path(str(sock_dir)) / "master_event_pub.ipc" + mode = os.lstat(p).st_mode + assert bool(os.lstat(p).st_mode & stat.S_IRUSR) + assert not bool(os.lstat(p).st_mode & stat.S_IRGRP) + assert not bool(os.lstat(p).st_mode & stat.S_IROTH) diff --git a/tests/unit/modules/test_boto_dynamodb.py b/tests/unit/modules/test_boto_dynamodb.py deleted file mode 100644 index 571fad5b1ba..00000000000 --- a/tests/unit/modules/test_boto_dynamodb.py +++ /dev/null @@ -1,81 +0,0 @@ -import salt.modules.boto_dynamodb as boto_dynamodb -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase - -ARN = "arn:aws:dynamodb:us-east-1:012345678901:table/my-table" -TAGS = {"foo": "bar", "hello": "world"} -TAGS_AS_LIST = [{"Key": "foo", "Value": "bar"}, {"Key": "hello", "Value": "world"}] - - -class DummyConn: - def __init__(self): - self.list_tags_of_resource = MagicMock( - return_value={"Tags": TAGS_AS_LIST, "NextToken": None} - ) - self.tag_resource = MagicMock(return_value=True) - self.untag_resource = MagicMock(return_value=True) - - -class BotoDynamoDBTestCase(TestCase, LoaderModuleMockMixin): - """ - TestCase for salt.modules.boto_elb module - """ - - def setup_loader_modules(self): - return {boto_dynamodb: {"__opts__": {}, "__utils__": {}}} - - def test_list_tags_of_resource(self): - """ - Test that the correct API call is made and correct return format is - returned. - """ - conn = DummyConn() - utils = {"boto3.get_connection": MagicMock(return_value=conn)} - with patch.dict(boto_dynamodb.__utils__, utils): - ret = boto_dynamodb.list_tags_of_resource(resource_arn=ARN) - - assert ret == TAGS, ret - conn.list_tags_of_resource.assert_called_once_with( - ResourceArn=ARN, NextToken="" - ) - - def test_tag_resource(self): - """ - Test that the correct API call is made and correct return format is - returned. - """ - conn = DummyConn() - utils = {"boto3.get_connection": MagicMock(return_value=conn)} - with patch.dict(boto_dynamodb.__utils__, utils): - ret = boto_dynamodb.tag_resource(resource_arn=ARN, tags=TAGS) - - assert ret is True, ret - # Account for differing dict iteration order among Python versions by - # being more explicit in asserts. - assert len(conn.tag_resource.mock_calls) == 1 - call = conn.tag_resource.mock_calls[0] - # No positional args - assert not call.args - # Make sure there aren't any additional kwargs beyond what we expect - assert len(call.kwargs) == 2 - assert call.kwargs["ResourceArn"] == ARN - # Make sure there aren't any additional tags beyond what we expect - assert len(call.kwargs["Tags"]) == 2 - for tag_dict in TAGS_AS_LIST: - assert tag_dict in call.kwargs["Tags"] - - def test_untag_resource(self): - """ - Test that the correct API call is made and correct return format is - returned. - """ - conn = DummyConn() - utils = {"boto3.get_connection": MagicMock(return_value=conn)} - with patch.dict(boto_dynamodb.__utils__, utils): - ret = boto_dynamodb.untag_resource(resource_arn=ARN, tag_keys=sorted(TAGS)) - - assert ret is True, ret - conn.untag_resource.assert_called_once_with( - ResourceArn=ARN, TagKeys=sorted(TAGS) - ) diff --git a/tests/unit/modules/test_drbd.py b/tests/unit/modules/test_drbd.py deleted file mode 100644 index 1c2fd5f5966..00000000000 --- a/tests/unit/modules/test_drbd.py +++ /dev/null @@ -1,191 +0,0 @@ -""" - :codeauthor: Jayesh Kariya -""" - - -import salt.modules.drbd as drbd -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase - - -class DrbdTestCase(TestCase, LoaderModuleMockMixin): - """ - Test cases for salt.modules.drbd - """ - - def setup_loader_modules(self): - return {drbd: {}} - - # 'overview' function tests: 1 - - def test_overview(self): - """ - Test if it shows status of the DRBD devices - """ - ret = { - "connection state": "True", - "device": "Stack", - "fs": "None", - "local disk state": "UpToDate", - "local role": "master", - "minor number": "Salt", - "mountpoint": "True", - "partner disk state": "UpToDate", - "partner role": "minion", - "percent": "888", - "remains": "666", - "total size": "50", - "used": "50", - } - mock = MagicMock( - return_value=( - "Salt:Stack True master/minion UpToDate/UpToDate True None 50 50 666 888" - ) - ) - with patch.dict(drbd.__salt__, {"cmd.run": mock}): - self.assertDictEqual(drbd.overview(), ret) - - ret = { - "connection state": "True", - "device": "Stack", - "local disk state": "UpToDate", - "local role": "master", - "minor number": "Salt", - "partner disk state": "partner", - "partner role": "minion", - "synched": "5050", - "synchronisation: ": "syncbar", - } - mock = MagicMock( - return_value=( - "Salt:Stack True master/minion UpToDate/partner syncbar None 50 50" - ) - ) - with patch.dict(drbd.__salt__, {"cmd.run": mock}): - self.assertDictEqual(drbd.overview(), ret) - - def test_status(self): - """ - Test if it shows status of the DRBD resources via drbdadm - """ - ret = [ - { - "local role": "Primary", - "local volumes": [{"disk": "UpToDate"}], - "peer nodes": [ - { - "peer volumes": [ - { - "done": "96.47", - "peer-disk": "Inconsistent", - "replication": "SyncSource", - } - ], - "peernode name": "opensuse-node2", - "role": "Secondary", - } - ], - "resource name": "single", - } - ] - - mock = MagicMock( - return_value=""" -single role:Primary - disk:UpToDate - opensuse-node2 role:Secondary - replication:SyncSource peer-disk:Inconsistent done:96.47 -""" - ) - - with patch.dict(drbd.__salt__, {"cmd.run": mock}): - try: # python2 - self.assertItemsEqual(drbd.status(), ret) - except AttributeError: # python3 - self.assertCountEqual(drbd.status(), ret) - - ret = [ - { - "local role": "Primary", - "local volumes": [ - {"disk": "UpToDate", "volume": "0"}, - {"disk": "UpToDate", "volume": "1"}, - ], - "peer nodes": [ - { - "peer volumes": [ - {"peer-disk": "UpToDate", "volume": "0"}, - {"peer-disk": "UpToDate", "volume": "1"}, - ], - "peernode name": "node2", - "role": "Secondary", - }, - { - "peer volumes": [ - {"peer-disk": "UpToDate", "volume": "0"}, - {"peer-disk": "UpToDate", "volume": "1"}, - ], - "peernode name": "node3", - "role": "Secondary", - }, - ], - "resource name": "test", - }, - { - "local role": "Primary", - "local volumes": [ - {"disk": "UpToDate", "volume": "0"}, - {"disk": "UpToDate", "volume": "1"}, - ], - "peer nodes": [ - { - "peer volumes": [ - {"peer-disk": "UpToDate", "volume": "0"}, - {"peer-disk": "UpToDate", "volume": "1"}, - ], - "peernode name": "node2", - "role": "Secondary", - }, - { - "peer volumes": [ - {"peer-disk": "UpToDate", "volume": "0"}, - {"peer-disk": "UpToDate", "volume": "1"}, - ], - "peernode name": "node3", - "role": "Secondary", - }, - ], - "resource name": "res", - }, - ] - - mock = MagicMock( - return_value=""" -res role:Primary - volume:0 disk:UpToDate - volume:1 disk:UpToDate - node2 role:Secondary - volume:0 peer-disk:UpToDate - volume:1 peer-disk:UpToDate - node3 role:Secondary - volume:0 peer-disk:UpToDate - volume:1 peer-disk:UpToDate - -test role:Primary - volume:0 disk:UpToDate - volume:1 disk:UpToDate - node2 role:Secondary - volume:0 peer-disk:UpToDate - volume:1 peer-disk:UpToDate - node3 role:Secondary - volume:0 peer-disk:UpToDate - volume:1 peer-disk:UpToDate - -""" - ) - with patch.dict(drbd.__salt__, {"cmd.run": mock}): - try: # python2 - self.assertItemsEqual(drbd.status(), ret) - except AttributeError: # python3 - self.assertCountEqual(drbd.status(), ret) diff --git a/tests/unit/modules/test_hashutil.py b/tests/unit/modules/test_hashutil.py deleted file mode 100644 index bb3ac46d0a9..00000000000 --- a/tests/unit/modules/test_hashutil.py +++ /dev/null @@ -1,63 +0,0 @@ -import os - -import salt.config -import salt.loader -from tests.support.case import ModuleCase -from tests.support.mixins import RUNTIME_VARS - - -class HashutilTestCase(ModuleCase): - the_string = "get salted" - the_string_base64 = "Z2V0IHNhbHRlZA==\n" - the_string_md5 = "2aacf29e92feaf528fb738bcf9d647ac" - the_string_sha256 = ( - "d49859ccbc854fa68d800b5734efc70d72383e6479d545468bc300263164ff33" - ) - the_string_sha512 = "a8c174a7941c64a068e686812a2fafd7624c840fde800f5965fbeca675f2f6e37061ffe41e17728c919bdea290eab7a21e13c04ae71661955a87f2e0e04bb045" - the_string_hmac = "eBWf9bstXg+NiP5AOwppB5HMvZiYMPzEM9W5YMm/AmQ=" - the_string_hmac_compute = ( - "78159ff5bb2d5e0f8d88fe403b0a690791ccbd989830fcc433d5b960c9bf0264" - ) - the_string_github = "sha1=b06aa56bdf4935eec82c4e53e83ed03f03fdb32d" - - def setUp(self): - minion_opts = salt.config.minion_config( - os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "minion") - ) - self.hashutil = salt.loader.raw_mod(minion_opts, "hashutil", None) - - def test_base64_encodestring(self): - ret = self.hashutil["hashutil.base64_encodestring"](self.the_string) - self.assertEqual(ret, self.the_string_base64) - - def test_base64_decodestring(self): - ret = self.hashutil["hashutil.base64_decodestring"](self.the_string_base64) - self.assertEqual(ret, self.the_string) - - def test_md5_digest(self): - ret = self.hashutil["hashutil.md5_digest"](self.the_string) - self.assertEqual(ret, self.the_string_md5) - - def test_sha256_digest(self): - ret = self.hashutil["hashutil.sha256_digest"](self.the_string) - self.assertEqual(ret, self.the_string_sha256) - - def test_sha512_digest(self): - ret = self.hashutil["hashutil.sha512_digest"](self.the_string) - self.assertEqual(ret, self.the_string_sha512) - - def test_hmac_signature(self): - ret = self.hashutil["hashutil.hmac_signature"]( - self.the_string, "shared secret", self.the_string_hmac - ) - self.assertTrue(ret) - - def test_hmac_compute(self): - ret = self.hashutil["hashutil.hmac_compute"](self.the_string, "shared secret") - self.assertEqual(ret, self.the_string_hmac_compute) - - def test_github_signature(self): - ret = self.hashutil["hashutil.github_signature"]( - self.the_string, "shared secret", self.the_string_github - ) - self.assertTrue(ret) diff --git a/tests/unit/modules/test_status.py b/tests/unit/modules/test_status.py deleted file mode 100644 index 406e0953b69..00000000000 --- a/tests/unit/modules/test_status.py +++ /dev/null @@ -1,405 +0,0 @@ -import os - -import salt.modules.status as status -import salt.utils.platform -from salt.exceptions import CommandExecutionError -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, mock_open, patch -from tests.support.unit import TestCase - - -class StatusTestCase(TestCase, LoaderModuleMockMixin): - """ - test modules.status functions - """ - - def setup_loader_modules(self): - return {status: {}} - - def _set_up_test_uptime(self): - """ - Define common mock data for status.uptime tests - """ - - class MockData: - """ - Store mock data - """ - - m = MockData() - m.now = 1477004312 - m.ut = 1540154.00 - m.idle = 3047777.32 - m.ret = { - "users": 3, - "seconds": 1540154, - "since_t": 1475464158, - "days": 17, - "since_iso": "2016-10-03T03:09:18", - "time": "19:49", - } - - return m - - def _set_up_test_uptime_sunos(self): - """ - Define common mock data for cmd.run_all for status.uptime on SunOS - """ - - class MockData: - """ - Store mock data - """ - - m = MockData() - m.ret = { - "retcode": 0, - "stdout": "unix:0:system_misc:boot_time 1475464158", - } - - return m - - def test_uptime_linux(self): - """ - Test modules.status.uptime function for Linux - """ - m = self._set_up_test_uptime() - - with patch.multiple( - salt.utils.platform, - is_linux=MagicMock(return_value=True), - is_sunos=MagicMock(return_value=False), - is_darwin=MagicMock(return_value=False), - is_freebsd=MagicMock(return_value=False), - is_openbsd=MagicMock(return_value=False), - is_netbsd=MagicMock(return_value=False), - ), patch("salt.utils.path.which", MagicMock(return_value=True)), patch.dict( - status.__salt__, - {"cmd.run": MagicMock(return_value=os.linesep.join(["1", "2", "3"]))}, - ), patch( - "time.time", MagicMock(return_value=m.now) - ), patch( - "os.path.exists", MagicMock(return_value=True) - ): - proc_uptime = salt.utils.stringutils.to_str("{} {}".format(m.ut, m.idle)) - - with patch("salt.utils.files.fopen", mock_open(read_data=proc_uptime)): - ret = status.uptime() - self.assertDictEqual(ret, m.ret) - with patch("os.path.exists", MagicMock(return_value=False)): - with self.assertRaises(CommandExecutionError): - status.uptime() - - def test_uptime_sunos(self): - """ - Test modules.status.uptime function for SunOS - """ - m = self._set_up_test_uptime() - m2 = self._set_up_test_uptime_sunos() - with patch.multiple( - salt.utils.platform, - is_linux=MagicMock(return_value=False), - is_sunos=MagicMock(return_value=True), - is_darwin=MagicMock(return_value=False), - is_freebsd=MagicMock(return_value=False), - is_openbsd=MagicMock(return_value=False), - is_netbsd=MagicMock(return_value=False), - ), patch("salt.utils.path.which", MagicMock(return_value=True)), patch.dict( - status.__salt__, - { - "cmd.run": MagicMock(return_value=os.linesep.join(["1", "2", "3"])), - "cmd.run_all": MagicMock(return_value=m2.ret), - }, - ), patch( - "time.time", MagicMock(return_value=m.now) - ): - ret = status.uptime() - self.assertDictEqual(ret, m.ret) - - def test_uptime_macos(self): - """ - Test modules.status.uptime function for macOS - """ - m = self._set_up_test_uptime() - - kern_boottime = ( - "{{ sec = {0}, usec = {1:0<6} }} Mon Oct 03 03:09:18.23 2016".format( - *str(m.now - m.ut).split(".") - ) - ) - with patch.multiple( - salt.utils.platform, - is_linux=MagicMock(return_value=False), - is_sunos=MagicMock(return_value=False), - is_darwin=MagicMock(return_value=True), - is_freebsd=MagicMock(return_value=False), - is_openbsd=MagicMock(return_value=False), - is_netbsd=MagicMock(return_value=False), - ), patch("salt.utils.path.which", MagicMock(return_value=True)), patch.dict( - status.__salt__, - { - "cmd.run": MagicMock(return_value=os.linesep.join(["1", "2", "3"])), - "sysctl.get": MagicMock(return_value=kern_boottime), - }, - ), patch( - "time.time", MagicMock(return_value=m.now) - ): - - ret = status.uptime() - self.assertDictEqual(ret, m.ret) - - with patch.dict( - status.__salt__, {"sysctl.get": MagicMock(return_value="")} - ): - with self.assertRaises(CommandExecutionError): - status.uptime() - - def test_uptime_return_success_not_supported(self): - """ - Test modules.status.uptime function for other platforms - """ - with patch.multiple( - salt.utils.platform, - is_linux=MagicMock(return_value=False), - is_sunos=MagicMock(return_value=False), - is_darwin=MagicMock(return_value=False), - is_freebsd=MagicMock(return_value=False), - is_openbsd=MagicMock(return_value=False), - is_netbsd=MagicMock(return_value=False), - ): - exc_mock = MagicMock(side_effect=CommandExecutionError) - with self.assertRaises(CommandExecutionError): - with patch.dict(status.__salt__, {"cmd.run": exc_mock}): - status.uptime() - - def _set_up_test_cpustats_openbsd(self): - """ - Define mock data for status.cpustats on OpenBSD - """ - - class MockData: - """ - Store mock data - """ - - m = MockData() - m.ret = { - "0": { - "User": "0.0%", - "Nice": "0.0%", - "System": "4.5%", - "Interrupt": "0.5%", - "Idle": "95.0%", - } - } - - return m - - def test_cpustats_openbsd(self): - """ - Test modules.status.cpustats function for OpenBSD - """ - m = self._set_up_test_cpustats_openbsd() - - systat = ( - "\n\n 1 users Load 0.20 0.07 0.05 salt.localdomain" - " 09:42:42\nCPU User Nice System " - " Interrupt Idle\n0 0.0% 0.0% " - " 4.5% 0.5% 95.0%\n" - ) - - with patch.multiple( - salt.utils.platform, - is_linux=MagicMock(return_value=False), - is_sunos=MagicMock(return_value=False), - is_darwin=MagicMock(return_value=False), - is_freebsd=MagicMock(return_value=False), - is_openbsd=MagicMock(return_value=True), - is_netbsd=MagicMock(return_value=False), - ), patch("salt.utils.path.which", MagicMock(return_value=True)), patch.dict( - status.__grains__, {"kernel": "OpenBSD"} - ), patch.dict( - status.__salt__, {"cmd.run": MagicMock(return_value=systat)} - ): - ret = status.cpustats() - self.assertDictEqual(ret, m.ret) - - def _set_up_test_cpuinfo_bsd(self): - class MockData: - """ - Store mock data - """ - - m = MockData() - m.ret = { - "hw.model": "Intel(R) Core(TM) i5-7287U CPU @ 3.30GHz", - "hw.ncpu": "4", - } - - return m - - def test_cpuinfo_freebsd(self): - m = self._set_up_test_cpuinfo_bsd() - sysctl = "hw.model:Intel(R) Core(TM) i5-7287U CPU @ 3.30GHz\nhw.ncpu:4" - - with patch.dict(status.__grains__, {"kernel": "FreeBSD"}): - with patch.dict( - status.__salt__, {"cmd.run": MagicMock(return_value=sysctl)} - ): - ret = status.cpuinfo() - self.assertDictEqual(ret, m.ret) - - def test_cpuinfo_openbsd(self): - m = self._set_up_test_cpuinfo_bsd() - sysctl = "hw.model=Intel(R) Core(TM) i5-7287U CPU @ 3.30GHz\nhw.ncpu=4" - - for bsd in ["NetBSD", "OpenBSD"]: - with patch.dict(status.__grains__, {"kernel": bsd}): - with patch.dict( - status.__salt__, {"cmd.run": MagicMock(return_value=sysctl)} - ): - ret = status.cpuinfo() - self.assertDictEqual(ret, m.ret) - - def _set_up_test_meminfo_openbsd(self): - class MockData: - """ - Store mock data - """ - - m = MockData() - m.ret = { - "active virtual pages": "355M", - "free list size": "305M", - "page faults": "845", - "pages reclaimed": "1", - "pages paged in": "2", - "pages paged out": "3", - "pages freed": "4", - "pages scanned": "5", - } - - return m - - def test_meminfo_openbsd(self): - m = self._set_up_test_meminfo_openbsd() - vmstat = ( - " procs memory page disks traps " - " cpu\n r s avm fre flt re pi po fr sr cd0 sd0 int sys " - " cs us sy id\n 2 103 355M 305M 845 1 2 3 4 5 0 1 21 " - " 682 86 1 1 98" - ) - - with patch.dict(status.__grains__, {"kernel": "OpenBSD"}): - with patch.dict( - status.__salt__, {"cmd.run": MagicMock(return_value=vmstat)} - ): - ret = status.meminfo() - self.assertDictEqual(ret, m.ret) - - def _set_up_test_w_linux(self): - """ - Define mock data for status.w on Linux - """ - - class MockData: - """ - Store mock data - """ - - m = MockData() - m.ret = [ - { - "idle": "0s", - "jcpu": "0.24s", - "login": "13:42", - "pcpu": "0.16s", - "tty": "pts/1", - "user": "root", - "what": "nmap -sV 10.2.2.2", - } - ] - - return m - - def _set_up_test_w_bsd(self): - """ - Define mock data for status.w on Linux - """ - - class MockData: - """ - Store mock data - """ - - m = MockData() - m.ret = [ - { - "idle": "0", - "from": "10.2.2.1", - "login": "1:42PM", - "tty": "p1", - "user": "root", - "what": "nmap -sV 10.2.2.2", - } - ] - - return m - - def test_w_linux(self): - m = self._set_up_test_w_linux() - w_output = "root pts/1 13:42 0s 0.24s 0.16s nmap -sV 10.2.2.2" - - with patch.dict(status.__grains__, {"kernel": "Linux"}): - with patch.dict( - status.__salt__, {"cmd.run": MagicMock(return_value=w_output)} - ): - ret = status.w() - self.assertListEqual(ret, m.ret) - - def test_w_bsd(self): - m = self._set_up_test_w_bsd() - w_output = "root p1 10.2.2.1 1:42PM 0 nmap -sV 10.2.2.2" - - for bsd in ["Darwin", "FreeBSD", "OpenBSD"]: - with patch.dict(status.__grains__, {"kernel": bsd}): - with patch.dict( - status.__salt__, {"cmd.run": MagicMock(return_value=w_output)} - ): - ret = status.w() - self.assertListEqual(ret, m.ret) - - def _set_up_test_status_pid_linux(self): - class MockData: - """ - Store mock data - """ - - m = MockData() - m.ret = "2701\n7539\n7540\n7542\n7623" - return m - - def test_status_pid_linux(self): - m = self._set_up_test_status_pid_linux() - ps = ( - "UID PID PPID C STIME TTY TIME CMD\nroot 360 2 0 Jun08 ?" - " 00:00:00 [jbd2/dm-0-8]\nroot 947 2 0 Jun08 ? 00:00:00 " - " [jbd2/dm-1-8]\nroot 949 2 0 Jun08 ? 00:00:09 " - " [jbd2/dm-3-8]\nroot 951 2 0 Jun08 ? 00:00:00 " - " [jbd2/dm-4-8]\nroot 2701 1 0 Jun08 ? 00:00:28 /usr/sbin/httpd" - " -k start\napache 7539 2701 0 04:40 ? 00:00:04 /usr/sbin/httpd -k" - " start\napache 7540 2701 0 04:40 ? 00:00:02 /usr/sbin/httpd -k" - " start\napache 7542 2701 0 04:40 ? 00:01:46 /usr/sbin/httpd -k" - " start\napache 7623 2701 0 04:40 ? 00:02:41 /usr/sbin/httpd -k" - " start\nroot 1564 1 0 Jun11 ? 00:07:19 /usr/bin/python3" - " /usr/bin/salt-minion -d\nroot 6674 1564 0 19:53 ? 00:00:00 " - " /usr/bin/python3 /usr/bin/salt-call status.pid httpd -l debug" - ) - - with patch.dict(status.__grains__, {"ps": "ps -efHww"}): - with patch.dict( - status.__salt__, {"cmd.run_stdout": MagicMock(return_value=ps)} - ): - with patch.object(os, "getpid", return_value="6674"): - ret = status.pid("httpd") - self.assertEqual(ret, m.ret) diff --git a/tests/unit/modules/test_win_iis.py b/tests/unit/modules/test_win_iis.py deleted file mode 100644 index 07ac7090c51..00000000000 --- a/tests/unit/modules/test_win_iis.py +++ /dev/null @@ -1,889 +0,0 @@ -""" - :synopsis: Unit Tests for Windows IIS Module 'module.win_iis' - :platform: Windows - :maturity: develop - versionadded:: 2016.11.0 -""" -import salt.modules.win_iis as win_iis -import salt.utils.json -from salt.exceptions import SaltInvocationError -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, call, patch -from tests.support.unit import TestCase - -APP_LIST = { - "testApp": { - "apppool": "MyTestPool", - "path": "/testApp", - "preload": False, - "protocols": ["http"], - "sourcepath": r"C:\inetpub\apps\testApp", - } -} - -APPPOOL_LIST = {"MyTestPool": {"applications": ["MyTestSite"], "state": "Started"}} - -BINDING_LIST = { - "*:80:": { - "certificatehash": None, - "certificatestorename": None, - "hostheader": None, - "ipaddress": "*", - "port": 80, - "protocol": "http", - "sslflags": 0, - }, - "*:443:mytestsite.local": { - "certificatehash": "9988776655443322111000AAABBBCCCDDDEEEFFF", - "certificatestorename": "My", - "hostheader": "mytestsite.local", - "ipaddress": "*", - "port": 443, - "protocol": "https", - "sslflags": 0, - }, -} - -SITE_LIST = { - "MyTestSite": { - "apppool": "MyTestPool", - "bindings": BINDING_LIST, - "id": 1, - "sourcepath": r"C:\inetpub\wwwroot", - "state": "Started", - } -} - -VDIR_LIST = {"TestVdir": {"sourcepath": r"C:\inetpub\vdirs\TestVdir"}} -NESTED_VDIR_LIST = { - "Test/Nested/Vdir": {"sourcepath": r"C:\inetpub\vdirs\NestedTestVdir"} -} - - -LIST_APPS_SRVMGR = { - "retcode": 0, - "stdout": salt.utils.json.dumps( - [ - { - "applicationPool": "MyTestPool", - "name": "testApp", - "path": "/testApp", - "PhysicalPath": r"C:\inetpub\apps\testApp", - "preloadEnabled": False, - "protocols": "http", - } - ] - ), -} - -LIST_APPPOOLS_SRVMGR = { - "retcode": 0, - "stdout": salt.utils.json.dumps( - [ - { - "name": "MyTestPool", - "state": "Started", - "Applications": {"value": ["MyTestSite"], "Count": 1}, - } - ] - ), -} - -LIST_VDIRS_SRVMGR = { - "retcode": 0, - "stdout": salt.utils.json.dumps( - [{"name": "TestVdir", "physicalPath": r"C:\inetpub\vdirs\TestVdir"}] - ), -} - -LIST_MORE_VDIRS_SRVMGR = { - "retcode": 0, - "stdout": salt.utils.json.dumps( - [ - {"name": "TestVdir", "physicalPath": r"C:\inetpub\vdirs\TestVdir"}, - { - "name": "Test/Nested/Vdir", - "physicalPath": r"C:\inetpub\vdirs\NestedTestVdir", - }, - ] - ), -} - -CONTAINER_SETTING = { - "retcode": 0, - "stdout": salt.utils.json.dumps([{"managedPipelineMode": "Integrated"}]), -} - -CERT_BINDING_INFO = "*:443:mytestsite.local" - - -class WinIisTestCase(TestCase, LoaderModuleMockMixin): - """ - Test cases for salt.modules.win_iis - """ - - def setup_loader_modules(self): - return {win_iis: {}} - - def test_create_apppool(self): - """ - Test - Create an IIS application pool. - """ - with patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ), patch( - "salt.modules.win_iis.list_apppools", MagicMock(return_value=dict()) - ), patch.dict( - win_iis.__salt__ - ): - self.assertTrue(win_iis.create_apppool("MyTestPool")) - - def test_list_apppools(self): - """ - Test - List all configured IIS application pools. - """ - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value=LIST_APPPOOLS_SRVMGR) - ): - self.assertEqual(win_iis.list_apppools(), APPPOOL_LIST) - - def test_remove_apppool(self): - """ - Test - Remove an IIS application pool. - """ - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ), patch( - "salt.modules.win_iis.list_apppools", - MagicMock( - return_value={ - "MyTestPool": {"applications": list(), "state": "Started"} - } - ), - ): - self.assertTrue(win_iis.remove_apppool("MyTestPool")) - - def test_restart_apppool(self): - """ - Test - Restart an IIS application pool. - """ - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ): - self.assertTrue(win_iis.restart_apppool("MyTestPool")) - - def test_create_site(self): - """ - Test - Create a basic website in IIS. - """ - kwargs = { - "name": "MyTestSite", - "sourcepath": r"C:\inetpub\wwwroot", - "apppool": "MyTestPool", - "hostheader": "mytestsite.local", - "ipaddress": "*", - "port": 80, - "protocol": "http", - } - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ), patch( - "salt.modules.win_iis.list_sites", MagicMock(return_value=dict()) - ), patch( - "salt.modules.win_iis.list_apppools", MagicMock(return_value=dict()) - ): - self.assertTrue(win_iis.create_site(**kwargs)) - - def test_create_site_failed(self): - """ - Test - Create a basic website in IIS using invalid data. - """ - kwargs = { - "name": "MyTestSite", - "sourcepath": r"C:\inetpub\wwwroot", - "apppool": "MyTestPool", - "hostheader": "mytestsite.local", - "ipaddress": "*", - "port": 80, - "protocol": "invalid-protocol-name", - } - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ), patch( - "salt.modules.win_iis.list_sites", MagicMock(return_value=dict()) - ), patch( - "salt.modules.win_iis.list_apppools", MagicMock(return_value=dict()) - ): - self.assertRaises(SaltInvocationError, win_iis.create_site, **kwargs) - - def test_remove_site(self): - """ - Test - Delete a website from IIS. - """ - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ), patch("salt.modules.win_iis.list_sites", MagicMock(return_value=SITE_LIST)): - self.assertTrue(win_iis.remove_site("MyTestSite")) - - def test_create_app(self): - """ - Test - Create an IIS application. - """ - kwargs = { - "name": "testApp", - "site": "MyTestSite", - "sourcepath": r"C:\inetpub\apps\testApp", - "apppool": "MyTestPool", - } - with patch.dict(win_iis.__salt__), patch( - "os.path.isdir", MagicMock(return_value=True) - ), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ), patch( - "salt.modules.win_iis.list_apps", MagicMock(return_value=APP_LIST) - ): - self.assertTrue(win_iis.create_app(**kwargs)) - - def test_list_apps(self): - """ - Test - Get all configured IIS applications for the specified site. - """ - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value=LIST_APPS_SRVMGR) - ): - self.assertEqual(win_iis.list_apps("MyTestSite"), APP_LIST) - - def test_remove_app(self): - """ - Test - Remove an IIS application. - """ - kwargs = {"name": "otherApp", "site": "MyTestSite"} - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ), patch("salt.modules.win_iis.list_apps", MagicMock(return_value=APP_LIST)): - self.assertTrue(win_iis.remove_app(**kwargs)) - - def test_create_binding(self): - """ - Test - Create an IIS binding. - """ - kwargs = { - "site": "MyTestSite", - "hostheader": "", - "ipaddress": "*", - "port": 80, - "protocol": "http", - "sslflags": 0, - } - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ), patch( - "salt.modules.win_iis.list_bindings", MagicMock(return_value=BINDING_LIST) - ): - self.assertTrue(win_iis.create_binding(**kwargs)) - - def test_create_binding_failed(self): - """ - Test - Create an IIS binding using invalid data. - """ - kwargs = { - "site": "MyTestSite", - "hostheader": "", - "ipaddress": "*", - "port": 80, - "protocol": "invalid-protocol-name", - "sslflags": 999, - } - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ), patch( - "salt.modules.win_iis.list_bindings", MagicMock(return_value=BINDING_LIST) - ): - self.assertRaises(SaltInvocationError, win_iis.create_binding, **kwargs) - - def test_list_bindings(self): - """ - Test - Get all configured IIS bindings for the specified site. - """ - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis.list_sites", MagicMock(return_value=SITE_LIST) - ): - self.assertEqual(win_iis.list_bindings("MyTestSite"), BINDING_LIST) - - def test_remove_binding(self): - """ - Test - Remove an IIS binding. - """ - kwargs = { - "site": "MyTestSite", - "hostheader": "myothertestsite.local", - "ipaddress": "*", - "port": 443, - } - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ), patch( - "salt.modules.win_iis.list_bindings", MagicMock(return_value=BINDING_LIST) - ): - self.assertTrue(win_iis.remove_binding(**kwargs)) - - def test_create_vdir(self): - """ - Test - Create an IIS virtual directory. - """ - kwargs = { - "name": "TestVdir", - "site": "MyTestSite", - "sourcepath": r"C:\inetpub\vdirs\TestVdir", - } - with patch.dict(win_iis.__salt__), patch( - "os.path.isdir", MagicMock(return_value=True) - ), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ), patch( - "salt.modules.win_iis.list_vdirs", MagicMock(return_value=VDIR_LIST) - ): - self.assertTrue(win_iis.create_vdir(**kwargs)) - - def test_list_vdirs(self): - """ - Test - Get configured IIS virtual directories. - """ - vdirs = {"TestVdir": {"sourcepath": r"C:\inetpub\vdirs\TestVdir"}} - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value=LIST_VDIRS_SRVMGR) - ): - self.assertEqual(win_iis.list_vdirs("MyTestSite"), vdirs) - - def test_remove_vdir(self): - """ - Test - Remove an IIS virtual directory. - """ - kwargs = {"name": "TestOtherVdir", "site": "MyTestSite"} - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ), patch("salt.modules.win_iis.list_vdirs", MagicMock(return_value=VDIR_LIST)): - self.assertTrue(win_iis.remove_vdir(**kwargs)) - - def test_create_nested_vdir(self): - """ - Test - Create a nested IIS virtual directory. - """ - kwargs = { - "name": "Test/Nested/Vdir", - "site": "MyTestSite", - "sourcepath": r"C:\inetpub\vdirs\NestedTestVdir", - } - with patch.dict(win_iis.__salt__), patch( - "os.path.isdir", MagicMock(return_value=True) - ), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ), patch( - "salt.modules.win_iis.list_vdirs", MagicMock(return_value=NESTED_VDIR_LIST) - ): - self.assertTrue(win_iis.create_vdir(**kwargs)) - - def test_list_nested_vdirs(self): - """ - Test - Get configured IIS virtual directories. - """ - vdirs = { - "TestVdir": {"sourcepath": r"C:\inetpub\vdirs\TestVdir"}, - "Test/Nested/Vdir": {"sourcepath": r"C:\inetpub\vdirs\NestedTestVdir"}, - } - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", - MagicMock(return_value=LIST_MORE_VDIRS_SRVMGR), - ): - self.assertEqual(win_iis.list_vdirs("MyTestSite"), vdirs) - - def test_create_cert_binding(self): - """ - Test - Assign a certificate to an IIS binding. - """ - kwargs = { - "name": "9988776655443322111000AAABBBCCCDDDEEEFFF", - "site": "MyTestSite", - "hostheader": "mytestsite.local", - "ipaddress": "*", - "port": 443, - } - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._list_certs", - MagicMock(return_value={"9988776655443322111000AAABBBCCCDDDEEEFFF": None}), - ), patch( - "salt.modules.win_iis._srvmgr", - MagicMock(return_value={"retcode": 0, "stdout": 10}), - ), patch( - "salt.utils.json.loads", - MagicMock(return_value=[{"MajorVersion": 10, "MinorVersion": 0}]), - ), patch( - "salt.modules.win_iis.list_bindings", MagicMock(return_value=BINDING_LIST) - ), patch( - "salt.modules.win_iis.list_cert_bindings", - MagicMock( - return_value={CERT_BINDING_INFO: BINDING_LIST[CERT_BINDING_INFO]} - ), - ): - self.assertTrue(win_iis.create_cert_binding(**kwargs)) - - def test_list_cert_bindings(self): - """ - Test - List certificate bindings for an IIS site. - """ - key = "*:443:mytestsite.local" - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis.list_sites", MagicMock(return_value=SITE_LIST) - ): - self.assertEqual( - win_iis.list_cert_bindings("MyTestSite"), {key: BINDING_LIST[key]} - ) - - def test_remove_cert_binding(self): - """ - Test - Remove a certificate from an IIS binding. - """ - kwargs = { - "name": "FFFEEEDDDCCCBBBAAA0001112233445566778899", - "site": "MyOtherTestSite", - "hostheader": "myothertestsite.local", - "ipaddress": "*", - "port": 443, - } - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ), patch( - "salt.modules.win_iis.list_cert_bindings", - MagicMock( - return_value={CERT_BINDING_INFO: BINDING_LIST[CERT_BINDING_INFO]} - ), - ): - self.assertTrue(win_iis.remove_cert_binding(**kwargs)) - - def test_get_container_setting(self): - """ - Test - Get the value of the setting for the IIS container. - """ - kwargs = { - "name": "MyTestSite", - "container": "AppPools", - "settings": ["managedPipelineMode"], - } - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value=CONTAINER_SETTING) - ): - self.assertEqual( - win_iis.get_container_setting(**kwargs), - {"managedPipelineMode": "Integrated"}, - ) - - def test_set_container_setting(self): - """ - Test - Set the value of the setting for an IIS container. - """ - kwargs = { - "name": "MyTestSite", - "container": "AppPools", - "settings": {"managedPipelineMode": "Integrated"}, - } - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._srvmgr", MagicMock(return_value={"retcode": 0}) - ), patch( - "salt.modules.win_iis.get_container_setting", - MagicMock(return_value={"managedPipelineMode": "Integrated"}), - ): - self.assertTrue(win_iis.set_container_setting(**kwargs)) - - def test__collection_match_to_index(self): - bad_match = {"key_0": "value"} - first_match = {"key_1": "value"} - second_match = {"key_2": "value"} - collection = [first_match, second_match] - settings = [{"name": "enabled", "value": collection}] - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis.get_webconfiguration_settings", - MagicMock(return_value=settings), - ): - ret = win_iis._collection_match_to_index( - "pspath", "colfilter", "name", bad_match - ) - self.assertEqual(ret, -1) - ret = win_iis._collection_match_to_index( - "pspath", "colfilter", "name", first_match - ) - self.assertEqual(ret, 0) - ret = win_iis._collection_match_to_index( - "pspath", "colfilter", "name", second_match - ) - self.assertEqual(ret, 1) - - def test__prepare_settings(self): - simple_setting = {"name": "value", "filter": "value"} - collection_setting = {"name": "Collection[{yaml:\n\tdata}]", "filter": "value"} - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._collection_match_to_index", MagicMock(return_value=0) - ): - ret = win_iis._prepare_settings( - "pspath", - [ - simple_setting, - collection_setting, - {"invalid": "setting"}, - {"name": "filter-less_setting"}, - ], - ) - self.assertEqual(ret, [simple_setting, collection_setting]) - - @patch("salt.modules.win_iis.log") - def test_get_webconfiguration_settings_empty(self, mock_log): - ret = win_iis.get_webconfiguration_settings("name", settings=[]) - mock_log.warning.assert_called_once_with("No settings provided") - self.assertEqual(ret, {}) - - def test_get_webconfiguration_settings(self): - # Setup - name = "IIS" - collection_setting = {"name": "Collection[{yaml:\n\tdata}]", "filter": "value"} - filter_setting = { - "name": "enabled", - "filter": ( - "system.webServer / security / authentication / anonymousAuthentication" - ), - } - settings = [collection_setting, filter_setting] - - ps_cmd = [ - "$Settings = New-Object System.Collections.ArrayList;", - ] - for setting in settings: - ps_cmd.extend( - [ - "$Property = Get-WebConfigurationProperty -PSPath '{}'".format( - name - ), - "-Name '{name}' -Filter '{filter}' -ErrorAction Stop;".format( - filter=setting["filter"], name=setting["name"] - ), - "if (([String]::IsNullOrEmpty($Property) -eq $False) -and", - "($Property.GetType()).Name -eq 'ConfigurationAttribute') {", - "$Property = $Property | Select-Object", - "-ExpandProperty Value };", - "$Settings.add(@{{filter='{filter}';name='{name}';value=[String]" - " $Property}})| Out-Null;".format( - filter=setting["filter"], name=setting["name"] - ), - "$Property = $Null;", - ] - ) - ps_cmd.append("$Settings") - - # Execute - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._prepare_settings", MagicMock(return_value=settings) - ), patch( - "salt.modules.win_iis._srvmgr", - MagicMock(return_value={"retcode": 0, "stdout": "{}"}), - ): - ret = win_iis.get_webconfiguration_settings(name, settings=settings) - - # Verify - win_iis._srvmgr.assert_called_with(cmd=ps_cmd, return_json=True) - self.assertEqual(ret, {}) - - @patch("salt.modules.win_iis.log") - def test_set_webconfiguration_settings_empty(self, mock_log): - ret = win_iis.set_webconfiguration_settings("name", settings=[]) - mock_log.warning.assert_called_once_with("No settings provided") - self.assertEqual(ret, False) - - @patch("salt.modules.win_iis.log") - def test_set_webconfiguration_settings_no_changes(self, mock_log): - # Setup - name = "IIS" - setting = { - "name": "Collection[{yaml:\n\tdata}]", - "filter": ( - "system.webServer / security / authentication / anonymousAuthentication" - ), - "value": [], - } - settings = [setting] - - # Execute - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._prepare_settings", MagicMock(return_value=settings) - ), patch( - "salt.modules.win_iis._srvmgr", - MagicMock(return_value={"retcode": 0, "stdout": "{}"}), - ), patch( - "salt.modules.win_iis.get_webconfiguration_settings", - MagicMock(return_value=settings), - ): - ret = win_iis.set_webconfiguration_settings(name, settings=settings) - - # Verify - mock_log.debug.assert_called_with( - "Settings already contain the provided values." - ) - self.assertEqual(ret, True) - - @patch("salt.modules.win_iis.log") - def test_set_webconfiguration_settings_failed(self, mock_log): - # Setup - name = "IIS" - setting = { - "name": "Collection[{yaml:\n\tdata}]", - "filter": ( - "system.webServer / security / authentication / anonymousAuthentication" - ), - "value": [], - } - settings = [setting] - - # Execute - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._prepare_settings", MagicMock(return_value=settings) - ), patch( - "salt.modules.win_iis._srvmgr", - MagicMock(return_value={"retcode": 0, "stdout": "{}"}), - ), patch( - "salt.modules.win_iis.get_webconfiguration_settings", - MagicMock(side_effect=[[], [{"value": "unexpected_change!"}]]), - ): - - ret = win_iis.set_webconfiguration_settings(name, settings=settings) - - # Verify - self.assertEqual(ret, False) - mock_log.error.assert_called_with("Failed to change settings: %s", settings) - - @patch("salt.modules.win_iis.log") - def test_set_webconfiguration_settings(self, mock_log): - # Setup - name = "IIS" - setting = { - "name": "Collection[{yaml:\n\tdata}]", - "filter": ( - "system.webServer / security / authentication / anonymousAuthentication" - ), - "value": [], - } - settings = [setting] - - # Execute - with patch.dict(win_iis.__salt__), patch( - "salt.modules.win_iis._prepare_settings", MagicMock(return_value=settings) - ), patch( - "salt.modules.win_iis._srvmgr", - MagicMock(return_value={"retcode": 0, "stdout": "{}"}), - ), patch( - "salt.modules.win_iis.get_webconfiguration_settings", - MagicMock(side_effect=[[], settings]), - ): - ret = win_iis.set_webconfiguration_settings(name, settings=settings) - - # Verify - self.assertEqual(ret, True) - mock_log.debug.assert_called_with( - "Settings configured successfully: %s", settings - ) - - def test_get_webconfiguration_settings_no_settings(self): - self.assertEqual(win_iis.get_webconfiguration_settings("salt", {}), {}) - - def test_get_webconfiguration_settings_pass(self): - settings = [ - { - "name": "enabled", - "filter": ( - "system.webServer/security/authentication/anonymousAuthentication" - ), - } - ] - - ps_cmd_validate = [ - "Get-WebConfigurationProperty", - "-PSPath", - "'salt'", - "-Filter", - "'system.webServer/security/authentication/anonymousAuthentication'", - "-Name", - "'enabled'", - "-ErrorAction", - "Stop", - "|", - "Out-Null;", - ] - - ps_cmd = [ - "$Settings = New-Object System.Collections.ArrayList;", - "$Property = Get-WebConfigurationProperty -PSPath 'salt'", - "-Name 'enabled' -Filter" - " 'system.webServer/security/authentication/anonymousAuthentication'" - " -ErrorAction Stop;", - "if (([String]::IsNullOrEmpty($Property) -eq $False) -and", - "($Property.GetType()).Name -eq 'ConfigurationAttribute') {", - "$Property = $Property | Select-Object", - "-ExpandProperty Value };", - "$Settings.add(@{filter='system.webServer/security/authentication/anonymousAuthentication';name='enabled';value=[String]" - " $Property})| Out-Null;", - "$Property = $Null;", - "$Settings", - ] - - func_ret = {"name": "enabled", "value": True} - with patch.object( - win_iis, "_srvmgr", return_value={"retcode": 0, "stdout": "json data"} - ) as _srvmgr: - with patch.object( - win_iis.salt.utils.json, "loads", return_value=func_ret - ) as loads: - ret = win_iis.get_webconfiguration_settings("salt", settings) - - self.assertEqual(_srvmgr.call_count, 2) - self.assertEqual( - _srvmgr.mock_calls[0], call(cmd=ps_cmd_validate, return_json=True) - ) - self.assertEqual( - _srvmgr.mock_calls[1], call(cmd=ps_cmd, return_json=True) - ) - - loads.assert_called_once_with("json data", strict=False) - self.assertEqual(func_ret, ret) - - def test_set_webconfiguration_settings_no_settings(self): - self.assertEqual(win_iis.set_webconfiguration_settings("salt", {}), False) - - def test_set_webconfiguration_settings_pass(self): - settings = [ - { - "name": "enabled", - "filter": ( - "system.webServer/security/authentication/anonymousAuthentication" - ), - "value": False, - } - ] - - current_settings = [ - { - "name": "enabled", - "filter": ( - "system.webServer/security/authentication/anonymousAuthentication" - ), - "value": True, - } - ] - - new_settings = [ - { - "name": "enabled", - "filter": ( - "system.webServer/security/authentication/anonymousAuthentication" - ), - "value": False, - } - ] - - ps_cmd = [ - "Set-WebConfigurationProperty", - "-PSPath", - "'salt'", - "-Filter", - "'system.webServer/security/authentication/anonymousAuthentication'", - "-Name", - "'enabled'", - "-Value", - "'False';", - ] - - with patch.object( - win_iis, - "get_webconfiguration_settings", - side_effect=[current_settings, new_settings], - ) as get_webconfiguration_settings: - with patch.object( - win_iis, "_srvmgr", return_value={"retcode": 0} - ) as _srvmgr: - ret = win_iis.set_webconfiguration_settings("salt", settings) - - self.assertEqual(get_webconfiguration_settings.call_count, 2) - self.assertEqual( - get_webconfiguration_settings.mock_calls[0], - call(name="salt", settings=settings), - ) - self.assertEqual( - get_webconfiguration_settings.mock_calls[1], - call(name="salt", settings=settings), - ) - - _srvmgr.assert_called_once_with(ps_cmd) - - self.assertTrue(ret) - - def test_set_webconfiguration_settings_fail(self): - settings = [ - { - "name": "enabled", - "filter": ( - "system.webServer/security/authentication/anonymousAuthentication" - ), - "value": False, - } - ] - - current_settings = [ - { - "name": "enabled", - "filter": ( - "system.webServer/security/authentication/anonymousAuthentication" - ), - "value": True, - } - ] - - new_settings = [ - { - "name": "enabled", - "filter": ( - "system.webServer/security/authentication/anonymousAuthentication" - ), - "value": True, - } - ] - - ps_cmd = [ - "Set-WebConfigurationProperty", - "-PSPath", - "'salt'", - "-Filter", - "'system.webServer/security/authentication/anonymousAuthentication'", - "-Name", - "'enabled'", - "-Value", - "'False';", - ] - - with patch.object( - win_iis, - "get_webconfiguration_settings", - side_effect=[current_settings, new_settings], - ) as get_webconfiguration_settings: - with patch.object( - win_iis, "_srvmgr", return_value={"retcode": 0} - ) as _srvmgr: - ret = win_iis.set_webconfiguration_settings("salt", settings) - - self.assertEqual(get_webconfiguration_settings.call_count, 2) - self.assertEqual( - get_webconfiguration_settings.mock_calls[0], - call(name="salt", settings=settings), - ) - self.assertEqual( - get_webconfiguration_settings.mock_calls[1], - call(name="salt", settings=settings), - ) - - _srvmgr.assert_called_once_with(ps_cmd) - - self.assertFalse(ret) diff --git a/tests/unit/modules/test_win_ip.py b/tests/unit/modules/test_win_ip.py deleted file mode 100644 index a29fc6e0238..00000000000 --- a/tests/unit/modules/test_win_ip.py +++ /dev/null @@ -1,377 +0,0 @@ -""" - :codeauthor: Jayesh Kariya -""" - -import pytest - -import salt.modules.win_ip as win_ip -from salt.exceptions import CommandExecutionError, SaltInvocationError -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, call, patch -from tests.support.unit import TestCase - -ETHERNET_CONFIG = ( - 'Configuration for interface "Ethernet"\n' - "DHCP enabled: Yes\n" - "IP Address: 1.2.3.74\n" - "Subnet Prefix: 1.2.3.0/24 (mask 255.255.255.0)\n" - "Default Gateway: 1.2.3.1\n" - "Gateway Metric: 0\n" - "InterfaceMetric: 20\n" - "DNS servers configured through DHCP: 1.2.3.4\n" - "Register with which suffix: Primary only\n" - "WINS servers configured through DHCP: None\n" -) - -ETHERNET_ENABLE = ( - "Ethernet\nType: Dedicated\nAdministrative state: Enabled\nConnect state: Connected" -) - - -class WinShadowTestCase(TestCase, LoaderModuleMockMixin): - """ - Test cases for salt.modules.win_ip - """ - - def setup_loader_modules(self): - return {win_ip: {}} - - # 'raw_interface_configs' function tests: 1 - - def test_raw_interface_configs(self): - """ - Test if it return raw configs for all interfaces. - """ - mock_cmd = MagicMock(return_value=ETHERNET_CONFIG) - with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): - self.assertEqual(win_ip.raw_interface_configs(), ETHERNET_CONFIG) - - # 'get_all_interfaces' function tests: 1 - - def test_get_all_interfaces(self): - """ - Test if it return configs for all interfaces. - """ - ret = { - "Ethernet": { - "DHCP enabled": "Yes", - "DNS servers configured through DHCP": ["1.2.3.4"], - "Default Gateway": "1.2.3.1", - "Gateway Metric": "0", - "InterfaceMetric": "20", - "Register with which suffix": "Primary only", - "WINS servers configured through DHCP": ["None"], - "ip_addrs": [ - { - "IP Address": "1.2.3.74", - "Netmask": "255.255.255.0", - "Subnet": "1.2.3.0/24", - } - ], - } - } - - mock_cmd = MagicMock(return_value=ETHERNET_CONFIG) - with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): - self.assertDictEqual(win_ip.get_all_interfaces(), ret) - - # 'get_interface' function tests: 1 - - def test_get_interface(self): - """ - Test if it return the configuration of a network interface. - """ - ret = { - "DHCP enabled": "Yes", - "DNS servers configured through DHCP": ["1.2.3.4"], - "Default Gateway": "1.2.3.1", - "Gateway Metric": "0", - "InterfaceMetric": "20", - "Register with which suffix": "Primary only", - "WINS servers configured through DHCP": ["None"], - "ip_addrs": [ - { - "IP Address": "1.2.3.74", - "Netmask": "255.255.255.0", - "Subnet": "1.2.3.0/24", - } - ], - } - - mock_cmd = MagicMock(return_value=ETHERNET_CONFIG) - with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): - self.assertDictEqual(win_ip.get_interface("Ethernet"), ret) - - # 'is_enabled' function tests: 1 - - def test_is_enabled(self): - """ - Test if it returns `True` if interface is enabled, otherwise `False`. - """ - mock_cmd = MagicMock(side_effect=[ETHERNET_ENABLE, ""]) - with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): - self.assertTrue(win_ip.is_enabled("Ethernet")) - self.assertRaises(CommandExecutionError, win_ip.is_enabled, "Ethernet") - - # 'is_disabled' function tests: 1 - - def test_is_disabled(self): - """ - Test if it returns `True` if interface is disabled, otherwise `False`. - """ - mock_cmd = MagicMock(return_value=ETHERNET_ENABLE) - with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): - self.assertFalse(win_ip.is_disabled("Ethernet")) - - # 'enable' function tests: 1 - - def test_enable(self): - """ - Test if it enable an interface. - """ - # Test with enabled interface - with patch.object(win_ip, "is_enabled", return_value=True): - self.assertTrue(win_ip.enable("Ethernet")) - - mock_cmd = MagicMock() - with patch.object(win_ip, "is_enabled", side_effect=[False, True]), patch.dict( - win_ip.__salt__, {"cmd.run": mock_cmd} - ): - self.assertTrue(win_ip.enable("Ethernet")) - - mock_cmd.called_once_with( - [ - "netsh", - "interface", - "set", - "interface", - "name=Ethernet", - "admin=ENABLED", - ], - python_shell=False, - ) - - # 'disable' function tests: 1 - - def test_disable(self): - """ - Test if it disable an interface. - """ - with patch.object(win_ip, "is_disabled", return_value=True): - self.assertTrue(win_ip.disable("Ethernet")) - - mock_cmd = MagicMock() - with patch.object(win_ip, "is_disabled", side_effect=[False, True]), patch.dict( - win_ip.__salt__, {"cmd.run": mock_cmd} - ): - self.assertTrue(win_ip.disable("Ethernet")) - - mock_cmd.called_once_with( - [ - "netsh", - "interface", - "set", - "interface", - "name=Ethernet", - "admin=DISABLED", - ], - python_shell=False, - ) - - # 'get_subnet_length' function tests: 1 - - def test_get_subnet_length(self): - """ - Test if it disable an interface. - """ - self.assertEqual(win_ip.get_subnet_length("255.255.255.0"), 24) - self.assertRaises(SaltInvocationError, win_ip.get_subnet_length, "255.255.0") - - # 'set_static_ip' function tests: 1 - - @pytest.mark.slow_test - def test_set_static_ip(self): - """ - Test if it set static IP configuration on a Windows NIC. - """ - self.assertRaises( - SaltInvocationError, - win_ip.set_static_ip, - "Local Area Connection", - "10.1.2/24", - ) - - mock_cmd = MagicMock(return_value=ETHERNET_CONFIG) - mock_all = MagicMock(return_value={"retcode": 1, "stderr": "Error"}) - with patch.dict( - win_ip.__salt__, {"cmd.run": mock_cmd, "cmd.run_all": mock_all} - ): - self.assertRaises( - CommandExecutionError, - win_ip.set_static_ip, - "Ethernet", - "1.2.3.74/24", - append=True, - ) - self.assertRaises( - CommandExecutionError, win_ip.set_static_ip, "Ethernet", "1.2.3.74/24" - ) - - mock_all = MagicMock(return_value={"retcode": 0}) - with patch.dict( - win_ip.__salt__, {"cmd.run": mock_cmd, "cmd.run_all": mock_all} - ): - self.assertDictEqual( - win_ip.set_static_ip("Local Area Connection", "1.2.3.74/24"), {} - ) - self.assertDictEqual( - win_ip.set_static_ip("Ethernet", "1.2.3.74/24"), - { - "Address Info": { - "IP Address": "1.2.3.74", - "Netmask": "255.255.255.0", - "Subnet": "1.2.3.0/24", - } - }, - ) - - # 'set_dhcp_ip' function tests: 1 - - def test_set_dhcp_ip(self): - """ - Test if it set Windows NIC to get IP from DHCP. - """ - mock_cmd = MagicMock(return_value=ETHERNET_CONFIG) - with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): - self.assertDictEqual( - win_ip.set_dhcp_ip("Ethernet"), - {"DHCP enabled": "Yes", "Interface": "Ethernet"}, - ) - - # 'set_static_dns' function tests: 1 - - def test_set_static_dns(self): - """ - Test if it set static DNS configuration on a Windows NIC. - """ - mock_cmd = MagicMock() - with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): - self.assertDictEqual( - win_ip.set_static_dns("Ethernet", "192.168.1.252", "192.168.1.253"), - { - "DNS Server": ("192.168.1.252", "192.168.1.253"), - "Interface": "Ethernet", - }, - ) - mock_cmd.assert_has_calls( - [ - call( - [ - "netsh", - "interface", - "ip", - "set", - "dns", - "name=Ethernet", - "source=static", - "address=192.168.1.252", - "register=primary", - ], - python_shell=False, - ), - call( - [ - "netsh", - "interface", - "ip", - "add", - "dns", - "name=Ethernet", - "address=192.168.1.253", - "index=2", - ], - python_shell=False, - ), - ] - ) - - def test_set_static_dns_clear(self): - """ - Test if it set static DNS configuration on a Windows NIC. - """ - mock_cmd = MagicMock() - with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): - self.assertDictEqual( - win_ip.set_static_dns("Ethernet", []), - {"DNS Server": [], "Interface": "Ethernet"}, - ) - mock_cmd.assert_called_once_with( - [ - "netsh", - "interface", - "ip", - "set", - "dns", - "name=Ethernet", - "source=static", - "address=none", - ], - python_shell=False, - ) - - def test_set_static_dns_no_action(self): - """ - Test if it set static DNS configuration on a Windows NIC. - """ - # Test passing nothing - self.assertDictEqual( - win_ip.set_static_dns("Ethernet"), - {"DNS Server": "No Changes", "Interface": "Ethernet"}, - ) - # Test passing None - self.assertDictEqual( - win_ip.set_static_dns("Ethernet", None), - {"DNS Server": "No Changes", "Interface": "Ethernet"}, - ) - - # Test passing string None - self.assertDictEqual( - win_ip.set_static_dns("Ethernet", "None"), - {"DNS Server": "No Changes", "Interface": "Ethernet"}, - ) - - # 'set_dhcp_dns' function tests: 1 - - def test_set_dhcp_dns(self): - """ - Test if it set DNS source to DHCP on Windows. - """ - mock_cmd = MagicMock(return_value=ETHERNET_CONFIG) - with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): - self.assertDictEqual( - win_ip.set_dhcp_dns("Ethernet"), - {"DNS Server": "DHCP", "Interface": "Ethernet"}, - ) - - # 'set_dhcp_all' function tests: 1 - - def test_set_dhcp_all(self): - """ - Test if it set both IP Address and DNS to DHCP. - """ - mock_cmd = MagicMock(return_value=ETHERNET_CONFIG) - with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): - self.assertDictEqual( - win_ip.set_dhcp_all("Ethernet"), - {"Interface": "Ethernet", "DNS Server": "DHCP", "DHCP enabled": "Yes"}, - ) - - # 'get_default_gateway' function tests: 1 - - def test_get_default_gateway(self): - """ - Test if it set DNS source to DHCP on Windows. - """ - mock_cmd = MagicMock(return_value=ETHERNET_CONFIG) - with patch.dict(win_ip.__salt__, {"cmd.run": mock_cmd}): - self.assertEqual(win_ip.get_default_gateway(), "1.2.3.1") diff --git a/tests/unit/modules/test_win_license.py b/tests/unit/modules/test_win_license.py deleted file mode 100644 index f80a3781574..00000000000 --- a/tests/unit/modules/test_win_license.py +++ /dev/null @@ -1,90 +0,0 @@ -import salt.modules.win_license as win_license -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase - - -class LicenseTestCase(TestCase, LoaderModuleMockMixin): - def setup_loader_modules(self): - return {win_license: {}} - - def test_installed(self): - """ - Test to see if the given license key is installed - """ - mock = MagicMock(return_value="Partial Product Key: ABCDE") - with patch.dict(win_license.__salt__, {"cmd.run": mock}): - out = win_license.installed("AAAAA-AAAAA-AAAAA-AAAA-AAAAA-ABCDE") - mock.assert_called_once_with(r"cscript C:\Windows\System32\slmgr.vbs /dli") - self.assertTrue(out) - - def test_installed_diff(self): - """ - Test to see if the given license key is installed when the key is different - """ - mock = MagicMock(return_value="Partial Product Key: 12345") - with patch.dict(win_license.__salt__, {"cmd.run": mock}): - out = win_license.installed("AAAAA-AAAAA-AAAAA-AAAA-AAAAA-ABCDE") - mock.assert_called_once_with(r"cscript C:\Windows\System32\slmgr.vbs /dli") - self.assertFalse(out) - - def test_install(self): - """ - Test installing the given product key - """ - mock = MagicMock() - with patch.dict(win_license.__salt__, {"cmd.run": mock}): - win_license.install("AAAAA-AAAAA-AAAAA-AAAA-AAAAA-ABCDE") - mock.assert_called_once_with( - r"cscript C:\Windows\System32\slmgr.vbs /ipk " - "AAAAA-AAAAA-AAAAA-AAAA-AAAAA-ABCDE" - ) - - def test_uninstall(self): - """ - Test uninstalling the given product key - """ - mock = MagicMock() - with patch.dict(win_license.__salt__, {"cmd.run": mock}): - win_license.uninstall() - mock.assert_called_once_with(r"cscript C:\Windows\System32\slmgr.vbs /upk") - - def test_activate(self): - """ - Test activating the current product key - """ - mock = MagicMock() - with patch.dict(win_license.__salt__, {"cmd.run": mock}): - win_license.activate() - mock.assert_called_once_with(r"cscript C:\Windows\System32\slmgr.vbs /ato") - - def test_licensed(self): - """ - Test checking if the minion is licensed - """ - mock = MagicMock(return_value="License Status: Licensed") - with patch.dict(win_license.__salt__, {"cmd.run": mock}): - win_license.licensed() - mock.assert_called_once_with(r"cscript C:\Windows\System32\slmgr.vbs /dli") - - def test_info(self): - """ - Test getting the info about the current license key - """ - expected = { - "description": "Prof", - "licensed": True, - "name": "Win7", - "partial_key": "12345", - } - - mock = MagicMock( - return_value=( - "Name: Win7\r\nDescription: Prof\r\nPartial Product Key: 12345\r\n" - "License Status: Licensed" - ) - ) - with patch.dict(win_license.__salt__, {"cmd.run": mock}): - out = win_license.info() - mock.assert_called_once_with(r"cscript C:\Windows\System32\slmgr.vbs /dli") - self.assertEqual(out, expected) diff --git a/tests/unit/modules/test_win_pki.py b/tests/unit/modules/test_win_pki.py deleted file mode 100644 index 883a69e8c84..00000000000 --- a/tests/unit/modules/test_win_pki.py +++ /dev/null @@ -1,169 +0,0 @@ -""" - :synopsis: Unit Tests for Windows PKI Module 'module.win_pki' - :platform: Windows - :maturity: develop - .. versionadded:: 2017.7.0 -""" - - -import salt.modules.win_pki as win_pki -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase - -CERT_PATH = r"C:\certs\testdomain.local.cer" -THUMBPRINT = "9988776655443322111000AAABBBCCCDDDEEEFFF" - -CERTS = { - THUMBPRINT: { - "dnsnames": ["testdomain.local"], - "serialnumber": "0123456789AABBCCDD", - "subject": "CN=testdomain.local, OU=testou, O=testorg, S=California, C=US", - "thumbprint": THUMBPRINT, - "version": 3, - } -} - -STORES = { - "CurrentUser": [ - "AuthRoot", - "CA", - "ClientAuthIssuer", - "Disallowed", - "MSIEHistoryJournal", - "My", - "Root", - "SmartCardRoot", - "Trust", - "TrustedPeople", - "TrustedPublisher", - "UserDS", - ], - "LocalMachine": [ - "AuthRoot", - "CA", - "ClientAuthIssuer", - "Disallowed", - "My", - "Remote Desktop", - "Root", - "SmartCardRoot", - "Trust", - "TrustedDevices", - "TrustedPeople", - "TrustedPublisher", - "WebHosting", - ], -} - -JSON_CERTS = [ - { - "DnsNameList": [ - {"Punycode": "testdomain.local", "Unicode": "testdomain.local"} - ], - "SerialNumber": "0123456789AABBCCDD", - "Subject": "CN=testdomain.local, OU=testou, O=testorg, S=California, C=US", - "Thumbprint": "9988776655443322111000AAABBBCCCDDDEEEFFF", - "Version": 3, - } -] - -JSON_STORES = [ - {"LocationName": "CurrentUser", "StoreNames": STORES["CurrentUser"]}, - {"LocationName": "LocalMachine", "StoreNames": STORES["LocalMachine"]}, -] - - -class WinPkiTestCase(TestCase, LoaderModuleMockMixin): - """ - Test cases for salt.modules.win_pki - """ - - def setup_loader_modules(self): - return {win_pki: {}} - - def test_get_stores(self): - """ - Test - Get the certificate location contexts and their corresponding stores. - """ - with patch.dict(win_pki.__salt__), patch( - "salt.modules.win_pki._cmd_run", MagicMock(return_value=JSON_STORES) - ): - self.assertEqual(win_pki.get_stores(), STORES) - - def test_get_certs(self): - """ - Test - Get the available certificates in the given store. - """ - with patch.dict(win_pki.__salt__), patch( - "salt.modules.win_pki._cmd_run", MagicMock(return_value=JSON_CERTS) - ), patch( - "salt.modules.win_pki._validate_cert_path", MagicMock(return_value=None) - ): - self.assertEqual(win_pki.get_certs(), CERTS) - - def test_get_cert_file(self): - """ - Test - Get the details of the certificate file. - """ - kwargs = {"name": CERT_PATH} - with patch.dict(win_pki.__salt__), patch( - "os.path.isfile", MagicMock(return_value=True) - ), patch("salt.modules.win_pki._cmd_run", MagicMock(return_value=JSON_CERTS)): - self.assertEqual(win_pki.get_cert_file(**kwargs), CERTS[THUMBPRINT]) - - def test_import_cert(self): - """ - Test - Import the certificate file into the given certificate store. - """ - kwargs = {"name": CERT_PATH} - mock_value = MagicMock(return_value=CERT_PATH) - with patch.dict(win_pki.__salt__, {"cp.cache_file": mock_value}), patch( - "salt.modules.win_pki._cmd_run", MagicMock(return_value=JSON_CERTS) - ), patch( - "salt.modules.win_pki._validate_cert_path", MagicMock(return_value=None) - ), patch( - "salt.modules.win_pki.get_cert_file", - MagicMock(return_value=CERTS[THUMBPRINT]), - ), patch( - "salt.modules.win_pki.get_certs", MagicMock(return_value=CERTS) - ): - self.assertTrue(win_pki.import_cert(**kwargs)) - - def test_export_cert(self): - """ - Test - Export the certificate to a file from the given certificate store. - """ - kwargs = {"name": CERT_PATH, "thumbprint": THUMBPRINT} - with patch.dict(win_pki.__salt__), patch( - "salt.modules.win_pki._cmd_run", MagicMock(return_value="True") - ), patch( - "salt.modules.win_pki._validate_cert_format", MagicMock(return_value=None) - ), patch( - "salt.modules.win_pki._validate_cert_path", MagicMock(return_value=None) - ): - self.assertTrue(win_pki.export_cert(**kwargs)) - - def test_test_cert(self): - """ - Test - Check the certificate for validity. - """ - with patch.dict(win_pki.__salt__), patch( - "salt.modules.win_pki._cmd_run", MagicMock(return_value="True") - ), patch( - "salt.modules.win_pki._validate_cert_path", MagicMock(return_value=None) - ): - self.assertTrue(win_pki.test_cert(thumbprint=THUMBPRINT)) - - def test_remove_cert(self): - """ - Test - Remove the certificate from the given certificate store. - """ - with patch.dict(win_pki.__salt__), patch( - "salt.modules.win_pki._cmd_run", MagicMock(return_value=None) - ), patch( - "salt.modules.win_pki._validate_cert_path", MagicMock(return_value=None) - ), patch( - "salt.modules.win_pki.get_certs", MagicMock(return_value=CERTS) - ): - self.assertTrue(win_pki.remove_cert(thumbprint=THUMBPRINT[::-1])) diff --git a/tests/unit/modules/test_win_powercfg.py b/tests/unit/modules/test_win_powercfg.py deleted file mode 100644 index 759284ee41e..00000000000 --- a/tests/unit/modules/test_win_powercfg.py +++ /dev/null @@ -1,270 +0,0 @@ -import salt.modules.win_powercfg as powercfg -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, call, patch -from tests.support.unit import TestCase - - -class PowerCfgTestCase(TestCase, LoaderModuleMockMixin): - """ - Validate the powercfg state - """ - - def setup_loader_modules(self): - return {powercfg: {"__grains__": {"osrelease": 8}}} - - query_output = """Subgroup GUID: 238c9fa8-0aad-41ed-83f4-97be242c8f20 (Hibernate) - GUID Alias: SUB_SLEEP - Power Setting GUID: 29f6c1db-86da-48c5-9fdb-f2b67b1f44da (Hibernate after) - GUID Alias: HIBERNATEIDLE - Minimum Possible Setting: 0x00000000 - Maximum Possible Setting: 0xffffffff - Possible Settings increment: 0x00000001 - Possible Settings units: Seconds - Current AC Power Setting Index: 0x00000708 - Current DC Power Setting Index: 0x00000384""" - - def test_set_monitor_timeout(self): - """ - Test to make sure we can set the monitor timeout value - """ - mock = MagicMock(return_value=0) - mock.side_effect = [ - "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", - self.query_output, - ] - - mock_retcode = MagicMock(return_value=0) - - with patch.dict(powercfg.__salt__, {"cmd.run": mock}): - with patch.dict(powercfg.__salt__, {"cmd.retcode": mock_retcode}): - powercfg.set_monitor_timeout(0, "dc") - mock.assert_called_once_with( - "powercfg /getactivescheme", python_shell=False - ) - mock_retcode.assert_called_once_with( - "powercfg /setdcvalueindex 381b4222-f694-41f0-9685-ff5bb260df2e" - " SUB_VIDEO VIDEOIDLE 0", - python_shell=False, - ) - - def test_set_disk_timeout(self): - """ - Test to make sure we can set the disk timeout value - """ - mock = MagicMock() - mock.side_effect = [ - "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", - self.query_output, - ] - - mock_retcode = MagicMock(return_value=0) - - with patch.dict(powercfg.__salt__, {"cmd.run": mock}): - with patch.dict(powercfg.__salt__, {"cmd.retcode": mock_retcode}): - powercfg.set_disk_timeout(0, "dc") - mock.assert_called_once_with( - "powercfg /getactivescheme", python_shell=False - ) - mock_retcode.assert_called_once_with( - "powercfg /setdcvalueindex 381b4222-f694-41f0-9685-ff5bb260df2e" - " SUB_DISK DISKIDLE 0", - python_shell=False, - ) - - def test_set_standby_timeout(self): - """ - Test to make sure we can set the standby timeout value - """ - mock = MagicMock(return_value=0) - mock.side_effect = [ - "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", - self.query_output, - ] - - mock_retcode = MagicMock(return_value=0) - - with patch.dict(powercfg.__salt__, {"cmd.run": mock}): - with patch.dict(powercfg.__salt__, {"cmd.retcode": mock_retcode}): - powercfg.set_standby_timeout(0, "dc") - mock.assert_called_once_with( - "powercfg /getactivescheme", python_shell=False - ) - mock_retcode.assert_called_once_with( - "powercfg /setdcvalueindex 381b4222-f694-41f0-9685-ff5bb260df2e" - " SUB_SLEEP STANDBYIDLE 0", - python_shell=False, - ) - - def test_set_hibernate_timeout(self): - """ - Test to make sure we can set the hibernate timeout value - """ - mock = MagicMock(return_value=0) - mock.side_effect = [ - "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", - self.query_output, - ] - - mock_retcode = MagicMock(return_value=0) - - with patch.dict(powercfg.__salt__, {"cmd.run": mock}): - with patch.dict(powercfg.__salt__, {"cmd.retcode": mock_retcode}): - powercfg.set_hibernate_timeout(0, "dc") - mock.assert_called_once_with( - "powercfg /getactivescheme", python_shell=False - ) - mock_retcode.assert_called_once_with( - "powercfg /setdcvalueindex 381b4222-f694-41f0-9685-ff5bb260df2e" - " SUB_SLEEP HIBERNATEIDLE 0", - python_shell=False, - ) - - def test_get_monitor_timeout(self): - """ - Test to make sure we can get the monitor timeout value - """ - mock = MagicMock() - mock.side_effect = [ - "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", - self.query_output, - ] - - with patch.dict(powercfg.__salt__, {"cmd.run": mock}): - ret = powercfg.get_monitor_timeout() - calls = [ - call("powercfg /getactivescheme", python_shell=False), - call( - "powercfg /q 381b4222-f694-41f0-9685-ff5bb260df2e SUB_VIDEO" - " VIDEOIDLE", - python_shell=False, - ), - ] - mock.assert_has_calls(calls) - - self.assertEqual({"ac": 30, "dc": 15}, ret) - - def test_get_disk_timeout(self): - """ - Test to make sure we can get the disk timeout value - """ - mock = MagicMock() - mock.side_effect = [ - "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", - self.query_output, - ] - - with patch.dict(powercfg.__salt__, {"cmd.run": mock}): - ret = powercfg.get_disk_timeout() - calls = [ - call("powercfg /getactivescheme", python_shell=False), - call( - "powercfg /q 381b4222-f694-41f0-9685-ff5bb260df2e SUB_DISK" - " DISKIDLE", - python_shell=False, - ), - ] - mock.assert_has_calls(calls) - - self.assertEqual({"ac": 30, "dc": 15}, ret) - - def test_get_standby_timeout(self): - """ - Test to make sure we can get the standby timeout value - """ - mock = MagicMock() - mock.side_effect = [ - "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", - self.query_output, - ] - - with patch.dict(powercfg.__salt__, {"cmd.run": mock}): - ret = powercfg.get_standby_timeout() - calls = [ - call("powercfg /getactivescheme", python_shell=False), - call( - "powercfg /q 381b4222-f694-41f0-9685-ff5bb260df2e SUB_SLEEP" - " STANDBYIDLE", - python_shell=False, - ), - ] - mock.assert_has_calls(calls) - - self.assertEqual({"ac": 30, "dc": 15}, ret) - - def test_get_hibernate_timeout(self): - """ - Test to make sure we can get the hibernate timeout value - """ - mock = MagicMock() - mock.side_effect = [ - "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", - self.query_output, - ] - - with patch.dict(powercfg.__salt__, {"cmd.run": mock}): - ret = powercfg.get_hibernate_timeout() - calls = [ - call("powercfg /getactivescheme", python_shell=False), - call( - "powercfg /q 381b4222-f694-41f0-9685-ff5bb260df2e SUB_SLEEP" - " HIBERNATEIDLE", - python_shell=False, - ), - ] - mock.assert_has_calls(calls) - - self.assertEqual({"ac": 30, "dc": 15}, ret) - - def test_windows_7(self): - """ - Test to make sure we can get the hibernate timeout value on windows 7 - """ - mock = MagicMock() - mock.side_effect = [ - "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", - self.query_output, - ] - - with patch.dict(powercfg.__salt__, {"cmd.run": mock}): - with patch.dict(powercfg.__grains__, {"osrelease": "7"}): - ret = powercfg.get_hibernate_timeout() - calls = [ - call("powercfg /getactivescheme", python_shell=False), - call( - "powercfg /q 381b4222-f694-41f0-9685-ff5bb260df2e SUB_SLEEP", - python_shell=False, - ), - ] - mock.assert_has_calls(calls) - - self.assertEqual({"ac": 30, "dc": 15}, ret) - - def test_set_hibernate_timeout_scheme(self): - """ - Test to make sure we can set the hibernate timeout value - """ - mock = MagicMock(return_value=0) - mock.side_effect = [self.query_output] - - with patch.dict(powercfg.__salt__, {"cmd.retcode": mock}): - powercfg.set_hibernate_timeout(0, "dc", scheme="SCHEME_MIN") - mock.assert_called_once_with( - "powercfg /setdcvalueindex SCHEME_MIN SUB_SLEEP HIBERNATEIDLE 0", - python_shell=False, - ) - - def test_get_hibernate_timeout_scheme(self): - """ - Test to make sure we can get the hibernate timeout value with a - specified scheme - """ - mock = MagicMock() - mock.side_effect = [self.query_output] - - with patch.dict(powercfg.__salt__, {"cmd.run": mock}): - ret = powercfg.get_hibernate_timeout(scheme="SCHEME_MIN") - mock.assert_called_once_with( - "powercfg /q SCHEME_MIN SUB_SLEEP HIBERNATEIDLE", python_shell=False - ) - - self.assertEqual({"ac": 30, "dc": 15}, ret) diff --git a/tests/unit/modules/test_win_shadow.py b/tests/unit/modules/test_win_shadow.py deleted file mode 100644 index 392da373775..00000000000 --- a/tests/unit/modules/test_win_shadow.py +++ /dev/null @@ -1,64 +0,0 @@ -""" - :codeauthor: Jayesh Kariya -""" - - -import salt.modules.win_shadow as win_shadow -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase - - -class WinShadowTestCase(TestCase, LoaderModuleMockMixin): - """ - Test cases for salt.modules.win_shadow - """ - - def setup_loader_modules(self): - return { - win_shadow: { - "__salt__": { - # 'user.info': MagicMock(return_value=True), - "user.update": MagicMock(return_value=True) - } - } - } - - # 'info' function tests: 1 - - def test_info(self): - """ - Test if it return information for the specified user - """ - mock_user_info = MagicMock( - return_value={"name": "SALT", "password_changed": "", "expiration_date": ""} - ) - with patch.dict(win_shadow.__salt__, {"user.info": mock_user_info}): - self.assertDictEqual( - win_shadow.info("SALT"), - { - "name": "SALT", - "passwd": "Unavailable", - "lstchg": "", - "min": "", - "max": "", - "warn": "", - "inact": "", - "expire": "", - }, - ) - - # 'set_password' function tests: 1 - - def test_set_password(self): - """ - Test if it set the password for a named user. - """ - mock_cmd = MagicMock(return_value={"retcode": False}) - mock_user_info = MagicMock( - return_value={"name": "SALT", "password_changed": "", "expiration_date": ""} - ) - with patch.dict( - win_shadow.__salt__, {"cmd.run_all": mock_cmd, "user.info": mock_user_info} - ): - self.assertTrue(win_shadow.set_password("root", "mysecretpassword")) diff --git a/tests/unit/modules/test_win_snmp.py b/tests/unit/modules/test_win_snmp.py deleted file mode 100644 index 4c3c746c0d5..00000000000 --- a/tests/unit/modules/test_win_snmp.py +++ /dev/null @@ -1,114 +0,0 @@ -""" - :synopsis: Unit Tests for Windows SNMP Module 'module.win_snmp' - :platform: Windows - :maturity: develop - .. versionadded:: 2017.7.0 -""" - - -import salt.modules.win_snmp as win_snmp -from salt.exceptions import CommandExecutionError -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase - -COMMUNITY_NAMES = {"TestCommunity": "Read Create"} - - -class WinSnmpTestCase(TestCase, LoaderModuleMockMixin): - """ - Test cases for salt.modules.win_snmp - """ - - def setup_loader_modules(self): - return {win_snmp: {}} - - def test_get_agent_service_types(self): - """ - Test - Get the sysServices types that can be configured. - """ - self.assertIsInstance(win_snmp.get_agent_service_types(), list) - - def test_get_permission_types(self): - """ - Test - Get the permission types that can be configured for communities. - """ - self.assertIsInstance(win_snmp.get_permission_types(), list) - - def test_get_auth_traps_enabled(self): - """ - Test - Determine whether the host is configured to send authentication traps. - """ - mock_value = MagicMock(return_value={"vdata": 1}) - with patch.dict(win_snmp.__utils__, {"reg.read_value": mock_value}): - self.assertTrue(win_snmp.get_auth_traps_enabled()) - - def test_set_auth_traps_enabled(self): - """ - Test - Manage the sending of authentication traps. - """ - mock_value = MagicMock(return_value=True) - kwargs = {"status": True} - with patch.dict(win_snmp.__utils__, {"reg.set_value": mock_value}), patch( - "salt.modules.win_snmp.get_auth_traps_enabled", MagicMock(return_value=True) - ): - self.assertTrue(win_snmp.set_auth_traps_enabled(**kwargs)) - - def test_get_community_names(self): - """ - Test - Get the current accepted SNMP community names and their permissions. - """ - mock_ret = MagicMock(return_value=[{"vdata": 16, "vname": "TestCommunity"}]) - mock_false = MagicMock(return_value=False) - with patch.dict( - win_snmp.__utils__, - {"reg.list_values": mock_ret, "reg.key_exists": mock_false}, - ): - self.assertEqual(win_snmp.get_community_names(), COMMUNITY_NAMES) - - def test_get_community_names_gpo(self): - """ - Test - Get the current accepted SNMP community names and their permissions. - """ - mock_ret = MagicMock(return_value=[{"vdata": "TestCommunity", "vname": 1}]) - mock_false = MagicMock(return_value=True) - with patch.dict( - win_snmp.__utils__, - {"reg.list_values": mock_ret, "reg.key_exists": mock_false}, - ): - self.assertEqual( - win_snmp.get_community_names(), {"TestCommunity": "Managed by GPO"} - ) - - def test_set_community_names(self): - """ - Test - Manage the SNMP accepted community names and their permissions. - """ - mock_true = MagicMock(return_value=True) - kwargs = {"communities": COMMUNITY_NAMES} - mock_false = MagicMock(return_value=False) - with patch.dict( - win_snmp.__utils__, - {"reg.set_value": mock_true, "reg.key_exists": mock_false}, - ), patch( - "salt.modules.win_snmp.get_community_names", - MagicMock(return_value=COMMUNITY_NAMES), - ): - self.assertTrue(win_snmp.set_community_names(**kwargs)) - - def test_set_community_names_gpo(self): - """ - Test - Manage the SNMP accepted community names and their permissions. - """ - mock_true = MagicMock(return_value=True) - kwargs = {"communities": COMMUNITY_NAMES} - with patch.dict( - win_snmp.__utils__, - {"reg.set_value": mock_true, "reg.key_exists": mock_true}, - ), patch( - "salt.modules.win_snmp.get_community_names", - MagicMock(return_value=COMMUNITY_NAMES), - ): - self.assertRaises( - CommandExecutionError, win_snmp.set_community_names, **kwargs - ) diff --git a/tests/unit/states/test_helm.py b/tests/unit/states/test_helm.py deleted file mode 100644 index a96ffa83b26..00000000000 --- a/tests/unit/states/test_helm.py +++ /dev/null @@ -1,255 +0,0 @@ -import salt.states.helm as helm -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase - - -class HelmTestCase(TestCase, LoaderModuleMockMixin): - """ - Test cases for salt.modules.helm - """ - - def setup_loader_modules(self): - return {helm: {}} - - def test_repo_managed_import_failed_repo_manage(self): - ret = { - "name": "state_id", - "changes": {}, - "result": False, - "comment": "'helm.repo_manage' modules not available on this minion.", - } - self.assertEqual(helm.repo_managed("state_id"), ret) - - def test_repo_managed_import_failed_repo_update(self): - mock_helm_modules = {"helm.repo_manage": MagicMock(return_value=True)} - with patch.dict(helm.__salt__, mock_helm_modules): - ret = { - "name": "state_id", - "changes": {}, - "result": False, - "comment": "'helm.repo_update' modules not available on this minion.", - } - self.assertEqual(helm.repo_managed("state_id"), ret) - - def test_repo_managed_is_testing(self): - mock_helm_modules = { - "helm.repo_manage": MagicMock(return_value=True), - "helm.repo_update": MagicMock(return_value=True), - } - with patch.dict(helm.__salt__, mock_helm_modules): - mock__opts__ = {"test": MagicMock(return_value=True)} - with patch.dict(helm.__opts__, mock__opts__): - ret = { - "name": "state_id", - "result": None, - "comment": "Helm repo would have been managed.", - "changes": {}, - } - self.assertEqual(helm.repo_managed("state_id"), ret) - - def test_repo_managed_success(self): - result_changes = {"added": True, "removed": True, "failed": False} - mock_helm_modules = { - "helm.repo_manage": MagicMock(return_value=result_changes), - "helm.repo_update": MagicMock(return_value=True), - } - with patch.dict(helm.__salt__, mock_helm_modules): - ret = { - "name": "state_id", - "result": True, - "comment": "Repositories were added or removed.", - "changes": result_changes, - } - self.assertEqual(helm.repo_managed("state_id"), ret) - - def test_repo_managed_success_with_update(self): - result_changes = {"added": True, "removed": True, "failed": False} - mock_helm_modules = { - "helm.repo_manage": MagicMock(return_value=result_changes), - "helm.repo_update": MagicMock(return_value=True), - } - result_wanted = result_changes - result_wanted.update({"repo_update": True}) - with patch.dict(helm.__salt__, mock_helm_modules): - ret = { - "name": "state_id", - "result": True, - "comment": "Repositories were added or removed.", - "changes": result_wanted, - } - self.assertEqual(helm.repo_managed("state_id"), ret) - - def test_repo_managed_failed(self): - result_changes = {"added": True, "removed": True, "failed": True} - mock_helm_modules = { - "helm.repo_manage": MagicMock(return_value=result_changes), - "helm.repo_update": MagicMock(return_value=True), - } - with patch.dict(helm.__salt__, mock_helm_modules): - ret = { - "name": "state_id", - "result": False, - "comment": "Failed to add or remove some repositories.", - "changes": result_changes, - } - self.assertEqual(helm.repo_managed("state_id"), ret) - - def test_repo_updated_import_failed(self): - ret = { - "name": "state_id", - "changes": {}, - "result": False, - "comment": "'helm.repo_update' modules not available on this minion.", - } - self.assertEqual(helm.repo_updated("state_id"), ret) - - def test_repo_updated_is_testing(self): - mock_helm_modules = {"helm.repo_update": MagicMock(return_value=True)} - with patch.dict(helm.__salt__, mock_helm_modules): - mock__opts__ = {"test": MagicMock(return_value=True)} - with patch.dict(helm.__opts__, mock__opts__): - ret = { - "name": "state_id", - "result": None, - "comment": "Helm repo would have been updated.", - "changes": {}, - } - self.assertEqual(helm.repo_updated("state_id"), ret) - - def test_repo_updated_success(self): - mock_helm_modules = {"helm.repo_update": MagicMock(return_value=True)} - with patch.dict(helm.__salt__, mock_helm_modules): - ret = { - "name": "state_id", - "result": True, - "comment": "Helm repo is updated.", - "changes": {}, - } - self.assertEqual(helm.repo_updated("state_id"), ret) - - def test_repo_updated_failed(self): - mock_helm_modules = {"helm.repo_update": MagicMock(return_value=False)} - with patch.dict(helm.__salt__, mock_helm_modules): - ret = { - "name": "state_id", - "result": False, - "comment": "Failed to sync some repositories.", - "changes": False, - } - self.assertEqual(helm.repo_updated("state_id"), ret) - - def test_release_present_import_failed_helm_status(self): - ret = { - "name": "state_id", - "changes": {}, - "result": False, - "comment": "'helm.status' modules not available on this minion.", - } - self.assertEqual(helm.release_present("state_id", "mychart"), ret) - - def test_release_present_import_failed_helm_install(self): - mock_helm_modules = {"helm.status": MagicMock(return_value=True)} - with patch.dict(helm.__salt__, mock_helm_modules): - ret = { - "name": "state_id", - "changes": {}, - "result": False, - "comment": "'helm.install' modules not available on this minion.", - } - self.assertEqual(helm.release_present("state_id", "mychart"), ret) - - def test_release_present_import_failed_helm_upgrade(self): - mock_helm_modules = { - "helm.status": MagicMock(return_value=True), - "helm.install": MagicMock(return_value=True), - } - with patch.dict(helm.__salt__, mock_helm_modules): - ret = { - "name": "state_id", - "changes": {}, - "result": False, - "comment": "'helm.upgrade' modules not available on this minion.", - } - self.assertEqual(helm.release_present("state_id", "mychart"), ret) - - def test_release_present_is_testing(self): - mock_helm_modules = { - "helm.status": MagicMock(return_value=True), - "helm.install": MagicMock(return_value=True), - "helm.upgrade": MagicMock(return_value=True), - } - with patch.dict(helm.__salt__, mock_helm_modules): - mock__opts__ = {"test": MagicMock(return_value=True)} - with patch.dict(helm.__opts__, mock__opts__): - ret = { - "name": "state_id", - "result": None, - "comment": "Helm release would have been installed or updated.", - "changes": {}, - } - self.assertEqual(helm.release_present("state_id", "mychart"), ret) - - def test_release_absent_import_failed_helm_uninstall(self): - ret = { - "name": "state_id", - "changes": {}, - "result": False, - "comment": "'helm.uninstall' modules not available on this minion.", - } - self.assertEqual(helm.release_absent("state_id"), ret) - - def test_release_absent_import_failed_helm_status(self): - mock_helm_modules = {"helm.uninstall": MagicMock(return_value=True)} - with patch.dict(helm.__salt__, mock_helm_modules): - ret = { - "name": "state_id", - "changes": {}, - "result": False, - "comment": "'helm.status' modules not available on this minion.", - } - self.assertEqual(helm.release_absent("state_id"), ret) - - def test_release_absent_is_testing(self): - mock_helm_modules = { - "helm.status": MagicMock(return_value=True), - "helm.uninstall": MagicMock(return_value=True), - } - with patch.dict(helm.__salt__, mock_helm_modules): - mock__opts__ = {"test": MagicMock(return_value=True)} - with patch.dict(helm.__opts__, mock__opts__): - ret = { - "name": "state_id", - "result": None, - "comment": "Helm release would have been uninstalled.", - "changes": {}, - } - self.assertEqual(helm.release_absent("state_id"), ret) - - def test_release_absent_success(self): - mock_helm_modules = { - "helm.status": MagicMock(return_value={}), - "helm.uninstall": MagicMock(return_value=True), - } - with patch.dict(helm.__salt__, mock_helm_modules): - ret = { - "name": "state_id", - "result": True, - "comment": "Helm release state_id is absent.", - "changes": {"absent": "state_id"}, - } - self.assertEqual(helm.release_absent("state_id"), ret) - - def test_release_absent_error(self): - mock_helm_modules = { - "helm.status": MagicMock(return_value={}), - "helm.uninstall": MagicMock(return_value="error"), - } - with patch.dict(helm.__salt__, mock_helm_modules): - ret = { - "name": "state_id", - "result": False, - "comment": "error", - "changes": {}, - } - self.assertEqual(helm.release_absent("state_id"), ret) diff --git a/tests/unit/states/test_hg.py b/tests/unit/states/test_hg.py deleted file mode 100644 index 2aac3e4bd27..00000000000 --- a/tests/unit/states/test_hg.py +++ /dev/null @@ -1,140 +0,0 @@ -""" - :codeauthor: Rahul Handay -""" - -import os - -import salt.states.hg as hg -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase - - -class HgTestCase(TestCase, LoaderModuleMockMixin): - """ - Validate the svn state - """ - - def setup_loader_modules(self): - return {hg: {}} - - def test_latest(self): - """ - Test to Make sure the repository is cloned to - the given directory and is up to date - """ - ret = {"changes": {}, "comment": "", "name": "salt", "result": True} - mock = MagicMock(return_value=True) - with patch.object(hg, "_fail", mock): - self.assertTrue(hg.latest("salt")) - - mock = MagicMock(side_effect=[False, True, False, False, False, False]) - with patch.object(os.path, "isdir", mock): - mock = MagicMock(return_value=True) - with patch.object(hg, "_handle_existing", mock): - self.assertTrue(hg.latest("salt", target="c:\\salt")) - - with patch.dict(hg.__opts__, {"test": True}): - mock = MagicMock(return_value=True) - with patch.object(hg, "_neutral_test", mock): - self.assertTrue(hg.latest("salt", target="c:\\salt")) - - with patch.dict(hg.__opts__, {"test": False}): - mock = MagicMock(return_value=True) - with patch.object(hg, "_clone_repo", mock): - self.assertDictEqual(hg.latest("salt", target="c:\\salt"), ret) - - def test_latest_update_changes(self): - """ - Test to make sure we don't update even if we have changes - """ - ret = {"changes": {}, "comment": "", "name": "salt", "result": True} - revision_mock = MagicMock(return_value="abcdef") - pull_mock = MagicMock(return_value="Blah.") - update_mock = MagicMock() - - with patch.dict( - hg.__salt__, - { - "hg.revision": revision_mock, - "hg.pull": pull_mock, - "hg.update": update_mock, - }, - ): - mock = MagicMock(side_effect=[True, True]) - with patch.object(os.path, "isdir", mock): - mock = MagicMock(return_value=True) - with patch.dict(hg.__opts__, {"test": False}): - with patch.object(hg, "_clone_repo", mock): - self.assertDictEqual( - hg.latest("salt", target="c:\\salt", update_head=True), ret - ) - assert update_mock.called - - def test_latest_no_update_changes(self): - """ - Test to make sure we don't update even if we have changes - """ - ret = { - "changes": {}, - "comment": ( - "Update is probably required but update_head=False so we will skip" - " updating." - ), - "name": "salt", - "result": True, - } - revision_mock = MagicMock(return_value="abcdef") - pull_mock = MagicMock(return_value="Blah.") - update_mock = MagicMock() - - with patch.dict( - hg.__salt__, - { - "hg.revision": revision_mock, - "hg.pull": pull_mock, - "hg.update": update_mock, - }, - ): - mock = MagicMock(side_effect=[True, True]) - with patch.object(os.path, "isdir", mock): - mock = MagicMock(return_value=True) - with patch.dict(hg.__opts__, {"test": False}): - with patch.object(hg, "_clone_repo", mock): - self.assertDictEqual( - hg.latest("salt", target="c:\\salt", update_head=False), ret - ) - assert not update_mock.called - - def test_latest_no_update_no_changes(self): - """ - Test to Make sure the repository is cloned to - the given directory and is up to date - """ - ret = { - "changes": {}, - "comment": "No changes found and update_head=False so will skip updating.", - "name": "salt", - "result": True, - } - revision_mock = MagicMock(return_value="abcdef") - pull_mock = MagicMock(return_value="Blah no changes found.") - update_mock = MagicMock() - - with patch.dict( - hg.__salt__, - { - "hg.revision": revision_mock, - "hg.pull": pull_mock, - "hg.update": update_mock, - }, - ): - mock = MagicMock(side_effect=[True, True]) - with patch.object(os.path, "isdir", mock): - mock = MagicMock(return_value=True) - with patch.dict(hg.__opts__, {"test": False}): - with patch.object(hg, "_clone_repo", mock): - self.assertDictEqual( - hg.latest("salt", target="c:\\salt", update_head=False), ret - ) - assert not update_mock.called diff --git a/tests/unit/states/test_ini_manage.py b/tests/unit/states/test_ini_manage.py deleted file mode 100644 index ce08736eb64..00000000000 --- a/tests/unit/states/test_ini_manage.py +++ /dev/null @@ -1,172 +0,0 @@ -""" - :codeauthor: Jayesh Kariya -""" - -import salt.states.ini_manage as ini_manage -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase - -# pylint: disable=no-member - - -class IniManageTestCase(TestCase, LoaderModuleMockMixin): - """ - Test cases for salt.states.ini_manage - """ - - def setup_loader_modules(self): - return {ini_manage: {}} - - # 'options_present' function tests: 1 - - def test_options_present(self): - """ - Test to verify options present in file. - """ - name = "salt" - - ret = {"name": name, "result": None, "comment": "", "changes": {}} - - with patch.dict(ini_manage.__opts__, {"test": True}): - comt = "" - ret.update({"comment": comt, "result": True}) - self.assertDictEqual(ini_manage.options_present(name), ret) - - changes = { - "first": "who is on", - "second": "what is on", - "third": "I don't know", - } - with patch.dict( - ini_manage.__salt__, {"ini.set_option": MagicMock(return_value=changes)} - ): - with patch.dict(ini_manage.__opts__, {"test": False}): - comt = "Changes take effect" - ret.update({"comment": comt, "result": True, "changes": changes}) - self.assertDictEqual(ini_manage.options_present(name), ret) - - original = { - "mysection": { - "first": "who is on", - "second": "what is on", - "third": "I don't know", - } - } - desired = {"mysection": {"first": "who is on", "second": "what is on"}} - changes = { - "mysection": { - "first": "who is on", - "second": "what is on", - "third": {"after": None, "before": "I don't know"}, - } - } - with patch.dict( - ini_manage.__salt__, {"ini.get_ini": MagicMock(return_value=original)} - ): - with patch.dict( - ini_manage.__salt__, - {"ini.remove_option": MagicMock(return_value="third")}, - ): - with patch.dict( - ini_manage.__salt__, - {"ini.get_option": MagicMock(return_value="I don't know")}, - ): - with patch.dict( - ini_manage.__salt__, - {"ini.set_option": MagicMock(return_value=desired)}, - ): - with patch.dict(ini_manage.__opts__, {"test": False}): - comt = "Changes take effect" - ret.update( - {"comment": comt, "result": True, "changes": changes} - ) - self.assertDictEqual( - ini_manage.options_present(name, desired, strict=True), - ret, - ) - - # 'options_absent' function tests: 1 - - def test_options_absent(self): - """ - Test to verify options absent in file. - """ - name = "salt" - - ret = {"name": name, "result": None, "comment": "", "changes": {}} - - with patch.dict(ini_manage.__opts__, {"test": True}): - comt = "No changes detected." - ret.update({"comment": comt, "result": True}) - self.assertDictEqual(ini_manage.options_absent(name), ret) - - with patch.dict(ini_manage.__opts__, {"test": False}): - comt = "No anomaly detected" - ret.update({"comment": comt, "result": True}) - self.assertDictEqual(ini_manage.options_absent(name), ret) - original = {"Tables": {"key1": "1", "key2": "2", "key3": "3", "key4": "4"}} - sections = {"Tables": ["key2", "key3"]} - changes = {"Tables": {"key2": "2", "key3": "3"}} - with patch.dict( - ini_manage.__salt__, - {"ini.remove_option": MagicMock(side_effect=["2", "3"])}, - ): - with patch.dict(ini_manage.__opts__, {"test": False}): - comt = "Changes take effect" - ret.update({"comment": comt, "result": True, "changes": changes}) - self.assertDictEqual(ini_manage.options_absent(name, sections), ret) - - # 'sections_present' function tests: 1 - - def test_sections_present(self): - """ - Test to verify sections present in file. - """ - name = "salt" - - ret = {"name": name, "result": None, "comment": "", "changes": {}} - - with patch.dict(ini_manage.__opts__, {"test": True}): - with patch.dict( - ini_manage.__salt__, {"ini.get_ini": MagicMock(return_value=None)} - ): - comt = "No changes detected." - ret.update({"comment": comt, "result": True}) - self.assertDictEqual(ini_manage.sections_present(name), ret) - - changes = { - "first": "who is on", - "second": "what is on", - "third": "I don't know", - } - with patch.dict( - ini_manage.__salt__, {"ini.set_option": MagicMock(return_value=changes)} - ): - with patch.dict(ini_manage.__opts__, {"test": False}): - comt = "Changes take effect" - ret.update({"comment": comt, "result": True, "changes": changes}) - self.assertDictEqual(ini_manage.sections_present(name), ret) - - # 'sections_absent' function tests: 1 - - def test_sections_absent(self): - """ - Test to verify sections absent in file. - """ - name = "salt" - - ret = {"name": name, "result": None, "comment": "", "changes": {}} - - with patch.dict(ini_manage.__opts__, {"test": True}): - with patch.dict( - ini_manage.__salt__, {"ini.get_ini": MagicMock(return_value=None)} - ): - comt = "No changes detected." - ret.update({"comment": comt, "result": True}) - self.assertDictEqual(ini_manage.sections_absent(name), ret) - - with patch.dict(ini_manage.__opts__, {"test": False}): - comt = "No anomaly detected" - ret.update({"comment": comt, "result": True}) - self.assertDictEqual(ini_manage.sections_absent(name), ret) diff --git a/tests/unit/states/test_ipmi.py b/tests/unit/states/test_ipmi.py deleted file mode 100644 index b6aea2a0452..00000000000 --- a/tests/unit/states/test_ipmi.py +++ /dev/null @@ -1,176 +0,0 @@ -""" - :codeauthor: Jayesh Kariya -""" - -import salt.states.ipmi as ipmi -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase - - -class IpmiTestCase(TestCase, LoaderModuleMockMixin): - """ - Test cases for salt.states.ipmi - """ - - def setup_loader_modules(self): - return {ipmi: {}} - - # 'boot_device' function tests: 1 - - def test_boot_device(self): - """ - Test to request power state change. - """ - name = "salt" - - ret = {"name": name, "result": True, "comment": "", "changes": {}} - - mock = MagicMock(return_value=name) - with patch.dict( - ipmi.__salt__, {"ipmi.get_bootdev": mock, "ipmi.set_bootdev": mock} - ): - comt = "system already in this state" - ret.update({"comment": comt}) - self.assertDictEqual(ipmi.boot_device(name), ret) - - with patch.dict(ipmi.__opts__, {"test": False}): - comt = "changed boot device" - ret.update( - { - "name": "default", - "comment": comt, - "result": True, - "changes": {"new": "default", "old": "salt"}, - } - ) - self.assertDictEqual(ipmi.boot_device(), ret) - - with patch.dict(ipmi.__opts__, {"test": True}): - comt = "would change boot device" - ret.update({"comment": comt, "result": None}) - self.assertDictEqual(ipmi.boot_device(), ret) - - # 'power' function tests: 1 - - def test_power(self): - """ - Test to request power state change - """ - ret = {"name": "power_on", "result": True, "comment": "", "changes": {}} - - mock = MagicMock(return_value="on") - with patch.dict( - ipmi.__salt__, {"ipmi.get_power": mock, "ipmi.set_power": mock} - ): - comt = "system already in this state" - ret.update({"comment": comt}) - self.assertDictEqual(ipmi.power(), ret) - - with patch.dict(ipmi.__opts__, {"test": False}): - comt = "changed system power" - ret.update( - { - "name": "off", - "comment": comt, - "result": True, - "changes": {"new": "off", "old": "on"}, - } - ) - self.assertDictEqual(ipmi.power("off"), ret) - - with patch.dict(ipmi.__opts__, {"test": True}): - comt = "would power: off system" - ret.update({"comment": comt, "result": None}) - self.assertDictEqual(ipmi.power("off"), ret) - - # 'user_present' function tests: 1 - - def test_user_present(self): - """ - Test to ensure IPMI user and user privileges. - """ - name = "salt" - - ret = {"name": name, "result": True, "comment": "", "changes": {}} - - mock_ret = { - "access": { - "callback": False, - "link_auth": True, - "ipmi_msg": True, - "privilege_level": "administrator", - } - } - mock = MagicMock(return_value=mock_ret) - mock_bool = MagicMock(side_effect=[True, False, False, False]) - with patch.dict( - ipmi.__salt__, - { - "ipmi.get_user": mock, - "ipmi.set_user_password": mock_bool, - "ipmi.ensure_user": mock_bool, - }, - ): - comt = "user already present" - ret.update({"comment": comt}) - self.assertDictEqual(ipmi.user_present(name, 5, "salt@123"), ret) - - with patch.dict(ipmi.__opts__, {"test": True}): - comt = "would (re)create user" - ret.update( - { - "comment": comt, - "result": None, - "changes": {"new": "salt", "old": mock_ret}, - } - ) - self.assertDictEqual(ipmi.user_present(name, 5, "pw@123"), ret) - - with patch.dict(ipmi.__opts__, {"test": False}): - comt = "(re)created user" - ret.update( - { - "comment": comt, - "result": True, - "changes": {"new": mock_ret, "old": mock_ret}, - } - ) - self.assertDictEqual(ipmi.user_present(name, 5, "pw@123"), ret) - - # 'user_absent' function tests: 1 - - def test_user_absent(self): - """ - Test to delete all user (uid) records having the matching name. - """ - name = "salt" - - ret = {"name": name, "result": True, "comment": "", "changes": {}} - - mock = MagicMock(side_effect=[[], [5], [5]]) - mock_bool = MagicMock(return_value=True) - with patch.dict( - ipmi.__salt__, {"ipmi.get_name_uids": mock, "ipmi.delete_user": mock_bool} - ): - comt = "user already absent" - ret.update({"comment": comt}) - self.assertDictEqual(ipmi.user_absent(name), ret) - - with patch.dict(ipmi.__opts__, {"test": True}): - comt = "would delete user(s)" - ret.update( - {"comment": comt, "result": None, "changes": {"delete": [5]}} - ) - self.assertDictEqual(ipmi.user_absent(name), ret) - - with patch.dict(ipmi.__opts__, {"test": False}): - comt = "user(s) removed" - ret.update( - { - "comment": comt, - "result": False, - "changes": {"new": "None", "old": [5]}, - } - ) - self.assertDictEqual(ipmi.user_absent(name), ret) diff --git a/tests/unit/states/test_kapacitor.py b/tests/unit/states/test_kapacitor.py deleted file mode 100644 index 2a7b78b96ab..00000000000 --- a/tests/unit/states/test_kapacitor.py +++ /dev/null @@ -1,130 +0,0 @@ -import salt.states.kapacitor as kapacitor -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import Mock, mock_open, patch -from tests.support.unit import TestCase - - -def _present( - name="testname", - tick_script="/tmp/script.tick", - task_type="stream", - database="testdb", - retention_policy="default", - dbrps=None, - enable=True, - task=None, - define_result=True, - enable_result=True, - disable_result=True, - script="testscript", -): - """ - Run a "kapacitor.present" state after setting up mocks, and return the - state return value as well as the mocks to make assertions. - """ - get_mock = Mock(return_value=task) - - if isinstance(define_result, bool): - define_result = {"success": define_result} - define_mock = Mock(return_value=define_result) - - if isinstance(enable_result, bool): - enable_result = {"success": enable_result} - enable_mock = Mock(return_value=enable_result) - - if isinstance(disable_result, bool): - disable_result = {"success": disable_result} - disable_mock = Mock(return_value=disable_result) - - with patch.dict( - kapacitor.__salt__, - { - "kapacitor.get_task": get_mock, - "kapacitor.define_task": define_mock, - "kapacitor.enable_task": enable_mock, - "kapacitor.disable_task": disable_mock, - }, - ): - with patch("salt.utils.files.fopen", mock_open(read_data=script)) as open_mock: - retval = kapacitor.task_present( - name, - tick_script, - task_type=task_type, - database=database, - retention_policy=retention_policy, - enable=enable, - dbrps=dbrps, - ) - - return retval, get_mock, define_mock, enable_mock, disable_mock - - -def _task( - script="testscript", enabled=True, task_type="stream", db="testdb", rp="default" -): - return { - "script": script, - "enabled": enabled, - "type": task_type, - "dbrps": [{"db": db, "rp": rp}], - } - - -class KapacitorTestCase(TestCase, LoaderModuleMockMixin): - def setup_loader_modules(self): - return {kapacitor: {"__opts__": {"test": False}, "__env__": "test"}} - - def test_task_present_new_task(self): - ret, get_mock, define_mock, enable_mock, _ = _present( - dbrps=["testdb2.default_rp"] - ) - get_mock.assert_called_once_with("testname") - define_mock.assert_called_once_with( - "testname", - "/tmp/script.tick", - database="testdb", - retention_policy="default", - task_type="stream", - dbrps=["testdb2.default_rp", "testdb.default"], - ) - enable_mock.assert_called_once_with("testname") - self.assertIn("TICKscript diff", ret["changes"]) - self.assertIn("enabled", ret["changes"]) - self.assertEqual(True, ret["changes"]["enabled"]["new"]) - - def test_task_present_existing_task_updated_script(self): - ret, get_mock, define_mock, enable_mock, _ = _present( - task=_task(script="oldscript") - ) - get_mock.assert_called_once_with("testname") - define_mock.assert_called_once_with( - "testname", - "/tmp/script.tick", - database="testdb", - retention_policy="default", - task_type="stream", - dbrps=["testdb.default"], - ) - self.assertEqual(False, enable_mock.called) - self.assertIn("TICKscript diff", ret["changes"]) - self.assertNotIn("enabled", ret["changes"]) - - def test_task_present_existing_task_not_enabled(self): - ret, get_mock, define_mock, enable_mock, _ = _present(task=_task(enabled=False)) - get_mock.assert_called_once_with("testname") - self.assertEqual(False, define_mock.called) - enable_mock.assert_called_once_with("testname") - self.assertNotIn("diff", ret["changes"]) - self.assertIn("enabled", ret["changes"]) - self.assertEqual(True, ret["changes"]["enabled"]["new"]) - - def test_task_present_disable_existing_task(self): - ret, get_mock, define_mock, _, disable_mock = _present( - task=_task(), enable=False - ) - get_mock.assert_called_once_with("testname") - self.assertEqual(False, define_mock.called) - disable_mock.assert_called_once_with("testname") - self.assertNotIn("diff", ret["changes"]) - self.assertIn("enabled", ret["changes"]) - self.assertEqual(False, ret["changes"]["enabled"]["new"]) diff --git a/tests/unit/states/test_kernelpkg.py b/tests/unit/states/test_kernelpkg.py deleted file mode 100644 index 4406dbe0393..00000000000 --- a/tests/unit/states/test_kernelpkg.py +++ /dev/null @@ -1,160 +0,0 @@ -""" - :synopsis: Unit Tests for 'module.aptkernelpkg' - :platform: Linux - :maturity: develop - versionadded:: 2018.3.0 -""" -# pylint: disable=invalid-name,no-member -import pytest - -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase - -try: - import salt.states.kernelpkg as kernelpkg - - HAS_MODULES = True -except ImportError: - HAS_MODULES = False - -KERNEL_LIST = ["4.4.0-70-generic", "4.4.0-71-generic", "4.5.1-14-generic"] -STATE_NAME = "kernelpkg-test" - - -@pytest.mark.skipif(not HAS_MODULES, reason="Salt modules could not be loaded") -class KernelPkgTestCase(TestCase, LoaderModuleMockMixin): - """ - Test cases for salt.states.aptpkg - """ - - def setup_loader_modules(self): - return { - kernelpkg: { - "__salt__": { - "system.reboot": MagicMock(return_value=None), - "kernelpkg.upgrade": MagicMock( - return_value={ - "upgrades": {"kernel": {"old": "1.0.0", "new": "2.0.0"}} - } - ), - "kernelpkg.active": MagicMock(return_value=0), - "kernelpkg.latest_installed": MagicMock(return_value=0), - } - } - } - - def test_latest_installed_with_changes(self): - """ - Test - latest_installed when an upgrade is available - """ - installed = MagicMock(return_value=KERNEL_LIST[:-1]) - upgrade = MagicMock(return_value=KERNEL_LIST[-1]) - with patch.dict(kernelpkg.__salt__, {"kernelpkg.list_installed": installed}): - with patch.dict( - kernelpkg.__salt__, {"kernelpkg.latest_available": upgrade} - ): - with patch.dict(kernelpkg.__opts__, {"test": False}): - kernelpkg.__salt__["kernelpkg.upgrade"].reset_mock() - ret = kernelpkg.latest_installed(name=STATE_NAME) - self.assertEqual(ret["name"], STATE_NAME) - self.assertTrue(ret["result"]) - self.assertIsInstance(ret["changes"], dict) - self.assertIsInstance(ret["comment"], str) - kernelpkg.__salt__["kernelpkg.upgrade"].assert_called_once() - - with patch.dict(kernelpkg.__opts__, {"test": True}): - kernelpkg.__salt__["kernelpkg.upgrade"].reset_mock() - ret = kernelpkg.latest_installed(name=STATE_NAME) - self.assertEqual(ret["name"], STATE_NAME) - self.assertIsNone(ret["result"]) - self.assertDictEqual(ret["changes"], {}) - self.assertIsInstance(ret["comment"], str) - kernelpkg.__salt__["kernelpkg.upgrade"].assert_not_called() - - def test_latest_installed_at_latest(self): - """ - Test - latest_installed when no upgrade is available - """ - installed = MagicMock(return_value=KERNEL_LIST) - upgrade = MagicMock(return_value=KERNEL_LIST[-1]) - with patch.dict(kernelpkg.__salt__, {"kernelpkg.list_installed": installed}): - with patch.dict( - kernelpkg.__salt__, {"kernelpkg.latest_available": upgrade} - ): - with patch.dict(kernelpkg.__opts__, {"test": False}): - ret = kernelpkg.latest_installed(name=STATE_NAME) - self.assertEqual(ret["name"], STATE_NAME) - self.assertTrue(ret["result"]) - self.assertDictEqual(ret["changes"], {}) - self.assertIsInstance(ret["comment"], str) - kernelpkg.__salt__["kernelpkg.upgrade"].assert_not_called() - - with patch.dict(kernelpkg.__opts__, {"test": True}): - ret = kernelpkg.latest_installed(name=STATE_NAME) - self.assertEqual(ret["name"], STATE_NAME) - self.assertTrue(ret["result"]) - self.assertDictEqual(ret["changes"], {}) - self.assertIsInstance(ret["comment"], str) - kernelpkg.__salt__["kernelpkg.upgrade"].assert_not_called() - - def test_latest_active_with_changes(self): - """ - Test - latest_active when a new kernel is available - """ - reboot = MagicMock(return_value=True) - latest = MagicMock(return_value=1) - with patch.dict( - kernelpkg.__salt__, - {"kernelpkg.needs_reboot": reboot, "kernelpkg.latest_installed": latest}, - ), patch.dict(kernelpkg.__opts__, {"test": False}): - kernelpkg.__salt__["system.reboot"].reset_mock() - ret = kernelpkg.latest_active(name=STATE_NAME) - self.assertEqual(ret["name"], STATE_NAME) - self.assertTrue(ret["result"]) - self.assertIsInstance(ret["changes"], dict) - self.assertIsInstance(ret["comment"], str) - kernelpkg.__salt__["system.reboot"].assert_called_once() - - with patch.dict(kernelpkg.__opts__, {"test": True}): - kernelpkg.__salt__["system.reboot"].reset_mock() - ret = kernelpkg.latest_active(name=STATE_NAME) - self.assertEqual(ret["name"], STATE_NAME) - self.assertIsNone(ret["result"]) - self.assertDictEqual(ret["changes"], {"kernel": {"new": 1, "old": 0}}) - self.assertIsInstance(ret["comment"], str) - kernelpkg.__salt__["system.reboot"].assert_not_called() - - def test_latest_active_at_latest(self): - """ - Test - latest_active when the newest kernel is already active - """ - reboot = MagicMock(return_value=False) - with patch.dict(kernelpkg.__salt__, {"kernelpkg.needs_reboot": reboot}): - with patch.dict(kernelpkg.__opts__, {"test": False}): - kernelpkg.__salt__["system.reboot"].reset_mock() - ret = kernelpkg.latest_active(name=STATE_NAME) - self.assertEqual(ret["name"], STATE_NAME) - self.assertTrue(ret["result"]) - self.assertDictEqual(ret["changes"], {}) - self.assertIsInstance(ret["comment"], str) - kernelpkg.__salt__["system.reboot"].assert_not_called() - - with patch.dict(kernelpkg.__opts__, {"test": True}): - kernelpkg.__salt__["system.reboot"].reset_mock() - ret = kernelpkg.latest_active(name=STATE_NAME) - self.assertEqual(ret["name"], STATE_NAME) - self.assertTrue(ret["result"]) - self.assertDictEqual(ret["changes"], {}) - self.assertIsInstance(ret["comment"], str) - kernelpkg.__salt__["system.reboot"].assert_not_called() - - def test_latest_wait(self): - """ - Test - latest_wait static results - """ - ret = kernelpkg.latest_wait(name=STATE_NAME) - self.assertEqual(ret["name"], STATE_NAME) - self.assertTrue(ret["result"]) - self.assertDictEqual(ret["changes"], {}) - self.assertIsInstance(ret["comment"], str) diff --git a/tests/unit/states/test_keystone.py b/tests/unit/states/test_keystone.py deleted file mode 100644 index 860b48e4ae0..00000000000 --- a/tests/unit/states/test_keystone.py +++ /dev/null @@ -1,413 +0,0 @@ -""" - :codeauthor: Jayesh Kariya -""" - -import salt.states.keystone as keystone -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase - - -class KeystoneTestCase(TestCase, LoaderModuleMockMixin): - """ - Test cases for salt.states.keystone - """ - - def setup_loader_modules(self): - return {keystone: {}} - - # 'user_present' function tests: 1 - - def test_user_present(self): - """ - Test to ensure that the keystone user is present - with the specified properties. - """ - name = "nova" - password = "$up3rn0v4" - email = "nova@domain.com" - tenant = "demo" - - ret = {"name": name, "result": False, "changes": {}, "comment": ""} - - mock_f = MagicMock(return_value=False) - mock_lst = MagicMock(return_value=["Error"]) - with patch.dict(keystone.__salt__, {"keystone.tenant_get": mock_lst}): - comt = 'Tenant / project "{}" does not exist'.format(tenant) - ret.update({"comment": comt}) - self.assertDictEqual( - keystone.user_present(name, password, email, tenant), ret - ) - - mock_dict = MagicMock( - side_effect=[ - {name: {"email": "a@a.com"}}, - {name: {"email": email, "enabled": False}}, - {name: {"email": email, "enabled": True}}, - {name: {"email": email, "enabled": True}}, - {"Error": "error"}, - {"Error": "error"}, - ] - ) - mock_l = MagicMock(return_value={tenant: {"id": "abc"}}) - with patch.dict( - keystone.__salt__, - { - "keystone.user_get": mock_dict, - "keystone.tenant_get": mock_l, - "keystone.user_verify_password": mock_f, - "keystone.user_create": mock_f, - }, - ): - with patch.dict(keystone.__opts__, {"test": True}): - comt = 'User "{}" will be updated'.format(name) - ret.update( - { - "comment": comt, - "result": None, - "changes": { - "Email": "Will be updated", - "Enabled": "Will be True", - "Password": "Will be updated", - }, - } - ) - self.assertDictEqual(keystone.user_present(name, password, email), ret) - - ret.update( - { - "comment": comt, - "result": None, - "changes": { - "Enabled": "Will be True", - "Password": "Will be updated", - }, - } - ) - self.assertDictEqual(keystone.user_present(name, password, email), ret) - - ret.update( - { - "comment": comt, - "result": None, - "changes": { - "Tenant": 'Will be added to "demo" tenant', - "Password": "Will be updated", - }, - } - ) - self.assertDictEqual( - keystone.user_present(name, password, email, tenant), ret - ) - - ret.update( - { - "comment": comt, - "result": None, - "changes": {"Password": "Will be updated"}, - } - ) - self.assertDictEqual(keystone.user_present(name, password, email), ret) - - comt = 'Keystone user "nova" will be added' - ret.update( - { - "comment": comt, - "result": None, - "changes": {"User": "Will be created"}, - } - ) - self.assertDictEqual(keystone.user_present(name, password, email), ret) - - with patch.dict(keystone.__opts__, {"test": False}): - comt = "Keystone user {} has been added".format(name) - ret.update( - {"comment": comt, "result": True, "changes": {"User": "Created"}} - ) - self.assertDictEqual(keystone.user_present(name, password, email), ret) - - # 'user_absent' function tests: 1 - - def test_user_absent(self): - """ - Test to ensure that the keystone user is absent. - """ - name = "nova" - - ret = { - "name": name, - "changes": {}, - "result": True, - "comment": 'User "{}" is already absent'.format(name), - } - - mock_lst = MagicMock(side_effect=[["Error"], []]) - with patch.dict(keystone.__salt__, {"keystone.user_get": mock_lst}): - self.assertDictEqual(keystone.user_absent(name), ret) - - with patch.dict(keystone.__opts__, {"test": True}): - comt = 'User "{}" will be deleted'.format(name) - ret.update({"comment": comt, "result": None}) - self.assertDictEqual(keystone.user_absent(name), ret) - - # 'tenant_present' function tests: 1 - - def test_tenant_present(self): - """ - Test to ensures that the keystone tenant exists - """ - name = "nova" - description = "OpenStack Compute Service" - - ret = { - "name": name, - "changes": {}, - "result": True, - "comment": 'Tenant / project "{}" already exists'.format(name), - } - - mock_dict = MagicMock( - side_effect=[ - {name: {"description": "desc"}}, - {name: {"description": description, "enabled": False}}, - {"Error": "error"}, - {"Error": "error"}, - ] - ) - mock_t = MagicMock(return_value=True) - with patch.dict( - keystone.__salt__, - {"keystone.tenant_get": mock_dict, "keystone.tenant_create": mock_t}, - ): - with patch.dict(keystone.__opts__, {"test": True}): - comt = 'Tenant / project "{}" will be updated'.format(name) - ret.update( - { - "comment": comt, - "result": None, - "changes": {"Description": "Will be updated"}, - } - ) - self.assertDictEqual(keystone.tenant_present(name), ret) - - comt = 'Tenant / project "{}" will be updated'.format(name) - ret.update( - { - "comment": comt, - "result": None, - "changes": {"Enabled": "Will be True"}, - } - ) - self.assertDictEqual(keystone.tenant_present(name, description), ret) - - comt = 'Tenant / project "{}" will be added'.format(name) - ret.update( - { - "comment": comt, - "result": None, - "changes": {"Tenant": "Will be created"}, - } - ) - self.assertDictEqual(keystone.tenant_present(name), ret) - - with patch.dict(keystone.__opts__, {"test": False}): - comt = 'Tenant / project "{}" has been added'.format(name) - ret.update( - {"comment": comt, "result": True, "changes": {"Tenant": "Created"}} - ) - self.assertDictEqual(keystone.tenant_present(name), ret) - - # 'tenant_absent' function tests: 1 - - def test_tenant_absent(self): - """ - Test to ensure that the keystone tenant is absent. - """ - name = "nova" - - ret = { - "name": name, - "changes": {}, - "result": True, - "comment": 'Tenant / project "{}" is already absent'.format(name), - } - - mock_lst = MagicMock(side_effect=[["Error"], []]) - with patch.dict(keystone.__salt__, {"keystone.tenant_get": mock_lst}): - self.assertDictEqual(keystone.tenant_absent(name), ret) - - with patch.dict(keystone.__opts__, {"test": True}): - comt = 'Tenant / project "{}" will be deleted'.format(name) - ret.update({"comment": comt, "result": None}) - self.assertDictEqual(keystone.tenant_absent(name), ret) - - # 'role_present' function tests: 1 - - def test_role_present(self): - """ - Test to ensures that the keystone role exists - """ - name = "nova" - - ret = { - "name": name, - "changes": {}, - "result": True, - "comment": 'Role "{}" already exists'.format(name), - } - - mock_lst = MagicMock(side_effect=[[], ["Error"]]) - with patch.dict(keystone.__salt__, {"keystone.role_get": mock_lst}): - self.assertDictEqual(keystone.role_present(name), ret) - - with patch.dict(keystone.__opts__, {"test": True}): - comt = 'Role "{}" will be added'.format(name) - ret.update({"comment": comt, "result": None}) - self.assertDictEqual(keystone.role_present(name), ret) - - # 'role_absent' function tests: 1 - - def test_role_absent(self): - """ - Test to ensure that the keystone role is absent. - """ - name = "nova" - - ret = { - "name": name, - "changes": {}, - "result": True, - "comment": 'Role "{}" is already absent'.format(name), - } - - mock_lst = MagicMock(side_effect=[["Error"], []]) - with patch.dict(keystone.__salt__, {"keystone.role_get": mock_lst}): - self.assertDictEqual(keystone.role_absent(name), ret) - - with patch.dict(keystone.__opts__, {"test": True}): - comt = 'Role "{}" will be deleted'.format(name) - ret.update({"comment": comt, "result": None}) - self.assertDictEqual(keystone.role_absent(name), ret) - - # 'service_present' function tests: 1 - - def test_service_present(self): - """ - Test to ensure service present in Keystone catalog - """ - name = "nova" - service_type = "compute" - - ret = { - "name": name, - "changes": {}, - "result": True, - "comment": 'Service "{}" already exists'.format(name), - } - - mock_lst = MagicMock(side_effect=[[], ["Error"]]) - with patch.dict(keystone.__salt__, {"keystone.service_get": mock_lst}): - self.assertDictEqual(keystone.service_present(name, service_type), ret) - - with patch.dict(keystone.__opts__, {"test": True}): - comt = 'Service "{}" will be added'.format(name) - ret.update({"comment": comt, "result": None}) - self.assertDictEqual(keystone.service_present(name, service_type), ret) - - # 'service_absent' function tests: 1 - - def test_service_absent(self): - """ - Test to ensure that the service doesn't exist in Keystone catalog - """ - name = "nova" - - ret = { - "name": name, - "changes": {}, - "result": True, - "comment": 'Service "{}" is already absent'.format(name), - } - - mock_lst = MagicMock(side_effect=[["Error"], []]) - with patch.dict(keystone.__salt__, {"keystone.service_get": mock_lst}): - self.assertDictEqual(keystone.service_absent(name), ret) - - with patch.dict(keystone.__opts__, {"test": True}): - comt = 'Service "{}" will be deleted'.format(name) - ret.update({"comment": comt, "result": None}) - self.assertDictEqual(keystone.service_absent(name), ret) - - # 'endpoint_present' function tests: 1 - - def test_endpoint_present(self): - """ - Test to ensure the specified endpoints exists for service - """ - name = "nova" - region = "RegionOne" - - ret = {"name": name, "changes": {}, "result": True, "comment": ""} - - endpoint = { - "adminurl": None, - "region": None, - "internalurl": None, - "publicurl": None, - "id": 1, - "service_id": None, - } - - mock_lst = MagicMock( - side_effect=[endpoint, ["Error"], {"id": 1, "service_id": None}, []] - ) - mock = MagicMock(return_value=True) - with patch.dict( - keystone.__salt__, - {"keystone.endpoint_get": mock_lst, "keystone.endpoint_create": mock}, - ): - - comt = 'Endpoint for service "{}" already exists'.format(name) - ret.update({"comment": comt, "result": True, "changes": {}}) - self.assertDictEqual(keystone.endpoint_present(name), ret) - - with patch.dict(keystone.__opts__, {"test": True}): - comt = 'Endpoint for service "{}" will be added'.format(name) - ret.update( - { - "comment": comt, - "result": None, - "changes": {"Endpoint": "Will be created"}, - } - ) - self.assertDictEqual(keystone.endpoint_present(name), ret) - - comt = 'Endpoint for service "{}" already exists'.format(name) - ret.update({"comment": comt, "result": True, "changes": {}}) - self.assertDictEqual(keystone.endpoint_present(name), ret) - - with patch.dict(keystone.__opts__, {"test": False}): - comt = 'Endpoint for service "{}" has been added'.format(name) - ret.update({"comment": comt, "result": True, "changes": True}) - self.assertDictEqual(keystone.endpoint_present(name), ret) - - # 'endpoint_absent' function tests: 1 - - def test_endpoint_absent(self): - """ - Test to ensure that the endpoint for a service doesn't - exist in Keystone catalog - """ - name = "nova" - region = "RegionOne" - comment = 'Endpoint for service "{}" is already absent'.format(name) - ret = {"name": name, "changes": {}, "result": True, "comment": comment} - - mock_lst = MagicMock(side_effect=[[], ["Error"]]) - with patch.dict(keystone.__salt__, {"keystone.endpoint_get": mock_lst}): - self.assertDictEqual(keystone.endpoint_absent(name, region), ret) - - with patch.dict(keystone.__opts__, {"test": True}): - comt = 'Endpoint for service "{}" will be deleted'.format(name) - ret.update({"comment": comt, "result": None}) - self.assertDictEqual(keystone.endpoint_absent(name, region), ret) diff --git a/tests/unit/states/test_keystore.py b/tests/unit/states/test_keystore.py deleted file mode 100644 index 45995a57a4f..00000000000 --- a/tests/unit/states/test_keystore.py +++ /dev/null @@ -1,510 +0,0 @@ -""" -Test cases for keystore state -""" - -import salt.states.keystore as keystore -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase - - -class KeystoreTestCase(TestCase, LoaderModuleMockMixin): - """ - Test cases for salt.states.keystore - """ - - def setup_loader_modules(self): - return {keystore: {"__opts__": {"test": False}}} - - def test_cert_already_present(self): - """ - Test for existing value_present - """ - - cert_return = [ - { - "valid_until": "August 21 2017", - "sha1": "07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D5".encode( - __salt_system_encoding__ - ), - "valid_start": "August 22 2012", - "type": "TrustedCertEntry", - "alias": "stringhost", - "expired": True, - } - ] - x509_return = { - "Not After": "2017-08-21 05:26:54", - "Subject Hash": "97:95:14:4F", - "Serial Number": "0D:FA", - "SHA1 Finger Print": ( - "07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D5".encode( - __salt_system_encoding__ - ) - ), - "SHA-256 Finger Print": "5F:0F:B5:16:65:81:AA:E6:4A:10:1C:15:83:B1:BE:BE:74:E8:14:A9:1E:7A:8A:14:BA:1E:83:5D:78:F6:E9:E7".encode( - __salt_system_encoding__ - ), - "MD5 Finger Print": "80:E6:17:AF:78:D8:E4:B8:FB:5F:41:3A:27:1D:CC:F2".encode( - __salt_system_encoding__ - ), - "Version": 1, - "Key Size": 512, - "Public Key": ( - "-----BEGIN PUBLIC" - " KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJv8ZpB5hEK7qxP9K3v43hUS5fGT4waK\ne7ix4Z4mu5UBv+cw7WSFAt0Vaag0sAbsPzU8Hhsrj/qPABvfB8asUwcCAwEAAQ==\n-----END" - " PUBLIC KEY-----\n" - ), - "Issuer": { - "C": "JP", - "organizationName": "Frank4DD", - "CN": "Frank4DD Web CA", - "SP": "Tokyo", - "L": "Chuo-ku", - "emailAddress": "support@frank4dd.com", - "OU": "WebCert Support", - }, - "Issuer Hash": "92:DA:45:6B", - "Not Before": "2012-08-22 05:26:54", - "Subject": { - "C": "JP", - "SP": "Tokyo", - "organizationName": "Frank4DD", - "CN": "www.example.com", - }, - } - - name = "keystore.jks" - passphrase = "changeit" - entries = [ - { - "alias": "stringhost", - "certificate": """-----BEGIN CERTIFICATE----- - MIICEjCCAXsCAg36MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG - A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE - MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl - YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw - ODIyMDUyNjU0WhcNMTcwODIxMDUyNjU0WjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE - CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs - ZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAm/xmkHmEQrurE/0re/jeFRLl - 8ZPjBop7uLHhnia7lQG/5zDtZIUC3RVpqDSwBuw/NTweGyuP+o8AG98HxqxTBwID - AQABMA0GCSqGSIb3DQEBBQUAA4GBABS2TLuBeTPmcaTaUW/LCB2NYOy8GMdzR1mx - 8iBIu2H6/E2tiY3RIevV2OW61qY2/XRQg7YPxx3ffeUugX9F4J/iPnnu1zAxxyBy - 2VguKv4SWjRFoRkIfIlHX0qVviMhSlNy2ioFLy7JcPZb+v3ftDGywUqcBiVDoea0 - Hn+GmxZA\n-----END CERTIFICATE-----""", - } - ] - - state_return = { - "name": name, - "changes": {}, - "result": True, - "comment": "No changes made.\n", - } - - # with patch.dict(keystore.__opts__, {'test': False}): - with patch("os.path.exists", return_value=True): - with patch.dict( - keystore.__salt__, - { - "keystore.list": MagicMock(return_value=cert_return), - "x509.read_certificate": MagicMock(return_value=x509_return), - }, - ): - self.assertDictEqual( - keystore.managed(name, passphrase, entries), state_return - ) - - with patch("os.path.exists", return_value=True): - with patch.dict(keystore.__opts__, {"test": True}): - with patch.dict( - keystore.__salt__, - { - "keystore.list": MagicMock(return_value=cert_return), - "x509.read_certificate": MagicMock(return_value=x509_return), - }, - ): - self.assertDictEqual( - keystore.managed(name, passphrase, entries), state_return - ) - - def test_cert_update(self): - """ - Test for existing value_present - """ - - cert_return = [ - { - "valid_until": "August 21 2017", - "sha1": "07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D5".encode( - __salt_system_encoding__ - ), - "valid_start": "August 22 2012", - "type": "TrustedCertEntry", - "alias": "stringhost", - "expired": True, - } - ] - x509_return = { - "Not After": "2017-08-21 05:26:54", - "Subject Hash": "97:95:14:4F", - "Serial Number": "0D:FA", - "SHA1 Finger Print": ( - "07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D6".encode( - __salt_system_encoding__ - ) - ), - "SHA-256 Finger Print": "5F:0F:B5:16:65:81:AA:E6:4A:10:1C:15:83:B1:BE:BE:74:E8:14:A9:1E:7A:8A:14:BA:1E:83:5D:78:F6:E9:E7", - "MD5 Finger Print": "80:E6:17:AF:78:D8:E4:B8:FB:5F:41:3A:27:1D:CC:F2", - "Version": 1, - "Key Size": 512, - "Public Key": ( - "-----BEGIN PUBLIC" - " KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJv8ZpB5hEK7qxP9K3v43hUS5fGT4waK\ne7ix4Z4mu5UBv+cw7WSFAt0Vaag0sAbsPzU8Hhsrj/qPABvfB8asUwcCAwEAAQ==\n-----END" - " PUBLIC KEY-----\n" - ), - "Issuer": { - "C": "JP", - "organizationName": "Frank4DD", - "CN": "Frank4DD Web CA", - "SP": "Tokyo", - "L": "Chuo-ku", - "emailAddress": "support@frank4dd.com", - "OU": "WebCert Support", - }, - "Issuer Hash": "92:DA:45:6B", - "Not Before": "2012-08-22 05:26:54", - "Subject": { - "C": "JP", - "SP": "Tokyo", - "organizationName": "Frank4DD", - "CN": "www.example.com", - }, - } - - name = "keystore.jks" - passphrase = "changeit" - entries = [ - { - "alias": "stringhost", - "certificate": """-----BEGIN CERTIFICATE----- - MIICEjCCAXsCAg36MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG - A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE - MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl - YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw - ODIyMDUyNjU0WhcNMTcwODIxMDUyNjU0WjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE - CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs - ZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAm/xmkHmEQrurE/0re/jeFRLl - 8ZPjBop7uLHhnia7lQG/5zDtZIUC3RVpqDSwBuw/NTweGyuP+o8AG98HxqxTBwID - AQABMA0GCSqGSIb3DQEBBQUAA4GBABS2TLuBeTPmcaTaUW/LCB2NYOy8GMdzR1mx - 8iBIu2H6/E2tiY3RIevV2OW61qY2/XRQg7YPxx3ffeUugX9F4J/iPnnu1zAxxyBy - 2VguKv4SWjRFoRkIfIlHX0qVviMhSlNy2ioFLy7JcPZb+v3ftDGywUqcBiVDoea0 - Hn+GmxZA\n-----END CERTIFICATE-----""", - } - ] - - test_return = { - "name": name, - "changes": {}, - "result": None, - "comment": "Alias stringhost would have been updated\n", - } - state_return = { - "name": name, - "changes": {"stringhost": "Updated"}, - "result": True, - "comment": "Alias stringhost updated.\n", - } - - with patch.dict(keystore.__opts__, {"test": True}): - with patch("os.path.exists", return_value=True): - with patch.dict( - keystore.__salt__, - { - "keystore.list": MagicMock(return_value=cert_return), - "x509.read_certificate": MagicMock(return_value=x509_return), - }, - ): - self.assertDictEqual( - keystore.managed(name, passphrase, entries), test_return - ) - - with patch("os.path.exists", return_value=True): - with patch.dict( - keystore.__salt__, - { - "keystore.list": MagicMock(return_value=cert_return), - "x509.read_certificate": MagicMock(return_value=x509_return), - "keystore.remove": MagicMock(return_value=True), - "keystore.add": MagicMock(return_value=True), - }, - ): - self.assertDictEqual( - keystore.managed(name, passphrase, entries), state_return - ) - - def test_cert_update_no_sha1_fingerprint_in_x509(self): - """ - Test for existing value_present - """ - - cert_return = [ - { - "valid_until": "August 21 2017", - "sha1": "07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D5".encode( - __salt_system_encoding__ - ), - "valid_start": "August 22 2012", - "type": "TrustedCertEntry", - "alias": "stringhost", - "expired": True, - } - ] - sha1_return = b"07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D5" - x509_return = { - "Not After": "2017-08-21 05:26:54", - "Subject Hash": "97:95:14:4F", - "Serial Number": "0D:FA", - "SHA-256 Finger Print": "5F:0F:B5:16:65:81:AA:E6:4A:10:1C:15:83:B1:BE:BE:74:E8:14:A9:1E:7A:8A:14:BA:1E:83:5D:78:F6:E9:E7", - "MD5 Finger Print": "80:E6:17:AF:78:D8:E4:B8:FB:5F:41:3A:27:1D:CC:F2", - "Version": 1, - "Key Size": 512, - "Public Key": ( - "-----BEGIN PUBLIC" - " KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJv8ZpB5hEK7qxP9K3v43hUS5fGT4waK\ne7ix4Z4mu5UBv+cw7WSFAt0Vaag0sAbsPzU8Hhsrj/qPABvfB8asUwcCAwEAAQ==\n-----END" - " PUBLIC KEY-----\n" - ), - "Issuer": { - "C": "JP", - "organizationName": "Frank4DD", - "CN": "Frank4DD Web CA", - "SP": "Tokyo", - "L": "Chuo-ku", - "emailAddress": "support@frank4dd.com", - "OU": "WebCert Support", - }, - "Issuer Hash": "92:DA:45:6B", - "Not Before": "2012-08-22 05:26:54", - "Subject": { - "C": "JP", - "SP": "Tokyo", - "organizationName": "Frank4DD", - "CN": "www.example.com", - }, - } - - name = "keystore.jks" - passphrase = "changeit" - entries = [ - { - "alias": "stringhost", - "certificate": """-----BEGIN CERTIFICATE----- - MIICEjCCAXsCAg36MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG - A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE - MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl - YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw - ODIyMDUyNjU0WhcNMTcwODIxMDUyNjU0WjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE - CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs - ZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAm/xmkHmEQrurE/0re/jeFRLl - 8ZPjBop7uLHhnia7lQG/5zDtZIUC3RVpqDSwBuw/NTweGyuP+o8AG98HxqxTBwID - AQABMA0GCSqGSIb3DQEBBQUAA4GBABS2TLuBeTPmcaTaUW/LCB2NYOy8GMdzR1mx - 8iBIu2H6/E2tiY3RIevV2OW61qY2/XRQg7YPxx3ffeUugX9F4J/iPnnu1zAxxyBy - 2VguKv4SWjRFoRkIfIlHX0qVviMhSlNy2ioFLy7JcPZb+v3ftDGywUqcBiVDoea0 - Hn+GmxZA\n-----END CERTIFICATE-----""", - } - ] - - test_return = { - "name": name, - "changes": {}, - "result": True, - "comment": "No changes made.\n", - } - with patch("os.path.exists", return_value=True): - with patch.dict(keystore.__opts__, {"test": True}): - with patch.dict( - keystore.__salt__, - { - "keystore.list": MagicMock(return_value=cert_return), - "x509.read_certificate": MagicMock(return_value=x509_return), - "keystore.get_sha1": MagicMock(return_value=sha1_return), - }, - ): - self.assertDictEqual( - keystore.managed(name, passphrase, entries), test_return - ) - - def test_new_file(self): - """ - Test for existing value_present - """ - name = "keystore.jks" - passphrase = "changeit" - entries = [ - { - "alias": "stringhost", - "certificate": """-----BEGIN CERTIFICATE----- - MIICEjCCAXsCAg36MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG - A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE - MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl - YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw - ODIyMDUyNjU0WhcNMTcwODIxMDUyNjU0WjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE - CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs - ZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAm/xmkHmEQrurE/0re/jeFRLl - 8ZPjBop7uLHhnia7lQG/5zDtZIUC3RVpqDSwBuw/NTweGyuP+o8AG98HxqxTBwID - AQABMA0GCSqGSIb3DQEBBQUAA4GBABS2TLuBeTPmcaTaUW/LCB2NYOy8GMdzR1mx - 8iBIu2H6/E2tiY3RIevV2OW61qY2/XRQg7YPxx3ffeUugX9F4J/iPnnu1zAxxyBy - 2VguKv4SWjRFoRkIfIlHX0qVviMhSlNy2ioFLy7JcPZb+v3ftDGywUqcBiVDoea0 - Hn+GmxZA\n-----END CERTIFICATE-----""", - } - ] - - test_return = { - "name": name, - "changes": {}, - "result": None, - "comment": "Alias stringhost would have been added\n", - } - state_return = { - "name": name, - "changes": {"stringhost": "Added"}, - "result": True, - "comment": "Alias stringhost added.\n", - } - - with patch.dict(keystore.__opts__, {"test": True}): - self.assertDictEqual( - keystore.managed(name, passphrase, entries), test_return - ) - - with patch("os.path.exists", return_value=False): - with patch.dict( - keystore.__salt__, - { - "keystore.remove": MagicMock(return_value=True), - "keystore.add": MagicMock(return_value=True), - }, - ): - self.assertDictEqual( - keystore.managed(name, passphrase, entries), state_return - ) - - def test_force_remove(self): - """ - Test for existing value_present - """ - - cert_return = [ - { - "valid_until": "August 21 2017", - "sha1": "07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D5".encode( - __salt_system_encoding__ - ), - "valid_start": "August 22 2012", - "type": "TrustedCertEntry", - "alias": "oldhost", - "expired": True, - } - ] - x509_return = { - "Not After": "2017-08-21 05:26:54", - "Subject Hash": "97:95:14:4F", - "Serial Number": "0D:FA", - "SHA1 Finger Print": ( - "07:1C:B9:4F:0C:C8:51:4D:02:41:24:70:8E:E8:B2:68:7B:D7:D9:D6".encode( - __salt_system_encoding__ - ) - ), - "SHA-256 Finger Print": "5F:0F:B5:16:65:81:AA:E6:4A:10:1C:15:83:B1:BE:BE:74:E8:14:A9:1E:7A:8A:14:BA:1E:83:5D:78:F6:E9:E7", - "MD5 Finger Print": "80:E6:17:AF:78:D8:E4:B8:FB:5F:41:3A:27:1D:CC:F2", - "Version": 1, - "Key Size": 512, - "Public Key": ( - "-----BEGIN PUBLIC" - " KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJv8ZpB5hEK7qxP9K3v43hUS5fGT4waK\ne7ix4Z4mu5UBv+cw7WSFAt0Vaag0sAbsPzU8Hhsrj/qPABvfB8asUwcCAwEAAQ==\n-----END" - " PUBLIC KEY-----\n" - ), - "Issuer": { - "C": "JP", - "organizationName": "Frank4DD", - "CN": "Frank4DD Web CA", - "SP": "Tokyo", - "L": "Chuo-ku", - "emailAddress": "support@frank4dd.com", - "OU": "WebCert Support", - }, - "Issuer Hash": "92:DA:45:6B", - "Not Before": "2012-08-22 05:26:54", - "Subject": { - "C": "JP", - "SP": "Tokyo", - "organizationName": "Frank4DD", - "CN": "www.example.com", - }, - } - - name = "keystore.jks" - passphrase = "changeit" - entries = [ - { - "alias": "stringhost", - "certificate": """-----BEGIN CERTIFICATE----- - MIICEjCCAXsCAg36MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG - A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE - MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl - YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw - ODIyMDUyNjU0WhcNMTcwODIxMDUyNjU0WjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE - CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs - ZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAm/xmkHmEQrurE/0re/jeFRLl - 8ZPjBop7uLHhnia7lQG/5zDtZIUC3RVpqDSwBuw/NTweGyuP+o8AG98HxqxTBwID - AQABMA0GCSqGSIb3DQEBBQUAA4GBABS2TLuBeTPmcaTaUW/LCB2NYOy8GMdzR1mx - 8iBIu2H6/E2tiY3RIevV2OW61qY2/XRQg7YPxx3ffeUugX9F4J/iPnnu1zAxxyBy - 2VguKv4SWjRFoRkIfIlHX0qVviMhSlNy2ioFLy7JcPZb+v3ftDGywUqcBiVDoea0 - Hn+GmxZA\n-----END CERTIFICATE-----""", - } - ] - - test_return = { - "name": name, - "changes": {}, - "result": None, - "comment": ( - "Alias stringhost would have been updated\nAlias oldhost would have" - " been removed" - ), - } - state_return = { - "name": name, - "changes": {"oldhost": "Removed", "stringhost": "Updated"}, - "result": True, - "comment": "Alias stringhost updated.\nAlias oldhost removed.\n", - } - - with patch.dict(keystore.__opts__, {"test": True}): - with patch("os.path.exists", return_value=True): - with patch.dict( - keystore.__salt__, - { - "keystore.list": MagicMock(return_value=cert_return), - "x509.read_certificate": MagicMock(return_value=x509_return), - }, - ): - self.assertDictEqual( - keystore.managed(name, passphrase, entries, force_remove=True), - test_return, - ) - - with patch("os.path.exists", return_value=True): - with patch.dict( - keystore.__salt__, - { - "keystore.list": MagicMock(return_value=cert_return), - "x509.read_certificate": MagicMock(return_value=x509_return), - "keystore.remove": MagicMock(return_value=True), - "keystore.add": MagicMock(return_value=True), - }, - ): - self.assertDictEqual( - keystore.managed(name, passphrase, entries, force_remove=True), - state_return, - ) diff --git a/tests/unit/states/test_net_napalm_yang.py b/tests/unit/states/test_net_napalm_yang.py deleted file mode 100644 index 5179ae92668..00000000000 --- a/tests/unit/states/test_net_napalm_yang.py +++ /dev/null @@ -1,57 +0,0 @@ -""" - :codeauthor: Anthony Shaw -""" - -import salt.states.net_napalm_yang as netyang -from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase - -TEST_DATA = {"foo": "bar"} - - -class NetyangTestCase(TestCase, LoaderModuleMockMixin): - def setup_loader_modules(self): - return {netyang: {}} - - def test_managed(self): - ret = {"changes": {}, "comment": "Loaded.", "name": "test", "result": False} - parse = MagicMock(return_value="abcdef") - temp_file = MagicMock(return_value="") - compliance_report = MagicMock(return_value={"complies": False}) - load_config = MagicMock(return_value={"comment": "Loaded."}) - file_remove = MagicMock() - - with patch("salt.utils.files.fopen"): - with patch.dict( - netyang.__salt__, - { - "temp.file": temp_file, - "napalm_yang.parse": parse, - "napalm_yang.load_config": load_config, - "napalm_yang.compliance_report": compliance_report, - "file.remove": file_remove, - }, - ): - with patch.dict(netyang.__opts__, {"test": False}): - self.assertDictEqual( - netyang.managed("test", "test", models=("model1",)), ret - ) - assert parse.called - assert temp_file.called - assert compliance_report.called - assert load_config.called - assert file_remove.called - - def test_configured(self): - ret = {"changes": {}, "comment": "Loaded.", "name": "test", "result": False} - load_config = MagicMock(return_value={"comment": "Loaded."}) - - with patch("salt.utils.files.fopen"): - with patch.dict(netyang.__salt__, {"napalm_yang.load_config": load_config}): - with patch.dict(netyang.__opts__, {"test": False}): - self.assertDictEqual( - netyang.configured("test", "test", models=("model1",)), ret - ) - - assert load_config.called diff --git a/tests/unit/test_master.py b/tests/unit/test_master.py index 26c0bdb19ae..b454882f06c 100644 --- a/tests/unit/test_master.py +++ b/tests/unit/test_master.py @@ -681,7 +681,9 @@ class MaintenanceTestCase(TestCase, AdaptedConfigurationTestCaseMixin): """ def setUp(self): - opts = self.get_temp_config("master", git_pillar_update_interval=180) + opts = self.get_temp_config( + "master", git_pillar_update_interval=180, maintenance_interval=181 + ) self.main_class = salt.master.Maintenance(opts) self.main_class._after_fork_methods = self.main_class._finalize_methods = [] @@ -758,10 +760,10 @@ class MaintenanceTestCase(TestCase, AdaptedConfigurationTestCaseMixin): self.assertEqual(str(exc), "Time passes") self.assertEqual(mocked_time._calls, [60] * 4) self.assertEqual(mocked__post_fork_init.call_times, [0]) - self.assertEqual(mocked_clean_old_jobs.call_times, [60, 120, 180]) - self.assertEqual(mocked_clean_expired_tokens.call_times, [60, 120, 180]) - self.assertEqual(mocked_clean_pub_auth.call_times, [60, 120, 180]) - self.assertEqual(mocked_handle_git_pillar.call_times, [0, 180]) + self.assertEqual(mocked_clean_old_jobs.call_times, [0, 120, 180]) + self.assertEqual(mocked_clean_expired_tokens.call_times, [0, 120, 180]) + self.assertEqual(mocked_clean_pub_auth.call_times, [0, 120, 180]) + self.assertEqual(mocked_handle_git_pillar.call_times, [0]) self.assertEqual(mocked_handle_schedule.call_times, [0, 60, 120, 180]) self.assertEqual(mocked_handle_key_cache.call_times, [0, 60, 120, 180]) self.assertEqual(mocked_handle_presence.call_times, [0, 60, 120, 180]) diff --git a/tools/changelog.py b/tools/changelog.py index 0a2762f6263..d4d8b662829 100644 --- a/tools/changelog.py +++ b/tools/changelog.py @@ -12,6 +12,7 @@ import re import sys import textwrap +from jinja2 import Environment, FileSystemLoader from ptscripts import Context, command_group from tools.utils import REPO_ROOT, Version @@ -174,8 +175,11 @@ def _get_pkg_changelog_contents(ctx: Context, version: Version): return changes -def _get_salt_version(ctx): - ret = ctx.run("python3", "salt/version.py", capture=True, check=False) +def _get_salt_version(ctx, next_release=False): + args = [] + if next_release: + args.append("--next-release") + ret = ctx.run("python3", "salt/version.py", *args, capture=True, check=False) if ret.returncode: ctx.error(ret.stderr.decode()) ctx.exit(1) @@ -260,7 +264,7 @@ def update_deb(ctx: Context, salt_version: Version, draft: bool = False): debian_changelog_path = "pkg/debian/changelog" tmp_debian_changelog_path = f"{debian_changelog_path}.1" with open(tmp_debian_changelog_path, "w") as wfp: - wfp.write(f"salt (1:{salt_version}) stable; urgency=medium\n\n") + wfp.write(f"salt ({salt_version}) stable; urgency=medium\n\n") wfp.write(formated) wfp.write( f"\n -- Salt Project Packaging {date}\n\n" @@ -295,13 +299,24 @@ def update_deb(ctx: Context, salt_version: Version, draft: bool = False): "release": { "help": "Update for an actual release and not just a temporary CI build.", }, + "template_only": { + "help": "Only generate a template file.", + }, + "next_release": { + "help": "Generate release notes for the next upcoming release.", + }, }, ) def update_release_notes( - ctx: Context, salt_version: Version, draft: bool = False, release: bool = False + ctx: Context, + salt_version: Version, + draft: bool = False, + release: bool = False, + template_only: bool = False, + next_release: bool = False, ): if salt_version is None: - salt_version = _get_salt_version(ctx) + salt_version = _get_salt_version(ctx, next_release=next_release) changes = _get_changelog_contents(ctx, salt_version) changes = "\n".join(changes.split("\n")[2:]) if salt_version.local: @@ -309,38 +324,80 @@ def update_release_notes( versions = {} for fpath in pathlib.Path("doc/topics/releases").glob("*.md"): versions[(Version(fpath.stem))] = fpath - release_notes_path = versions[sorted(versions)[-1]] + latest_version = sorted(versions)[-1] + release_notes_path = versions[latest_version] + version = ".".join(str(part) for part in latest_version.release) else: + version = ".".join(str(part) for part in salt_version.release) release_notes_path = pathlib.Path("doc/topics/releases") / "{}.md".format( - ".".join(str(part) for part in salt_version.release) + version ) - if not release_notes_path.exists(): - release_notes_path.write_text( + + template_release_path = ( + release_notes_path.parent / "templates" / f"{version}.md.template" + ) + if not template_release_path.exists(): + template_release_path.write_text( textwrap.dedent( f"""\ (release-{salt_version})= - # Salt {salt_version} release notes - UNRELEASED + # Salt {salt_version} release notes{{{{ unreleased }}}} + {{{{ warning }}}} + + + + + ## Changelog + {{{{ changelog }}}} """ ) ) - ctx.run("git", "add", str(release_notes_path)) - ctx.info(f"Created bare {release_notes_path} release notes file") - - existing = release_notes_path.read_text() + ctx.run("git", "add", str(template_release_path)) + ctx.info(f"Created template {template_release_path} release notes file") + if template_only: + # Only generate the template for a new release + return + unreleased = " - UNRELEASED" + warning = f""" + + """ if release is True: - existing = existing.replace(" - UNRELEASED", "") + unreleased = "" tmp_release_notes_path = ( release_notes_path.parent / f"{release_notes_path.name}.tmp" ) - tmp_release_notes_path.write_text(f"{existing}\n## Changelog\n{changes}") + + # render the release notes jinja template + environment = Environment(loader=FileSystemLoader(template_release_path.parent)) + template = environment.get_template(template_release_path.name) + content = template.render( + {"changelog": changes, "unreleased": unreleased, "warning": warning} + ) + + tmp_release_notes_path.write_text(content) try: contents = tmp_release_notes_path.read_text().strip() if draft: ctx.print(contents, soft_wrap=True) else: + new_release_file = False + if not release_notes_path.exists(): + new_release_file = True release_notes_path.write_text(contents) + if new_release_file: + ctx.run("git", "add", str(release_notes_path)) + ctx.info(f"Created bare {release_notes_path} release notes file") finally: os.remove(tmp_release_notes_path) diff --git a/tools/ci.py b/tools/ci.py index 87f88a90ee7..748bea85ac5 100644 --- a/tools/ci.py +++ b/tools/ci.py @@ -229,6 +229,9 @@ def runner_types(ctx: Context, event_name: str): "skip_pkg_tests": { "help": "Skip running the Salt Package tests", }, + "skip_pkg_download_tests": { + "help": "Skip running the Salt Package download tests", + }, "changed_files": { "help": ( "Path to '.json' file containing the payload of changed files " @@ -243,6 +246,7 @@ def define_jobs( changed_files: pathlib.Path, skip_tests: bool = False, skip_pkg_tests: bool = False, + skip_pkg_download_tests: bool = False, ): """ Set GH Actions 'jobs' output to know which jobs should run. @@ -267,6 +271,7 @@ def define_jobs( "lint": True, "test": True, "test-pkg": True, + "test-pkg-download": True, "prepare-release": True, "build-docs": True, "build-source-tarball": True, @@ -279,6 +284,8 @@ def define_jobs( jobs["test"] = False if skip_pkg_tests: jobs["test-pkg"] = False + if skip_pkg_download_tests: + jobs["test-pkg-download"] = False if event_name != "pull_request": # In this case, all defined jobs should run @@ -345,7 +352,12 @@ def define_jobs( wfh.write("De-selecting the 'test-pkg' job.\n") jobs["test-pkg"] = False - if not jobs["test"] and not jobs["test-pkg"]: + if jobs["test-pkg-download"] and required_pkg_test_changes == {"false"}: + with open(github_step_summary, "a", encoding="utf-8") as wfh: + wfh.write("De-selecting the 'test-pkg-download' job.\n") + jobs["test-pkg-download"] = False + + if not jobs["test"] and not jobs["test-pkg"] and not jobs["test-pkg-download"]: with open(github_step_summary, "a", encoding="utf-8") as wfh: for job in ( "build-deps-onedir", @@ -595,6 +607,8 @@ def pkg_matrix(ctx: Context, distro_slug: str, pkg_type: str): "debian-11-arm64", "ubuntu-20.04-arm64", "ubuntu-22.04-arm64", + "photonos-3", + "photonos-4", ] and pkg_type != "MSI" ): @@ -605,7 +619,14 @@ def pkg_matrix(ctx: Context, distro_slug: str, pkg_type: str): # we will have arm64 onedir packages to upgrade from sessions.append("upgrade") if ( - distro_slug not in ["centosstream-9", "ubuntu-22.04", "ubuntu-22.04-arm64"] + distro_slug + not in [ + "centosstream-9", + "ubuntu-22.04", + "ubuntu-22.04-arm64", + "photonos-3", + "photonos-4", + ] and pkg_type != "MSI" ): # Packages for these OSs where never built for classic previously diff --git a/tools/pkg/build.py b/tools/pkg/build.py index d7735e2d4e7..b3f92ef615c 100644 --- a/tools/pkg/build.py +++ b/tools/pkg/build.py @@ -12,6 +12,7 @@ import tarfile import zipfile from typing import TYPE_CHECKING +import yaml from ptscripts import Context, command_group import tools.utils @@ -27,22 +28,42 @@ build = command_group( ) +def _get_shared_constants(): + shared_constants = ( + tools.utils.REPO_ROOT / "cicd" / "shared-gh-workflows-context.yml" + ) + return yaml.safe_load(shared_constants.read_text()) + + @build.command( name="deb", arguments={ "onedir": { - "help": "The name of the onedir artifact, if given it should be under artifacts/", + "help": "The path to the onedir artifact", + }, + "relenv_version": { + "help": "The version of relenv to use", + }, + "python_version": { + "help": "The version of python to build with using relenv", + }, + "arch": { + "help": "The arch to build for", }, }, ) def debian( ctx: Context, onedir: str = None, # pylint: disable=bad-whitespace + relenv_version: str = None, + python_version: str = None, + arch: str = None, ): """ Build the deb package. """ checkout = pathlib.Path.cwd() + env_args = ["-e", "SALT_ONEDIR_ARCHIVE"] if onedir: onedir_artifact = checkout / "artifacts" / onedir _check_pkg_build_files_exist(ctx, onedir_artifact=onedir_artifact) @@ -51,10 +72,25 @@ def debian( ) os.environ["SALT_ONEDIR_ARCHIVE"] = str(onedir_artifact) else: - ctx.info(f"Building the package from the source files") + if arch is None: + ctx.error( + "Building the package from the source files but the arch to build for has not been given" + ) + ctx.exit(1) + ctx.info("Building the package from the source files") + shared_constants = _get_shared_constants() + new_env = { + "SALT_RELENV_VERSION": relenv_version or shared_constants["relenv_version"], + "SALT_PYTHON_VERSION": python_version + or shared_constants["python_version_linux"], + "SALT_PACKAGE_ARCH": str(arch), + } + for key, value in new_env.items(): + os.environ[key] = value + env_args.extend(["-e", key]) ctx.run("ln", "-sf", "pkg/debian/", ".") - ctx.run("debuild", "-e", "SALT_ONEDIR_ARCHIVE", "-uc", "-us") + ctx.run("debuild", *env_args, "-uc", "-us") ctx.info("Done") @@ -63,13 +99,25 @@ def debian( name="rpm", arguments={ "onedir": { - "help": "The name of the onedir artifact, if given it should be under artifacts/", + "help": "The path to the onedir artifact", + }, + "relenv_version": { + "help": "The version of relenv to use", + }, + "python_version": { + "help": "The version of python to build with using relenv", + }, + "arch": { + "help": "The arch to build for", }, }, ) def rpm( ctx: Context, onedir: str = None, # pylint: disable=bad-whitespace + relenv_version: str = None, + python_version: str = None, + arch: str = None, ): """ Build the RPM package. @@ -84,6 +132,21 @@ def rpm( os.environ["SALT_ONEDIR_ARCHIVE"] = str(onedir_artifact) else: ctx.info(f"Building the package from the source files") + if arch is None: + ctx.error( + "Building the package from the source files but the arch to build for has not been given" + ) + ctx.exit(1) + ctx.info(f"Building the package from the source files") + shared_constants = _get_shared_constants() + new_env = { + "SALT_RELENV_VERSION": relenv_version or shared_constants["relenv_version"], + "SALT_PYTHON_VERSION": python_version + or shared_constants["python_version_linux"], + "SALT_PACKAGE_ARCH": str(arch), + } + for key, value in new_env.items(): + os.environ[key] = value spec_file = checkout / "pkg" / "rpm" / "salt.spec" ctx.run("rpmbuild", "-bb", f"--define=_salt_src {checkout}", str(spec_file)) @@ -105,9 +168,14 @@ def rpm( ), "required": True, }, + "sign": { + "help": "Sign and notorize built package", + }, }, ) -def macos(ctx: Context, onedir: str = None, salt_version: str = None): +def macos( + ctx: Context, onedir: str = None, salt_version: str = None, sign: bool = False +): """ Build the macOS package. """ @@ -126,10 +194,24 @@ def macos(ctx: Context, onedir: str = None, salt_version: str = None): with ctx.chdir(onedir_artifact.parent): tarball.extractall(path=build_root) + if sign: + ctx.info("Signing binaries") + with ctx.chdir(checkout / "pkg" / "macos"): + ctx.run("./sign_binaries.sh") ctx.info("Building the macos package") with ctx.chdir(checkout / "pkg" / "macos"): ctx.run("./prep_salt.sh") - ctx.run("sudo", "./package.sh", "-n", salt_version) + if sign: + package_args = ["--sign", salt_version] + else: + package_args = [salt_version] + ctx.run("./package.sh", *package_args) + if sign: + ctx.info("Notarizing package") + ret = ctx.run("uname", "-m", capture=True) + cpu_arch = ret.stdout.strip().decode() + with ctx.chdir(checkout / "pkg" / "macos"): + ctx.run("./notarize.sh", f"salt-{salt_version}-py3-{cpu_arch}.pkg") ctx.info("Done") @@ -153,6 +235,9 @@ def macos(ctx: Context, onedir: str = None, salt_version: str = None): "choices": ("x86", "amd64"), "required": True, }, + "sign": { + "help": "Sign and notorize built package", + }, }, ) def windows( @@ -160,6 +245,7 @@ def windows( onedir: str = None, salt_version: str = None, arch: str = None, + sign: bool = False, ): """ Build the Windows package. @@ -198,6 +284,70 @@ def windows( "-SkipInstall", ) + if sign: + env = os.environ.copy() + envpath = env.get("PATH") + if envpath is None: + path_parts = [] + else: + path_parts = envpath.split(os.pathsep) + path_parts.extend( + [ + r"C:\Program Files (x86)\Windows Kits\10\App Certification Kit", + r"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools", + r"C:\Program Files\DigiCert\DigiCert One Signing Manager Tools", + ] + ) + env["PATH"] = os.pathsep.join(path_parts) + command = ["smksp_registrar.exe", "list"] + ctx.info(f"Running: '{' '.join(command)}' ...") + ctx.run(*command, env=env) + command = ["smctl.exe", "keypair", "ls"] + ctx.info(f"Running: '{' '.join(command)}' ...") + ret = ctx.run(*command, env=env, check=False) + if ret.returncode: + ctx.error(f"Failed to run '{' '.join(command)}'") + command = [ + r"C:\Windows\System32\certutil.exe", + "-csp", + "DigiCert Signing Manager KSP", + "-key", + "-user", + ] + ctx.info(f"Running: '{' '.join(command)}' ...") + ret = ctx.run(*command, env=env, check=False) + if ret.returncode: + ctx.error(f"Failed to run '{' '.join(command)}'") + + command = ["smksp_cert_sync.exe"] + ctx.info(f"Running: '{' '.join(command)}' ...") + ret = ctx.run(*command, env=env, check=False) + if ret.returncode: + ctx.error(f"Failed to run '{' '.join(command)}'") + + for fname in ( + f"pkg/windows/build/Salt-Minion-{salt_version}-Py3-{arch}-Setup.exe", + f"pkg/windows/build/Salt-Minion-{salt_version}-Py3-{arch}.msi", + ): + fpath = str(pathlib.Path(fname).resolve()) + ctx.info(f"Signing {fname} ...") + ctx.run( + "signtool.exe", + "sign", + "/sha1", + os.environ["WIN_SIGN_CERT_SHA1_HASH"], + "/tr", + "http://timestamp.digicert.com", + "/td", + "SHA256", + "/fd", + "SHA256", + fpath, + env=env, + ) + ctx.info(f"Verifying {fname} ...") + ctx.run("signtool.exe", "verify", "/v", "/pa", fpath, env=env) + ctx.info("Done") @@ -214,7 +364,7 @@ def windows( "required": True, }, "package_name": { - "help": "The name of the relenv environment to be created under artifacts/", + "help": "The name of the relenv environment to be created", "required": True, }, "platform": { @@ -247,16 +397,15 @@ def onedir_dependencies( except ImportError: ctx.exit(1, "Relenv not installed in the current environment.") - artifacts_dir = pathlib.Path("artifacts").resolve() - artifacts_dir.mkdir(exist_ok=True) - dest = artifacts_dir / package_name - + dest = pathlib.Path(package_name).resolve() create(dest, arch=arch, version=python_version) + env = os.environ.copy() install_args = ["-v"] if platform == "windows": python_bin = dest / "Scripts" / "python" else: + env["RELENV_BUILDENV"] = "1" python_bin = dest / "bin" / "python3" install_args.extend( [ @@ -283,9 +432,30 @@ def onedir_dependencies( ) _check_pkg_build_files_exist(ctx, requirements_file=requirements_file) - ctx.run(str(python_bin), "-m", "pip", "install", "-U", "wheel") - ctx.run(str(python_bin), "-m", "pip", "install", "-U", "pip>=22.3.1,<23.0") - ctx.run(str(python_bin), "-m", "pip", "install", "-U", "setuptools>=65.6.3,<66") + ctx.run( + str(python_bin), + "-m", + "pip", + "install", + "-U", + "wheel", + ) + ctx.run( + str(python_bin), + "-m", + "pip", + "install", + "-U", + "pip>=22.3.1,<23.0", + ) + ctx.run( + str(python_bin), + "-m", + "pip", + "install", + "-U", + "setuptools>=65.6.3,<66", + ) ctx.run( str(python_bin), "-m", @@ -294,21 +464,24 @@ def onedir_dependencies( *install_args, "-r", str(requirements_file), + env=env, ) + extras_dir = dest / f"extras-{requirements_version}" + extras_dir.mkdir() @build.command( name="salt-onedir", arguments={ "salt_name": { - "help": "The name of the source tarball containing salt, stored under the repo root", + "help": "The path to the salt code to install, relative to the repo root", }, "platform": { "help": "The platform that installed is being installed on", "required": True, }, "package_name": { - "help": "The name of the relenv environment to install salt into, stored under artifacts/", + "help": "The name of the relenv environment to install salt into", "required": True, }, }, @@ -327,10 +500,12 @@ def salt_onedir( assert package_name is not None salt_archive = pathlib.Path(salt_name).resolve() - onedir_env = pathlib.Path("artifacts", package_name) + onedir_env = pathlib.Path(package_name).resolve() _check_pkg_build_files_exist(ctx, onedir_env=onedir_env, salt_archive=salt_archive) - os.environ["USE_STATIC_REQUIREMENTS"] = "1" + env = os.environ.copy() + env["USE_STATIC_REQUIREMENTS"] = "1" + env["RELENV_BUILDENV"] = "1" if platform == "windows": ctx.run( "powershell.exe", @@ -340,6 +515,7 @@ def salt_onedir( "-CICD", "-SourceTarball", str(salt_archive), + env=env, ) ctx.run( "powershell.exe", @@ -347,11 +523,12 @@ def salt_onedir( "-BuildDir", str(onedir_env), "-CICD", + env=env, ) else: - os.environ["RELENV_PIP_DIR"] = "1" + env["RELENV_PIP_DIR"] = "1" pip_bin = onedir_env / "bin" / "pip3" - ctx.run(str(pip_bin), "install", str(salt_archive)) + ctx.run(str(pip_bin), "install", str(salt_archive), env=env) if platform == "darwin": def errfn(fn, path, err): diff --git a/tools/pkg/repo.py b/tools/pkg/repo.py index 261f0e938c9..88f0115a810 100644 --- a/tools/pkg/repo.py +++ b/tools/pkg/repo.py @@ -197,6 +197,16 @@ def debian( }} """ ctx.info("Creating repository directory structure ...") + create_repo_path = _create_top_level_repo_path( + repo_path, + salt_version, + distro, + distro_version=distro_version, + distro_arch=distro_arch, + ) + # Export the GPG key in use + tools.utils.export_gpg_key(ctx, key_id, create_repo_path) + create_repo_path = _create_repo_path( repo_path, salt_version, @@ -205,7 +215,6 @@ def debian( distro_arch=distro_arch, nightly_build=nightly_build, ) - ftp_archive_config_file = create_repo_path / "apt-ftparchive.conf" ctx.info(f"Writing {ftp_archive_config_file} ...") ftp_archive_config_file.write_text(textwrap.dedent(ftp_archive_config)) @@ -302,11 +311,11 @@ def debian( if version.major == major_version: matching_major = version break - if not matching_major or matching_major < salt_version: + if not matching_major or matching_major <= salt_version: major_link = create_repo_path.parent.parent / str(major_version) ctx.info(f"Creating '{major_link.relative_to(repo_path)}' symlink ...") major_link.symlink_to(f"minor/{salt_version}") - if not remote_versions or remote_versions[0] < salt_version: + if not remote_versions or remote_versions[0] <= salt_version: latest_link = create_repo_path.parent.parent / "latest" ctx.info(f"Creating '{latest_link.relative_to(repo_path)}' symlink ...") latest_link.symlink_to(f"minor/{salt_version}") @@ -322,6 +331,7 @@ _rpm_distro_info = { "amazon": ["2"], "redhat": ["7", "8", "9"], "fedora": ["36", "37", "38"], + "photon": ["3", "4"], } @@ -399,6 +409,16 @@ def rpm( distro_arch = "arm64" ctx.info("Creating repository directory structure ...") + create_repo_path = _create_top_level_repo_path( + repo_path, + salt_version, + distro, + distro_version=distro_version, + distro_arch=distro_arch, + ) + # Export the GPG key in use + tools.utils.export_gpg_key(ctx, key_id, create_repo_path) + create_repo_path = _create_repo_path( repo_path, salt_version, @@ -493,7 +513,7 @@ def rpm( else: distro_name = distro.capitalize() - if int(distro_version) < 8: + if distro != "photon" and int(distro_version) < 8: failovermethod = "\n failovermethod=priority" else: failovermethod = "" @@ -530,13 +550,13 @@ def rpm( if version.major == major_version: matching_major = version break - if not matching_major or matching_major < salt_version: + if not matching_major or matching_major <= salt_version: major_link = create_repo_path.parent.parent / str(major_version) ctx.info(f"Creating '{major_link.relative_to(repo_path)}' symlink ...") major_link.symlink_to(f"minor/{salt_version}") repo_file_path = create_repo_path.parent.parent / f"{major_version}.repo" _create_repo_file(repo_file_path, str(major_version)) - if not remote_versions or remote_versions[0] < salt_version: + if not remote_versions or remote_versions[0] <= salt_version: latest_link = create_repo_path.parent.parent / "latest" ctx.info(f"Creating '{latest_link.relative_to(repo_path)}' symlink ...") latest_link.symlink_to(f"minor/{salt_version}") @@ -934,11 +954,11 @@ def release(ctx: Context, salt_version: str): log.exception(f"Error downloading {repo_release_files_path}: {exc}") ctx.exit(1) if exc.response["Error"]["Code"] == "404": - ctx.error(f"Cloud not find {repo_release_files_path} in bucket.") + ctx.error(f"Could not find {repo_release_files_path} in bucket.") ctx.exit(1) if exc.response["Error"]["Code"] == "400": ctx.error( - f"Cloud not download {repo_release_files_path} from bucket: {exc}" + f"Could not download {repo_release_files_path} from bucket: {exc}" ) ctx.exit(1) log.exception(f"Error downloading {repo_release_files_path}: {exc}") @@ -960,11 +980,11 @@ def release(ctx: Context, salt_version: str): log.exception(f"Error downloading {repo_release_symlinks_path}: {exc}") ctx.exit(1) if exc.response["Error"]["Code"] == "404": - ctx.error(f"Cloud not find {repo_release_symlinks_path} in bucket.") + ctx.error(f"Could not find {repo_release_symlinks_path} in bucket.") ctx.exit(1) if exc.response["Error"]["Code"] == "400": ctx.error( - f"Cloud not download {repo_release_symlinks_path} from bucket: {exc}" + f"Could not download {repo_release_symlinks_path} from bucket: {exc}" ) ctx.exit(1) log.exception(f"Error downloading {repo_release_symlinks_path}: {exc}") @@ -1146,7 +1166,7 @@ def release(ctx: Context, salt_version: str): raise if exc.response["Error"]["Code"] != "404": raise - ctx.info(f"Cloud not find {repo_file_path} in bucket {bucket_name}") + ctx.info(f"Could not find {repo_file_path} in bucket {bucket_name}") for dirpath, dirnames, filenames in os.walk(repo_path, followlinks=True): for path in filenames: @@ -1431,7 +1451,7 @@ def _get_remote_versions(bucket_name: str, remote_path: str): continue versions.append(Version(version)) versions.sort(reverse=True) - log.info("Remove versions collected: %s", versions) + log.info("Remote versions collected: %s", versions) return versions @@ -1446,6 +1466,14 @@ def _create_onedir_based_repo( pkg_suffixes: tuple[str, ...], ): ctx.info("Creating repository directory structure ...") + create_repo_path = _create_top_level_repo_path( + repo_path, + salt_version, + distro, + ) + # Export the GPG key in use + tools.utils.export_gpg_key(ctx, key_id, create_repo_path) + create_repo_path = _create_repo_path( repo_path, salt_version, distro, nightly_build=nightly_build ) @@ -1642,7 +1670,7 @@ def _get_repo_json_file_contents( raise if exc.response["Error"]["Code"] != "404": raise - ctx.info(f"Cloud not find {repo_json_path} in bucket {bucket_name}") + ctx.info(f"Could not find {repo_json_path} in bucket {bucket_name}") if repo_json: ctx.print(repo_json, soft_wrap=True) return repo_json @@ -1787,7 +1815,7 @@ def _publish_repo( pass -def _create_repo_path( +def _create_top_level_repo_path( repo_path: pathlib.Path, salt_version: str, distro: str, @@ -1805,6 +1833,21 @@ def _create_repo_path( create_repo_path = create_repo_path / distro_version if distro_arch: create_repo_path = create_repo_path / distro_arch + create_repo_path.mkdir(exist_ok=True, parents=True) + return create_repo_path + + +def _create_repo_path( + repo_path: pathlib.Path, + salt_version: str, + distro: str, + distro_version: str | None = None, # pylint: disable=bad-whitespace + distro_arch: str | None = None, # pylint: disable=bad-whitespace + nightly_build: bool = False, +): + create_repo_path = _create_top_level_repo_path( + repo_path, salt_version, distro, distro_version, distro_arch + ) if nightly_build is False: create_repo_path = create_repo_path / "minor" / salt_version else: diff --git a/tools/pre_commit.py b/tools/pre_commit.py index 8fe80b632dd..1ecfc2b0050 100644 --- a/tools/pre_commit.py +++ b/tools/pre_commit.py @@ -8,6 +8,7 @@ import logging import shutil from typing import TYPE_CHECKING, cast +import yaml from jinja2 import Environment, FileSystemLoader from ptscripts import Context, command_group @@ -76,7 +77,7 @@ def generate_workflows(ctx: Context): "lint": False, "pkg-tests": False, "salt-tests": False, - "test-pkg-downloads": True, + "test-pkg-downloads": False, }, }, } @@ -115,6 +116,12 @@ def generate_workflows(ctx: Context): "prepare_workflow_needs": NeedsTracker(), "build_repo_needs": NeedsTracker(), } + shared_context_file = ( + tools.utils.REPO_ROOT / "cicd" / "shared-gh-workflows-context.yml" + ) + shared_context = yaml.safe_load(shared_context_file.read_text()) + for key, value in shared_context.items(): + context[key] = value loaded_template = env.get_template(template_path.name) rendered_template = loaded_template.render(**context) workflow_path.write_text(rendered_template.rstrip() + "\n") diff --git a/tools/release.py b/tools/release.py index 6fd8ce5af52..f13661d090c 100644 --- a/tools/release.py +++ b/tools/release.py @@ -4,10 +4,15 @@ These commands are used to release Salt. # pylint: disable=resource-leakage,broad-except,3rd-party-module-not-gated from __future__ import annotations +import json import logging +import os import pathlib import sys +import tempfile +import time +import virustotal3.core from ptscripts import Context, command_group import tools.utils @@ -112,3 +117,149 @@ def upload_artifacts(ctx: Context, salt_version: str, artifacts_path: pathlib.Pa ) except KeyboardInterrupt: pass + + +@release.command( + name="upload-virustotal", + arguments={ + "salt_version": { + "help": "The salt version to release.", + }, + }, +) +def upload_virustotal(ctx: Context, salt_version: str): + + # Get a list of files to upload + files_to_copy: list[str] + + if salt_version.startswith("v"): + salt_version = salt_version[1:] + + ctx.info("Grabbing remote file listing of files in staging ...") + s3 = boto3.client("s3") + repo_release_files_path = pathlib.Path( + f"release-artifacts/{salt_version}/.release-files.json" + ) + with tempfile.TemporaryDirectory(prefix=f"{salt_version}_release_") as tsd: + local_release_files_path = pathlib.Path(tsd) / repo_release_files_path.name + try: + with local_release_files_path.open("wb") as wfh: + ctx.info(f"Downloading file: {repo_release_files_path}") + s3.download_fileobj( + Bucket=tools.utils.STAGING_BUCKET_NAME, + Key=str(repo_release_files_path.as_posix()), + Fileobj=wfh, + ) + files_to_copy = json.loads(local_release_files_path.read_text()) + except ClientError as exc: + if "Error" not in exc.response: + log.exception(f"Error downloading {repo_release_files_path}: {exc}") + ctx.exit(1) + if exc.response["Error"]["Code"] == "404": + ctx.error(f"Could not find {repo_release_files_path} in bucket.") + ctx.exit(1) + if exc.response["Error"]["Code"] == "400": + ctx.error( + f"Could not download {repo_release_files_path} from bucket: {exc}" + ) + ctx.exit(1) + log.exception(f"Error downloading {repo_release_files_path}: {exc}") + ctx.exit(1) + + # If we get approval, we can add RPM and DEB + file_types = [".msi", ".exe", ".pkg"] + files_to_upload = [] + for file in sorted(files_to_copy): + if f"minor/{salt_version}" in file: + if os.path.splitext(file)[1] in file_types: + files_to_upload.append(file) + # These are showing errors for Windows and macOS + # if f"onedir/minor/{salt_version}" in file: + # if file.endswith("tar.xz"): + # files_to_upload.append(file) + + ctx.info("Found the following files to upload:") + for file in files_to_upload: + ctx.info(f"- {os.path.basename(file)}") + + # download each file, then upload to VirusTotal + # This takes around 4 minutes per file + # Maybe we could do this asynchronously + failed_files = {} + for file in files_to_upload: + ctx.info("-" * 80) + download_file = pathlib.Path(file) + with tempfile.TemporaryDirectory(prefix=f"{salt_version}_release_") as tsd: + local_download_file = pathlib.Path(tsd) / download_file.name + try: + with local_download_file.open("wb") as wfh: + ctx.info(f"Downloading from repo: {download_file}") + s3.download_fileobj( + Bucket=tools.utils.STAGING_BUCKET_NAME, + Key=str(download_file.as_posix()), + Fileobj=wfh, + ) + except ClientError as exc: + if "Error" not in exc.response: + log.exception(f"Error downloading {download_file}: {exc}") + ctx.exit(1) + if exc.response["Error"]["Code"] == "404": + ctx.error(f"Could not find {download_file} in bucket.") + ctx.exit(1) + if exc.response["Error"]["Code"] == "400": + ctx.error(f"Could not download {download_file} from bucket: {exc}") + ctx.exit(1) + log.exception(f"Error downloading {download_file}: {exc}") + ctx.exit(1) + + # API key should be an environment variable + api_key = os.environ.get("VIRUSTOTAL_API_KEY") + + ctx.info( + f"Uploading to VirusTotal: {os.path.basename(local_download_file)}" + ) + vt = virustotal3.core.Files(api_key) + response = vt.upload(local_download_file) + + # We want the id + analysis_id = response["data"]["id"] + + # Lets check the results + results = virustotal3.core.get_analysis(api_key, analysis_id) + + status = results["data"]["attributes"]["status"] + + ctx.info("Waiting for results from VirusTotal (takes a few minutes)") + while "completed" not in status: + time.sleep(10) + results = virustotal3.core.get_analysis(api_key, analysis_id) + status = results["data"]["attributes"]["status"] + + ctx.info("Results summary:") + stats = results["data"]["attributes"]["stats"] + + failures = False + for field in stats: + ctx.info(f"- {field}: {stats[field]}") + if field in ["malicious", "suspicious"]: + if stats[field] > 0: + failures = True + + sha256 = results["meta"]["file_info"]["sha256"] + + if failures: + ctx.info("ERROR: VirusTotal scan encountered failures") + failed_files[os.path.basename(local_download_file)] = sha256 + + ctx.info("See details here:") + ctx.info(f"- File: {os.path.basename(local_download_file)}") + ctx.info(f"- URL: https://www.virustotal.com/gui/file/{sha256}") + + if failed_files: + # We want to exit with errors if there are failures + ctx.info("-" * 80) + ctx.info("VirusTotal flagged the following files:") + for file in failed_files: + ctx.info(f"- {file}") + ctx.info(f" https://www.virustotal.com/gui/file/{failed_files[file]}") + ctx.exit(1) diff --git a/tools/vm.py b/tools/vm.py index a9684fa3869..9500317f520 100644 --- a/tools/vm.py +++ b/tools/vm.py @@ -175,14 +175,20 @@ def create( "help": "The VM Name", "metavar": "VM_NAME", }, + "no_wait": { + "help": ( + "Don't wait for the destroy process to complete. " + "Just confirm it started and exit." + ) + }, } ) -def destroy(ctx: Context, name: str): +def destroy(ctx: Context, name: str, no_wait: bool = False): """ Destroy VM. """ vm = VM(ctx=ctx, name=name, region_name=ctx.parser.options.region) - vm.destroy() + vm.destroy(no_wait=no_wait) @vm.command( @@ -1029,13 +1035,13 @@ class VM: return error return True - def destroy(self): + def destroy(self, no_wait: bool = False): try: if not self.is_running: log.info(f"{self!r} is not running...") return timeout = self.config.terminate_timeout - timeout_progress = 0 + timeout_progress = 0.0 progress = create_progress_bar() task = progress.add_task(f"Terminatting {self!r}...", total=timeout) self.instance.terminate() @@ -1044,6 +1050,12 @@ class VM: while timeout_progress <= timeout: start = time.time() time.sleep(1) + if no_wait and not self.is_running: + log.info( + f"{self!r} started the destroy process. " + "Not waiting for completion of that process." + ) + break if self.state == "terminated": progress.update( task,