баг-фикс 30/34
This commit is contained in:
64
scripts/deploy-images.sh
Normal file
64
scripts/deploy-images.sh
Normal file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
NAMESPACE=${KUBE_NAMESPACE:-magistr}
|
||||
BACKEND_REF=${1:-}
|
||||
FRONTEND_REF=${2:-}
|
||||
|
||||
log() {
|
||||
printf '[CI/CD] %s\n' "$1"
|
||||
}
|
||||
|
||||
fail() {
|
||||
printf '[CI/CD] Ошибка: %s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
require_digest() {
|
||||
local image_ref=$1
|
||||
local component=$2
|
||||
if [[ ! "$image_ref" =~ ^[^[:space:]@]+@sha256:[0-9a-f]{64}$ ]]; then
|
||||
fail "для ${component} требуется полный immutable image digest"
|
||||
fi
|
||||
}
|
||||
|
||||
require_digest "$BACKEND_REF" "backend"
|
||||
require_digest "$FRONTEND_REF" "frontend"
|
||||
|
||||
previous_backend=$(kubectl get deployment backend -n "$NAMESPACE" \
|
||||
-o 'jsonpath={.spec.template.spec.containers[?(@.name=="backend")].image}')
|
||||
previous_frontend=$(kubectl get deployment frontend -n "$NAMESPACE" \
|
||||
-o 'jsonpath={.spec.template.spec.containers[?(@.name=="frontend")].image}')
|
||||
|
||||
[[ -n "$previous_backend" ]] || fail "не удалось определить текущий образ backend"
|
||||
[[ -n "$previous_frontend" ]] || fail "не удалось определить текущий образ frontend"
|
||||
|
||||
rollback() {
|
||||
local failed=0
|
||||
log "Rollout завершился ошибкой, возвращаем предыдущие образы"
|
||||
kubectl set image deployment/backend backend="$previous_backend" -n "$NAMESPACE" || failed=1
|
||||
kubectl set image deployment/frontend frontend="$previous_frontend" -n "$NAMESPACE" || failed=1
|
||||
kubectl rollout status deployment/frontend -n "$NAMESPACE" --timeout=120s || failed=1
|
||||
kubectl rollout status deployment/backend -n "$NAMESPACE" --timeout=300s || failed=1
|
||||
if [[ "$failed" -ne 0 ]]; then
|
||||
printf '[CI/CD] Ошибка: автоматический rollback требует вмешательства оператора\n' >&2
|
||||
return 1
|
||||
fi
|
||||
log "Предыдущие образы восстановлены"
|
||||
}
|
||||
|
||||
log "Применяем проверенные image digests"
|
||||
if ! kubectl set image deployment/backend backend="$BACKEND_REF" -n "$NAMESPACE" \
|
||||
|| ! kubectl set image deployment/frontend frontend="$FRONTEND_REF" -n "$NAMESPACE"; then
|
||||
rollback || true
|
||||
fail "не удалось обновить Deployment"
|
||||
fi
|
||||
|
||||
if ! kubectl rollout status deployment/frontend -n "$NAMESPACE" --timeout=120s \
|
||||
|| ! kubectl rollout status deployment/backend -n "$NAMESPACE" --timeout=300s; then
|
||||
rollback || true
|
||||
fail "новая ревизия не достигла состояния Ready"
|
||||
fi
|
||||
|
||||
log "Immutable rollout успешно завершён"
|
||||
56
scripts/test-deploy-images.sh
Normal file
56
scripts/test-deploy-images.sh
Normal file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
DEPLOY_SCRIPT="$ROOT_DIR/scripts/deploy-images.sh"
|
||||
CALL_LOG=$(mktemp)
|
||||
trap 'rm -f "$CALL_LOG"' EXIT
|
||||
|
||||
OLD_BACKEND='registry.local/magistr-backend@sha256:1111111111111111111111111111111111111111111111111111111111111111'
|
||||
OLD_FRONTEND='registry.local/magistr-frontend@sha256:2222222222222222222222222222222222222222222222222222222222222222'
|
||||
NEW_BACKEND='registry.local/magistr-backend@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
||||
NEW_FRONTEND='registry.local/magistr-frontend@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
|
||||
|
||||
kubectl() {
|
||||
printf '%s\n' "$*" >> "$CALL_LOG"
|
||||
if [[ "$1" == "get" && "$3" == "backend" ]]; then
|
||||
printf '%s' "$OLD_BACKEND"
|
||||
return 0
|
||||
fi
|
||||
if [[ "$1" == "get" && "$3" == "frontend" ]]; then
|
||||
printf '%s' "$OLD_FRONTEND"
|
||||
return 0
|
||||
fi
|
||||
if [[ "${DEPLOY_TEST_MODE:-success}" == "failure" \
|
||||
&& "$1" == "rollout" \
|
||||
&& "$3" == "deployment/backend" \
|
||||
&& "${DEPLOY_TEST_FAILURE_EMITTED:-false}" == "false" ]]; then
|
||||
DEPLOY_TEST_FAILURE_EMITTED=true
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
export -f kubectl
|
||||
export CALL_LOG OLD_BACKEND OLD_FRONTEND DEPLOY_TEST_MODE DEPLOY_TEST_FAILURE_EMITTED
|
||||
|
||||
if bash "$DEPLOY_SCRIPT" 'registry.local/backend:main' "$NEW_FRONTEND" >/dev/null 2>&1; then
|
||||
printf 'Ошибка теста: mutable backend tag не был отклонён\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
: > "$CALL_LOG"
|
||||
DEPLOY_TEST_MODE=success bash "$DEPLOY_SCRIPT" "$NEW_BACKEND" "$NEW_FRONTEND"
|
||||
grep --fixed-strings "set image deployment/backend backend=$NEW_BACKEND" "$CALL_LOG" >/dev/null
|
||||
grep --fixed-strings "set image deployment/frontend frontend=$NEW_FRONTEND" "$CALL_LOG" >/dev/null
|
||||
|
||||
: > "$CALL_LOG"
|
||||
if DEPLOY_TEST_MODE=failure DEPLOY_TEST_FAILURE_EMITTED=false \
|
||||
bash "$DEPLOY_SCRIPT" "$NEW_BACKEND" "$NEW_FRONTEND"; then
|
||||
printf 'Ошибка теста: неуспешный rollout завершился кодом 0\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
grep --fixed-strings "set image deployment/backend backend=$OLD_BACKEND" "$CALL_LOG" >/dev/null
|
||||
grep --fixed-strings "set image deployment/frontend frontend=$OLD_FRONTEND" "$CALL_LOG" >/dev/null
|
||||
|
||||
printf 'Проверка immutable rollout и rollback завершена успешно\n'
|
||||
Reference in New Issue
Block a user