tuxflotte-installer/scripts/modules/30_runtime_blueprint.sh
Thomas Stallinger 1a38f8ef3c fix: set execute bit on Fedora backend and runtime-blueprint/backend modules
These are run as standalone subprocesses via run_module()/source, which
requires the execute bit. Missing since their initial creation - only
noticed because manually chmod'd copies were used for testing on anode,
never the checked-in files. Would have failed on a fresh checkout.
2026-07-20 14:51:12 +02:00

120 lines
3.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -Eeuo pipefail
SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")"
readonly SCRIPT_NAME
readonly NETWORK_STATE="/run/tuxflotte/network/state.env"
readonly SERVER_RESPONSE_FILE="/run/tuxflotte/server/response.json"
readonly TEMPLATE_FILE="/run/tuxflotte/assignment/template.json"
readonly RUNTIME_DIR="/run/tuxflotte/runtime"
readonly RESOLVE_REQUEST_FILE="${RUNTIME_DIR}/resolve_request.json"
readonly BLUEPRINT_FILE="${RUNTIME_DIR}/runtime_blueprint.json"
log() {
printf '[%s] %s\n' "${SCRIPT_NAME}" "$*" >&2
}
fatal() {
printf '[%s] FEHLER: %s\n' "${SCRIPT_NAME}" "$*" >&2
exit 1
}
require_root() {
if [[ "${EUID}" -ne 0 ]]; then
fatal "Das Runtime-Blueprint-Modul muss als root ausgeführt werden."
fi
}
prepare_runtime_directory() {
install -d \
--mode=0700 \
--owner=root \
--group=root \
"${RUNTIME_DIR}"
rm -f -- "${RESOLVE_REQUEST_FILE}" "${BLUEPRINT_FILE}"
}
validate_inputs() {
[[ -r "${NETWORK_STATE}" ]] ||
fatal "Netzwerkstatus nicht gefunden: ${NETWORK_STATE}"
[[ -r "${SERVER_RESPONSE_FILE}" ]] ||
fatal "Serverantwort nicht gefunden: ${SERVER_RESPONSE_FILE}"
jq --exit-status '.device.id | type == "string" and length > 0' \
"${SERVER_RESPONSE_FILE}" >/dev/null ||
fatal "Serverantwort enthält keine gültige Geräte-ID."
[[ -r "${TEMPLATE_FILE}" ]] ||
fatal "Bereitstellungsvorlage nicht gefunden: ${TEMPLATE_FILE}"
jq --exit-status '.template.id | type == "string" and length > 0' \
"${TEMPLATE_FILE}" >/dev/null ||
fatal "Bereitstellungsvorlage enthält keine gültige ID."
}
build_resolve_request() {
jq \
--null-input \
--slurpfile response "${SERVER_RESPONSE_FILE}" \
'{ device_id: $response[0].device.id }' \
>"${RESOLVE_REQUEST_FILE}"
chmod 0600 "${RESOLVE_REQUEST_FILE}"
}
send_resolve_request() {
local server_url
local template_id
# shellcheck disable=SC1090
source "${NETWORK_STATE}"
server_url="${TUXFLOTTE_SERVER_URL%/health}"
template_id="$(jq --raw-output '.template.id' "${TEMPLATE_FILE}")"
curl \
--silent \
--show-error \
--fail \
--location \
--header 'Content-Type: application/json' \
--data-binary "@${RESOLVE_REQUEST_FILE}" \
--output "${BLUEPRINT_FILE}" \
"${server_url}/api/v1/templates/${template_id}/resolve" ||
fatal "Runtime Blueprint konnte nicht aufgelöst werden."
chmod 0600 "${BLUEPRINT_FILE}"
jq --exit-status . "${BLUEPRINT_FILE}" >/dev/null ||
fatal "Antwort auf die Runtime-Blueprint-Anfrage enthält kein gültiges JSON."
jq --exit-status '.success == true' "${BLUEPRINT_FILE}" >/dev/null ||
fatal "$(jq -r '.message // "Provisioning-Server hat die Auflösung abgelehnt."' "${BLUEPRINT_FILE}")"
jq --exit-status '
.runtime_blueprint
| (.workspace_id | type == "string")
and (.backend_id | type == "string")
and (.blueprints | type == "array")
and (.installation_directives | type == "object")
' "${BLUEPRINT_FILE}" >/dev/null ||
fatal "Runtime Blueprint enthält keine gültige Zielbeschreibung."
log "Runtime Blueprint für Backend $(jq -r '.runtime_blueprint.backend_id' "${BLUEPRINT_FILE}") erzeugt."
log "Runtime Blueprint wurde unter ${BLUEPRINT_FILE} gespeichert."
}
main() {
require_root
prepare_runtime_directory
validate_inputs
build_resolve_request
send_resolve_request
}
main "$@"