aboutsummaryrefslogtreecommitdiff
path: root/tests/post-rebuild-check
diff options
context:
space:
mode:
Diffstat (limited to 'tests/post-rebuild-check')
-rw-r--r--tests/post-rebuild-check/test_post_rebuild_check.py65
1 files changed, 65 insertions, 0 deletions
diff --git a/tests/post-rebuild-check/test_post_rebuild_check.py b/tests/post-rebuild-check/test_post_rebuild_check.py
index 757039b..bad337e 100644
--- a/tests/post-rebuild-check/test_post_rebuild_check.py
+++ b/tests/post-rebuild-check/test_post_rebuild_check.py
@@ -30,6 +30,7 @@ Run from repo root:
"""
import os
+import shutil
import subprocess
import tempfile
import time
@@ -124,6 +125,70 @@ class NtpBootstrap(unittest.TestCase):
self.assertIn("no NTP sources are configured", r.stdout)
self.assertEqual(r.returncode, 1)
+ # --- the confdir false pass ------------------------------------------
+ #
+ # A drop-in is inert unless chrony.conf names its directory, and Arch's
+ # stock chrony.conf names none. Reading the drop-in without checking for
+ # confdir would find the IP-addressed source, call the machine healthy, and
+ # be describing a file chrony never opens — a false pass on exactly the
+ # misconfiguration this check exists to catch.
+
+ def _chrony_fixture(self, main_lines, dropin_lines=None):
+ """Write a chrony.conf (plus an adjacent drop-in dir) and return its path."""
+ d = tempfile.mkdtemp(prefix="prc-chrony-")
+ self.addCleanup(shutil.rmtree, d, True)
+ dropin_dir = os.path.join(d, "chrony.d")
+ os.makedirs(dropin_dir)
+ if dropin_lines is not None:
+ with open(os.path.join(dropin_dir, "10-bootstrap-ip-ntp.conf"), "w") as f:
+ f.write(dropin_lines)
+ conf = os.path.join(d, "chrony.conf")
+ with open(conf, "w") as f:
+ f.write(main_lines.replace("@DROPIN@", dropin_dir))
+ return conf
+
+ def _run_real_probe(self, chrony_conf):
+ """Run with PRC_NTP_SOURCES unset so the real chrony reader runs."""
+ env = dict(os.environ)
+ env.update({"PRC_FAILED_UNITS": "", "PRC_UNIT_STATES": "",
+ "PRC_LOCAL_SCAN_ROOTS": "", "PRC_PROJECT_ROOTS": "",
+ "PRC_SIGNAL_ACCOUNTS": "+15045551234",
+ "PRC_CHRONY_CONF": chrony_conf})
+ env.pop("PRC_NTP_SOURCES", None)
+ return subprocess.run(["sh", CHECK], capture_output=True, text=True,
+ timeout=30, env=env)
+
+ def test_dropin_without_confdir_does_not_count(self):
+ # The regression. The IP-addressed source is present on disk but
+ # chrony.conf never points at it, so the machine is still deadlock-prone
+ # and the check has to say so.
+ conf = self._chrony_fixture("pool 2.arch.pool.ntp.org iburst\n",
+ "server 162.159.200.1 iburst\n")
+ r = self._run_real_probe(conf)
+ if "no NTP implementation is active" in r.stdout:
+ self.skipTest("no chronyd on this host — the reader branch can't run")
+ self.assertIn("every NTP source is named by hostname", r.stdout)
+
+ def test_dropin_with_confdir_counts(self):
+ # The same two files, with chrony.conf actually naming the directory.
+ conf = self._chrony_fixture(
+ "pool 2.arch.pool.ntp.org iburst\nconfdir @DROPIN@\n",
+ "server 162.159.200.1 iburst\n")
+ r = self._run_real_probe(conf)
+ if "no NTP implementation is active" in r.stdout:
+ self.skipTest("no chronyd on this host — the reader branch can't run")
+ self.assertIn("check 6/6: NTP bootstrap — ok", r.stdout)
+
+ def test_confdir_naming_an_empty_directory_is_not_a_pass(self):
+ # confdir present, nothing behind it: the sources are the hostname-only
+ # main file, so the finding stands.
+ conf = self._chrony_fixture(
+ "pool 2.arch.pool.ntp.org iburst\nconfdir @DROPIN@\n", None)
+ r = self._run_real_probe(conf)
+ if "no NTP implementation is active" in r.stdout:
+ self.skipTest("no chronyd on this host — the reader branch can't run")
+ self.assertIn("every NTP source is named by hostname", r.stdout)
+
def test_unset_seam_falls_through_to_the_real_probe(self):
# Same contract as every other seam: unset means "really look", so a
# caller who forgets the variable cannot silently skip the check.