containers: derive DCP package id from logical name
Generate the package if from logical name when it is not specified in the json. If case it is set, use it. Signed-off-by: Isaac Hermida <isaac.hermida@digi.com>
This commit is contained in:
parent
3b93a2c2e1
commit
267f78ac9d
|
|
@ -68,8 +68,10 @@ The script generates exactly one runtime artifact per execution.
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
- `--output-dir` is optional. If omitted, the script writes the DCP to the current directory.
|
- `--output-dir` is optional. If omitted, the script writes the DCP to the current directory.
|
||||||
- The generator appends a unique suffix to the input `package_id` using the
|
- If the input manifest omits `package_id`, the generator derives the final
|
||||||
`created_at` timestamp encoded in base36 milliseconds.
|
`package_id` from `name` and appends a unique suffix using the `created_at`
|
||||||
|
timestamp encoded in base36 milliseconds.
|
||||||
|
- If the input manifest provides `package_id`, that value is kept unchanged.
|
||||||
- The output file name is always derived from the generated package ID and
|
- The output file name is always derived from the generated package ID and
|
||||||
manifest fields as:
|
manifest fields as:
|
||||||
- `<generated_package_id>_artifact_<runtime>_<device_types[0]>.tar.gz`
|
- `<generated_package_id>_artifact_<runtime>_<device_types[0]>.tar.gz`
|
||||||
|
|
@ -96,9 +98,10 @@ This generates a bundle named like:
|
||||||
|
|
||||||
In those manifests:
|
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.
|
- `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.
|
- `friendly_name` is the user-facing label shown by DRM and the manager output when available.
|
||||||
|
- the final `package_id` is generated automatically from `name` unless the
|
||||||
|
input manifest provides an explicit `package_id`
|
||||||
|
|
||||||
## Digi Remote Manager metrics support
|
## Digi Remote Manager metrics support
|
||||||
|
|
||||||
|
|
@ -200,16 +203,18 @@ Outputs are generated in:
|
||||||
|
|
||||||
Final outputs:
|
Final outputs:
|
||||||
|
|
||||||
- `${CONTAINER_PACKAGE_ID}-<base36_created_at_ms>_artifact_podman_<device_types[0]>.tar.gz`
|
- `${CONTAINER_NAME}-<base36_created_at_ms>_artifact_podman_<device_types[0]>.tar.gz`
|
||||||
- `${CONTAINER_PACKAGE_ID}-<base36_created_at_ms>_artifact_lxc_<device_types[0]>.tar.gz`
|
- `${CONTAINER_NAME}-<base36_created_at_ms>_artifact_lxc_<device_types[0]>.tar.gz`
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
- The generator script appends a base36-encoded millisecond timestamp suffix to
|
- The generator script derives `package_id` from the input `name` only when the
|
||||||
the input `package_id`, stores that generated value in the final
|
manifest does not provide one explicitly. In that default case it appends a
|
||||||
`manifest.json`, and uses it in the DCP file name.
|
base36-encoded millisecond timestamp suffix, stores the generated `package_id`
|
||||||
- In Yocto builds, `CONTAINER_PACKAGE_ID` defaults to `${CONTAINER_NAME}` before
|
in the final `manifest.json`, and uses it in the DCP file name.
|
||||||
the generator adds the unique suffix.
|
- In Yocto builds, `dey-image-container` does not set `package_id`, so the
|
||||||
|
generated value always starts from `${CONTAINER_NAME}` before the generator
|
||||||
|
adds the unique suffix.
|
||||||
|
|
||||||
Intermediate outputs generated during the build (LXC bundle, Podman archive, OCI/rootfs files)
|
Intermediate outputs generated during the build (LXC bundle, Podman archive, OCI/rootfs files)
|
||||||
are removed automatically at the end of artifact creation.
|
are removed automatically at the end of artifact creation.
|
||||||
|
|
@ -318,7 +323,6 @@ The artifact manifest is generated automatically and includes:
|
||||||
Relevant variables:
|
Relevant variables:
|
||||||
|
|
||||||
- `CONTAINER_NAME`
|
- `CONTAINER_NAME`
|
||||||
- `CONTAINER_PACKAGE_ID`
|
|
||||||
- `CONTAINER_FRIENDLY_NAME`
|
- `CONTAINER_FRIENDLY_NAME`
|
||||||
- `CONTAINER_ARTIFACT_VERSION`
|
- `CONTAINER_ARTIFACT_VERSION`
|
||||||
- `CONTAINER_CREATE_ARGS_PODMAN`
|
- `CONTAINER_CREATE_ARGS_PODMAN`
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
{
|
{
|
||||||
"package_id": "flutter-demo",
|
|
||||||
"name": "flutter-demo",
|
"name": "flutter-demo",
|
||||||
"friendly_name": "Flutter Demo",
|
"friendly_name": "Flutter Demo",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
{
|
{
|
||||||
"package_id": "flutter-demo",
|
|
||||||
"name": "flutter-demo",
|
"name": "flutter-demo",
|
||||||
"friendly_name": "Flutter Demo",
|
"friendly_name": "Flutter Demo",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@ do_image_container_artifacts() {
|
||||||
manifest_path="$2"
|
manifest_path="$2"
|
||||||
create_args="$3"
|
create_args="$3"
|
||||||
build_id="$4"
|
build_id="$4"
|
||||||
PACKAGE_ID="${CONTAINER_PACKAGE_ID}" \
|
|
||||||
NAME="${CONTAINER_NAME}" \
|
NAME="${CONTAINER_NAME}" \
|
||||||
FRIENDLY_NAME="${CONTAINER_FRIENDLY_NAME}" \
|
FRIENDLY_NAME="${CONTAINER_FRIENDLY_NAME}" \
|
||||||
VERSION="${CONTAINER_ARTIFACT_VERSION}" \
|
VERSION="${CONTAINER_ARTIFACT_VERSION}" \
|
||||||
|
|
@ -69,7 +68,7 @@ do_image_container_artifacts() {
|
||||||
LABELS_JSON="${CONTAINER_ARTIFACT_LABELS_JSON}" \
|
LABELS_JSON="${CONTAINER_ARTIFACT_LABELS_JSON}" \
|
||||||
python3 -c 'import json, os, sys; \
|
python3 -c 'import json, os, sys; \
|
||||||
parse_bool = lambda name: os.environ[name].strip().lower() == "true"; \
|
parse_bool = lambda name: os.environ[name].strip().lower() == "true"; \
|
||||||
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"])}; \
|
payload = {"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(); \
|
create_args = os.environ["CREATE_ARGS"].strip(); \
|
||||||
payload.update({"create_args": create_args} if create_args else {}); \
|
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")' \
|
open(sys.argv[1], "w", encoding="utf-8").write(json.dumps(payload, indent=2) + "\n")' \
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,6 @@ LXC_CONFIG_FILE ?= "${LXC_CONFIG_DIR}/config_lxc_${MACHINE}"
|
||||||
CONTAINER_ARTIFACT_TEMPLATE_DIR ?= ""
|
CONTAINER_ARTIFACT_TEMPLATE_DIR ?= ""
|
||||||
CONTAINER_DEFAULT_ARTIFACT_TEMPLATE_DIR ?= "${CONTAINER_PROFILE_DIR}/artifact"
|
CONTAINER_DEFAULT_ARTIFACT_TEMPLATE_DIR ?= "${CONTAINER_PROFILE_DIR}/artifact"
|
||||||
META_DIGI_REPO_DIR ?= "${THISDIR}/../../.."
|
META_DIGI_REPO_DIR ?= "${THISDIR}/../../.."
|
||||||
CONTAINER_PACKAGE_ID ?= "${CONTAINER_NAME}"
|
|
||||||
CONTAINER_FRIENDLY_NAME ?= "${CONTAINER_NAME}"
|
CONTAINER_FRIENDLY_NAME ?= "${CONTAINER_NAME}"
|
||||||
CONTAINER_ARTIFACT_VERSION ?= "${PV}"
|
CONTAINER_ARTIFACT_VERSION ?= "${PV}"
|
||||||
CONTAINER_CREATE_ARGS ?= ""
|
CONTAINER_CREATE_ARGS ?= ""
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,8 @@ def format_created_at(timestamp: datetime) -> str:
|
||||||
return timestamp.astimezone(timezone.utc).isoformat(timespec="milliseconds").replace("+00:00", "Z")
|
return timestamp.astimezone(timezone.utc).isoformat(timespec="milliseconds").replace("+00:00", "Z")
|
||||||
|
|
||||||
|
|
||||||
def build_generated_package_id(base_package_id: str, *, created_at_ms: int) -> str:
|
def build_generated_package_id(base_name: str, *, created_at_ms: int) -> str:
|
||||||
return f"{base_package_id}-{to_base36(created_at_ms)}"
|
return f"{base_name}-{to_base36(created_at_ms)}"
|
||||||
|
|
||||||
|
|
||||||
def load_manifest(path: Path) -> dict:
|
def load_manifest(path: Path) -> dict:
|
||||||
|
|
@ -139,7 +139,11 @@ def normalize_drm_stats_metrics(metrics: list[str]) -> list[str]:
|
||||||
|
|
||||||
|
|
||||||
def validate_manifest(data: dict) -> dict:
|
def validate_manifest(data: dict) -> dict:
|
||||||
package_id = validate_string(data, "package_id", path="manifest")
|
package_id = data.get("package_id")
|
||||||
|
if package_id is not None:
|
||||||
|
if not isinstance(package_id, str) or not package_id.strip():
|
||||||
|
fail("invalid manifest: package_id must be a non-empty string")
|
||||||
|
package_id = package_id.strip()
|
||||||
version = validate_string(data, "version", path="manifest")
|
version = validate_string(data, "version", path="manifest")
|
||||||
runtime = validate_string(data, "runtime", path="manifest")
|
runtime = validate_string(data, "runtime", path="manifest")
|
||||||
if runtime not in {"lxc", "podman"}:
|
if runtime not in {"lxc", "podman"}:
|
||||||
|
|
@ -175,11 +179,7 @@ def validate_manifest(data: dict) -> dict:
|
||||||
description = data.get("description", "")
|
description = data.get("description", "")
|
||||||
if description is not None and not isinstance(description, str):
|
if description is not None and not isinstance(description, str):
|
||||||
fail("invalid manifest: description must be a string")
|
fail("invalid manifest: description must be a string")
|
||||||
name = data.get("name")
|
name = validate_string(data, "name", path="manifest")
|
||||||
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")
|
friendly_name = data.get("friendly_name")
|
||||||
if friendly_name is not None:
|
if friendly_name is not None:
|
||||||
if not isinstance(friendly_name, str) or not friendly_name.strip():
|
if not isinstance(friendly_name, str) or not friendly_name.strip():
|
||||||
|
|
@ -394,10 +394,14 @@ def main() -> int:
|
||||||
created_at_dt = datetime.now(timezone.utc)
|
created_at_dt = datetime.now(timezone.utc)
|
||||||
created_at_ms = int(created_at_dt.timestamp() * 1000)
|
created_at_ms = int(created_at_dt.timestamp() * 1000)
|
||||||
created_at = format_created_at(created_at_dt)
|
created_at = format_created_at(created_at_dt)
|
||||||
generated_package_id = build_generated_package_id(
|
generated_package_id = (
|
||||||
manifest["package_id"],
|
manifest["package_id"]
|
||||||
|
if manifest["package_id"]
|
||||||
|
else build_generated_package_id(
|
||||||
|
manifest["name"],
|
||||||
created_at_ms=created_at_ms,
|
created_at_ms=created_at_ms,
|
||||||
)
|
)
|
||||||
|
)
|
||||||
output_name = build_output_name(
|
output_name = build_output_name(
|
||||||
package_id=generated_package_id,
|
package_id=generated_package_id,
|
||||||
runtime=manifest["runtime"],
|
runtime=manifest["runtime"],
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue