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.
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -70,6 +70,11 @@
|
||||
<select id="buildVariant"><option value="desktop" selected>Desktop (recommended)</option><option value="lite">Lite</option><option value="full">Full</option></select>
|
||||
<span id="buildRaspiosUrl" class="mono" style="margin-left:0.5rem;"></span>
|
||||
</div>
|
||||
<div style="margin-bottom:0.5rem;">
|
||||
<label>Image name (optional):</label>
|
||||
<input type="text" id="buildImageName" placeholder="e.g. reterminal-kiosk" style="width:12rem; margin-left:0.25rem;" />
|
||||
<span class="mono" style="font-size:0.85rem; margin-left:0.25rem;">+ date suffix</span>
|
||||
</div>
|
||||
<div style="margin-bottom:0.5rem;"><label><input type="checkbox" id="buildSetGolden" /> Set as golden after build</label></div>
|
||||
<div style="margin-bottom:0.75rem;"><button type="button" id="buildCloudInitBtn" class="btn btn-primary">Download & build</button></div>
|
||||
<div id="buildCloudInitStatus" class="mono" style="min-height:1.2em;"></div>
|
||||
@@ -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();
|
||||
|
||||
@@ -437,6 +437,11 @@
|
||||
</select>
|
||||
<span id="buildRaspiosUrl" class="backups-mono" style="font-size:0.8rem; margin-left:0.5rem;"></span>
|
||||
</div>
|
||||
<div style="margin-bottom:0.5rem;">
|
||||
<label>Image name (optional): </label>
|
||||
<input type="text" id="buildImageName" placeholder="e.g. reterminal-kiosk" style="width:12rem;" />
|
||||
<span class="backups-mono" style="font-size:0.8rem; margin-left:0.5rem;">+ date suffix (e.g. 20251204-143022)</span>
|
||||
</div>
|
||||
<div style="margin-bottom:0.5rem;">
|
||||
<label><input type="checkbox" id="buildSetGolden" /> Set as golden image after build</label>
|
||||
<span class="backups-mono" style="font-size:0.8rem;"> (use for Deploy without clicking manually)</span>
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user