]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
tests/: implement feature detection
authorIker Pedrosa <ipedrosa@redhat.com>
Mon, 31 Mar 2025 15:49:22 +0000 (17:49 +0200)
committerIker Pedrosa <ikerpedrosam@gmail.com>
Wed, 21 May 2025 08:04:42 +0000 (10:04 +0200)
Implement a general function to detect features in shadow host.

Apparently, musl doesn't provide `getent gshadow`, but shadow still needs
it to check for several group attributes. Thus, check whether it exists
in the host, and if it does run it. If not, let's just skip that part of
the test.

Link: <https://gitlab.alpinelinux.org/alpine/aports/-/issues/16979>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Reviewed-by: Dan Lavu <dlavu@redhat.com>
tests/system/framework/hosts/shadow.py

index 1fb656b6324ae16fb7e4c5152ac90b2126c4ed76..2a0ca3e5dde01db6cdb1d4f5bce95fa3aa69e59b 100644 (file)
@@ -42,6 +42,9 @@ class ShadowHost(BaseHost, BaseLinuxHost):
         ]
         """Files to verify for mismatch."""
 
+        self._features: dict[str, bool] | None = None
+        """Features supported by the host."""
+
     def pytest_setup(self) -> None:
         super().pytest_setup()
 
@@ -61,6 +64,34 @@ class ShadowHost(BaseHost, BaseLinuxHost):
         """
         raise NotImplementedError("Stopping shadow service is not implemented.")
 
+    @property
+    def features(self) -> dict[str, bool]:
+        """
+        Features supported by the host.
+        """
+        if self._features is not None:
+            return self._features
+
+        self.logger.info(f"Detecting shadow features on {self.hostname}")
+        result = self.conn.run(
+            """
+            set -ex
+
+            getent gshadow > /dev/null 2>&1 && echo "gshadow" || :
+            """,
+            log_level=ProcessLogLevel.Error,
+        )
+
+        # Set default values
+        self._features = {
+            "gshadow": False,
+        }
+
+        self._features.update({k: True for k in result.stdout_lines})
+        self.logger.info("Detected features:", extra={"data": {"Features": self._features}})
+
+        return self._features
+
     def backup(self) -> Any:
         """
         Backup all shadow data.