936 lines
32 KiB
Bash
Executable File
936 lines
32 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
|
||
export ARGUS_TARGET_ARCH="arm64"
|
||
ARGUS_BUILDX_BUILDER="${ARGUS_BUILDX_BUILDER:-mybuilder}"
|
||
|
||
# 自动加载 HTTP/HTTPS 代理配置(仅在变量未预先设置时)
|
||
if [[ -z "${HTTP_PROXY:-}" && -z "${http_proxy:-}" ]]; then
|
||
if [[ -f /home/yuyr/.source_http_proxy.sh ]]; then
|
||
# shellcheck disable=SC1090
|
||
source /home/yuyr/.source_http_proxy.sh || true
|
||
fi
|
||
fi
|
||
|
||
# 自动准备并切换到指定的 buildx builder(用于 x86_64 上构建 ARM 镜像)
|
||
if command -v docker >/dev/null 2>&1; then
|
||
if docker buildx ls >/dev/null 2>&1; then
|
||
# 若指定的 builder 不存在,则自动创建(带代理环境变量)
|
||
if ! docker buildx ls | awk '{print $1}' | grep -qx "${ARGUS_BUILDX_BUILDER}"; then
|
||
echo "🔧 Creating buildx builder '${ARGUS_BUILDX_BUILDER}' for ARM builds..."
|
||
create_args=(create --name "${ARGUS_BUILDX_BUILDER}" --driver docker-container)
|
||
if [[ -n "${HTTP_PROXY:-}" ]]; then
|
||
create_args+=(--driver-opt "env.HTTP_PROXY=${HTTP_PROXY}" --driver-opt "env.http_proxy=${HTTP_PROXY}")
|
||
fi
|
||
if [[ -n "${HTTPS_PROXY:-}" ]]; then
|
||
create_args+=(--driver-opt "env.HTTPS_PROXY=${HTTPS_PROXY}" --driver-opt "env.https_proxy=${HTTPS_PROXY}")
|
||
fi
|
||
if [[ -n "${NO_PROXY:-}" ]]; then
|
||
create_args+=(--driver-opt "env.NO_PROXY=${NO_PROXY}" --driver-opt "env.no_proxy=${NO_PROXY}")
|
||
fi
|
||
docker buildx "${create_args[@]}" --bootstrap >/dev/null 2>&1 || true
|
||
fi
|
||
docker buildx use "${ARGUS_BUILDX_BUILDER}" >/dev/null 2>&1 || true
|
||
fi
|
||
fi
|
||
|
||
show_help() {
|
||
cat <<'EOF'
|
||
ARGUS Unified Build System - Image Build Tool
|
||
|
||
Usage: $0 [OPTIONS]
|
||
|
||
Options:
|
||
--intranet Use intranet mirror for log/bind builds
|
||
--master-offline Build master offline image (requires src/master/offline_wheels.tar.gz)
|
||
--metric Build metric module images (ftp, prometheus, grafana, test nodes)
|
||
--no-cache Build all images without using Docker layer cache
|
||
--only LIST Comma-separated targets to build: core,master,metric,web,alert,sys,gpu_bundle,cpu_bundle,server_pkg,client_pkg,all
|
||
--version DATE Date tag used by gpu_bundle/server_pkg/client_pkg (e.g. 20251112)
|
||
--client-semver X.Y.Z Override client semver used in all-in-one-full artifact (optional)
|
||
--cuda VER CUDA runtime version for NVIDIA base (default: 12.2.2)
|
||
--tag-latest Also tag bundle image as :latest (for cpu_bundle only; default off)
|
||
-h, --help Show this help message
|
||
|
||
Examples:
|
||
$0 # Build with default sources
|
||
$0 --intranet # Build with intranet mirror
|
||
$0 --master-offline # Additionally build argus-master:offline
|
||
$0 --metric # Additionally build metric module images
|
||
$0 --intranet --master-offline --metric
|
||
EOF
|
||
}
|
||
|
||
use_intranet=false
|
||
build_core=true
|
||
build_master=true
|
||
build_master_offline=false
|
||
build_metric=true
|
||
build_web=true
|
||
build_alert=true
|
||
build_sys=true
|
||
build_gpu_bundle=false
|
||
build_cpu_bundle=false
|
||
build_server_pkg=false
|
||
build_client_pkg=false
|
||
no_cache=false
|
||
|
||
bundle_date=""
|
||
client_semver=""
|
||
cuda_ver="12.2.2"
|
||
DEFAULT_IMAGE_TAG="latest"
|
||
tag_latest=false
|
||
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
--intranet)
|
||
use_intranet=true
|
||
shift
|
||
;;
|
||
--master)
|
||
build_master=true
|
||
shift
|
||
;;
|
||
--master-offline)
|
||
build_master=true
|
||
build_master_offline=true
|
||
shift
|
||
;;
|
||
--metric)
|
||
build_metric=true
|
||
shift
|
||
;;
|
||
--no-cache)
|
||
no_cache=true
|
||
shift
|
||
;;
|
||
--only)
|
||
if [[ -z ${2:-} ]]; then
|
||
echo "--only requires a target list" >&2; exit 1
|
||
fi
|
||
sel="$2"; shift 2
|
||
# reset all, then enable selected
|
||
build_core=false; build_master=false; build_metric=false; build_web=false; build_alert=false; build_sys=false; build_gpu_bundle=false; build_cpu_bundle=false; build_server_pkg=false; build_client_pkg=false
|
||
IFS=',' read -ra parts <<< "$sel"
|
||
for p in "${parts[@]}"; do
|
||
case "$p" in
|
||
core) build_core=true ;;
|
||
master) build_master=true ;;
|
||
metric) build_metric=true ;;
|
||
web) build_web=true ;;
|
||
alert) build_alert=true ;;
|
||
sys) build_sys=true ;;
|
||
gpu_bundle) build_gpu_bundle=true ;;
|
||
cpu_bundle) build_cpu_bundle=true ;;
|
||
server_pkg) build_server_pkg=true; build_core=true; build_master=true; build_metric=true; build_web=true; build_alert=true ;;
|
||
client_pkg) build_client_pkg=true ;;
|
||
all) build_core=true; build_master=true; build_metric=true; build_web=true; build_alert=true; build_sys=true ;;
|
||
*) echo "Unknown --only target: $p" >&2; exit 1 ;;
|
||
esac
|
||
done
|
||
;;
|
||
--version)
|
||
if [[ -z ${2:-} ]]; then echo "--version requires a value like 20251112" >&2; exit 1; fi
|
||
bundle_date="$2"; shift 2
|
||
;;
|
||
--client-semver)
|
||
if [[ -z ${2:-} ]]; then echo "--client-semver requires a value like 1.43.0" >&2; exit 1; fi
|
||
client_semver="$2"; shift 2
|
||
;;
|
||
--cuda)
|
||
if [[ -z ${2:-} ]]; then echo "--cuda requires a value like 12.2.2" >&2; exit 1; fi
|
||
cuda_ver="$2"; shift 2
|
||
;;
|
||
--tag-latest)
|
||
tag_latest=true
|
||
shift
|
||
;;
|
||
-h|--help)
|
||
show_help
|
||
exit 0
|
||
;;
|
||
*)
|
||
echo "Unknown option: $1" >&2
|
||
show_help
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||
. "$root/scripts/common/build_user.sh"
|
||
|
||
declare -a build_args=()
|
||
|
||
if [[ "$use_intranet" == true ]]; then
|
||
build_args+=("--build-arg" "USE_INTRANET=true")
|
||
fi
|
||
|
||
cd "$root"
|
||
|
||
# Set default image tag policy before building
|
||
if [[ "$build_server_pkg" == true ]]; then
|
||
DEFAULT_IMAGE_TAG="${bundle_date:-latest}"
|
||
fi
|
||
|
||
# Select build user profile for pkg vs default
|
||
if [[ "$build_server_pkg" == true || "$build_client_pkg" == true ]]; then
|
||
export ARGUS_BUILD_PROFILE=pkg
|
||
fi
|
||
|
||
load_build_user
|
||
build_args+=("--build-arg" "ARGUS_BUILD_UID=${ARGUS_BUILD_UID}" "--build-arg" "ARGUS_BUILD_GID=${ARGUS_BUILD_GID}")
|
||
|
||
if [[ "$no_cache" == true ]]; then
|
||
build_args+=("--no-cache")
|
||
fi
|
||
|
||
master_root="$root/src/master"
|
||
master_offline_tar="$master_root/offline_wheels.tar.gz"
|
||
master_offline_dir="$master_root/offline_wheels"
|
||
|
||
if [[ "$build_master_offline" == true ]]; then
|
||
if [[ ! -f "$master_offline_tar" ]]; then
|
||
echo "❌ offline wheels tar not found: $master_offline_tar" >&2
|
||
echo " 请提前准备好 offline_wheels.tar.gz 后再执行 --master-offline" >&2
|
||
exit 1
|
||
fi
|
||
echo "📦 Preparing offline wheels for master (extracting $master_offline_tar)"
|
||
rm -rf "$master_offline_dir"
|
||
mkdir -p "$master_offline_dir"
|
||
tar -xzf "$master_offline_tar" -C "$master_root"
|
||
has_wheel=$(find "$master_offline_dir" -maxdepth 1 -type f -name '*.whl' -print -quit)
|
||
if [[ -z "$has_wheel" ]]; then
|
||
echo "❌ offline_wheels extraction failed或无 wheel: $master_offline_dir" >&2
|
||
exit 1
|
||
fi
|
||
# ARM 构建下,offline 模式仍通过 Dockerfile 中的 USE_OFFLINE/USE_INTRANET 参数控制
|
||
build_args+=("--build-arg" "USE_OFFLINE=1" "--build-arg" "USE_INTRANET=true")
|
||
fi
|
||
|
||
echo "======================================="
|
||
echo "ARGUS Unified Build System"
|
||
echo "======================================="
|
||
|
||
if [[ "$use_intranet" == true ]]; then
|
||
echo "🌐 Mode: Intranet (Using internal mirror: 10.68.64.1)"
|
||
else
|
||
echo "🌐 Mode: Public (Using default package sources)"
|
||
fi
|
||
|
||
echo "👤 Build user UID:GID -> ${ARGUS_BUILD_UID}:${ARGUS_BUILD_GID}"
|
||
|
||
echo "📁 Build context: $root"
|
||
echo ""
|
||
|
||
build_image() {
|
||
local image_name=$1
|
||
local dockerfile_path=$2
|
||
local tag=$3
|
||
local context="."
|
||
shift 3
|
||
|
||
if [[ $# -gt 0 ]]; then
|
||
context=$1
|
||
shift
|
||
fi
|
||
|
||
local extra_args=("$@")
|
||
|
||
# ARM 专用:如果存在带 .arm64 后缀的 Dockerfile,则优先使用
|
||
local dockerfile_for_arch="$dockerfile_path"
|
||
if [[ -n "${ARGUS_TARGET_ARCH:-}" && "$ARGUS_TARGET_ARCH" == "arm64" ]]; then
|
||
if [[ -f "${dockerfile_path}.arm64" ]]; then
|
||
dockerfile_for_arch="${dockerfile_path}.arm64"
|
||
fi
|
||
fi
|
||
|
||
echo "🔄 Building $image_name image..."
|
||
echo " Dockerfile: $dockerfile_for_arch"
|
||
echo " Tag: $tag"
|
||
echo " Context: $context"
|
||
|
||
local tries=${ARGUS_BUILD_RETRIES:-3}
|
||
local delay=${ARGUS_BUILD_RETRY_DELAY:-5}
|
||
local attempt=1
|
||
# 在非 ARM 主机上构建 ARM 镜像时,使用 buildx+--platform=linux/arm64
|
||
local use_buildx=false
|
||
if [[ "${ARGUS_TARGET_ARCH:-}" == "arm64" && "$(uname -m)" != "aarch64" ]]; then
|
||
use_buildx=true
|
||
fi
|
||
|
||
while (( attempt <= tries )); do
|
||
echo " Attempt ${attempt}/${tries}"
|
||
if [[ "$use_buildx" == true ]]; then
|
||
# 通过 buildx 在 x86_64 等非 ARM 主机上构建 ARM64 镜像
|
||
if docker buildx build \
|
||
--builder "${ARGUS_BUILDX_BUILDER}" \
|
||
--platform=linux/arm64 \
|
||
"${build_args[@]}" "${extra_args[@]}" \
|
||
-f "$dockerfile_for_arch" \
|
||
-t "$tag" \
|
||
"$context" \
|
||
--load; then
|
||
echo "✅ $image_name image built successfully (via buildx, platform=linux/arm64)"
|
||
return 0
|
||
fi
|
||
else
|
||
# 在 ARM 主机上直接使用 docker build(保留原有 DOCKER_BUILDKIT 回退行为)
|
||
local prefix=""
|
||
if (( attempt == tries )); then
|
||
prefix="DOCKER_BUILDKIT=0"
|
||
echo " (final attempt with DOCKER_BUILDKIT=0)"
|
||
fi
|
||
if eval $prefix docker build "${build_args[@]}" "${extra_args[@]}" -f "$dockerfile_for_arch" -t "$tag" "$context"; then
|
||
echo "✅ $image_name image built successfully"
|
||
return 0
|
||
fi
|
||
fi
|
||
|
||
echo "⚠️ Build failed for $image_name (attempt ${attempt}/${tries})."
|
||
if (( attempt < tries )); then
|
||
echo " Retrying in ${delay}s..."
|
||
sleep "$delay"
|
||
fi
|
||
attempt=$((attempt+1))
|
||
done
|
||
echo "❌ Failed to build $image_name image after ${tries} attempts"
|
||
return 1
|
||
}
|
||
|
||
pull_base_image() {
|
||
local image_ref=$1
|
||
local attempts=${2:-3}
|
||
local delay=${3:-5}
|
||
|
||
# If the image already exists locally, skip pulling.
|
||
if docker image inspect "$image_ref" >/dev/null 2>&1; then
|
||
echo " Local image present; skip pull: $image_ref"
|
||
return 0
|
||
fi
|
||
|
||
for ((i=1; i<=attempts; i++)); do
|
||
echo " Pulling base image ($i/$attempts): $image_ref"
|
||
if docker pull "$image_ref" >/dev/null; then
|
||
echo " Base image ready: $image_ref"
|
||
return 0
|
||
fi
|
||
echo " Pull failed: $image_ref"
|
||
if (( i < attempts )); then
|
||
echo " Retrying in ${delay}s..."
|
||
sleep "$delay"
|
||
fi
|
||
done
|
||
|
||
echo "❌ Unable to pull base image after ${attempts} attempts: $image_ref"
|
||
return 1
|
||
}
|
||
|
||
images_built=()
|
||
build_failed=false
|
||
|
||
build_gpu_bundle_image() {
|
||
local date_tag="$1" # e.g. 20251112
|
||
local cuda_ver_local="$2" # e.g. 12.2.2
|
||
local client_ver="$3" # semver like 1.43.0
|
||
|
||
if [[ -z "$date_tag" ]]; then
|
||
echo "❌ gpu_bundle requires --version YYMMDD (e.g. 20251112)" >&2
|
||
return 1
|
||
fi
|
||
|
||
# sanitize cuda version (trim trailing dots like '12.2.')
|
||
while [[ "$cuda_ver_local" == *"." ]]; do cuda_ver_local="${cuda_ver_local%.}"; done
|
||
|
||
# Resolve effective CUDA base tag
|
||
local resolve_cuda_base_tag
|
||
resolve_cuda_base_tag() {
|
||
local want="$1" # can be 12, 12.2 or 12.2.2
|
||
local major minor patch
|
||
if [[ "$want" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
|
||
major="${BASH_REMATCH[1]}"; minor="${BASH_REMATCH[2]}"; patch="${BASH_REMATCH[3]}"
|
||
echo "nvidia/cuda:${major}.${minor}.${patch}-runtime-ubuntu22.04"; return 0
|
||
elif [[ "$want" =~ ^([0-9]+)\.([0-9]+)$ ]]; then
|
||
major="${BASH_REMATCH[1]}"; minor="${BASH_REMATCH[2]}"
|
||
# try to find best local patch for major.minor
|
||
local best
|
||
best=$(docker images --format '{{.Repository}}:{{.Tag}}' nvidia/cuda 2>/dev/null | \
|
||
grep -E "^nvidia/cuda:${major}\.${minor}\\.[0-9]+-runtime-ubuntu22\.04$" | \
|
||
sed -E 's#^nvidia/cuda:([0-9]+\.[0-9]+\.)([0-9]+)-runtime-ubuntu22\.04$#\1\2#g' | \
|
||
sort -V | tail -n1 || true)
|
||
if [[ -n "$best" ]]; then
|
||
echo "nvidia/cuda:${best}-runtime-ubuntu22.04"; return 0
|
||
fi
|
||
# fallback patch if none local
|
||
echo "nvidia/cuda:${major}.${minor}.2-runtime-ubuntu22.04"; return 0
|
||
elif [[ "$want" =~ ^([0-9]+)$ ]]; then
|
||
major="${BASH_REMATCH[1]}"
|
||
# try to find best local for this major
|
||
local best
|
||
best=$(docker images --format '{{.Repository}}:{{.Tag}}' nvidia/cuda 2>/dev/null | \
|
||
grep -E "^nvidia/cuda:${major}\\.[0-9]+\\.[0-9]+-runtime-ubuntu22\.04$" | \
|
||
sed -E 's#^nvidia/cuda:([0-9]+\.[0-9]+\.[0-9]+)-runtime-ubuntu22\.04$#\1#g' | \
|
||
sort -V | tail -n1 || true)
|
||
if [[ -n "$best" ]]; then
|
||
echo "nvidia/cuda:${best}-runtime-ubuntu22.04"; return 0
|
||
fi
|
||
echo "nvidia/cuda:${major}.2.2-runtime-ubuntu22.04"; return 0
|
||
else
|
||
# invalid format, fallback to default
|
||
echo "nvidia/cuda:12.2.2-runtime-ubuntu22.04"; return 0
|
||
fi
|
||
}
|
||
|
||
local base_image
|
||
base_image=$(resolve_cuda_base_tag "$cuda_ver_local")
|
||
|
||
echo
|
||
echo "🔧 Preparing one-click GPU bundle build"
|
||
echo " CUDA runtime base: ${base_image}"
|
||
echo " Bundle tag : ${date_tag}"
|
||
|
||
# 1) Ensure NVIDIA base image (skip pull if local)
|
||
if ! pull_base_image "$base_image"; then
|
||
# try once more with default if resolution failed
|
||
if ! pull_base_image "nvidia/cuda:12.2.2-runtime-ubuntu22.04"; then
|
||
return 1
|
||
else
|
||
base_image="nvidia/cuda:12.2.2-runtime-ubuntu22.04"
|
||
fi
|
||
fi
|
||
|
||
# 2) Build latest argus-agent from source
|
||
echo "\n🛠 Building argus-agent from src/agent"
|
||
pushd "$root/src/agent" >/dev/null
|
||
if ! bash scripts/build_binary.sh; then
|
||
echo "❌ argus-agent build failed" >&2
|
||
popd >/dev/null
|
||
return 1
|
||
fi
|
||
if [[ ! -f "dist/argus-agent" ]]; then
|
||
echo "❌ argus-agent binary missing after build" >&2
|
||
popd >/dev/null
|
||
return 1
|
||
fi
|
||
popd >/dev/null
|
||
|
||
# 3) Inject agent into all-in-one-full plugin and package artifact
|
||
local aio_root="$root/src/metric/client-plugins/all-in-one-full"
|
||
local agent_bin_src="$root/src/agent/dist/argus-agent"
|
||
local agent_bin_dst="$aio_root/plugins/argus-agent/bin/argus-agent"
|
||
echo "\n📦 Updating all-in-one-full agent binary → $agent_bin_dst"
|
||
cp -f "$agent_bin_src" "$agent_bin_dst"
|
||
chmod +x "$agent_bin_dst" || true
|
||
|
||
pushd "$aio_root" >/dev/null
|
||
local prev_version
|
||
prev_version="$(cat config/VERSION 2>/dev/null || echo "1.0.0")"
|
||
local use_version="$prev_version"
|
||
if [[ -n "$client_semver" ]]; then
|
||
echo "${client_semver}" > config/VERSION
|
||
use_version="$client_semver"
|
||
fi
|
||
echo " Packaging all-in-one-full artifact version: $use_version"
|
||
if ! bash scripts/package_artifact.sh --force; then
|
||
echo "❌ package_artifact.sh failed" >&2
|
||
# restore VERSION if changed
|
||
if [[ -n "$client_semver" ]]; then echo "$prev_version" > config/VERSION; fi
|
||
popd >/dev/null
|
||
return 1
|
||
fi
|
||
|
||
local artifact_dir="$aio_root/artifact/$use_version"
|
||
local artifact_tar
|
||
artifact_tar="$(ls -1 "$artifact_dir"/argus-metric_*.tar.gz 2>/dev/null | head -n1 || true)"
|
||
if [[ -z "$artifact_tar" ]]; then
|
||
echo " No argus-metric_*.tar.gz found; invoking publish_artifact.sh to assemble..."
|
||
local owner="$(id -u):$(id -g)"
|
||
if ! bash scripts/publish_artifact.sh "$use_version" --output-dir "$artifact_dir" --owner "$owner"; then
|
||
echo "❌ publish_artifact.sh failed" >&2
|
||
if [[ -n "$client_semver" ]]; then echo "$prev_version" > config/VERSION; fi
|
||
popd >/dev/null
|
||
return 1
|
||
fi
|
||
artifact_tar="$(ls -1 "$artifact_dir"/argus-metric_*.tar.gz 2>/dev/null | head -n1 || true)"
|
||
fi
|
||
if [[ -z "$artifact_tar" ]]; then
|
||
echo "❌ artifact tar not found under $artifact_dir" >&2
|
||
if [[ -n "$client_semver" ]]; then echo "$prev_version" > config/VERSION; fi
|
||
popd >/dev/null
|
||
return 1
|
||
fi
|
||
# restore VERSION if changed (keep filesystem clean)
|
||
if [[ -n "$client_semver" ]]; then echo "$prev_version" > config/VERSION; fi
|
||
popd >/dev/null
|
||
|
||
# 4) Stage docker build context
|
||
local bundle_ctx="$root/src/bundle/gpu-node-bundle/.build-$date_tag"
|
||
echo "\n🧰 Staging docker build context: $bundle_ctx"
|
||
rm -rf "$bundle_ctx"
|
||
mkdir -p "$bundle_ctx/bundle" "$bundle_ctx/private"
|
||
cp "$root/src/bundle/gpu-node-bundle/Dockerfile" "$bundle_ctx/"
|
||
cp "$root/src/bundle/gpu-node-bundle/node-bootstrap.sh" "$bundle_ctx/"
|
||
cp "$root/src/bundle/gpu-node-bundle/health-watcher.sh" "$bundle_ctx/"
|
||
# bundle tar
|
||
cp "$artifact_tar" "$bundle_ctx/bundle/"
|
||
# offline fluent-bit assets (optional but useful)
|
||
if [[ -d "$root/src/log/fluent-bit/build/etc" ]]; then
|
||
cp -r "$root/src/log/fluent-bit/build/etc" "$bundle_ctx/private/"
|
||
fi
|
||
if [[ -d "$root/src/log/fluent-bit/build/packages" ]]; then
|
||
cp -r "$root/src/log/fluent-bit/build/packages" "$bundle_ctx/private/"
|
||
fi
|
||
if [[ -f "$root/src/log/fluent-bit/build/start-fluent-bit.sh" ]]; then
|
||
cp "$root/src/log/fluent-bit/build/start-fluent-bit.sh" "$bundle_ctx/private/"
|
||
fi
|
||
|
||
# 5) Build the final bundle image (directly from NVIDIA base)
|
||
local image_tag="argus-sys-metric-test-node-bundle-gpu-arm64:${date_tag}"
|
||
echo "\n🔄 Building GPU Bundle image"
|
||
if build_image "GPU Bundle" "$bundle_ctx/Dockerfile" "$image_tag" "$bundle_ctx" \
|
||
--build-arg CUDA_VER="$(echo "$base_image" | sed -E 's#^nvidia/cuda:([0-9]+\.[0-9]+\.[0-9]+)-runtime-ubuntu22\.04$#\1#')" \
|
||
--build-arg CLIENT_VER="$use_version" \
|
||
--build-arg BUNDLE_DATE="$date_tag"; then
|
||
images_built+=("$image_tag")
|
||
# In non-pkg mode, also tag latest for convenience
|
||
if [[ "${ARGUS_PKG_BUILD:-0}" != "1" ]]; then
|
||
docker tag "$image_tag" argus-sys-metric-test-node-bundle-gpu-arm64:latest >/dev/null 2>&1 || true
|
||
fi
|
||
return 0
|
||
else
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Tag helper: ensure :<date_tag> exists for a list of repos
|
||
ensure_version_tags() {
|
||
local date_tag="$1"; shift
|
||
local repos=("$@")
|
||
for repo in "${repos[@]}"; do
|
||
if docker image inspect "$repo:$date_tag" >/dev/null 2>&1; then
|
||
:
|
||
elif docker image inspect "$repo:latest" >/dev/null 2>&1; then
|
||
docker tag "$repo:latest" "$repo:$date_tag" || true
|
||
else
|
||
echo "❌ missing image for tagging: $repo (need :latest or :$date_tag)" >&2
|
||
return 1
|
||
fi
|
||
done
|
||
return 0
|
||
}
|
||
|
||
# Build server package after images are built
|
||
build_server_pkg_bundle() {
|
||
local date_tag="$1"
|
||
if [[ -z "$date_tag" ]]; then
|
||
echo "❌ server_pkg requires --version YYMMDD" >&2
|
||
return 1
|
||
fi
|
||
local repos=(
|
||
argus-bind9-arm64 argus-master-arm64 argus-elasticsearch-arm64 argus-kibana-arm64 \
|
||
argus-metric-ftp-arm64 argus-metric-prometheus-arm64 argus-metric-grafana-arm64 \
|
||
argus-alertmanager-arm64 argus-web-frontend-arm64 argus-web-proxy-arm64
|
||
)
|
||
echo "\n🔖 Verifying server images with :$date_tag and collecting digests"
|
||
for repo in "${repos[@]}"; do
|
||
if ! docker image inspect "$repo:$date_tag" >/dev/null 2>&1; then
|
||
echo "❌ required image missing: $repo:$date_tag (build phase should have produced it)" >&2
|
||
return 1
|
||
fi
|
||
done
|
||
# Optional: show digests
|
||
for repo in "${repos[@]}"; do
|
||
local digest
|
||
digest=$(docker images --digests --format '{{.Repository}}:{{.Tag}} {{.Digest}}' | awk -v r="$repo:$date_tag" '$1==r{print $2}' | head -n1)
|
||
printf ' • %s@%s\n' "$repo:$date_tag" "${digest:-<none>}"
|
||
done
|
||
echo "\n📦 Building server package via deployment_new/build/make_server_package.sh --version $date_tag"
|
||
if ! "$root/deployment_new/build/make_server_package.sh" --version "$date_tag"; then
|
||
echo "❌ make_server_package.sh failed" >&2
|
||
return 1
|
||
fi
|
||
return 0
|
||
}
|
||
|
||
# Build client package: ensure gpu bundle image exists, then package client_gpu
|
||
build_client_pkg_bundle() {
|
||
local date_tag="$1"
|
||
local semver="$2"
|
||
local cuda="$3"
|
||
if [[ -z "$date_tag" ]]; then
|
||
echo "❌ client_pkg requires --version YYMMDD" >&2
|
||
return 1
|
||
fi
|
||
local bundle_tag="argus-sys-metric-test-node-bundle-gpu-arm64:${date_tag}"
|
||
if ! docker image inspect "$bundle_tag" >/dev/null 2>&1; then
|
||
echo "\n🧩 GPU bundle image $bundle_tag missing; building it first..."
|
||
ARGUS_PKG_BUILD=1
|
||
export ARGUS_PKG_BUILD
|
||
if ! build_gpu_bundle_image "$date_tag" "$cuda" "$semver"; then
|
||
return 1
|
||
fi
|
||
else
|
||
echo "\n✅ Using existing GPU bundle image: $bundle_tag"
|
||
fi
|
||
echo "\n📦 Building client GPU package via deployment_new/build/make_client_gpu_package.sh --version $date_tag --image $bundle_tag"
|
||
if ! "$root/deployment_new/build/make_client_gpu_package.sh" --version "$date_tag" --image "$bundle_tag"; then
|
||
echo "❌ make_client_gpu_package.sh failed" >&2
|
||
return 1
|
||
fi
|
||
return 0
|
||
}
|
||
|
||
# Build CPU bundle image directly FROM ubuntu:22.04 (no intermediate base)
|
||
build_cpu_bundle_image() {
|
||
local date_tag="$1" # e.g. 20251113
|
||
local client_ver_in="$2" # semver like 1.43.0 (optional)
|
||
local want_tag_latest="$3" # true/false
|
||
|
||
if [[ -z "$date_tag" ]]; then
|
||
echo "❌ cpu_bundle requires --version YYMMDD" >&2
|
||
return 1
|
||
fi
|
||
|
||
echo "\n🔧 Preparing one-click CPU bundle build"
|
||
echo " Base: ubuntu:22.04"
|
||
echo " Bundle tag: ${date_tag}"
|
||
|
||
# 1) Build latest argus-agent from source
|
||
echo "\n🛠 Building argus-agent from src/agent"
|
||
pushd "$root/src/agent" >/dev/null
|
||
if ! bash scripts/build_binary.sh; then
|
||
echo "❌ argus-agent build failed" >&2
|
||
popd >/dev/null
|
||
return 1
|
||
fi
|
||
if [[ ! -f "dist/argus-agent" ]]; then
|
||
echo "❌ argus-agent binary missing after build" >&2
|
||
popd >/dev/null
|
||
return 1
|
||
fi
|
||
popd >/dev/null
|
||
|
||
# 2) Inject agent into all-in-one-full plugin and package artifact
|
||
local aio_root="$root/src/metric/client-plugins/all-in-one-full"
|
||
local agent_bin_src="$root/src/agent/dist/argus-agent"
|
||
local agent_bin_dst="$aio_root/plugins/argus-agent/bin/argus-agent"
|
||
echo "\n📦 Updating all-in-one-full agent binary → $agent_bin_dst"
|
||
cp -f "$agent_bin_src" "$agent_bin_dst"
|
||
chmod +x "$agent_bin_dst" || true
|
||
|
||
pushd "$aio_root" >/dev/null
|
||
local prev_version use_version
|
||
prev_version="$(cat config/VERSION 2>/dev/null || echo "1.0.0")"
|
||
use_version="$prev_version"
|
||
if [[ -n "$client_ver_in" ]]; then
|
||
echo "$client_ver_in" > config/VERSION
|
||
use_version="$client_ver_in"
|
||
fi
|
||
echo " Packaging all-in-one-full artifact: version=$use_version"
|
||
if ! bash scripts/package_artifact.sh --force; then
|
||
echo "❌ package_artifact.sh failed" >&2
|
||
[[ -n "$client_ver_in" ]] && echo "$prev_version" > config/VERSION
|
||
popd >/dev/null
|
||
return 1
|
||
fi
|
||
local artifact_dir="$aio_root/artifact/$use_version"
|
||
local artifact_tar
|
||
artifact_tar="$(ls -1 "$artifact_dir"/argus-metric_*.tar.gz 2>/dev/null | head -n1 || true)"
|
||
if [[ -z "$artifact_tar" ]]; then
|
||
echo " No argus-metric_*.tar.gz found; invoking publish_artifact.sh ..."
|
||
local owner="$(id -u):$(id -g)"
|
||
if ! bash scripts/publish_artifact.sh "$use_version" --output-dir "$artifact_dir" --owner "$owner"; then
|
||
echo "❌ publish_artifact.sh failed" >&2
|
||
[[ -n "$client_ver_in" ]] && echo "$prev_version" > config/VERSION
|
||
popd >/dev/null
|
||
return 1
|
||
fi
|
||
artifact_tar="$(ls -1 "$artifact_dir"/argus-metric_*.tar.gz 2>/dev/null | head -n1 || true)"
|
||
fi
|
||
[[ -n "$client_ver_in" ]] && echo "$prev_version" > config/VERSION
|
||
popd >/dev/null
|
||
|
||
# 3) Stage docker build context
|
||
local bundle_ctx="$root/src/bundle/cpu-node-bundle/.build-$date_tag"
|
||
echo "\n🧰 Staging docker build context: $bundle_ctx"
|
||
rm -rf "$bundle_ctx"
|
||
mkdir -p "$bundle_ctx/bundle" "$bundle_ctx/private"
|
||
cp "$root/src/bundle/cpu-node-bundle/Dockerfile" "$bundle_ctx/"
|
||
cp "$root/src/bundle/cpu-node-bundle/node-bootstrap.sh" "$bundle_ctx/"
|
||
cp "$root/src/bundle/cpu-node-bundle/health-watcher.sh" "$bundle_ctx/"
|
||
# bundle tar
|
||
cp "$artifact_tar" "$bundle_ctx/bundle/"
|
||
# offline fluent-bit assets
|
||
if [[ -d "$root/src/log/fluent-bit/build/etc" ]]; then
|
||
cp -r "$root/src/log/fluent-bit/build/etc" "$bundle_ctx/private/"
|
||
fi
|
||
if [[ -d "$root/src/log/fluent-bit/build/packages" ]]; then
|
||
cp -r "$root/src/log/fluent-bit/build/packages" "$bundle_ctx/private/"
|
||
fi
|
||
if [[ -f "$root/src/log/fluent-bit/build/start-fluent-bit.sh" ]]; then
|
||
cp "$root/src/log/fluent-bit/build/start-fluent-bit.sh" "$bundle_ctx/private/"
|
||
fi
|
||
|
||
# 4) Build final bundle image
|
||
local image_tag="argus-sys-metric-test-node-bundle-arm64:${date_tag}"
|
||
echo "\n🔄 Building CPU Bundle image"
|
||
if build_image "CPU Bundle" "$bundle_ctx/Dockerfile" "$image_tag" "$bundle_ctx"; then
|
||
images_built+=("$image_tag")
|
||
# 为兼容现有 compose/部署,额外打无后缀别名
|
||
docker tag "$image_tag" "argus-sys-metric-test-node-bundle:${date_tag}" >/dev/null 2>&1 || true
|
||
if [[ "$want_tag_latest" == "true" ]]; then
|
||
docker tag "$image_tag" argus-sys-metric-test-node-bundle-arm64:latest >/dev/null 2>&1 || true
|
||
docker tag "$image_tag" argus-sys-metric-test-node-bundle:latest >/dev/null 2>&1 || true
|
||
fi
|
||
return 0
|
||
else
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
if [[ "$build_core" == true ]]; then
|
||
if build_image "Elasticsearch" "src/log/elasticsearch/build/Dockerfile" "argus-elasticsearch-arm64:${DEFAULT_IMAGE_TAG}"; then
|
||
images_built+=("argus-elasticsearch-arm64:${DEFAULT_IMAGE_TAG}")
|
||
else
|
||
build_failed=true
|
||
fi
|
||
|
||
echo ""
|
||
|
||
if build_image "Kibana" "src/log/kibana/build/Dockerfile" "argus-kibana-arm64:${DEFAULT_IMAGE_TAG}"; then
|
||
images_built+=("argus-kibana-arm64:${DEFAULT_IMAGE_TAG}")
|
||
else
|
||
build_failed=true
|
||
fi
|
||
|
||
echo ""
|
||
|
||
if build_image "BIND9" "src/bind/build/Dockerfile" "argus-bind9-arm64:${DEFAULT_IMAGE_TAG}"; then
|
||
images_built+=("argus-bind9-arm64:${DEFAULT_IMAGE_TAG}")
|
||
else
|
||
build_failed=true
|
||
fi
|
||
fi
|
||
|
||
echo ""
|
||
|
||
if [[ "$build_master" == true ]]; then
|
||
echo ""
|
||
echo "🔄 Building Master image..."
|
||
# 复用通用 build_image 函数,通过 buildx 构建 ARM64 master 镜像
|
||
if build_image "Master" "src/master/Dockerfile" "argus-master-arm64:${DEFAULT_IMAGE_TAG}" "."; then
|
||
images_built+=("argus-master-arm64:${DEFAULT_IMAGE_TAG}")
|
||
else
|
||
build_failed=true
|
||
fi
|
||
fi
|
||
|
||
if [[ "$build_metric" == true ]]; then
|
||
echo ""
|
||
echo "Building Metric module images..."
|
||
|
||
metric_base_images=(
|
||
"ubuntu:22.04"
|
||
"prom/prometheus:v3.5.0"
|
||
"grafana/grafana:11.1.0"
|
||
)
|
||
|
||
for base_image in "${metric_base_images[@]}"; do
|
||
if ! pull_base_image "$base_image"; then
|
||
build_failed=true
|
||
fi
|
||
done
|
||
|
||
metric_builds=(
|
||
"Metric FTP|src/metric/ftp/build/Dockerfile|argus-metric-ftp-arm64:${DEFAULT_IMAGE_TAG}|src/metric/ftp/build"
|
||
"Metric Prometheus|src/metric/prometheus/build/Dockerfile|argus-metric-prometheus-arm64:${DEFAULT_IMAGE_TAG}|src/metric/prometheus/build"
|
||
"Metric Grafana|src/metric/grafana/build/Dockerfile|argus-metric-grafana-arm64:${DEFAULT_IMAGE_TAG}|src/metric/grafana/build"
|
||
"Metric Prometheus Targets Updater|src/metric/prometheus/build/Dockerfile.targets-updater|argus-metric-prometheus-targets-updater-arm64:${DEFAULT_IMAGE_TAG}|src/metric/prometheus/build"
|
||
)
|
||
|
||
for build_spec in "${metric_builds[@]}"; do
|
||
IFS='|' read -r image_label dockerfile_path image_tag build_context <<< "$build_spec"
|
||
if build_image "$image_label" "$dockerfile_path" "$image_tag" "$build_context"; then
|
||
images_built+=("$image_tag")
|
||
else
|
||
build_failed=true
|
||
fi
|
||
echo ""
|
||
done
|
||
fi
|
||
|
||
# =======================================
|
||
# Sys (system tests) node images
|
||
# =======================================
|
||
|
||
if [[ "$build_sys" == true ]]; then
|
||
echo ""
|
||
echo "Building Sys node images..."
|
||
|
||
sys_base_images=(
|
||
"ubuntu:22.04"
|
||
)
|
||
|
||
# GPU 相关镜像目前仅在 x86_64 上支持;ARM 上不拉取 nvidia/cuda 基础镜像
|
||
if [[ "${ARGUS_TARGET_ARCH:-}" != "arm64" ]]; then
|
||
sys_base_images+=("nvidia/cuda:12.2.2-runtime-ubuntu22.04")
|
||
fi
|
||
|
||
for base_image in "${sys_base_images[@]}"; do
|
||
if ! pull_base_image "$base_image"; then
|
||
build_failed=true
|
||
fi
|
||
done
|
||
sys_builds=(
|
||
"Sys Node|src/sys/build/node/Dockerfile|argus-sys-node-arm64:latest|."
|
||
"Sys Metric Test Node|src/sys/build/arm-cpu-node/Dockerfile|argus-sys-metric-test-node-arm64:latest|."
|
||
)
|
||
|
||
# GPU 测试节点镜像仅在 x86_64 路径构建,ARM 版本暂不支持 DCGM/GPU
|
||
if [[ "${ARGUS_TARGET_ARCH:-}" != "arm64" ]]; then
|
||
sys_builds+=("Sys Metric Test GPU Node|src/sys/build/test-gpu-node/Dockerfile|argus-sys-metric-test-gpu-node:latest|.")
|
||
fi
|
||
|
||
for build_spec in "${sys_builds[@]}"; do
|
||
IFS='|' read -r image_label dockerfile_path image_tag build_context <<< "$build_spec"
|
||
if build_image "$image_label" "$dockerfile_path" "$image_tag" "$build_context"; then
|
||
images_built+=("$image_tag")
|
||
# 与历史 NODE_BUNDLE_IMAGE_TAG 保持兼容:为 ARM CPU 节点镜像打 bundle 别名
|
||
if [[ "$image_tag" == "argus-sys-metric-test-node-arm64:latest" ]]; then
|
||
docker tag "$image_tag" argus-sys-metric-test-node-bundle-arm64:latest >/dev/null 2>&1 || true
|
||
docker tag "$image_tag" argus-sys-metric-test-node-bundle:latest >/dev/null 2>&1 || true
|
||
fi
|
||
else
|
||
build_failed=true
|
||
fi
|
||
echo ""
|
||
done
|
||
fi
|
||
|
||
# =======================================
|
||
# Web & Alert module images
|
||
# =======================================
|
||
|
||
if [[ "$build_web" == true || "$build_alert" == true ]]; then
|
||
echo ""
|
||
echo "Building Web and Alert module images..."
|
||
|
||
# Pre-pull commonly used base images for stability
|
||
web_alert_base_images=(
|
||
"node:20"
|
||
"ubuntu:24.04"
|
||
)
|
||
|
||
for base_image in "${web_alert_base_images[@]}"; do
|
||
if ! pull_base_image "$base_image"; then
|
||
build_failed=true
|
||
fi
|
||
done
|
||
|
||
if [[ "$build_web" == true ]]; then
|
||
web_builds=(
|
||
"Web Frontend|src/web/build_tools/frontend/Dockerfile|argus-web-frontend-arm64:${DEFAULT_IMAGE_TAG}|."
|
||
"Web Proxy|src/web/build_tools/proxy/Dockerfile|argus-web-proxy-arm64:${DEFAULT_IMAGE_TAG}|."
|
||
)
|
||
for build_spec in "${web_builds[@]}"; do
|
||
IFS='|' read -r image_label dockerfile_path image_tag build_context <<< "$build_spec"
|
||
if build_image "$image_label" "$dockerfile_path" "$image_tag" "$build_context"; then
|
||
images_built+=("$image_tag")
|
||
else
|
||
build_failed=true
|
||
fi
|
||
echo ""
|
||
done
|
||
fi
|
||
|
||
if [[ "$build_alert" == true ]]; then
|
||
alert_builds=(
|
||
"Alertmanager|src/alert/alertmanager/build/Dockerfile|argus-alertmanager-arm64:${DEFAULT_IMAGE_TAG}|."
|
||
)
|
||
for build_spec in "${alert_builds[@]}"; do
|
||
IFS='|' read -r image_label dockerfile_path image_tag build_context <<< "$build_spec"
|
||
if build_image "$image_label" "$dockerfile_path" "$image_tag" "$build_context"; then
|
||
images_built+=("$image_tag")
|
||
else
|
||
build_failed=true
|
||
fi
|
||
echo ""
|
||
done
|
||
fi
|
||
fi
|
||
|
||
# =======================================
|
||
# One-click GPU bundle (direct NVIDIA base)
|
||
# =======================================
|
||
|
||
if [[ "$build_gpu_bundle" == true ]]; then
|
||
echo ""
|
||
echo "Building one-click GPU bundle image..."
|
||
if ! build_gpu_bundle_image "$bundle_date" "$cuda_ver" "$client_semver"; then
|
||
build_failed=true
|
||
fi
|
||
fi
|
||
|
||
# =======================================
|
||
# One-click CPU bundle (from ubuntu:22.04)
|
||
# =======================================
|
||
if [[ "$build_cpu_bundle" == true ]]; then
|
||
echo ""
|
||
echo "Building one-click CPU bundle image..."
|
||
if ! build_cpu_bundle_image "${bundle_date}" "${client_semver}" "${tag_latest}"; then
|
||
build_failed=true
|
||
fi
|
||
fi
|
||
|
||
# =======================================
|
||
# One-click Server/Client packaging
|
||
# =======================================
|
||
|
||
if [[ "$build_server_pkg" == true ]]; then
|
||
echo ""
|
||
echo "🧳 Building one-click Server package..."
|
||
if ! build_server_pkg_bundle "${bundle_date}"; then
|
||
build_failed=true
|
||
fi
|
||
fi
|
||
|
||
if [[ "$build_client_pkg" == true ]]; then
|
||
echo ""
|
||
echo "🧳 Building one-click Client-GPU package..."
|
||
if ! build_client_pkg_bundle "${bundle_date}" "${client_semver}" "${cuda_ver}"; then
|
||
build_failed=true
|
||
fi
|
||
fi
|
||
|
||
echo "======================================="
|
||
echo "📦 Build Summary"
|
||
echo "======================================="
|
||
|
||
if [[ ${#images_built[@]} -gt 0 ]]; then
|
||
echo "✅ Successfully built images:"
|
||
for image in "${images_built[@]}"; do
|
||
echo " • $image"
|
||
done
|
||
fi
|
||
|
||
if [[ "$build_failed" == true ]]; then
|
||
echo ""
|
||
echo "❌ Some images failed to build. Please check the errors above."
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "$use_intranet" == true ]]; then
|
||
echo ""
|
||
echo "🌐 Built with intranet mirror configuration"
|
||
fi
|
||
|
||
if [[ "$build_master_offline" == true ]]; then
|
||
echo ""
|
||
echo "🧳 Master offline wheels 已解压到 $master_offline_dir"
|
||
fi
|
||
echo ""
|
||
echo "🚀 Next steps:"
|
||
echo " ./build/save_images.sh --compress # 导出镜像"
|
||
echo " cd src/master/tests && MASTER_IMAGE_TAG=argus-master:offline ./scripts/00_e2e_test.sh"
|
||
echo ""
|