From cd279bd7d48cbde0fae78fc9603200e29b311b22 Mon Sep 17 00:00:00 2001 From: David Murphy < dmurphy@saltstack.com> Date: Fri, 17 Nov 2023 13:11:31 -0700 Subject: [PATCH 01/20] Fill out lsb_distrib_xxx grains (best guess) if lsb_release information unavailable --- changelog/64473.fixed.md | 1 + salt/grains/core.py | 5 ++-- .../pytests/functional/grains/test_grains.py | 26 +++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 changelog/64473.fixed.md create mode 100644 tests/pytests/functional/grains/test_grains.py diff --git a/changelog/64473.fixed.md b/changelog/64473.fixed.md new file mode 100644 index 00000000000..411d90bf9be --- /dev/null +++ b/changelog/64473.fixed.md @@ -0,0 +1 @@ +Fill out lsb_distrib_xxxx (best estimate) grains if problems with retrieving lsb_release data diff --git a/salt/grains/core.py b/salt/grains/core.py index 7dd350a3453..dae45bfb559 100644 --- a/salt/grains/core.py +++ b/salt/grains/core.py @@ -2175,8 +2175,9 @@ def _linux_distribution_data(): "rocky", "ubuntu", ): - # Solely use os-release data. See description of the function. - return grains + if lsb_has_error is False: + # Solely use os-release data. See description of the function. + return grains except OSError: os_release = {} diff --git a/tests/pytests/functional/grains/test_grains.py b/tests/pytests/functional/grains/test_grains.py new file mode 100644 index 00000000000..0206fcd81a1 --- /dev/null +++ b/tests/pytests/functional/grains/test_grains.py @@ -0,0 +1,26 @@ +import logging + +import pytest + +log = logging.getLogger(__name__) + + +pytestmark = [ + pytest.mark.skip_unless_on_linux, + pytest.mark.skipif( + 'grains["os_family"] != "Debian"', + reason="Tests applicable only to Debian and Ubuntu", + ), +] + + +def test_grains(grains): + log.warning(f"DGM test_grains '{grains}'") + + assert "lsb_distrib_id" in grains + assert "lsb_distrib_release" in grains + assert "lsb_distrib_codename" in grains + + assert grains["lsb_distrib_id"] == grains["osfullname"] + assert grains["lsb_distrib_release"] == grains["osrelease"] + assert grains["lsb_distrib_codename"] == grains["oscodename"] From 71cc67d1aff91f05b25e1e4cee63993e4c4ac102 Mon Sep 17 00:00:00 2001 From: David Murphy < dmurphy@saltstack.com> Date: Fri, 17 Nov 2023 13:36:30 -0700 Subject: [PATCH 02/20] Remove debug logging and add comment for test --- tests/pytests/functional/grains/test_grains.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/pytests/functional/grains/test_grains.py b/tests/pytests/functional/grains/test_grains.py index 0206fcd81a1..0d5619ab5cb 100644 --- a/tests/pytests/functional/grains/test_grains.py +++ b/tests/pytests/functional/grains/test_grains.py @@ -1,10 +1,5 @@ -import logging - import pytest -log = logging.getLogger(__name__) - - pytestmark = [ pytest.mark.skip_unless_on_linux, pytest.mark.skipif( @@ -15,8 +10,10 @@ pytestmark = [ def test_grains(grains): - log.warning(f"DGM test_grains '{grains}'") - + """ + Test to ensure that the lsb_distrib_xxxx grains are + populated on Debian machines + """ assert "lsb_distrib_id" in grains assert "lsb_distrib_release" in grains assert "lsb_distrib_codename" in grains From a4ef5039829acbd8e04ed8889f811f4e981c7816 Mon Sep 17 00:00:00 2001 From: David Murphy < dmurphy@saltstack.com> Date: Mon, 27 Nov 2023 16:49:56 -0700 Subject: [PATCH 03/20] Adjusted generation of oscodename and lsb_distrib_codename for grains. --- salt/grains/core.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/salt/grains/core.py b/salt/grains/core.py index dae45bfb559..707d81ca747 100644 --- a/salt/grains/core.py +++ b/salt/grains/core.py @@ -2231,6 +2231,11 @@ def _legacy_linux_distribution_data(grains, os_release, lsb_has_error): cpe.get("version") and cpe.get("vendor") == "opensuse" ): # Keep VERSION_ID for SLES grains["lsb_distrib_release"] = cpe["version"] + if grains["lsb_distrib_codename"]: + test_strg = grains["lsb_distrib_codename"].split("(", maxsplit=1) + if len(test_strg) >= 2: + test_strg_2 = test_strg[1].split(")", maxsplit=1) + grains["lsb_distrib_codename"] = test_strg_2[0] elif os.path.isfile("/etc/SuSE-release"): log.trace("Parsing distrib info from /etc/SuSE-release") @@ -2348,9 +2353,7 @@ def _legacy_linux_distribution_data(grains, os_release, lsb_has_error): ): grains.pop("lsb_distrib_release", None) grains["osrelease"] = grains.get("lsb_distrib_release", osrelease).strip() - grains["oscodename"] = grains.get("lsb_distrib_codename", "").strip() or oscodename - if "Red Hat" in grains["oscodename"]: - grains["oscodename"] = oscodename + grains["oscodename"] = oscodename or grains.get("lsb_distrib_codename", "").strip() if "os" not in grains: grains["os"] = _derive_os_grain(grains["osfullname"]) # this assigns family names based on the os name From fd990ea30053f6611f8f5e690a532353ab4763d9 Mon Sep 17 00:00:00 2001 From: David Murphy < dmurphy@saltstack.com> Date: Tue, 28 Nov 2023 08:58:50 -0700 Subject: [PATCH 04/20] Revert to original setting grain oscodename from lsb_distrib_codename first --- salt/grains/core.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/salt/grains/core.py b/salt/grains/core.py index 707d81ca747..e57df87a6e1 100644 --- a/salt/grains/core.py +++ b/salt/grains/core.py @@ -2353,7 +2353,9 @@ def _legacy_linux_distribution_data(grains, os_release, lsb_has_error): ): grains.pop("lsb_distrib_release", None) grains["osrelease"] = grains.get("lsb_distrib_release", osrelease).strip() - grains["oscodename"] = oscodename or grains.get("lsb_distrib_codename", "").strip() + grains["oscodename"] = grains.get("lsb_distrib_codename", "").strip() or oscodename + if "Red Hat" in grains["oscodename"]: + grains["oscodename"] = oscodename if "os" not in grains: grains["os"] = _derive_os_grain(grains["osfullname"]) # this assigns family names based on the os name From 6502f4c7303813949529edaada6b95be43b79aaa Mon Sep 17 00:00:00 2001 From: David Murphy < dmurphy@saltstack.com> Date: Tue, 28 Nov 2023 16:55:01 -0700 Subject: [PATCH 05/20] Fix support for Mendel OS when lsb errors --- salt/grains/core.py | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/salt/grains/core.py b/salt/grains/core.py index e57df87a6e1..07e44fc10a9 100644 --- a/salt/grains/core.py +++ b/salt/grains/core.py @@ -2106,9 +2106,11 @@ def _os_release_quirks_for_osrelease(os_release): if os_release["ID"] in ("mendel",): # Mendel sets VERSION_CODENAME but not VERSION_ID. # Only PRETTY_NAME mentions the version number. - match = _PRETTY_NAME_RE.match(os_release["PRETTY_NAME"]) - if match: - return match.group("version") + # for example: Mendel GNU/Linux 5 (Eagle) + test_strg = os_release["PRETTY_NAME"].split() + if len(test_strg) >= 3: + return test_strg[2] + return None @@ -2231,11 +2233,10 @@ def _legacy_linux_distribution_data(grains, os_release, lsb_has_error): cpe.get("version") and cpe.get("vendor") == "opensuse" ): # Keep VERSION_ID for SLES grains["lsb_distrib_release"] = cpe["version"] - if grains["lsb_distrib_codename"]: - test_strg = grains["lsb_distrib_codename"].split("(", maxsplit=1) - if len(test_strg) >= 2: - test_strg_2 = test_strg[1].split(")", maxsplit=1) - grains["lsb_distrib_codename"] = test_strg_2[0] + if "ID" in os_release and os_release["ID"].strip() == "mendel": + test_strg = os_release["PRETTY_NAME"].split() + if len(test_strg) >= 3: + grains["lsb_distrib_release"] = test_strg[2] elif os.path.isfile("/etc/SuSE-release"): log.trace("Parsing distrib info from /etc/SuSE-release") @@ -2353,6 +2354,21 @@ def _legacy_linux_distribution_data(grains, os_release, lsb_has_error): ): grains.pop("lsb_distrib_release", None) grains["osrelease"] = grains.get("lsb_distrib_release", osrelease).strip() + + # allow for codename being within brackets on certain OS + if grains["lsb_distrib_codename"] and ( + grains["os"] == "Rocky" + or grains["os"] == "AlmaLinux" + or grains["os"] == "AstraLinuxSE" + ): + test_strg = grains["lsb_distrib_codename"].split("(", maxsplit=1) + if len(test_strg) >= 2: + test_strg_2 = test_strg[1].split(")", maxsplit=1) + if grains["os"] == "AstraLinuxSE": + grains["lsb_distrib_codename"] = test_strg_2[0].lower() + else: + grains["lsb_distrib_codename"] = test_strg_2[0] + grains["oscodename"] = grains.get("lsb_distrib_codename", "").strip() or oscodename if "Red Hat" in grains["oscodename"]: grains["oscodename"] = oscodename From 8e5d94b2108929096ed648e3c6f4d6aebcb29460 Mon Sep 17 00:00:00 2001 From: David Murphy < dmurphy@saltstack.com> Date: Wed, 29 Nov 2023 09:27:28 -0700 Subject: [PATCH 06/20] Further refinement of handling for verious OS's when lsb error --- salt/grains/core.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/salt/grains/core.py b/salt/grains/core.py index 07e44fc10a9..b29a012ae67 100644 --- a/salt/grains/core.py +++ b/salt/grains/core.py @@ -2356,16 +2356,15 @@ def _legacy_linux_distribution_data(grains, os_release, lsb_has_error): grains["osrelease"] = grains.get("lsb_distrib_release", osrelease).strip() # allow for codename being within brackets on certain OS - if grains["lsb_distrib_codename"] and ( - grains["os"] == "Rocky" - or grains["os"] == "AlmaLinux" - or grains["os"] == "AstraLinuxSE" + if grains.get("lsb_distrib_codename", "") and ( + any(os in grains.get("os", "") for os in ["Rocky", "AlmaLinux", "AstraLinuxSE"]) ): test_strg = grains["lsb_distrib_codename"].split("(", maxsplit=1) if len(test_strg) >= 2: test_strg_2 = test_strg[1].split(")", maxsplit=1) if grains["os"] == "AstraLinuxSE": - grains["lsb_distrib_codename"] = test_strg_2[0].lower() + # AstraLinuxSE has version aka 'Smolensk 1.6' + grains["lsb_distrib_codename"] = test_strg_2[0].split()[0].lower() else: grains["lsb_distrib_codename"] = test_strg_2[0] From c5e9cc2d0d942884b3c141c3e576f535e015e883 Mon Sep 17 00:00:00 2001 From: Felippe Burk Date: Thu, 24 Aug 2023 15:01:25 -0600 Subject: [PATCH 07/20] adding usermod, groupadd, useradd to requires for rpm Signed-off-by: Felippe Burk --- pkg/rpm/salt.spec | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/rpm/salt.spec b/pkg/rpm/salt.spec index 17f9b6544fb..54da61d50dd 100644 --- a/pkg/rpm/salt.spec +++ b/pkg/rpm/salt.spec @@ -50,6 +50,9 @@ Requires: dmidecode Requires: pciutils Requires: which Requires: openssl +Requires: /usr/sbin/usermod +Requires: /usr/sbin/groupadd +Requires: /usr/sbin/useradd BuildRequires: python3 BuildRequires: python3-pip From 51506d8784efac6e709da6364b8809a14512362b Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Wed, 29 Nov 2023 22:27:54 +0000 Subject: [PATCH 08/20] MacOS packages include `arm64` in their name, not `aarch64` Signed-off-by: Pedro Algarvio --- pkg/tests/download/test_pkg_download.py | 2 -- tools/precommit/workflows.py | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/tests/download/test_pkg_download.py b/pkg/tests/download/test_pkg_download.py index 81542ec4583..f14114d143e 100644 --- a/pkg/tests/download/test_pkg_download.py +++ b/pkg/tests/download/test_pkg_download.py @@ -401,8 +401,6 @@ def setup_macos( ): arch = os.environ.get("SALT_REPO_ARCH") or "x86_64" if package_type == "package": - if arch == "aarch64": - arch = "arm64" if packaging.version.parse(salt_release) > packaging.version.parse("3005"): mac_pkg = f"salt-{salt_release}-py3-{arch}.pkg" diff --git a/tools/precommit/workflows.py b/tools/precommit/workflows.py index b749edf907f..2946ae9f279 100644 --- a/tools/precommit/workflows.py +++ b/tools/precommit/workflows.py @@ -266,8 +266,12 @@ def generate_workflows(ctx: Context): continue test_salt_pkg_downloads_listing["linux"].append((slug, arch, "onedir")) for slug, display_name, arch in build_ci_deps_listing["macos"]: + if arch == "aarch64": + arch = "arm64" test_salt_pkg_downloads_listing["macos"].append((slug, arch, "package")) for slug, display_name, arch in build_ci_deps_listing["macos"][-1:]: + if arch == "aarch64": + arch = "arm64" test_salt_pkg_downloads_listing["macos"].append((slug, arch, "onedir")) for slug, display_name, arch in build_ci_deps_listing["windows"][-1:]: for pkg_type in ("nsis", "msi", "onedir"): From 2fbb160905bbdbad7c82f016aeeb4222a2a07d1f Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Thu, 30 Nov 2023 08:59:52 +0000 Subject: [PATCH 09/20] The previous PR only updated the template, not the actual workflow Signed-off-by: Pedro Algarvio --- .github/workflows/test-package-downloads-action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-package-downloads-action.yml b/.github/workflows/test-package-downloads-action.yml index d36b00d295c..4ddc5267f51 100644 --- a/.github/workflows/test-package-downloads-action.yml +++ b/.github/workflows/test-package-downloads-action.yml @@ -442,10 +442,10 @@ jobs: arch: x86_64 pkg-type: package - distro-slug: macos-13-xlarge - arch: aarch64 + arch: arm64 pkg-type: package - distro-slug: macos-13-xlarge - arch: aarch64 + arch: arm64 pkg-type: onedir steps: From 90a3cbed44582f0f5afc30a5732df672180a2167 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Thu, 30 Nov 2023 09:43:44 +0000 Subject: [PATCH 10/20] If `tools/precommit/workflows.py` changes the workflows must be generated Signed-off-by: Pedro Algarvio --- .github/workflows/ci.yml | 1 + .github/workflows/nightly.yml | 1 + .github/workflows/scheduled.yml | 1 + .github/workflows/staging.yml | 1 + .github/workflows/templates/layout.yml.jinja | 1 + .pre-commit-config.yaml | 2 +- 6 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 57141976bbd..4949c233c59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,6 +99,7 @@ jobs: - .github/actions/**/action.yml - .github/workflows/*.yml - .github/workflows/templates/*.yml.jinja2 + - tools/precommit/workflows.py salt: - added|modified: &salt_added_modified - setup.py diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index d212a7518a4..06bbecd6e06 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -143,6 +143,7 @@ jobs: - .github/actions/**/action.yml - .github/workflows/*.yml - .github/workflows/templates/*.yml.jinja2 + - tools/precommit/workflows.py salt: - added|modified: &salt_added_modified - setup.py diff --git a/.github/workflows/scheduled.yml b/.github/workflows/scheduled.yml index 1a5488310b3..f8ce37c72fe 100644 --- a/.github/workflows/scheduled.yml +++ b/.github/workflows/scheduled.yml @@ -133,6 +133,7 @@ jobs: - .github/actions/**/action.yml - .github/workflows/*.yml - .github/workflows/templates/*.yml.jinja2 + - tools/precommit/workflows.py salt: - added|modified: &salt_added_modified - setup.py diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml index 837d4c97c15..da7f6fd2c36 100644 --- a/.github/workflows/staging.yml +++ b/.github/workflows/staging.yml @@ -129,6 +129,7 @@ jobs: - .github/actions/**/action.yml - .github/workflows/*.yml - .github/workflows/templates/*.yml.jinja2 + - tools/precommit/workflows.py salt: - added|modified: &salt_added_modified - setup.py diff --git a/.github/workflows/templates/layout.yml.jinja b/.github/workflows/templates/layout.yml.jinja index 2d7afcb51bb..45c529f1e86 100644 --- a/.github/workflows/templates/layout.yml.jinja +++ b/.github/workflows/templates/layout.yml.jinja @@ -147,6 +147,7 @@ jobs: - .github/actions/**/action.yml - .github/workflows/*.yml - .github/workflows/templates/*.yml.jinja2 + - tools/precommit/workflows.py salt: - added|modified: &salt_added_modified - setup.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 49158cdbfb1..0f926d986d5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -59,7 +59,7 @@ repos: - id: tools alias: generate-workflows name: Generate GitHub Workflow Templates - files: ^(cicd/shared-gh-workflows-context\.yml|tools/pre_commit\.py|.github/workflows/templates/.*)$ + files: ^(cicd/shared-gh-workflows-context\.yml|tools/precommit/workflows\.py|.github/workflows/templates/.*)$ pass_filenames: false args: - pre-commit From e242ae3bf2cad105acbd9d679e7b5a9c82fedecd Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Mon, 4 Dec 2023 16:40:44 +0000 Subject: [PATCH 11/20] Stop trying when codecov replies with `Too many uploads to this commit` Signed-off-by: Pedro Algarvio --- tools/ci.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tools/ci.py b/tools/ci.py index 9add8826907..e4ef802d9f2 100644 --- a/tools/ci.py +++ b/tools/ci.py @@ -1214,8 +1214,22 @@ def upload_coverage(ctx: Context, reports_path: pathlib.Path, commit_sha: str = "--flags", flags, check=False, + capture=True, ) + stdout = ret.stdout.strip().decode() + stderr = ret.stderr.strip().decode() if ret.returncode == 0: + ctx.console_stdout.print(stdout) + ctx.console.print(stderr) + break + + if ( + "Too many uploads to this commit" in stdout + or "Too many uploads to this commit" in stderr + ): + # Let's just stop trying + ctx.console_stdout.print(stdout) + ctx.console.print(stderr) break if current_attempt >= max_attempts: From 7092fe59ef4611de0aad25e7e83e4f0f09b18396 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Mon, 4 Dec 2023 17:00:57 +0000 Subject: [PATCH 12/20] Adjust the architecture for the onedir artifact Signed-off-by: Pedro Algarvio --- .github/workflows/test-package-downloads-action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-package-downloads-action.yml b/.github/workflows/test-package-downloads-action.yml index 4ddc5267f51..8390f27be54 100644 --- a/.github/workflows/test-package-downloads-action.yml +++ b/.github/workflows/test-package-downloads-action.yml @@ -461,7 +461,7 @@ jobs: - name: Download Onedir Tarball as an Artifact uses: actions/download-artifact@v3 with: - name: ${{ inputs.package-name }}-${{ inputs.salt-version }}-onedir-darwin-${{ matrix.arch }}.tar.xz + name: ${{ inputs.package-name }}-${{ inputs.salt-version }}-onedir-darwin-${{ matrix.arch == 'arm64' && 'aarch64' || matrix.arch }}.tar.xz path: artifacts/ - name: Install System Dependencies From 989790cb90687d0bb8ec7a51135d693453ba62bc Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Thu, 30 Nov 2023 23:26:29 -0700 Subject: [PATCH 13/20] Add __file_client__ for execution modules --- salt/fileclient.py | 14 ++++++++++++++ salt/loader/__init__.py | 2 ++ salt/loader/context.py | 6 +----- salt/loader/dunder.py | 9 +++++++++ salt/modules/cp.py | 6 ++++++ salt/state.py | 41 +++++++++++++++++++++++++++++++++++++---- 6 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 salt/loader/dunder.py diff --git a/salt/fileclient.py b/salt/fileclient.py index b7966b2029b..42e7120aab1 100644 --- a/salt/fileclient.py +++ b/salt/fileclient.py @@ -1532,3 +1532,17 @@ class DumbAuth: def gen_token(self, clear_tok): return clear_tok + + +class ContextlessFileClient: + def __init__(self, file_client): + self.file_client = file_client + + def __getattr__(self, key): + return getattr(self.file_client, key) + + def __exit__(self, *_): + pass + + def __enter__(self): + return self diff --git a/salt/loader/__init__.py b/salt/loader/__init__.py index 72a5e544012..2493f22cc48 100644 --- a/salt/loader/__init__.py +++ b/salt/loader/__init__.py @@ -263,6 +263,7 @@ def minion_mods( notify=False, static_modules=None, proxy=None, + file_client=None, ): """ Load execution modules @@ -314,6 +315,7 @@ def minion_mods( "__utils__": utils, "__proxy__": proxy, "__opts__": opts, + "__file_client__": file_client, }, whitelist=whitelist, loaded_base_name=loaded_base_name, diff --git a/salt/loader/context.py b/salt/loader/context.py index 86f879cc592..6bbfe4dbd81 100644 --- a/salt/loader/context.py +++ b/salt/loader/context.py @@ -84,11 +84,7 @@ class NamedLoaderContext(collections.abc.MutableMapping): self.value()[item] = value def __bool__(self): - try: - self.loader - except LookupError: - return False - return True + return bool(self.value()) def __len__(self): return self.value().__len__() diff --git a/salt/loader/dunder.py b/salt/loader/dunder.py new file mode 100644 index 00000000000..5fae9014797 --- /dev/null +++ b/salt/loader/dunder.py @@ -0,0 +1,9 @@ +""" +Salt dunders. +""" +import salt.loader.context + +loader_context = salt.loader.context.LoaderContext() + + +__file_client__ = loader_context.named_context("__file_client__") diff --git a/salt/modules/cp.py b/salt/modules/cp.py index 4c5396949fe..4898e4ca3c8 100644 --- a/salt/modules/cp.py +++ b/salt/modules/cp.py @@ -20,6 +20,7 @@ import salt.utils.path import salt.utils.templates import salt.utils.url from salt.exceptions import CommandExecutionError +from salt.loader.dunder import __file_client__ log = logging.getLogger(__name__) @@ -161,6 +162,11 @@ def _client(): """ Return a client, hashed by the list of masters """ + if __file_client__: + val = __file_client__.value() + fc = salt.fileclient.ContextlessFileClient(val) + log.error("Using context client %r %r", val, fc) + return fc return salt.fileclient.get_file_client(__opts__) diff --git a/salt/state.py b/salt/state.py index d5956981eed..d70e105013f 100644 --- a/salt/state.py +++ b/salt/state.py @@ -758,6 +758,7 @@ class State: mocked=False, loader="states", initial_pillar=None, + file_client=None, ): self._init_kwargs = { "opts": opts, @@ -774,6 +775,12 @@ class State: if "grains" not in opts: opts["grains"] = salt.loader.grains(opts) self.opts = opts + if file_client: + self.file_client = file_client + self.preserve_file_client = True + else: + self.file_client = salt.fileclient.get_file_client(self.opts) + self.preserve_file_client = False self.proxy = proxy self._pillar_override = pillar_override if pillar_enc is not None: @@ -798,7 +805,11 @@ class State: self.opts.get("pillar_merge_lists", False), ) log.debug("Finished gathering pillar data for state run") - self.state_con = context or {} + if context is None: + self.state_con = {} + else: + self.state_con = context + self.state_con["fileclient"] = self.file_client self.load_modules() self.active = set() self.mod_init = set() @@ -1285,7 +1296,11 @@ class State: log.info("Loading fresh modules for state activity") self.utils = salt.loader.utils(self.opts) self.functions = salt.loader.minion_mods( - self.opts, self.state_con, utils=self.utils, proxy=self.proxy + self.opts, + self.state_con, + utils=self.utils, + proxy=self.proxy, + file_client=self.file_client, ) if isinstance(data, dict): if data.get("provider", False): @@ -3672,6 +3687,16 @@ class State: return errors return self.call_high(high) + def destroy(self): + if not self.preserve_file_client: + self.file_client.close() + + def __enter__(self): + return self + + def __exit__(self, *_): + self.destroy() + class LazyAvailStates: """ @@ -4917,9 +4942,15 @@ class HighState(BaseHighState): mocked=False, loader="states", initial_pillar=None, + file_client=None, ): self.opts = opts - self.client = salt.fileclient.get_file_client(self.opts) + if file_client: + self.client = file_client + self.preserve_client = True + else: + self.client = salt.fileclient.get_file_client(self.opts) + self.preserve_client = False BaseHighState.__init__(self, opts) self.state = State( self.opts, @@ -4931,6 +4962,7 @@ class HighState(BaseHighState): mocked=mocked, loader=loader, initial_pillar=initial_pillar, + file_client=self.client, ) self.matchers = salt.loader.matchers(self.opts) self.proxy = proxy @@ -4965,7 +4997,8 @@ class HighState(BaseHighState): return None def destroy(self): - self.client.destroy() + if not self.preserve_client: + self.client.destroy() def __enter__(self): return self From 3faee7dc283e9249829061eb16fbadcc844a285f Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Fri, 1 Dec 2023 01:16:03 -0700 Subject: [PATCH 14/20] Add master_uri to minion_opts for tests --- tests/pytests/unit/conftest.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/pytests/unit/conftest.py b/tests/pytests/unit/conftest.py index 443f0b67008..587fc43babc 100644 --- a/tests/pytests/unit/conftest.py +++ b/tests/pytests/unit/conftest.py @@ -12,6 +12,9 @@ def minion_opts(tmp_path): opts = salt.config.DEFAULT_MINION_OPTS.copy() opts["__role"] = "minion" opts["root_dir"] = str(root_dir) + opts["master_uri"] = "tcp://{ip}:{port}".format( + ip="127.0.0.1", port=opts["master_port"] + ) for name in ("cachedir", "pki_dir", "sock_dir", "conf_dir"): dirpath = root_dir / name dirpath.mkdir(parents=True) From 8223a27948eacd5d51743a302415a35022e3838f Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Fri, 1 Dec 2023 15:49:06 -0700 Subject: [PATCH 15/20] Populate __file_client__ for states Also start using __file_client__ wherever we used to pull a client from __context__> --- salt/loader/__init__.py | 2 ++ salt/modules/cp.py | 10 +++++----- salt/modules/dockermod.py | 15 ++++++++++++++- salt/state.py | 3 ++- salt/states/ansiblegate.py | 15 ++++++++++++++- 5 files changed, 37 insertions(+), 8 deletions(-) diff --git a/salt/loader/__init__.py b/salt/loader/__init__.py index 2493f22cc48..8f2a69dc6b6 100644 --- a/salt/loader/__init__.py +++ b/salt/loader/__init__.py @@ -780,6 +780,7 @@ def states( proxy=None, context=None, loaded_base_name=None, + file_client=None, ): """ Returns the state modules @@ -817,6 +818,7 @@ def states( "__utils__": utils, "__serializers__": serializers, "__context__": context, + "__file_client__": file_client, }, whitelist=whitelist, extra_module_dirs=utils.module_dirs if utils else None, diff --git a/salt/modules/cp.py b/salt/modules/cp.py index 4898e4ca3c8..64666aefa5d 100644 --- a/salt/modules/cp.py +++ b/salt/modules/cp.py @@ -160,13 +160,13 @@ def recv_chunked(dest, chunk, append=False, compressed=True, mode=None): def _client(): """ - Return a client, hashed by the list of masters + Return a file client + + If the __file_client__ context is set return it, otherwize create a new + file client using __opts__. """ if __file_client__: - val = __file_client__.value() - fc = salt.fileclient.ContextlessFileClient(val) - log.error("Using context client %r %r", val, fc) - return fc + return __file_client__.value() return salt.fileclient.get_file_client(__opts__) diff --git a/salt/modules/dockermod.py b/salt/modules/dockermod.py index 415c03d24b7..f9ffd2dda9e 100644 --- a/salt/modules/dockermod.py +++ b/salt/modules/dockermod.py @@ -222,6 +222,7 @@ import salt.utils.functools import salt.utils.json import salt.utils.path from salt.exceptions import CommandExecutionError, SaltInvocationError +from salt.loader.dunder import __file_client__ from salt.state import HighState __docformat__ = "restructuredtext en" @@ -325,6 +326,18 @@ def __virtual__(): return (False, "Could not import docker module, is docker-py installed?") +def _file_client(): + """ + Return a file client + + If the __file_client__ context is set return it, otherwize create a new + file client using __opts__. + """ + if __file_client__: + return __file_client__.value() + return salt.fileclient.get_file_client(__opts__) + + class DockerJSONDecoder(json.JSONDecoder): def decode(self, s, _w=None): objs = [] @@ -6633,7 +6646,7 @@ def _prepare_trans_tar(name, sls_opts, mods=None, pillar=None, extra_filerefs="" # reuse it from salt.ssh, however this function should # be somewhere else refs = salt.client.ssh.state.lowstate_file_refs(chunks, extra_filerefs) - with salt.fileclient.get_file_client(__opts__) as fileclient: + with _file_client() as fileclient: return salt.client.ssh.state.prep_trans_tar( fileclient, chunks, refs, pillar, name ) diff --git a/salt/state.py b/salt/state.py index d70e105013f..dfa64adae0e 100644 --- a/salt/state.py +++ b/salt/state.py @@ -1287,6 +1287,7 @@ class State: self.serializers, context=self.state_con, proxy=self.proxy, + file_client=salt.fileclient.ContextlessFileClient(self.file_client), ) def load_modules(self, data=None, proxy=None): @@ -1300,7 +1301,7 @@ class State: self.state_con, utils=self.utils, proxy=self.proxy, - file_client=self.file_client, + file_client=salt.fileclient.ContextlessFileClient(self.file_client), ) if isinstance(data, dict): if data.get("provider", False): diff --git a/salt/states/ansiblegate.py b/salt/states/ansiblegate.py index 9abd418c42c..ec8913dee59 100644 --- a/salt/states/ansiblegate.py +++ b/salt/states/ansiblegate.py @@ -38,12 +38,25 @@ import sys import salt.fileclient import salt.utils.decorators.path +from salt.loader.dunder import __file_client__ from salt.utils.decorators import depends log = logging.getLogger(__name__) __virtualname__ = "ansible" +def _file_client(): + """ + Return a file client + + If the __file_client__ context is set return it, otherwize create a new + file client using __opts__. + """ + if __file_client__: + return __file_client__.value() + return salt.fileclient.get_file_client(__opts__) + + @depends("ansible") class AnsibleState: """ @@ -162,7 +175,7 @@ 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): - with salt.fileclient.get_file_client(__opts__) as client: + with _file_client() as client: rundir = client._extrn_path(git_repo, "base") log.trace("rundir set to %s", rundir) if not isinstance(git_kwargs, dict): From 21a3f6aa306855bc7d230f86c6c47130f5980678 Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Fri, 1 Dec 2023 23:03:59 -0700 Subject: [PATCH 16/20] Add changelog for 65450 --- changelog/65450.fixed.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/65450.fixed.md diff --git a/changelog/65450.fixed.md b/changelog/65450.fixed.md new file mode 100644 index 00000000000..c680d37692c --- /dev/null +++ b/changelog/65450.fixed.md @@ -0,0 +1 @@ +Fix regression in file module which was not re-using a file client. From 9fb71a7559d17f04746dceb1bb307d625013cba0 Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Sat, 2 Dec 2023 15:06:02 -0700 Subject: [PATCH 17/20] Update documentation to reflect __file_client__ --- doc/topics/development/modules/developing.rst | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/doc/topics/development/modules/developing.rst b/doc/topics/development/modules/developing.rst index 5e9a9219ac4..82e8d793bc9 100644 --- a/doc/topics/development/modules/developing.rst +++ b/doc/topics/development/modules/developing.rst @@ -155,7 +155,7 @@ The following dunder dictionaries are always defined, but may be empty __opts__ -------- -..versionchanged:: 3006.0 +.. versionchanged:: 3006.0 The ``__opts__`` dictionary can now be accessed via :py:mod:`~salt.loader.context``. @@ -248,13 +248,6 @@ executions until the modules are refreshed; such as when :py:func:`saltutil.sync_all ` or :py:func:`state.apply ` are executed. -A great place to see how to use ``__context__`` is in the cp.py module in -salt/modules/cp.py. The fileclient authenticates with the master when it is -instantiated and then is used to copy files to the minion. Rather than create a -new fileclient for each file that is to be copied down, one instance of the -fileclient is instantiated in the ``__context__`` dictionary and is reused for -each file. Here is an example from salt/modules/cp.py: - .. code-block:: python if not "cp.fileclient" in __context__: @@ -303,3 +296,13 @@ Defined in: State __sdb__ ------- Defined in: SDB + + +__file_client__ +--------------- + +.. versionchanged:: 3006.5 + +The ``__file_client__`` dunder was added to states and execution modules. This +enables the use of a file client without haveing to instantiate one in +the module. From 25e250e749c7446725dc865e459816ba4a4c4684 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Mon, 4 Dec 2023 21:33:21 +0000 Subject: [PATCH 18/20] Adjust the architecture for the onedir artifact(in the template) Signed-off-by: Pedro Algarvio --- .../workflows/templates/test-package-downloads-action.yml.jinja | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/templates/test-package-downloads-action.yml.jinja b/.github/workflows/templates/test-package-downloads-action.yml.jinja index 25c9bd82c8b..260e8ba9b48 100644 --- a/.github/workflows/templates/test-package-downloads-action.yml.jinja +++ b/.github/workflows/templates/test-package-downloads-action.yml.jinja @@ -318,7 +318,7 @@ jobs: - name: Download Onedir Tarball as an Artifact uses: actions/download-artifact@v3 with: - name: ${{ inputs.package-name }}-${{ inputs.salt-version }}-onedir-darwin-${{ matrix.arch }}.tar.xz + name: ${{ inputs.package-name }}-${{ inputs.salt-version }}-onedir-darwin-${{ matrix.arch == 'arm64' && 'aarch64' || matrix.arch }}.tar.xz path: artifacts/ - name: Install System Dependencies From 4d8eac3bac8a4675c03a48e75168217208b17bd6 Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Mon, 4 Dec 2023 16:14:29 -0700 Subject: [PATCH 19/20] Update security reporting email --- SECURITY.md | 6 +++--- doc/man/salt.7 | 6 +++--- doc/security/index.rst | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index b161605e9f0..97afd202de6 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,7 +1,7 @@ # SaltStack's Security Disclosure Policy **Email** -- security@saltstack.com +- saltproject-security.pdl@broadcom.com **GPG key ID:** - 4EA0793D @@ -78,7 +78,7 @@ vtBIWO4LPeGEvb2Gs65PL2eouOqU6yvBr5Y= -----END PGP PUBLIC KEY BLOCK----- ``` -The SaltStack Security Team is available at security@saltstack.com for +The SaltStack Security Team is available at saltproject-security.pdl@broadcom.com for security-related bug reports or questions. We request the disclosure of any security-related bugs or issues be reported @@ -92,7 +92,7 @@ SaltStack takes security and the trust of our customers and users very seriously. Our disclosure policy is intended to resolve security issues as quickly and safely as is possible. -1. A security report sent to security@saltstack.com is assigned to a team +1. A security report sent to saltproject-security.pdl@broadcom.com is assigned to a team member. This person is the primary contact for questions and will coordinate the fix, release, and announcement. diff --git a/doc/man/salt.7 b/doc/man/salt.7 index 37909803cad..7457d9dd5f4 100644 --- a/doc/man/salt.7 +++ b/doc/man/salt.7 @@ -23710,7 +23710,7 @@ most secure setup, only connect syndics directly to master of masters. .INDENT 0.0 .TP .B email -\fI\%security@saltstack.com\fP +\fI\%saltproject-security.pdl@broadcom.com\fP .TP .B gpg key ID 4EA0793D @@ -23831,7 +23831,7 @@ fwPKmQ2cKnCBs5ASj1DkgUcz2c8DTUPVqg== .UNINDENT .UNINDENT .sp -The SaltStack Security Team is available at \fI\%security@saltstack.com\fP for +The SaltStack Security Team is available at \fI\%saltproject-security.pdl@broadcom.com\fP for security\-related bug reports or questions. .sp We request the disclosure of any security\-related bugs or issues be reported @@ -23845,7 +23845,7 @@ seriously. Our disclosure policy is intended to resolve security issues as quickly and safely as is possible. .INDENT 0.0 .IP 1. 3 -A security report sent to \fI\%security@saltstack.com\fP is assigned to a team +A security report sent to \fI\%saltproject-security.pdl@broadcom.com\fP is assigned to a team member. This person is the primary contact for questions and will coordinate the fix, release, and announcement. .IP 2. 3 diff --git a/doc/security/index.rst b/doc/security/index.rst index ab7b048940e..e5a36381e4e 100644 --- a/doc/security/index.rst +++ b/doc/security/index.rst @@ -4,7 +4,7 @@ Security disclosure policy ========================== -:email: security@saltstack.com +:email: saltproject-security.pdl@broadcom.com :gpg key ID: 4EA0793D :gpg key fingerprint: ``8ABE 4EFC F0F4 B24B FF2A AF90 D570 F2D3 4EA0 793D`` @@ -114,7 +114,7 @@ Security disclosure policy =i1Tf -----END PGP PUBLIC KEY BLOCK----- -The SaltStack Security Team is available at security@saltstack.com for +The SaltStack Security Team is available at saltproject-security.pdl@broadcom.com for security-related bug reports or questions. We request the disclosure of any security-related bugs or issues be reported @@ -129,7 +129,7 @@ SaltStack takes security and the trust of our customers and users very seriously. Our disclosure policy is intended to resolve security issues as quickly and safely as is possible. -1. A security report sent to security@saltstack.com is assigned to a team +1. A security report sent to saltproject-security.pdl@broadcom.com is assigned to a team member. This person is the primary contact for questions and will coordinate the fix, release, and announcement. From 619b614b761cc71e39d199fe6a0bbdaf1b9ace88 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Tue, 5 Dec 2023 05:22:28 +0000 Subject: [PATCH 20/20] One more place where `arch` needs to be translated Signed-off-by: Pedro Algarvio --- .../workflows/templates/test-package-downloads-action.yml.jinja | 2 +- .github/workflows/test-package-downloads-action.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/templates/test-package-downloads-action.yml.jinja b/.github/workflows/templates/test-package-downloads-action.yml.jinja index 260e8ba9b48..ce608ce98bb 100644 --- a/.github/workflows/templates/test-package-downloads-action.yml.jinja +++ b/.github/workflows/templates/test-package-downloads-action.yml.jinja @@ -330,7 +330,7 @@ jobs: run: | python3 -c "import os; os.makedirs('artifacts', exist_ok=True)" cd artifacts - tar xvf ${{ inputs.package-name }}-${{ inputs.salt-version }}-onedir-darwin-${{ matrix.arch }}.tar.xz + tar xvf ${{ inputs.package-name }}-${{ inputs.salt-version }}-onedir-darwin-${{ matrix.arch == 'arm64' && 'aarch64' || matrix.arch }}.tar.xz - name: Set up Python ${{ inputs.python-version }} uses: actions/setup-python@v4 diff --git a/.github/workflows/test-package-downloads-action.yml b/.github/workflows/test-package-downloads-action.yml index 8390f27be54..1a1b8a50268 100644 --- a/.github/workflows/test-package-downloads-action.yml +++ b/.github/workflows/test-package-downloads-action.yml @@ -473,7 +473,7 @@ jobs: run: | python3 -c "import os; os.makedirs('artifacts', exist_ok=True)" cd artifacts - tar xvf ${{ inputs.package-name }}-${{ inputs.salt-version }}-onedir-darwin-${{ matrix.arch }}.tar.xz + tar xvf ${{ inputs.package-name }}-${{ inputs.salt-version }}-onedir-darwin-${{ matrix.arch == 'arm64' && 'aarch64' || matrix.arch }}.tar.xz - name: Set up Python ${{ inputs.python-version }} uses: actions/setup-python@v4