#!/usr/bin/env bash # etcd 이미지 기능 검증 — 호스트에서 bash 로 실행된다(build-hardened-image.sh 가 # `env TAG=... PLATFORM=... SOURCE_COMMIT=... XTEXT_FIX_VERSION=... bash verify.sh` # 형태로 호출한다). 최종 베이스가 bci-micro 라 bash/coreutils 가 있으므로(패키지 # 매니저만 없음 — .claude/image-authoring.md), cnpg-postgresql/verify.sh 와 같은 # 게스트 셸 패턴을 쓴다(cloudnative-pg 처럼 셸 없는 distroless 가 아니다). # # 마지막 줄에 VERIFY-OK 를 출력하면 통과다. build-hardened-image.sh 가 그것으로 판정한다. # # 이 이미지에 요구하는 것 # - /usr/local/bin/etcd·etcdctl·etcdutl 이 PATH 에 있어야 한다 (chart 의 startup/ # liveness/readiness probe 가 /usr/local/bin/etcdctl 을 하드코딩해 호출한다) # - 단일 노드로 기동해 put/get 왕복이 실제로 동작해야 한다 (게이트 0건이어도 못 쓰는 # 이미지는 무의미하다 — .claude/image-authoring.md 5번) set -e TAG="${TAG:?TAG 환경변수가 필요하다}" PLATFORM="${PLATFORM:-linux/amd64}" SOURCE_COMMIT="${SOURCE_COMMIT:?SOURCE_COMMIT 환경변수가 필요하다 (build-hardened-image.sh 가 build.env 에서 전달)}" docker run --rm -i --platform "$PLATFORM" -e SOURCE_COMMIT="$SOURCE_COMMIT" --entrypoint sh "$TAG" <<'GUEST' set -e echo "== 바이너리 탐색 (PATH 기준) ==" for b in etcd etcdctl etcdutl; do p=$(command -v "$b") || { echo "FAIL: $b 를 PATH 에서 찾을 수 없다"; exit 1; } echo " $b -> $p" done echo "== 버전 (pinned commit 반영 확인) ==" # sed 가 없다(bci-micro 는 bash·coreutils 는 있지만 sed 는 별도 패키지라 빠져 있다 — # 2026-07-31 CI 에서 실측: "sh: sed: command not found"). 순수 셸 루프로 들여쓴다. OUT="$(etcd --version)" while IFS= read -r line; do echo " $line"; done </tmp/etcd-verify.log 2>&1 & ETCD_PID=$! trap 'kill $ETCD_PID 2>/dev/null || true' EXIT echo "== health 대기 (최대 30s) ==" ok=0 for i in $(seq 1 30); do if etcdctl endpoint health >/dev/null 2>&1; then ok=1; break; fi sleep 1 done if [ "$ok" != "1" ]; then echo "FAIL: etcd 가 30초 내에 healthy 상태가 되지 못했다" cat /tmp/etcd-verify.log exit 1 fi HEALTH="$(etcdctl endpoint health)" while IFS= read -r line; do echo " $line"; done </dev/null answer="$(etcdctl get smoke-test --print-value-only)" [ "$answer" = "ok" ] || { echo "FAIL: get 응답 이상 (got: '$answer')"; exit 1; } echo " get smoke-test => '$answer'" kill "$ETCD_PID" 2>/dev/null || true trap - EXIT echo "VERIFY-OK" GUEST