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"
|
separator == "=" and key in SERVICE_PROPERTIES and key not in value, "systemd property output was invalid"
|
||||||
)
|
)
|
||||||
value[key] = item
|
value[key] = item
|
||||||
# systemd 252 omits EnvironmentFiles entirely when its string array is
|
# systemd 252 omits empty array/command properties. For a nonexistent
|
||||||
# empty. A nonempty array is emitted and remains subject to the exact
|
# service, there cannot be an effective command to conceal, so normalize
|
||||||
# no-EnvironmentFile checks below.
|
# the three omitted Exec* properties to their explicit empty form. Loaded
|
||||||
|
# units must still report every command property for exact verification.
|
||||||
value.setdefault("EnvironmentFiles", "")
|
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")
|
_require(set(value) == set(SERVICE_PROPERTIES), "systemd property output was incomplete")
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,7 @@ class FakeHost:
|
||||||
self.race_applied = False
|
self.race_applied = False
|
||||||
self.property_overrides: dict[str, str] = {}
|
self.property_overrides: dict[str, str] = {}
|
||||||
self.omitted_properties: set[str] = set()
|
self.omitted_properties: set[str] = set()
|
||||||
|
self.not_found_omitted_properties: set[str] = set()
|
||||||
self.not_found_security_defaults: dict[str, str] = {}
|
self.not_found_security_defaults: dict[str, str] = {}
|
||||||
self.unstable_readbacks = False
|
self.unstable_readbacks = False
|
||||||
self.show_count = 0
|
self.show_count = 0
|
||||||
|
|
@ -241,6 +242,7 @@ class FakeHost:
|
||||||
f"{name}={value[name]}\n"
|
f"{name}={value[name]}\n"
|
||||||
for name in installer.SERVICE_PROPERTIES
|
for name in installer.SERVICE_PROPERTIES
|
||||||
if name not in self.omitted_properties
|
if name not in self.omitted_properties
|
||||||
|
and (loaded or name not in self.not_found_omitted_properties)
|
||||||
).encode()
|
).encode()
|
||||||
return subprocess.CompletedProcess(arguments, 0, stdout=payload, stderr=b"")
|
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
|
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:
|
def test_systemd_252_omission_does_not_hide_a_later_dropin(tmp_path: Path) -> None:
|
||||||
bundle, release, image = release_bundle(tmp_path, "2")
|
bundle, release, image = release_bundle(tmp_path, "2")
|
||||||
paths = install_paths(tmp_path)
|
paths = install_paths(tmp_path)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue