From 3b93a2c2e121c3c67cb52d64b1d826b42a65bdbd Mon Sep 17 00:00:00 2001 From: Isaac Hermida Date: Wed, 22 Apr 2026 13:52:20 +0200 Subject: [PATCH] containers: preserve friendly names in generated DCP manifests Propagate an optional manifest name field through the DCP generator, so the container manager can publish friendly names DRM. Signed-off-by: Isaac Hermida --- meta-digi-containers/README.md | 16 ++++++++++++++++ meta-digi-containers/examples/manifest-lxc.json | 2 ++ .../examples/manifest-podman.json | 2 ++ .../images/dey-image-container-artifact.inc | 4 +++- .../recipes-core/images/dey-image-container.bb | 4 ++++ meta-digi-containers/scripts/generate-dcp.py | 14 ++++++++++++++ 6 files changed, 41 insertions(+), 1 deletion(-) diff --git a/meta-digi-containers/README.md b/meta-digi-containers/README.md index e9bbd698f..d128644ae 100644 --- a/meta-digi-containers/README.md +++ b/meta-digi-containers/README.md @@ -94,6 +94,12 @@ This generates a bundle named like: - `./flutter-demo-_artifact_podman_ccmp25-dvk.tar.gz` +In those manifests: + +- `package_id` is the base identifier used to derive the final unique DCP package ID. +- `name` is the stable logical container name stored on the target. +- `friendly_name` is the user-facing label shown by DRM and the manager output when available. + ## Digi Remote Manager metrics support `dey-image-container-manager` includes `cc-container-mng` that has the capability to @@ -128,6 +134,12 @@ manager: Generated manifests and target-side effective configuration use the explicit metric list. +`dey-image-container-manager` also overrides the manager persistent base path +through `CC_CONTAINER_PATH`, which defaults to `${ROOT_HOME}/cc-container` in +the Digi platform defaults. This makes the effective target paths live under +`/root/cc-container` in DEY images, while the upstream `cc-container-mng` +project keeps `/opt/cc-container` as its built-in default. + ## Layer Scope Main recipes: @@ -283,6 +295,8 @@ Supported placeholders in LXC config fragments: The artifact manifest is generated automatically and includes: - `package_id` +- `name` [stable logical container name] +- `friendly_name` [optional user-facing display name] - `version` - `runtime` - `artifact_type` @@ -303,7 +317,9 @@ The artifact manifest is generated automatically and includes: Relevant variables: +- `CONTAINER_NAME` - `CONTAINER_PACKAGE_ID` +- `CONTAINER_FRIENDLY_NAME` - `CONTAINER_ARTIFACT_VERSION` - `CONTAINER_CREATE_ARGS_PODMAN` - `CONTAINER_DRM_ENABLED` diff --git a/meta-digi-containers/examples/manifest-lxc.json b/meta-digi-containers/examples/manifest-lxc.json index 472b17b60..c2ea293dd 100644 --- a/meta-digi-containers/examples/manifest-lxc.json +++ b/meta-digi-containers/examples/manifest-lxc.json @@ -1,5 +1,7 @@ { "package_id": "flutter-demo", + "name": "flutter-demo", + "friendly_name": "Flutter Demo", "version": "1.0", "runtime": "lxc", "registration_defaults": { diff --git a/meta-digi-containers/examples/manifest-podman.json b/meta-digi-containers/examples/manifest-podman.json index d312c987d..7081a0bb7 100644 --- a/meta-digi-containers/examples/manifest-podman.json +++ b/meta-digi-containers/examples/manifest-podman.json @@ -1,5 +1,7 @@ { "package_id": "flutter-demo", + "name": "flutter-demo", + "friendly_name": "Flutter Demo", "version": "1.0", "runtime": "podman", "create_args": "--privileged --network none --tmpfs /dev/shm:rw,nosuid,nodev,mode=1777 --device /dev/dri --device /dev/input --device /dev/galcore --device /dev/tty --device /dev/tty0 --device /dev/tty1 --device /dev/tty7 --volume /run/udev:/run/udev:ro --tty --entrypoint '[\"/usr/bin/docker-init\",\"/start-flutter-demo.sh\"]'", diff --git a/meta-digi-containers/recipes-core/images/dey-image-container-artifact.inc b/meta-digi-containers/recipes-core/images/dey-image-container-artifact.inc index a4f711b13..ffc1c2e7e 100644 --- a/meta-digi-containers/recipes-core/images/dey-image-container-artifact.inc +++ b/meta-digi-containers/recipes-core/images/dey-image-container-artifact.inc @@ -48,6 +48,8 @@ do_image_container_artifacts() { create_args="$3" build_id="$4" PACKAGE_ID="${CONTAINER_PACKAGE_ID}" \ + NAME="${CONTAINER_NAME}" \ + FRIENDLY_NAME="${CONTAINER_FRIENDLY_NAME}" \ VERSION="${CONTAINER_ARTIFACT_VERSION}" \ RUNTIME="${runtime}" \ CREATE_ARGS="${create_args}" \ @@ -67,7 +69,7 @@ do_image_container_artifacts() { LABELS_JSON="${CONTAINER_ARTIFACT_LABELS_JSON}" \ python3 -c 'import json, os, sys; \ parse_bool = lambda name: os.environ[name].strip().lower() == "true"; \ -payload = {"package_id": os.environ["PACKAGE_ID"], "version": os.environ["VERSION"], "runtime": os.environ["RUNTIME"], "registration_defaults": {"autostart": parse_bool("AUTOSTART"), "monitor": parse_bool("MONITOR"), "drm": {"enabled": parse_bool("DRM_ENABLED"), "stats_sample_interval_s": int(os.environ["DRM_STATS_SAMPLE_INTERVAL"]), "stats_list_of_metrics": json.loads(os.environ["DRM_STATS_LIST_OF_METRICS"])}, "restart": {"enabled": parse_bool("RESTART_ENABLED"), "max_retries": int(os.environ["RESTART_MAX_RETRIES"]), "window": int(os.environ["RESTART_WINDOW"]), "retry_delay": int(os.environ["RESTART_RETRY_DELAY"]) } }, "device_types": json.loads(os.environ["DEVICE_TYPES_JSON"]), "firmware_versions": os.environ["FIRMWARE_VERSIONS"], "build_id": os.environ["BUILD_ID"], "description": os.environ["DESCRIPTION"], "labels": json.loads(os.environ["LABELS_JSON"])}; \ +payload = {"package_id": os.environ["PACKAGE_ID"], "name": os.environ["NAME"], "friendly_name": os.environ["FRIENDLY_NAME"], "version": os.environ["VERSION"], "runtime": os.environ["RUNTIME"], "registration_defaults": {"autostart": parse_bool("AUTOSTART"), "monitor": parse_bool("MONITOR"), "drm": {"enabled": parse_bool("DRM_ENABLED"), "stats_sample_interval_s": int(os.environ["DRM_STATS_SAMPLE_INTERVAL"]), "stats_list_of_metrics": json.loads(os.environ["DRM_STATS_LIST_OF_METRICS"])}, "restart": {"enabled": parse_bool("RESTART_ENABLED"), "max_retries": int(os.environ["RESTART_MAX_RETRIES"]), "window": int(os.environ["RESTART_WINDOW"]), "retry_delay": int(os.environ["RESTART_RETRY_DELAY"]) } }, "device_types": json.loads(os.environ["DEVICE_TYPES_JSON"]), "firmware_versions": os.environ["FIRMWARE_VERSIONS"], "build_id": os.environ["BUILD_ID"], "description": os.environ["DESCRIPTION"], "labels": json.loads(os.environ["LABELS_JSON"])}; \ create_args = os.environ["CREATE_ARGS"].strip(); \ payload.update({"create_args": create_args} if create_args else {}); \ open(sys.argv[1], "w", encoding="utf-8").write(json.dumps(payload, indent=2) + "\n")' \ diff --git a/meta-digi-containers/recipes-core/images/dey-image-container.bb b/meta-digi-containers/recipes-core/images/dey-image-container.bb index b330db5c7..e10e19b59 100644 --- a/meta-digi-containers/recipes-core/images/dey-image-container.bb +++ b/meta-digi-containers/recipes-core/images/dey-image-container.bb @@ -58,6 +58,7 @@ CONTAINER_ARTIFACT_TEMPLATE_DIR ?= "" CONTAINER_DEFAULT_ARTIFACT_TEMPLATE_DIR ?= "${CONTAINER_PROFILE_DIR}/artifact" META_DIGI_REPO_DIR ?= "${THISDIR}/../../.." CONTAINER_PACKAGE_ID ?= "${CONTAINER_NAME}" +CONTAINER_FRIENDLY_NAME ?= "${CONTAINER_NAME}" CONTAINER_ARTIFACT_VERSION ?= "${PV}" CONTAINER_CREATE_ARGS ?= "" CONTAINER_CREATE_ARGS_PODMAN ?= "${CONTAINER_CREATE_ARGS}" @@ -107,6 +108,7 @@ IMAGE_INSTALL = " \ # Container type customizations LVGL ######################## CONTAINER_INIT_SCRIPT:container-lvgl = "/start-lvgl-demo.sh" +CONTAINER_FRIENDLY_NAME:container-lvgl = "LVGL Demo" CONTAINER_CREATE_ARGS_PODMAN:container-lvgl:ccmp25 = " \ --privileged \ --network none \ @@ -132,6 +134,7 @@ DISTRO_FEATURES:remove:container-lvgl = " wayland" # Container type customizations webkit ######################## CONTAINER_INIT_SCRIPT:container-webkit = "/start-webkit-demo.sh" +CONTAINER_FRIENDLY_NAME:container-webkit = "WebKit Demo" CONTAINER_CREATE_ARGS_PODMAN:container-webkit:ccmp25 = " \ --privileged \ --network host \ @@ -217,6 +220,7 @@ IMAGE_INSTALL:append:container-webkit:ccmp25 = " \ # Container type customizations flutter ######################## CONTAINER_INIT_SCRIPT:container-flutter = "/start-flutter-demo.sh" +CONTAINER_FRIENDLY_NAME:container-flutter = "Flutter Demo" CONTAINER_CREATE_ARGS_PODMAN:container-flutter:ccmp25 = " \ --privileged \ --network none \ diff --git a/meta-digi-containers/scripts/generate-dcp.py b/meta-digi-containers/scripts/generate-dcp.py index 6bf277fd6..327ee6df8 100755 --- a/meta-digi-containers/scripts/generate-dcp.py +++ b/meta-digi-containers/scripts/generate-dcp.py @@ -175,9 +175,21 @@ def validate_manifest(data: dict) -> dict: description = data.get("description", "") if description is not None and not isinstance(description, str): fail("invalid manifest: description must be a string") + name = data.get("name") + if name is not None: + if not isinstance(name, str) or not name.strip(): + fail("invalid manifest: name must be a non-empty string") + name = name.strip() + friendly_name = data.get("friendly_name") + if friendly_name is not None: + if not isinstance(friendly_name, str) or not friendly_name.strip(): + fail("invalid manifest: friendly_name must be a non-empty string") + friendly_name = friendly_name.strip() validated = { "package_id": package_id, + "name": name, + "friendly_name": friendly_name, "version": version, "runtime": runtime, "create_args": create_args, @@ -317,6 +329,8 @@ def build_final_manifest( ) -> dict: output = { "package_id": package_id, + "name": base["name"], + "friendly_name": base["friendly_name"], "version": base["version"], "runtime": base["runtime"], "artifact_type": artifact_type,