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.
120 lines
3.5 KiB
Bash
Executable File
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 "$@"
|