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 e53dac419..8c4ffbc61 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 @@ -9,6 +9,7 @@ do_image_container_artifacts() { podman_archive="${DEPLOY_DIR_IMAGE}/${PODMAN_OUTPUT_NAME}" template_dir="${CONTAINER_ARTIFACT_TEMPLATE_DIR}" default_template_dir="${CONTAINER_DEFAULT_ARTIFACT_TEMPLATE_DIR}" + generator_script="${THISDIR}/../../scripts/generate-dcp.py" image_prefix="${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}" workdir="$(mktemp -d)" trap 'rm -rf "${workdir}"' EXIT @@ -25,25 +26,6 @@ do_image_container_artifacts() { bbfatal "Expected Podman archive not found: ${podman_archive}" fi - copy_template_files() { - artifact_dir="$1" - - if [ -z "${template_dir}" ]; then - return 0 - fi - if [ ! -d "${template_dir}" ]; then - bbfatal "CONTAINER_ARTIFACT_TEMPLATE_DIR does not exist: ${template_dir}" - fi - - if [ -d "${template_dir}/metadata" ]; then - cp -a "${template_dir}/metadata" "${artifact_dir}/metadata" - fi - } - - json_escape() { - printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g' - } - compose_podman_create_args() { base_args="$1" @@ -60,124 +42,92 @@ do_image_container_artifacts() { printf '%s' "${base_args}" } - write_manifest() { - artifact_dir="$1" - runtime="$2" - artifact_type="$3" - payload_name="$4" - digest="$5" - size_bytes="$6" - created_at="$7" - create_args="$8" - build_id="$9" - - package_id_esc="$(json_escape "${CONTAINER_PACKAGE_ID}")" - version_esc="$(json_escape "${CONTAINER_ARTIFACT_VERSION}")" - create_args_esc="$(json_escape "${create_args}")" - fw_versions_esc="$(json_escape "${CONTAINER_FIRMWARE_VERSIONS}")" - description_esc="$(json_escape "${CONTAINER_ARTIFACT_DESCRIPTION}")" - build_id_esc="$(json_escape "${build_id}")" - autostart_value="$(printf '%s' "${CONTAINER_AUTOSTART}" | tr '[:upper:]' '[:lower:]')" - monitor_value="$(printf '%s' "${CONTAINER_MONITOR}" | tr '[:upper:]' '[:lower:]')" - restart_enabled_value="$(printf '%s' "${CONTAINER_RESTART_ENABLED}" | tr '[:upper:]' '[:lower:]')" - - printf '%s\n' \ - '{' \ - " \"package_id\": \"${package_id_esc}\"," \ - " \"version\": \"${version_esc}\"," \ - " \"runtime\": \"${runtime}\"," \ - " \"artifact_type\": \"${artifact_type}\"," \ - > "${artifact_dir}/manifest.json" - - if [ -n "${create_args}" ]; then - printf '%s\n' " \"create_args\": \"${create_args_esc}\"," >> "${artifact_dir}/manifest.json" - fi - - printf '%s\n' \ - ' "registration_defaults": {' \ - " \"autostart\": ${autostart_value}," \ - " \"monitor\": ${monitor_value}," \ - ' "restart": {' \ - " \"enabled\": ${restart_enabled_value}," \ - " \"max_retries\": ${CONTAINER_RESTART_MAX_RETRIES}," \ - " \"window\": ${CONTAINER_RESTART_WINDOW}," \ - " \"retry_delay\": ${CONTAINER_RESTART_RETRY_DELAY}" \ - ' }' \ - ' },' \ - >> "${artifact_dir}/manifest.json" - - printf '%s\n' \ - " \"created_at\": \"${created_at}\"," \ - " \"digest\": \"sha256:${digest}\"," \ - " \"device_types\": ${CONTAINER_DEVICE_TYPES_JSON}," \ - " \"firmware_versions\": \"${fw_versions_esc}\"," \ - " \"size_bytes\": ${size_bytes}," \ - " \"build_id\": \"${build_id_esc}\"," \ - " \"description\": \"${description_esc}\"," \ - " \"labels\": ${CONTAINER_ARTIFACT_LABELS_JSON}" \ - '}' \ - >> "${artifact_dir}/manifest.json" + write_input_manifest() { + runtime="$1" + manifest_path="$2" + create_args="$3" + build_id="$4" + PACKAGE_ID="${CONTAINER_PACKAGE_ID}" \ + VERSION="${CONTAINER_ARTIFACT_VERSION}" \ + RUNTIME="${runtime}" \ + CREATE_ARGS="${create_args}" \ + AUTOSTART="${CONTAINER_AUTOSTART}" \ + MONITOR="${CONTAINER_MONITOR}" \ + RESTART_ENABLED="${CONTAINER_RESTART_ENABLED}" \ + RESTART_MAX_RETRIES="${CONTAINER_RESTART_MAX_RETRIES}" \ + RESTART_WINDOW="${CONTAINER_RESTART_WINDOW}" \ + RESTART_RETRY_DELAY="${CONTAINER_RESTART_RETRY_DELAY}" \ + DEVICE_TYPES_JSON="${CONTAINER_DEVICE_TYPES_JSON}" \ + FIRMWARE_VERSIONS="${CONTAINER_FIRMWARE_VERSIONS}" \ + BUILD_ID="${build_id}" \ + DESCRIPTION="${CONTAINER_ARTIFACT_DESCRIPTION}" \ + 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"), "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")' \ + "${manifest_path}" } create_artifact_bundle() { runtime="$1" src_payload="$2" - payload_name="$3" - output_name="$4" - mode="$5" - artifact_type="$6" - create_args="$7" - bundle_dir="${workdir}/bundle-${runtime}" - artifact_dir="${bundle_dir}" + create_args="$3" + manifest_path="${workdir}/${runtime}-manifest.json" + readme_arg="" + changelog_arg="" + primary_device_type="$(DEVICE_TYPES_JSON="${CONTAINER_DEVICE_TYPES_JSON}" python3 -c 'import json, os; data = json.loads(os.environ["DEVICE_TYPES_JSON"]); print(data[0])' 2>/dev/null)" - rm -rf "${bundle_dir}" - mkdir -p "${artifact_dir}/payload" "${artifact_dir}/checksums" - - copy_template_files "${artifact_dir}" - - if [ "${mode}" = "lxc" ]; then - lxc_unpack="${workdir}/lxc-unpack" - rm -rf "${lxc_unpack}" - mkdir -p "${lxc_unpack}" - tar -xJf "${src_payload}" -C "${lxc_unpack}" - - if [ ! -d "${lxc_unpack}/${CONTAINER_NAME}/rootfs" ] || [ ! -f "${lxc_unpack}/${CONTAINER_NAME}/config" ]; then - bbfatal "LXC bundle does not contain expected ${CONTAINER_NAME}/rootfs and ${CONTAINER_NAME}/config" - fi - - tar -C "${lxc_unpack}/${CONTAINER_NAME}" \ - -czf "${artifact_dir}/payload/${payload_name}" \ - rootfs config - else - cp "${src_payload}" "${artifact_dir}/payload/${payload_name}" - fi - - digest="$(sha256sum "${artifact_dir}/payload/${payload_name}" | awk '{print $1}')" - size_bytes="$(stat -c %s "${artifact_dir}/payload/${payload_name}")" - created_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)" if [ "${runtime}" = "podman" ]; then create_args="$(compose_podman_create_args "${create_args}")" fi + + if [ -z "${primary_device_type}" ]; then + bbfatal "Unable to determine primary device type from CONTAINER_DEVICE_TYPES_JSON=${CONTAINER_DEVICE_TYPES_JSON}" + fi + build_id="${CONTAINER_ARTIFACT_BUILD_ID}" if [ -z "${build_id}" ]; then if command -v git >/dev/null 2>&1; then build_id="$(git -C "${META_DIGI_REPO_DIR}" rev-parse HEAD 2>/dev/null || true)" fi fi - printf '%s %s\n' "${digest}" "payload/${payload_name}" > "${artifact_dir}/checksums/sha256sums.txt" - write_manifest "${artifact_dir}" "${runtime}" "${artifact_type}" "${payload_name}" "${digest}" "${size_bytes}" "${created_at}" "${create_args}" "${build_id}" - tar -C "${bundle_dir}" -czf "${DEPLOY_DIR_IMAGE}/${output_name}" . + write_input_manifest "${runtime}" "${manifest_path}" "${create_args}" "${build_id}" - if [ ! -s "${DEPLOY_DIR_IMAGE}/${output_name}" ]; then - bbfatal "Container artifact bundle not generated correctly: ${DEPLOY_DIR_IMAGE}/${output_name}" + if [ -n "${template_dir}" ] && [ ! -d "${template_dir}" ]; then + bbfatal "CONTAINER_ARTIFACT_TEMPLATE_DIR does not exist: ${template_dir}" + fi + if [ -f "${template_dir}/metadata/README.txt" ]; then + readme_arg="--readme ${template_dir}/metadata/README.txt" + fi + if [ -f "${template_dir}/metadata/changelog.txt" ]; then + changelog_arg="--changelog ${template_dir}/metadata/changelog.txt" fi - bbnote "Container ${runtime} artifact ready: ${DEPLOY_DIR_IMAGE}/${output_name}" + python3 "${generator_script}" \ + --manifest "${manifest_path}" \ + --payload "${src_payload}" \ + --output-dir "${DEPLOY_DIR_IMAGE}" \ + ${readme_arg} \ + ${changelog_arg} + + generated_output="${DEPLOY_DIR_IMAGE}/${CONTAINER_PACKAGE_ID}_artifact_${runtime}_${primary_device_type}.tar.gz" + if [ ! -s "${generated_output}" ]; then + bbfatal "Container artifact bundle not generated correctly: ${generated_output}" + fi + + bbnote "Container ${runtime} artifact ready: ${generated_output}" } - create_artifact_bundle "lxc" "${lxc_bundle}" "rootfs_and_config.tgz" "${LXC_ARTIFACT_OUTPUT_NAME}" "lxc" "lxc-tgz" "" - create_artifact_bundle "podman" "${podman_archive}" "image.tar" "${PODMAN_ARTIFACT_OUTPUT_NAME}" "podman" "podman-image-tar" "${CONTAINER_CREATE_ARGS_PODMAN}" + if [ ! -f "${generator_script}" ]; then + bbfatal "Expected DCP generator script not found: ${generator_script}" + fi + + create_artifact_bundle "lxc" "${lxc_bundle}" "" + create_artifact_bundle "podman" "${podman_archive}" "${CONTAINER_CREATE_ARGS_PODMAN}" bbnote "Removing intermediate container artifacts from this build..." rm -f "${lxc_bundle}" "${podman_archive}" 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 ff0d041d9..cd60f164e 100644 --- a/meta-digi-containers/recipes-core/images/dey-image-container.bb +++ b/meta-digi-containers/recipes-core/images/dey-image-container.bb @@ -41,7 +41,6 @@ CONTAINER_ROOTFS_OVERLAY_TARBALLS ?= "" ######################## PODMAN_TAG ?= "${CONTAINER_NAME}-tag" PODMAN_OUTPUT_NAME ?= "${CONTAINER_NAME}_podman_${MACHINE}.tar" -PODMAN_ARTIFACT_OUTPUT_NAME ?= "${CONTAINER_NAME}_artifact_podman_${MACHINE}.tar.gz" ######################## # LXC output knobs @@ -49,7 +48,6 @@ PODMAN_ARTIFACT_OUTPUT_NAME ?= "${CONTAINER_NAME}_artifact_podman_${MACHINE}.tar CONTAINERS_DIR ?= "${THISDIR}/../../containers" LXC_FOLDER ?= "/var/lib/lxc" LXC_OUTPUT_NAME ?= "${CONTAINER_NAME}_lxc_${MACHINE}.tar.xz" -LXC_ARTIFACT_OUTPUT_NAME ?= "${CONTAINER_NAME}_artifact_lxc_${MACHINE}.tar.gz" LXC_CONFIG_DIR ?= "${CONTAINER_PROFILE_DIR}/configs_lxc" LXC_CONFIG_FILE ?= "${LXC_CONFIG_DIR}/config_lxc_${MACHINE}"