Merge pull request #236 from living-ip/fix/systemd-252-first-install
Some checks are pending
CI / lint-and-test (push) Waiting to run
Some checks are pending
CI / lint-and-test (push) Waiting to run
Handle systemd 252 first-install omissions
This commit is contained in:
commit
0701db4aa5
2 changed files with 31 additions and 3 deletions
|
|
@ -694,10 +694,14 @@ def _parse_properties(raw: bytes) -> dict[str, str]:
|
|||
separator == "=" and key in SERVICE_PROPERTIES and key not in value, "systemd property output was invalid"
|
||||
)
|
||||
value[key] = item
|
||||
# systemd 252 omits EnvironmentFiles entirely when its string array is
|
||||
# empty. A nonempty array is emitted and remains subject to the exact
|
||||
# no-EnvironmentFile checks below.
|
||||
# systemd 252 omits empty array/command properties. For a nonexistent
|
||||
# service, there cannot be an effective command to conceal, so normalize
|
||||
# the three omitted Exec* properties to their explicit empty form. Loaded
|
||||
# units must still report every command property for exact verification.
|
||||
value.setdefault("EnvironmentFiles", "")
|
||||
if value.get("LoadState") == "not-found":
|
||||
for property_name in SERVICE_EXEC_PROPERTIES:
|
||||
value.setdefault(property_name, "")
|
||||
_require(set(value) == set(SERVICE_PROPERTIES), "systemd property output was incomplete")
|
||||
return value
|
||||
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ class FakeHost:
|
|||
self.race_applied = False
|
||||
self.property_overrides: dict[str, str] = {}
|
||||
self.omitted_properties: set[str] = set()
|
||||
self.not_found_omitted_properties: set[str] = set()
|
||||
self.not_found_security_defaults: dict[str, str] = {}
|
||||
self.unstable_readbacks = False
|
||||
self.show_count = 0
|
||||
|
|
@ -241,6 +242,7 @@ class FakeHost:
|
|||
f"{name}={value[name]}\n"
|
||||
for name in installer.SERVICE_PROPERTIES
|
||||
if name not in self.omitted_properties
|
||||
and (loaded or name not in self.not_found_omitted_properties)
|
||||
).encode()
|
||||
return subprocess.CompletedProcess(arguments, 0, stdout=payload, stderr=b"")
|
||||
|
||||
|
|
@ -475,6 +477,28 @@ def test_systemd_252_omitted_environment_files_property_is_normalized(tmp_path:
|
|||
assert host.restart_calls == 1
|
||||
|
||||
|
||||
def test_systemd_252_omitted_not_found_commands_are_normalized(tmp_path: Path) -> None:
|
||||
bundle, release, image = release_bundle(tmp_path, "2")
|
||||
paths = install_paths(tmp_path)
|
||||
host = FakeHost(paths)
|
||||
host.add_release(release, image)
|
||||
host.not_found_security_defaults = dict(PRODUCTION_SHAPED_NOT_FOUND_SECURITY)
|
||||
host.not_found_omitted_properties.update({"EnvironmentFiles", *installer.SERVICE_EXEC_PROPERTIES})
|
||||
|
||||
receipt = installer.install_release(
|
||||
bundle,
|
||||
paths=paths,
|
||||
source_binding=source_binding(),
|
||||
runner=host,
|
||||
sleeper=lambda _seconds: None,
|
||||
execute_restart=True,
|
||||
)
|
||||
|
||||
assert receipt["status"] == "pass"
|
||||
assert receipt["release_sha256"] == release["release_sha256"]
|
||||
assert host.restart_calls == 1
|
||||
|
||||
|
||||
def test_systemd_252_omission_does_not_hide_a_later_dropin(tmp_path: Path) -> None:
|
||||
bundle, release, image = release_bundle(tmp_path, "2")
|
||||
paths = install_paths(tmp_path)
|
||||
|
|
|
|||
Loading…
Reference in a new issue