#!/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 "$@"