From e13ad3d8f9e4649b2c2063e05c9ec17e16735a72 Mon Sep 17 00:00:00 2001 From: nearxos Date: Mon, 23 Feb 2026 10:14:49 +0200 Subject: [PATCH] Add image name input to cloud-init build process and update handling Enhance the dashboard UI by introducing an optional input field for the image name in the cloud-init build form. Update the API to process the image name, ensuring it is sanitized and included in the build request. Modify the build script to utilize the provided image name, allowing for customized output filenames during the image creation process. This improves user experience by offering more flexibility in naming cloud-init images. --- emmc-provisioning/dashboard/app.py | 3 +++ .../dashboard/templates/cloudinit_build.html | 7 +++++++ emmc-provisioning/dashboard/templates/index.html | 7 +++++++ emmc-provisioning/host/build-cloudinit-image.sh | 12 +++++++++++- 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/emmc-provisioning/dashboard/app.py b/emmc-provisioning/dashboard/app.py index 21ef57e..7e191c8 100644 --- a/emmc-provisioning/dashboard/app.py +++ b/emmc-provisioning/dashboard/app.py @@ -1636,12 +1636,15 @@ def api_build_cloudinit(): meta_data = body.get("meta_data") or DEFAULT_META_DATA network_config = body.get("network_config") or DEFAULT_NETWORK_CONFIG set_as_golden_after = bool(body.get("set_as_golden_after")) + image_name = (body.get("image_name") or "").strip()[:64] + image_name = re.sub(r"[^\w\-]", "", image_name) # only alphanumeric, underscore, dash try: BUILD_REQUEST_FILE.parent.mkdir(parents=True, exist_ok=True) with open(BUILD_REQUEST_FILE, "w") as f: json.dump({ "url": url, "variant": variant, + "image_name": image_name or None, "user_data": user_data, "meta_data": meta_data, "network_config": network_config, diff --git a/emmc-provisioning/dashboard/templates/cloudinit_build.html b/emmc-provisioning/dashboard/templates/cloudinit_build.html index 1e8b8db..174fa79 100644 --- a/emmc-provisioning/dashboard/templates/cloudinit_build.html +++ b/emmc-provisioning/dashboard/templates/cloudinit_build.html @@ -70,6 +70,11 @@ +
+ + + + date suffix +
@@ -143,7 +148,9 @@ function startBuild() { var btn = document.getElementById('buildCloudInitBtn'); if (btn) btn.disabled = true; + var nameEl = document.getElementById('buildImageName'); var body = { variant: document.getElementById('buildVariant').value, set_as_golden_after: document.getElementById('buildSetGolden').checked }; + if (nameEl && nameEl.value.trim()) body.image_name = nameEl.value.trim(); body.user_data = document.getElementById('buildUserData').value.trim(); body.meta_data = document.getElementById('buildMetaData').value.trim(); body.network_config = document.getElementById('buildNetworkConfig').value.trim(); diff --git a/emmc-provisioning/dashboard/templates/index.html b/emmc-provisioning/dashboard/templates/index.html index 045a331..fafd088 100644 --- a/emmc-provisioning/dashboard/templates/index.html +++ b/emmc-provisioning/dashboard/templates/index.html @@ -437,6 +437,11 @@ +
+ + + + date suffix (e.g. 20251204-143022) +
(use for Deploy without clicking manually) @@ -913,9 +918,11 @@ var md = document.getElementById('buildMetaData'); var nc = document.getElementById('buildNetworkConfig'); var setGolden = document.getElementById('buildSetGolden'); + var nameEl = document.getElementById('buildImageName'); var body = { variant: getBuildVariant(), set_as_golden_after: setGolden && setGolden.checked, + image_name: (nameEl && nameEl.value.trim()) ? nameEl.value.trim() : undefined, user_data: (ud && ud.value.trim()) ? ud.value.trim() : undefined, meta_data: (md && md.value.trim()) ? md.value.trim() : undefined, network_config: (nc && nc.value.trim()) ? nc.value.trim() : undefined diff --git a/emmc-provisioning/host/build-cloudinit-image.sh b/emmc-provisioning/host/build-cloudinit-image.sh index c709a59..b38999a 100644 --- a/emmc-provisioning/host/build-cloudinit-image.sh +++ b/emmc-provisioning/host/build-cloudinit-image.sh @@ -47,14 +47,24 @@ with open(f"{out}/url", "w") as f: f.write(d.get("url", "")) with open(f"{out}/set_golden", "w") as f: f.write("1" if d.get("set_as_golden_after") else "0") +name = (d.get("image_name") or "").strip()[:64] +name = "".join(c for c in name if c.isalnum() or c in "_-") +with open(f"{out}/image_name", "w") as f: + f.write(name) PY URL=$(cat "$TEMP_DIR/url") VARIANT=$(cat "$TEMP_DIR/variant") SET_AS_GOLDEN=$(cat "$TEMP_DIR/set_golden") +IMAGE_NAME="$(cat "$TEMP_DIR/image_name" 2>/dev/null || true)" [[ -n "$URL" ]] || { write_status "error" "" "" "Missing url in request"; exit 1; } -OUT_NAME="raspios-${VARIANT}-cloudinit-$(date +%Y%m%d-%H%M%S).img" +DATE_SUFFIX="$(date +%Y%m%d-%H%M%S)" +if [[ -n "$IMAGE_NAME" ]]; then + OUT_NAME="${IMAGE_NAME}-${DATE_SUFFIX}.img" +else + OUT_NAME="raspios-${VARIANT}-cloudinit-${DATE_SUFFIX}.img" +fi OUT_PATH="$OUTPUT_DIR/$OUT_NAME" BASENAME=$(basename "$URL")