Move shared config params into template
This commit is contained in:
parent
502991d026
commit
cd6d299bd3
@ -17,14 +17,7 @@
|
||||
"publish_hls_path": "./web/hls/cam1/index.m3u8",
|
||||
"publish_rtsp_port": 8555,
|
||||
"publish_rtsp_path": "/live/cam1",
|
||||
"channel_no": "cam1",
|
||||
"minio_endpoint": "http://10.0.0.49:9000",
|
||||
"minio_bucket": "myminio",
|
||||
"minio_access_key": "admin",
|
||||
"minio_secret_key": "password",
|
||||
"external_get_token_url": "http://10.0.0.49:8080/api/getToken",
|
||||
"external_put_message_url": "http://10.0.0.49:8080/api/putMessage",
|
||||
"tenant_code": "32"
|
||||
"channel_no": "cam1"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -2,6 +2,15 @@
|
||||
"name": "workshop_face_shoe_alarm",
|
||||
"description": "Full 1080p workshop pipeline with face detection/recognition, person tracking, shoe detection, OSD, publishing, alarms, snapshots, clips, and external API upload.",
|
||||
"source": "configs/full_pipeline_1080p_test_alarm.json",
|
||||
"params": {
|
||||
"minio_endpoint": "http://10.0.0.49:9000",
|
||||
"minio_bucket": "myminio",
|
||||
"minio_access_key": "admin",
|
||||
"minio_secret_key": "password",
|
||||
"external_get_token_url": "http://10.0.0.49:8080/api/getToken",
|
||||
"external_put_message_url": "http://10.0.0.49:8080/api/putMessage",
|
||||
"tenant_code": "32"
|
||||
},
|
||||
"template": {
|
||||
"executor": {
|
||||
"batch_size": 2,
|
||||
|
||||
@ -39,6 +39,14 @@ class RenderConfigTest(unittest.TestCase):
|
||||
self.assertIn("publish_rtsp_port", params)
|
||||
self.assertIn("publish_rtsp_path", params)
|
||||
self.assertIn("channel_no", params)
|
||||
self.assertNotIn("minio_endpoint", params)
|
||||
self.assertNotIn("external_get_token_url", params)
|
||||
self.assertNotIn("tenant_code", params)
|
||||
|
||||
shared_params = template["params"]
|
||||
self.assertEqual(shared_params["minio_endpoint"], "http://10.0.0.49:9000")
|
||||
self.assertEqual(shared_params["external_get_token_url"], "http://10.0.0.49:8080/api/getToken")
|
||||
self.assertEqual(shared_params["tenant_code"], "32")
|
||||
|
||||
def test_render_profile_no_longer_requires_face_gallery_path(self):
|
||||
profile_path = REPO_ROOT / "configs" / "profiles" / "local_3588_test.json"
|
||||
@ -62,6 +70,7 @@ class RenderConfigTest(unittest.TestCase):
|
||||
module = load_module()
|
||||
template = {
|
||||
"name": "pipeline",
|
||||
"params": {"tenant_code": "32"},
|
||||
"template": {
|
||||
"executor": {"batch_size": 2},
|
||||
"nodes": [
|
||||
@ -94,7 +103,7 @@ class RenderConfigTest(unittest.TestCase):
|
||||
|
||||
root = {
|
||||
"templates": {module.template_name(template, pathlib.Path("x.json")): module.template_body(template)},
|
||||
"instances": module.profile_instances(profile, "pipeline"),
|
||||
"instances": module.merge_template_params(module.profile_instances(profile, "pipeline"), module.template_params(template)),
|
||||
"queue": profile["queue"],
|
||||
}
|
||||
rendered = module.apply_overlay(root, overlay)
|
||||
@ -102,10 +111,55 @@ class RenderConfigTest(unittest.TestCase):
|
||||
self.assertEqual(rendered["queue"]["size"], 8)
|
||||
self.assertEqual(rendered["instances"][0]["template"], "pipeline")
|
||||
self.assertEqual(rendered["instances"][0]["params"]["rtsp_url"], "rtsp://example/cam1")
|
||||
self.assertEqual(rendered["instances"][0]["params"]["tenant_code"], "32")
|
||||
node_override = rendered["instances"][0]["override"]["nodes"]["face_recog"]
|
||||
self.assertTrue(node_override["debug"]["enabled"])
|
||||
self.assertTrue(node_override["debug"]["log_matches"])
|
||||
|
||||
def test_template_params_fill_placeholders_without_staying_in_profile(self):
|
||||
module = load_module()
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
tmp = pathlib.Path(tmp_dir)
|
||||
template_path = tmp / "template.json"
|
||||
profile_path = tmp / "profile.json"
|
||||
|
||||
template_path.write_text(
|
||||
"""
|
||||
{
|
||||
"name": "pipeline",
|
||||
"params": {
|
||||
"minio_endpoint": "http://10.0.0.49:9000",
|
||||
"tenant_code": "32"
|
||||
},
|
||||
"template": {
|
||||
"nodes": [{"id": "alarm", "type": "alarm", "endpoint": "${minio_endpoint}", "tenant": "${tenant_code}"}],
|
||||
"edges": []
|
||||
}
|
||||
}
|
||||
""",
|
||||
encoding="utf-8",
|
||||
)
|
||||
profile_path.write_text(
|
||||
"""
|
||||
{
|
||||
"name": "local_3588_test",
|
||||
"instances": [
|
||||
{
|
||||
"name": "cam1",
|
||||
"params": {"rtsp_url": "rtsp://example/cam1"}
|
||||
}
|
||||
]
|
||||
}
|
||||
""",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
rendered = module.render(template_path, profile_path, [])
|
||||
params = rendered["instances"][0]["params"]
|
||||
self.assertEqual(params["minio_endpoint"], "http://10.0.0.49:9000")
|
||||
self.assertEqual(params["tenant_code"], "32")
|
||||
self.assertEqual(params["rtsp_url"], "rtsp://example/cam1")
|
||||
|
||||
def test_render_applies_multiple_overlays_in_order(self):
|
||||
module = load_module()
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
|
||||
@ -50,6 +50,15 @@ def template_body(template_doc: JsonObject) -> JsonObject:
|
||||
return {key: copy.deepcopy(value) for key, value in body.items() if key in allowed}
|
||||
|
||||
|
||||
def template_params(template_doc: JsonObject) -> JsonObject:
|
||||
params = template_doc.get("params", {})
|
||||
if params is None:
|
||||
return {}
|
||||
if not isinstance(params, dict):
|
||||
raise ValueError("template params must be a JSON object")
|
||||
return copy.deepcopy(params)
|
||||
|
||||
|
||||
def profile_instances(profile: JsonObject, tpl_name: str) -> list[JsonObject]:
|
||||
if "instances" in profile:
|
||||
instances = profile["instances"]
|
||||
@ -77,6 +86,22 @@ def profile_instances(profile: JsonObject, tpl_name: str) -> list[JsonObject]:
|
||||
]
|
||||
|
||||
|
||||
def merge_template_params(instances: list[JsonObject], shared_params: JsonObject) -> list[JsonObject]:
|
||||
if not shared_params:
|
||||
return instances
|
||||
out: list[JsonObject] = []
|
||||
for item in instances:
|
||||
inst = copy.deepcopy(item)
|
||||
params = inst.get("params", {})
|
||||
if params is None:
|
||||
params = {}
|
||||
if not isinstance(params, dict):
|
||||
raise ValueError("instance params must be a JSON object")
|
||||
inst["params"] = deep_merge(shared_params, params)
|
||||
out.append(inst)
|
||||
return out
|
||||
|
||||
|
||||
def merge_instance_patch(instance: JsonObject, patch: JsonObject) -> JsonObject:
|
||||
merged = copy.deepcopy(instance)
|
||||
if "params" in patch:
|
||||
@ -137,7 +162,7 @@ def render(
|
||||
|
||||
root: JsonObject = {
|
||||
"templates": {tpl_name: template_body(template_doc)},
|
||||
"instances": profile_instances(profile, tpl_name),
|
||||
"instances": merge_template_params(profile_instances(profile, tpl_name), template_params(template_doc)),
|
||||
}
|
||||
for key in ("global", "queue"):
|
||||
if key in profile:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user