From a67b8ab84d871c96ad683ad0584bd68cc37a96d4 Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Fri, 22 Oct 2021 19:41:28 -0500 Subject: [PATCH] validate with runtime config (fixes #2055) --- frigate/config.py | 32 +++++++++--------- frigate/test/test_config.py | 65 ++++++++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 18 deletions(-) diff --git a/frigate/config.py b/frigate/config.py index 986ba12413..d464bb9702 100644 --- a/frigate/config.py +++ b/frigate/config.py @@ -794,6 +794,21 @@ def runtime_config(self) -> FrigateConfig: config.cameras[name] = camera_config + # check runtime config + for name, camera in config.cameras.items(): + assigned_roles = list( + set([r for i in camera.ffmpeg.inputs for r in i.roles]) + ) + if camera.record.enabled and not "record" in assigned_roles: + raise ValueError( + f"Camera {name} has record enabled, but record is not assigned to an input." + ) + + if camera.rtmp.enabled and not "rtmp" in assigned_roles: + raise ValueError( + f"Camera {name} has rtmp enabled, but rtmp is not assigned to an input." + ) + return config @validator("cameras") @@ -804,23 +819,6 @@ def ensure_zones_and_cameras_have_different_names(cls, v: Dict[str, CameraConfig raise ValueError("Zones cannot share names with cameras") return v - @validator("cameras") - def ensure_cameras_are_not_missing_roles(cls, v: Dict[str, CameraConfig]): - for name, camera in v.items(): - assigned_roles = list( - set([r for i in camera.ffmpeg.inputs for r in i.roles]) - ) - if camera.record.enabled and not "record" in assigned_roles: - raise ValueError( - f"Camera {name} has record enabled, but record is not assigned to an input." - ) - - if camera.rtmp.enabled and not "rtmp" in assigned_roles: - raise ValueError( - f"Camera {name} has rtmp enabled, but rtmp is not assigned to an input." - ) - return v - @classmethod def parse_file(cls, config_file): with open(config_file) as f: diff --git a/frigate/test/test_config.py b/frigate/test/test_config.py index 523291cf87..92b30d542b 100644 --- a/frigate/test/test_config.py +++ b/frigate/test/test_config.py @@ -702,7 +702,11 @@ def test_fails_on_invalid_role(self): "inputs": [ { "path": "rtsp://10.0.0.1:554/video", - "roles": ["detect", "clips"], + "roles": ["detect"], + }, + { + "path": "rtsp://10.0.0.1:554/video2", + "roles": ["clips"], }, ] }, @@ -717,6 +721,37 @@ def test_fails_on_invalid_role(self): self.assertRaises(ValidationError, lambda: FrigateConfig(**config)) + def test_fails_on_missing_role(self): + + config = { + "mqtt": {"host": "mqtt"}, + "cameras": { + "back": { + "ffmpeg": { + "inputs": [ + { + "path": "rtsp://10.0.0.1:554/video", + "roles": ["detect"], + }, + { + "path": "rtsp://10.0.0.1:554/video2", + "roles": ["record"], + }, + ] + }, + "detect": { + "height": 1080, + "width": 1920, + "fps": 5, + }, + "rtmp": {"enabled": True}, + } + }, + } + + frigate_config = FrigateConfig(**config) + self.assertRaises(ValueError, lambda: frigate_config.runtime_config) + def test_global_detect(self): config = { @@ -958,6 +993,34 @@ def test_global_rtmp_merge(self): runtime_config = frigate_config.runtime_config assert runtime_config.cameras["back"].rtmp.enabled + def test_global_rtmp_default(self): + + config = { + "mqtt": {"host": "mqtt"}, + "rtmp": {"enabled": False}, + "cameras": { + "back": { + "ffmpeg": { + "inputs": [ + { + "path": "rtsp://10.0.0.1:554/video", + "roles": ["detect"], + }, + { + "path": "rtsp://10.0.0.1:554/video2", + "roles": ["record"], + }, + ] + }, + } + }, + } + frigate_config = FrigateConfig(**config) + assert config == frigate_config.dict(exclude_unset=True) + + runtime_config = frigate_config.runtime_config + assert not runtime_config.cameras["back"].rtmp.enabled + def test_global_live(self): config = {