20260707 通用化Docker安装包模板命名
This commit is contained in:
521
deploy/docker-installer/scripts/common.sh
Normal file
521
deploy/docker-installer/scripts/common.sh
Normal file
@@ -0,0 +1,521 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
INSTALLER_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
ENV_FILE="${ENV_FILE:-$INSTALLER_ROOT/.env}"
|
||||
ENV_EXAMPLE="$INSTALLER_ROOT/.env.example"
|
||||
COMPOSE_FILE="$INSTALLER_ROOT/compose/docker-compose.yml"
|
||||
MANIFEST_FILE="${MANIFEST_FILE:-$INSTALLER_ROOT/PACKAGE-MANIFEST.env}"
|
||||
|
||||
log() {
|
||||
printf '[ours-rp-installer] %s\n' "$*"
|
||||
}
|
||||
|
||||
warn() {
|
||||
printf '[ours-rp-installer][WARN] %s\n' "$*" >&2
|
||||
}
|
||||
|
||||
die() {
|
||||
printf '[ours-rp-installer][ERROR] %s\n' "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
require_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || die "missing command: $1"
|
||||
}
|
||||
|
||||
normalize_arch() {
|
||||
case "$1" in
|
||||
amd64|x86_64|linux/amd64)
|
||||
printf 'amd64\n'
|
||||
;;
|
||||
arm64|aarch64|linux/arm64)
|
||||
printf 'arm64\n'
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
platform_for_arch() {
|
||||
printf 'linux/%s\n' "$1"
|
||||
}
|
||||
|
||||
env_file_has_key() {
|
||||
local env_path="$1"
|
||||
local key="$2"
|
||||
[[ -f "$env_path" ]] && grep -Eq "^${key}=" "$env_path"
|
||||
}
|
||||
|
||||
persist_env_default() {
|
||||
local env_path="$1"
|
||||
local key="$2"
|
||||
local value="$3"
|
||||
local tmp_env
|
||||
if env_file_has_key "$env_path" "$key"; then
|
||||
return 0
|
||||
fi
|
||||
tmp_env="$(mktemp)"
|
||||
cat "$env_path" > "$tmp_env"
|
||||
printf '%s=%s\n' "$key" "$value" >> "$tmp_env"
|
||||
mv "$tmp_env" "$env_path"
|
||||
}
|
||||
|
||||
env_flag_enabled() {
|
||||
case "${1:-0}" in
|
||||
1|true|TRUE|yes|YES|on|ON)
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
detect_host_arch() {
|
||||
local raw_arch
|
||||
raw_arch="$(uname -m)"
|
||||
normalize_arch "$raw_arch" || die "unsupported host architecture: $raw_arch"
|
||||
}
|
||||
|
||||
load_manifest() {
|
||||
MANIFEST_PACKAGE_ARCH_RAW=""
|
||||
MANIFEST_PACKAGE_PLATFORM_RAW=""
|
||||
if [[ -f "$MANIFEST_FILE" ]]; then
|
||||
set -a
|
||||
# shellcheck disable=SC1090
|
||||
source "$MANIFEST_FILE"
|
||||
set +a
|
||||
MANIFEST_PACKAGE_ARCH_RAW="${PACKAGE_ARCH:-${package_arch:-}}"
|
||||
MANIFEST_PACKAGE_PLATFORM_RAW="${PACKAGE_PLATFORM:-${package_platform:-}}"
|
||||
fi
|
||||
}
|
||||
|
||||
effective_package_arch() {
|
||||
if [[ -n "${PACKAGE_ARCH:-}" ]]; then
|
||||
normalize_arch "$PACKAGE_ARCH" || die "unsupported PACKAGE_ARCH=${PACKAGE_ARCH}"
|
||||
return 0
|
||||
fi
|
||||
if [[ -n "${PACKAGE_PLATFORM:-}" ]]; then
|
||||
normalize_arch "$PACKAGE_PLATFORM" || die "unsupported PACKAGE_PLATFORM=${PACKAGE_PLATFORM}"
|
||||
return 0
|
||||
fi
|
||||
if [[ -n "${RPKI_PLATFORM:-}" ]]; then
|
||||
normalize_arch "$RPKI_PLATFORM" || die "unsupported RPKI_PLATFORM=${RPKI_PLATFORM}"
|
||||
return 0
|
||||
fi
|
||||
if [[ -n "${METRICS_PLATFORM:-}" ]]; then
|
||||
normalize_arch "$METRICS_PLATFORM" || die "unsupported METRICS_PLATFORM=${METRICS_PLATFORM}"
|
||||
return 0
|
||||
fi
|
||||
if [[ -n "${MONITOR_PLATFORM:-}" ]]; then
|
||||
normalize_arch "$MONITOR_PLATFORM" || die "unsupported MONITOR_PLATFORM=${MONITOR_PLATFORM}"
|
||||
return 0
|
||||
fi
|
||||
die "unable to determine package architecture from manifest or env"
|
||||
}
|
||||
|
||||
arch_mode() {
|
||||
local host_arch package_arch
|
||||
host_arch="$(detect_host_arch)"
|
||||
package_arch="$(effective_package_arch)"
|
||||
if [[ "$host_arch" == "$package_arch" ]]; then
|
||||
printf 'native\n'
|
||||
return 0
|
||||
fi
|
||||
if env_flag_enabled "${ALLOW_CROSS_ARCH:-0}"; then
|
||||
printf 'cross-arch-enabled\n'
|
||||
return 0
|
||||
fi
|
||||
printf 'mismatch-blocked\n'
|
||||
}
|
||||
|
||||
assert_arch_compatibility() {
|
||||
local host_arch package_arch package_platform mode
|
||||
host_arch="$(detect_host_arch)"
|
||||
package_arch="$(effective_package_arch)"
|
||||
package_platform="${PACKAGE_PLATFORM:-${RPKI_PLATFORM:-$(platform_for_arch "$package_arch")}}"
|
||||
mode="$(arch_mode)"
|
||||
case "$mode" in
|
||||
native)
|
||||
return 0
|
||||
;;
|
||||
cross-arch-enabled)
|
||||
log "cross-arch execution explicitly enabled: host_arch=$host_arch package_arch=$package_arch package_platform=$package_platform"
|
||||
return 0
|
||||
;;
|
||||
mismatch-blocked)
|
||||
die "package architecture mismatch: host_arch=$host_arch package_arch=$package_arch package_platform=$package_platform. Set ALLOW_CROSS_ARCH=1 in $ENV_FILE to allow explicit QEMU/binfmt emulation."
|
||||
;;
|
||||
*)
|
||||
die "unknown arch compatibility mode: $mode"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
load_env() {
|
||||
load_manifest
|
||||
if [[ ! -f "$ENV_FILE" ]]; then
|
||||
[[ -f "$ENV_EXAMPLE" ]] || die "missing $ENV_EXAMPLE"
|
||||
cp "$ENV_EXAMPLE" "$ENV_FILE"
|
||||
log "created .env from .env.example"
|
||||
fi
|
||||
set -a
|
||||
# shellcheck disable=SC1090
|
||||
source "$ENV_FILE"
|
||||
set +a
|
||||
|
||||
if [[ -n "${MANIFEST_PACKAGE_ARCH_RAW:-}" ]]; then
|
||||
manifest_package_arch="$(normalize_arch "$MANIFEST_PACKAGE_ARCH_RAW")" || die "unsupported manifest package arch: $MANIFEST_PACKAGE_ARCH_RAW"
|
||||
if [[ -n "${PACKAGE_ARCH:-}" ]]; then
|
||||
env_package_arch="$(normalize_arch "$PACKAGE_ARCH")" || die "unsupported env package arch: $PACKAGE_ARCH"
|
||||
[[ "$env_package_arch" == "$manifest_package_arch" ]] || die "env PACKAGE_ARCH=$env_package_arch mismatches manifest PACKAGE_ARCH=$manifest_package_arch"
|
||||
fi
|
||||
PACKAGE_ARCH="$manifest_package_arch"
|
||||
else
|
||||
if [[ -z "${PACKAGE_ARCH:-}" ]]; then
|
||||
PACKAGE_ARCH="$(effective_package_arch)"
|
||||
else
|
||||
PACKAGE_ARCH="$(normalize_arch "$PACKAGE_ARCH")"
|
||||
fi
|
||||
fi
|
||||
if [[ -n "${MANIFEST_PACKAGE_PLATFORM_RAW:-}" ]]; then
|
||||
manifest_package_platform="$MANIFEST_PACKAGE_PLATFORM_RAW"
|
||||
if [[ -n "${PACKAGE_PLATFORM:-}" && "$PACKAGE_PLATFORM" != "$manifest_package_platform" ]]; then
|
||||
die "env PACKAGE_PLATFORM=$PACKAGE_PLATFORM mismatches manifest PACKAGE_PLATFORM=$manifest_package_platform"
|
||||
fi
|
||||
PACKAGE_PLATFORM="$manifest_package_platform"
|
||||
else
|
||||
PACKAGE_PLATFORM="${PACKAGE_PLATFORM:-$(platform_for_arch "$PACKAGE_ARCH")}"
|
||||
fi
|
||||
|
||||
HOST_DATA_DIR="${HOST_DATA_DIR:-/var/lib/ours-rp-${PACKAGE_ARCH}-installer}"
|
||||
COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-ours-rp-${PACKAGE_ARCH}-installer}"
|
||||
RPKI_IMAGE="${RPKI_IMAGE:-ours-rp-runtime-${PACKAGE_ARCH}:dev}"
|
||||
RPKI_PLATFORM="${RPKI_PLATFORM:-$PACKAGE_PLATFORM}"
|
||||
METRICS_IMAGE="${METRICS_IMAGE:-ours-rp-metrics-${PACKAGE_ARCH}:dev}"
|
||||
METRICS_PLATFORM="${METRICS_PLATFORM:-$PACKAGE_PLATFORM}"
|
||||
RTR_REPORT_DIR="${RTR_REPORT_DIR:-$HOST_DATA_DIR/empty-rtr-report}"
|
||||
RTR_REPORT_CONTAINER_DIR="${RTR_REPORT_CONTAINER_DIR:-/var/lib/ours-rp/rtr-report}"
|
||||
MONITOR_PLATFORM="${MONITOR_PLATFORM:-$PACKAGE_PLATFORM}"
|
||||
PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-prom/prometheus:v2.55.1}"
|
||||
GRAFANA_IMAGE="${GRAFANA_IMAGE:-grafana/grafana:11.3.1}"
|
||||
METRICS_INSTANCE="${METRICS_INSTANCE:-${PACKAGE_ARCH}-installer}"
|
||||
ALLOW_CROSS_ARCH="${ALLOW_CROSS_ARCH:-0}"
|
||||
RESOURCE_VALIDATION_MODE="${RESOURCE_VALIDATION_MODE:-validation-update-03}"
|
||||
FIRST_RUN_WAIT_TIMEOUT_SECS="${FIRST_RUN_WAIT_TIMEOUT_SECS:-7200}"
|
||||
|
||||
persist_env_default "$ENV_FILE" "METRICS_IMAGE" "$METRICS_IMAGE"
|
||||
persist_env_default "$ENV_FILE" "METRICS_PLATFORM" "$METRICS_PLATFORM"
|
||||
persist_env_default "$ENV_FILE" "RTR_REPORT_DIR" "$RTR_REPORT_DIR"
|
||||
persist_env_default "$ENV_FILE" "RTR_REPORT_CONTAINER_DIR" "$RTR_REPORT_CONTAINER_DIR"
|
||||
persist_env_default "$ENV_FILE" "RESOURCE_VALIDATION_MODE" "$RESOURCE_VALIDATION_MODE"
|
||||
}
|
||||
|
||||
compose_cmd() {
|
||||
docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" -p "$COMPOSE_PROJECT_NAME" "$@"
|
||||
}
|
||||
|
||||
validate_rtr_report_dir() {
|
||||
load_env
|
||||
[[ -n "${RTR_REPORT_DIR:-}" ]] || return 0
|
||||
[[ "$RTR_REPORT_DIR" = /* ]] || die "RTR_REPORT_DIR must be an absolute host path: $RTR_REPORT_DIR"
|
||||
[[ -d "$RTR_REPORT_DIR" ]] || die "RTR_REPORT_DIR does not exist or is not a directory: $RTR_REPORT_DIR"
|
||||
}
|
||||
|
||||
create_data_dirs() {
|
||||
load_env
|
||||
mkdir -p \
|
||||
"$HOST_DATA_DIR/state" \
|
||||
"$HOST_DATA_DIR/runs" \
|
||||
"$HOST_DATA_DIR/logs" \
|
||||
"$HOST_DATA_DIR/tmp" \
|
||||
"$HOST_DATA_DIR/empty-rtr-report" \
|
||||
"$HOST_DATA_DIR/prometheus" \
|
||||
"$HOST_DATA_DIR/grafana"
|
||||
validate_rtr_report_dir
|
||||
chmod 755 "$HOST_DATA_DIR" "$HOST_DATA_DIR/state" "$HOST_DATA_DIR/runs" "$HOST_DATA_DIR/logs" "$HOST_DATA_DIR/tmp" || true
|
||||
chmod 777 "$HOST_DATA_DIR/prometheus" "$HOST_DATA_DIR/grafana" || true
|
||||
}
|
||||
|
||||
latest_run_dir() {
|
||||
load_env
|
||||
find "$HOST_DATA_DIR/runs" -maxdepth 1 -mindepth 1 -type d -name 'run_*' 2>/dev/null | sort | tail -1
|
||||
}
|
||||
|
||||
latest_success_run_dir() {
|
||||
load_env
|
||||
find "$HOST_DATA_DIR/runs" -maxdepth 2 -type f -path '*/run-summary.json' 2>/dev/null \
|
||||
| while read -r summary; do
|
||||
if jq -e '.status == "success"' "$summary" >/dev/null 2>&1; then
|
||||
dirname "$summary"
|
||||
fi
|
||||
done | sort | tail -1
|
||||
}
|
||||
|
||||
has_success_run() {
|
||||
[[ -n "$(latest_success_run_dir)" ]]
|
||||
}
|
||||
|
||||
print_run_summary() {
|
||||
local run_dir="$1"
|
||||
local summary="$run_dir/run-summary.json"
|
||||
local meta="$run_dir/run-meta.json"
|
||||
local timing="$run_dir/stage-timing.json"
|
||||
local process_time="$run_dir/process-time.txt"
|
||||
local vrps_file="$run_dir/vrps.csv"
|
||||
local vaps_file="$run_dir/vaps.csv"
|
||||
local status="unknown"
|
||||
local sync_mode="unknown"
|
||||
local wall_ms="null"
|
||||
local validation_ms="null"
|
||||
local repo_sync_ms="null"
|
||||
local max_rss_kb="null"
|
||||
local publication_points="null"
|
||||
local vrps="null"
|
||||
local vaps="null"
|
||||
local warnings="null"
|
||||
[[ -f "$summary" ]] || {
|
||||
warn "missing run-summary.json in $run_dir"
|
||||
return 1
|
||||
}
|
||||
status="$(jq -r '.status // "unknown"' "$summary" 2>/dev/null || echo unknown)"
|
||||
wall_ms="$(jq -r '.wallMs // .wall_ms // "null"' "$summary" 2>/dev/null || echo null)"
|
||||
warnings="$(jq -r '.warningCount // .warnings // "null"' "$summary" 2>/dev/null || echo null)"
|
||||
if [[ -f "$meta" ]]; then
|
||||
sync_mode="$(jq -r '.sync_mode // .syncMode // "unknown"' "$meta" 2>/dev/null || echo unknown)"
|
||||
status="$(jq -r --arg fallback "$status" '.status // $fallback' "$meta" 2>/dev/null || echo "$status")"
|
||||
fi
|
||||
if [[ -f "$timing" ]]; then
|
||||
validation_ms="$(jq -r '.validation_ms // "null"' "$timing" 2>/dev/null || echo null)"
|
||||
repo_sync_ms="$(jq -r '.repo_sync_ms_total // "null"' "$timing" 2>/dev/null || echo null)"
|
||||
publication_points="$(jq -r '.publication_points // "null"' "$timing" 2>/dev/null || echo null)"
|
||||
fi
|
||||
if [[ -f "$process_time" ]]; then
|
||||
max_rss_kb="$(awk -F': ' '/Maximum resident set size/ {print $2; found=1} END {if (!found) print "null"}' "$process_time")"
|
||||
fi
|
||||
if [[ -f "$vrps_file" ]]; then
|
||||
vrps="$(( $(wc -l < "$vrps_file") > 0 ? $(wc -l < "$vrps_file") - 1 : 0 ))"
|
||||
fi
|
||||
if [[ -f "$vaps_file" ]]; then
|
||||
vaps="$(( $(wc -l < "$vaps_file") > 0 ? $(wc -l < "$vaps_file") - 1 : 0 ))"
|
||||
fi
|
||||
jq -n \
|
||||
--arg run "$(basename "$run_dir")" \
|
||||
--arg status "$status" \
|
||||
--arg syncMode "$sync_mode" \
|
||||
--argjson wallMs "$wall_ms" \
|
||||
--argjson validationMs "$validation_ms" \
|
||||
--argjson repoSyncMs "$repo_sync_ms" \
|
||||
--argjson maxRssKb "$max_rss_kb" \
|
||||
--argjson vrps "$vrps" \
|
||||
--argjson vaps "$vaps" \
|
||||
--argjson publicationPoints "$publication_points" \
|
||||
--argjson warnings "$warnings" \
|
||||
'{run:$run,status:$status,syncMode:$syncMode,wallMs:$wallMs,validationMs:$validationMs,repoSyncMs:$repoSyncMs,maxRssKb:$maxRssKb,vrps:$vrps,vaps:$vaps,publicationPoints:$publicationPoints,warnings:$warnings}'
|
||||
}
|
||||
|
||||
wait_for_new_success_run() {
|
||||
local before_latest="$1"
|
||||
local timeout_secs="$2"
|
||||
local start_epoch now run_dir summary meta status meta_status
|
||||
start_epoch="$(date +%s)"
|
||||
while true; do
|
||||
run_dir="$(latest_run_dir || true)"
|
||||
if [[ -n "$run_dir" && "$run_dir" != "$before_latest" ]]; then
|
||||
summary="$run_dir/run-summary.json"
|
||||
meta="$run_dir/run-meta.json"
|
||||
if [[ -f "$summary" ]]; then
|
||||
status="$(jq -r '.status // "unknown"' "$summary" 2>/dev/null || echo unknown)"
|
||||
if [[ "$status" == "success" ]]; then
|
||||
meta_status="unknown"
|
||||
if [[ -f "$meta" ]]; then
|
||||
meta_status="$(jq -r '.status // "unknown"' "$meta" 2>/dev/null || echo unknown)"
|
||||
fi
|
||||
if [[ "$meta_status" == "success" ]]; then
|
||||
print_run_summary "$run_dir" || true
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
if [[ "$status" == "failed" || "$status" == "error" ]]; then
|
||||
print_run_summary "$run_dir" || true
|
||||
die "run failed: $run_dir"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
now="$(date +%s)"
|
||||
if (( now - start_epoch > timeout_secs )); then
|
||||
die "timed out waiting for first successful run after ${timeout_secs}s"
|
||||
fi
|
||||
sleep 10
|
||||
done
|
||||
}
|
||||
|
||||
docker_compose_available() {
|
||||
docker compose version >/dev/null 2>&1
|
||||
}
|
||||
|
||||
install_docker_if_missing() {
|
||||
if command -v docker >/dev/null 2>&1 && docker_compose_available && command -v jq >/dev/null 2>&1 && command -v rsync >/dev/null 2>&1 && command -v curl >/dev/null 2>&1; then
|
||||
log "docker and docker compose are already installed"
|
||||
return 0
|
||||
fi
|
||||
if [[ "${SKIP_DEP_INSTALL:-0}" == "1" ]]; then
|
||||
die "docker/docker compose missing and SKIP_DEP_INSTALL=1"
|
||||
fi
|
||||
if ! command -v apt-get >/dev/null 2>&1; then
|
||||
die "docker/docker compose missing; automatic install currently supports apt-get only"
|
||||
fi
|
||||
log "installing missing runtime packages via apt"
|
||||
apt-get update
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates curl jq rsync gzip tar docker.io
|
||||
if ! docker_compose_available; then
|
||||
if apt-cache show docker-compose-v2 >/dev/null 2>&1; then
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y docker-compose-v2
|
||||
elif apt-cache show docker-compose-plugin >/dev/null 2>&1; then
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y docker-compose-plugin
|
||||
elif apt-cache show docker-compose >/dev/null 2>&1; then
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y docker-compose
|
||||
fi
|
||||
fi
|
||||
systemctl enable --now docker >/dev/null 2>&1 || true
|
||||
docker_compose_available || die "docker compose is still unavailable after install"
|
||||
}
|
||||
|
||||
load_installer_images() {
|
||||
load_env
|
||||
require_cmd docker
|
||||
shopt -s nullglob
|
||||
local image load_output desired_tag
|
||||
local found=0
|
||||
for image in "$INSTALLER_ROOT"/images/*.tar "$INSTALLER_ROOT"/images/*.tar.gz; do
|
||||
found=1
|
||||
log "loading docker image: $image"
|
||||
if [[ "$image" == *.gz ]]; then
|
||||
load_output="$(gzip -dc "$image" | docker load)"
|
||||
else
|
||||
load_output="$(docker load -i "$image")"
|
||||
fi
|
||||
printf '%s\n' "$load_output"
|
||||
desired_tag=""
|
||||
case "$(basename "$image")" in
|
||||
"${image_tar:-}")
|
||||
desired_tag="${image_tag:-$RPKI_IMAGE}"
|
||||
;;
|
||||
"${metrics_image_tar:-}")
|
||||
desired_tag="${metrics_image:-$METRICS_IMAGE}"
|
||||
;;
|
||||
"${prometheus_image_tar:-}")
|
||||
desired_tag="${prometheus_image:-$PROMETHEUS_IMAGE}"
|
||||
;;
|
||||
"${grafana_image_tar:-}")
|
||||
desired_tag="${grafana_image:-$GRAFANA_IMAGE}"
|
||||
;;
|
||||
esac
|
||||
if [[ -n "$desired_tag" ]]; then
|
||||
ensure_loaded_image_tag "$desired_tag" "$load_output" "$image"
|
||||
fi
|
||||
done
|
||||
shopt -u nullglob
|
||||
(( found == 1 )) || warn "no image tar found under $INSTALLER_ROOT/images"
|
||||
}
|
||||
|
||||
ensure_loaded_image_tag() {
|
||||
local desired_tag="$1"
|
||||
local load_output="$2"
|
||||
local image_path="$3"
|
||||
local loaded_ref=""
|
||||
local loaded_id=""
|
||||
local desired_id=""
|
||||
loaded_ref="$(printf '%s\n' "$load_output" | awk -F'Loaded image: ' '/Loaded image: / {print $2; exit}')"
|
||||
if [[ -z "$loaded_ref" ]]; then
|
||||
loaded_ref="$(printf '%s\n' "$load_output" | awk -F'Loaded image ID: ' '/Loaded image ID: / {print $2; exit}')"
|
||||
fi
|
||||
[[ -n "$loaded_ref" ]] || die "unable to determine loaded image reference for $image_path"
|
||||
loaded_id="$(docker image inspect --format '{{.Id}}' "$loaded_ref" 2>/dev/null || true)"
|
||||
desired_id="$(docker image inspect --format '{{.Id}}' "$desired_tag" 2>/dev/null || true)"
|
||||
if [[ -n "$loaded_id" && -n "$desired_id" && "$loaded_id" == "$desired_id" ]]; then
|
||||
return 0
|
||||
fi
|
||||
log "tagging loaded image for package use: source=$loaded_ref target=$desired_tag"
|
||||
docker tag "$loaded_ref" "$desired_tag"
|
||||
}
|
||||
|
||||
ensure_binfmt_if_needed() {
|
||||
require_cmd docker
|
||||
load_env
|
||||
local host_arch package_arch
|
||||
host_arch="$(detect_host_arch)"
|
||||
package_arch="$(effective_package_arch)"
|
||||
if [[ "$host_arch" == "$package_arch" ]]; then
|
||||
return 0
|
||||
fi
|
||||
assert_arch_compatibility
|
||||
log "host arch is $host_arch; enabling binfmt/qemu for package arch $package_arch"
|
||||
docker run --rm --privileged tonistiigi/binfmt --install "$package_arch"
|
||||
}
|
||||
|
||||
verify_runtime_image() {
|
||||
load_env
|
||||
require_cmd docker
|
||||
log "verifying runtime image $RPKI_IMAGE on $RPKI_PLATFORM"
|
||||
verify_image_platform "$RPKI_IMAGE" "$RPKI_PLATFORM" "runtime"
|
||||
verify_image_usage_output "$RPKI_IMAGE" "$RPKI_PLATFORM" "runtime" /opt/ours-rp/bin/rpki --help
|
||||
}
|
||||
|
||||
verify_metrics_image() {
|
||||
load_env
|
||||
require_cmd docker
|
||||
log "verifying metrics image $METRICS_IMAGE on $METRICS_PLATFORM"
|
||||
verify_image_platform "$METRICS_IMAGE" "$METRICS_PLATFORM" "metrics"
|
||||
verify_image_usage_output "$METRICS_IMAGE" "$METRICS_PLATFORM" "metrics" /opt/ours-rp/bin/rpki_artifact_metrics --help
|
||||
}
|
||||
|
||||
verify_image_platform() {
|
||||
local image="$1"
|
||||
local expected_platform="$2"
|
||||
local role="$3"
|
||||
local actual_platform
|
||||
docker image inspect "$image" >/dev/null
|
||||
actual_platform="$(docker image inspect --format '{{.Os}}/{{.Architecture}}' "$image" 2>/dev/null || echo unknown)"
|
||||
[[ "$actual_platform" == "$expected_platform" ]] || die "$role image platform mismatch: image=$image expected=$expected_platform actual=$actual_platform"
|
||||
}
|
||||
|
||||
verify_image_usage_output() {
|
||||
local image="$1"
|
||||
local expected_platform="$2"
|
||||
local role="$3"
|
||||
shift 3
|
||||
local help_path
|
||||
local status
|
||||
help_path="$(mktemp "${TMPDIR:-/tmp}/ours-rp-image-help.XXXXXX")"
|
||||
set +e
|
||||
docker run --rm --platform "$expected_platform" "$image" "$@" >"$help_path" 2>&1
|
||||
status=$?
|
||||
set -e
|
||||
if [[ "$status" != "0" && "$status" != "1" ]]; then
|
||||
cat "$help_path" >&2 || true
|
||||
rm -f "$help_path"
|
||||
die "$role image command failed: image=$image platform=$expected_platform exit=$status"
|
||||
fi
|
||||
grep -q '^Usage' "$help_path" || {
|
||||
cat "$help_path" >&2 || true
|
||||
rm -f "$help_path"
|
||||
die "$role image did not emit usage output: image=$image platform=$expected_platform exit=$status"
|
||||
}
|
||||
head -5 "$help_path" || true
|
||||
rm -f "$help_path"
|
||||
}
|
||||
|
||||
verify_monitor_images() {
|
||||
load_env
|
||||
require_cmd docker
|
||||
verify_image_platform "$PROMETHEUS_IMAGE" "$MONITOR_PLATFORM" "prometheus"
|
||||
verify_image_platform "$GRAFANA_IMAGE" "$MONITOR_PLATFORM" "grafana"
|
||||
}
|
||||
|
||||
endpoint_ok() {
|
||||
local url="$1"
|
||||
curl -fsS --max-time 5 "$url" >/dev/null 2>&1
|
||||
}
|
||||
Reference in New Issue
Block a user