#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" TEST_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" REPO_ROOT="$(cd "$TEST_ROOT/../../.." && pwd)" PRIVATE_CORE="$TEST_ROOT/private" PRIVATE_NODEA="$TEST_ROOT/private-nodea" PRIVATE_NODEB="$TEST_ROOT/private-nodeb" TMP_DIR="$TEST_ROOT/tmp" source "$REPO_ROOT/scripts/common/build_user.sh" load_build_user ensure_image() { local image="$1" if ! docker image inspect "$image" >/dev/null 2>&1; then echo "[ERROR] Missing image: $image. Please run ./build/build_images.sh" >&2 exit 1 fi } echo "[INFO] Preparing directories..." ensure_writable_dir() { local path="$1" local parent parent="$(dirname "$path")" mkdir -p "$parent" 2>/dev/null || true mkdir -p "$path" 2>/dev/null || true if [[ ! -w "$path" ]]; then docker run --rm -v "$parent:/target" ubuntu:24.04 bash -lc "chown -R $(id -u):$(id -g) /target" >/dev/null 2>&1 || true fi mkdir -p "$path" } # preflight: make base dirs writable if inherited from root-owned mounts ensure_writable_dir "$PRIVATE_CORE/argus" ensure_writable_dir "$PRIVATE_CORE/argus/metric" ensure_writable_dir "$PRIVATE_CORE/argus/metric/grafana" ensure_writable_dir "$PRIVATE_CORE/argus/metric/prometheus" mkdir -p \ "$PRIVATE_CORE/argus/etc" \ "$PRIVATE_CORE/argus/bind" \ "$PRIVATE_CORE/argus/master" \ "$PRIVATE_CORE/argus/metric/prometheus" \ "$PRIVATE_CORE/argus/alert/alertmanager" \ "$PRIVATE_CORE/argus/metric/ftp/share" \ "$PRIVATE_CORE/argus/metric/grafana/data" \ "$PRIVATE_CORE/argus/metric/grafana/logs" \ "$PRIVATE_CORE/argus/metric/grafana/plugins" \ "$PRIVATE_CORE/argus/metric/grafana/provisioning/datasources" \ "$PRIVATE_CORE/argus/metric/grafana/provisioning/dashboards" \ "$PRIVATE_CORE/argus/metric/grafana/data/sessions" \ "$PRIVATE_CORE/argus/metric/grafana/data/dashboards" \ "$PRIVATE_CORE/argus/metric/grafana/config" \ "$PRIVATE_CORE/argus/metric/prometheus/data" \ "$PRIVATE_CORE/argus/metric/prometheus/rules" \ "$PRIVATE_CORE/argus/metric/prometheus/targets" \ "$PRIVATE_CORE/argus/agent" \ "$PRIVATE_CORE/argus/log/elasticsearch" \ "$PRIVATE_CORE/argus/log/kibana" \ "$PRIVATE_NODEA/argus/agent/dev-yyrshare-nbnyx10-cp2f-pod-0/health" \ "$PRIVATE_NODEB/argus/agent/dev-yyrshare-uuuu10-ep2f-pod-0/health" \ "$TMP_DIR" # Align ownership for supervisor-managed services (ES/Kibana/Grafana expect UID/GID inside container) echo "[INFO] Fixing ownership for core private directories..." chown -R "${ARGUS_BUILD_UID}:${ARGUS_BUILD_GID}" \ "$PRIVATE_CORE/argus/log/elasticsearch" \ "$PRIVATE_CORE/argus/log/kibana" \ "$PRIVATE_CORE/argus/metric/grafana" \ "$PRIVATE_CORE/argus/metric/prometheus" \ "$PRIVATE_CORE/argus/alert" \ "$PRIVATE_CORE/argus/metric/ftp" \ "$PRIVATE_CORE/argus/agent" \ "$PRIVATE_CORE/argus/etc" 2>/dev/null || true # 确保 alert 与 etc 目录组可写,便于非 root 且仅匹配 GID 的服务写入运行文件 chmod -R g+w "$PRIVATE_CORE/argus/alert" "$PRIVATE_CORE/argus/etc" 2>/dev/null || true echo "[INFO] Using compose-managed network (auto-created by docker compose)" echo "[INFO] Distributing update-dns.sh for core services (bind/master/es/kibana)" BIND_UPDATE_SRC="$REPO_ROOT/src/bind/build/update-dns.sh" BIND_UPDATE_DEST="$PRIVATE_CORE/argus/etc/update-dns.sh" if [[ -f "$BIND_UPDATE_SRC" ]]; then cp "$BIND_UPDATE_SRC" "$BIND_UPDATE_DEST" chmod +x "$BIND_UPDATE_DEST" else echo "[WARN] bind update-dns.sh not found at $BIND_UPDATE_SRC" fi echo "[INFO] Ensuring images present..." ensure_image "argus-elasticsearch:latest" ensure_image "argus-kibana:latest" ensure_image "argus-bind9:latest" ensure_image "argus-master:latest" ensure_image "argus-metric-ftp:latest" ensure_image "argus-metric-prometheus:latest" ensure_image "argus-metric-grafana:latest" ensure_image "argus-web-frontend:latest" ensure_image "argus-web-proxy:latest" ensure_image "argus-alertmanager:latest" echo "[INFO] Preparing Fluent Bit local dependency packages..." FLB_BUILD_PACKAGES_DIR="$REPO_ROOT/src/log/fluent-bit/build/packages" mkdir -p "$FLB_BUILD_PACKAGES_DIR" for deb in \ "$REPO_ROOT/src/metric/client-plugins/all-in-one-full/plugins/fluent-bit/bin/libyaml-0-2_"*_amd64.deb \ "$REPO_ROOT/src/metric/client-plugins/all-in-one-full/plugins/fluent-bit/bin/libpq5_"*_amd64.deb ; do if ls $deb >/dev/null 2>&1; then for f in $deb; do base="$(basename "$f")" if [[ ! -f "$FLB_BUILD_PACKAGES_DIR/$base" ]]; then cp "$f" "$FLB_BUILD_PACKAGES_DIR/" echo " [+] copied $base" fi done fi done # 额外:从 all-in-one-full 的 ubuntu22/curl.tar.gz 解包必要依赖(libsasl2/ldap),便于离线安装 CURLOPT_TAR="$REPO_ROOT/src/metric/client-plugins/all-in-one-full/deps/ubuntu22/curl.tar.gz" if [[ -f "$CURLOPT_TAR" ]]; then tmpdir=$(mktemp -d) if tar -xzf "$CURLOPT_TAR" -C "$tmpdir" 2>/dev/null; then for p in \ libsasl2-2_*_amd64.deb \ libsasl2-modules-db_*_amd64.deb \ libldap-2.5-0_*_amd64.deb \ libidn2-0_*_amd64.deb \ libbrotli1_*_amd64.deb \ libssl3_*_amd64.deb ; do src=$(ls "$tmpdir"/curl/$p 2>/dev/null | head -n1 || true) if [[ -n "$src" ]]; then base="$(basename "$src")" [[ -f "$FLB_BUILD_PACKAGES_DIR/$base" ]] || cp "$src" "$FLB_BUILD_PACKAGES_DIR/" && echo " [+] staged $base" fi done fi rm -rf "$tmpdir" fi echo "[INFO] Building agent binary..." pushd "$REPO_ROOT/src/agent" >/dev/null ./scripts/build_binary.sh popd >/dev/null AGENT_BIN="$REPO_ROOT/src/agent/dist/argus-agent" if [[ ! -x "$AGENT_BIN" ]]; then echo "[ERROR] Agent binary not found at $AGENT_BIN" >&2 exit 1 fi echo "$AGENT_BIN" > "$TMP_DIR/agent_binary_path" # 检测GPU环境 REQUEST_GPU=${ARGUS_SYS_ENABLE_GPU:-false} GPU_CHECK_SCRIPT="$REPO_ROOT/src/metric/tests/scripts/common/check-gpu.sh" if [[ "$REQUEST_GPU" == "true" ]]; then echo "[INFO] --enable-gpu 已启用,开始检测GPU环境..." if [[ -f "$GPU_CHECK_SCRIPT" ]]; then if bash "$GPU_CHECK_SCRIPT" >/dev/null 2>&1; then echo "[INFO] GPU环境可用,将在 compose 中启用 test-gpu-node" GPU_AVAILABLE=true else echo "[ERROR] 未检测到可用 GPU,但指定了 --enable-gpu" >&2 exit 1 fi else echo "[ERROR] 未找到 GPU 检测脚本: $GPU_CHECK_SCRIPT" >&2 exit 1 fi else GPU_AVAILABLE=false echo "[INFO] GPU 支持未启用,跳过 GPU 检测" fi echo "[INFO] Writing .env with UID/GID and metric configuration" ############################################# # 动态分配宿主机端口并写入 .env ############################################# # 读取现有 .env(若存在),用于保留密码/域名等 EXIST_DOTENV="$TEST_ROOT/.env" if [[ -f "$EXIST_DOTENV" ]]; then EXISTING_FTP_PASSWORD="$(grep -E '^FTP_PASSWORD=' "$EXIST_DOTENV" | tail -n1 | sed 's/^FTP_PASSWORD=//')" EXISTING_FTP_DOMAIN="$(grep -E '^FTP_DOMAIN=' "$EXIST_DOTENV" | tail -n1 | sed 's/^FTP_DOMAIN=//')" EXISTING_USE_INTRANET="$(grep -E '^USE_INTRANET=' "$EXIST_DOTENV" | tail -n1 | sed 's/^USE_INTRANET=//')" else EXISTING_FTP_PASSWORD="" EXISTING_FTP_DOMAIN="" EXISTING_USE_INTRANET="" fi is_port_free() { local p="$1" ss -ltnH 2>/dev/null | awk -v pat=":${p}$" '$4 ~ pat{f=1} END{exit f?1:0}' } find_free_port() { local prefer="$1"; local start_scan="${2:-20000}"; local max="${3:-65000}" if is_port_free "$prefer"; then echo "$prefer"; return 0; fi local p for (( p=start_scan; p<=max; p++ )); do if is_port_free "$p"; then echo "$p"; return 0; fi done return 1 } find_free_range() { local begin="$1"; local end="$2"; local need_count=$((end-begin+1)) local try_start="$begin" while (( try_start + need_count - 1 <= 65000 )); do local ok=1 for (( p=try_start; p "$TEST_ROOT/.env" <