fix(oci): preserve caller-owned install plans

This commit is contained in:
VAIO73
2026-09-27 13:28:39 +02:00
parent 6e7be4c029
commit 1367bcb7d4
2 changed files with 37 additions and 2 deletions
+17 -2
View File
@@ -250,6 +250,7 @@ VOLUME_SEED_STAGE_ROOT=""
VOLUME_SEED_TARGETS=()
VOLUME_SEED_STAGES=()
VOLUME_SEED_MOUNT_TYPES=()
CANONICAL_INPUT_DIR=""
cleanup_runtime_console_log() {
# The console log is the container's own log from here on, and its line in
@@ -259,6 +260,14 @@ cleanup_runtime_console_log() {
RUNTIME_CONSOLE_LOG=""
}
cleanup_canonical_inputs() {
[[ -n ${CANONICAL_INPUT_DIR:-} ]] || return 0
[[ $CANONICAL_INPUT_DIR == "/var/tmp/proxmenux-oci-inputs-${VMID}."* && -d $CANONICAL_INPUT_DIR && ! -L $CANONICAL_INPUT_DIR ]] \
|| { oci_log "Refusing to remove an unexpected canonical input directory: ${CANONICAL_INPUT_DIR}"; return 1; }
rm -rf -- "$CANONICAL_INPUT_DIR" || return 1
CANONICAL_INPUT_DIR=""
}
# A derived check accepts any HTTP answer below 500: the application is up,
# even when its first page is a redirect or asks for a login.
healthcheck_probe() {
@@ -275,6 +284,7 @@ cleanup_failed_install() {
local status=$?
stop_spinner
cleanup_volume_seed_staging || true
cleanup_canonical_inputs || true
if [[ -n ${PROXMENUX_OCI_TRANSACTION:-} ]]; then
# The transaction owns recovery. Destroying this CT could destroy reused data.
cleanup_runtime_console_log || true
@@ -1282,8 +1292,13 @@ INSTANCE_ID=$(python3 "${SCRIPT_DIR}/oci_instances.py" prepare "$VMID" \
--template "$TEMPLATE_FILE" --deployment "$DEPLOYMENT_FILE")
INSTANCE_CONTRACT="$INSTANCE_ROOT/$VMID/oci-compose.json"
# The persisted contract is the source for the actual installation inputs.
jq '.template' "$INSTANCE_CONTRACT" >"$TEMPLATE_FILE"
jq '.deployment' "$INSTANCE_CONTRACT" >"$DEPLOYMENT_FILE"
# Do not rewrite caller-owned files, notably a regular user's file in sticky /tmp.
CANONICAL_INPUT_DIR=$(mktemp -d "/var/tmp/proxmenux-oci-inputs-${VMID}.XXXXXX") \
|| die "$(translate "Could not prepare canonical installation inputs")"
jq '.template' "$INSTANCE_CONTRACT" >"${CANONICAL_INPUT_DIR}/template.json"
jq '.deployment' "$INSTANCE_CONTRACT" >"${CANONICAL_INPUT_DIR}/deployment.json"
TEMPLATE_FILE="${CANONICAL_INPUT_DIR}/template.json"
DEPLOYMENT_FILE="${CANONICAL_INPUT_DIR}/deployment.json"
fi
skopeo_transport_reference() {
@@ -0,0 +1,20 @@
"""The installer must not need to rewrite files supplied by its caller."""
from pathlib import Path
import unittest
ROOT = Path(__file__).resolve().parents[1]
INSTALLER = ROOT / "remote" / "install_oci.sh"
class CanonicalInstallerInputTests(unittest.TestCase):
def test_persisted_contract_uses_private_copies_not_caller_files(self):
installer = INSTALLER.read_text(encoding="utf-8")
self.assertIn('mktemp -d "/var/tmp/proxmenux-oci-inputs-${VMID}.XXXXXX"', installer)
self.assertIn('TEMPLATE_FILE="${CANONICAL_INPUT_DIR}/template.json"', installer)
self.assertIn('DEPLOYMENT_FILE="${CANONICAL_INPUT_DIR}/deployment.json"', installer)
self.assertIn('cleanup_canonical_inputs || true', installer)
self.assertNotIn('jq \'.template\' "$INSTANCE_CONTRACT" >"$TEMPLATE_FILE"', installer)
self.assertNotIn('jq \'.deployment\' "$INSTANCE_CONTRACT" >"$DEPLOYMENT_FILE"', installer)