158 lines
5.4 KiB
Bash
Executable File
158 lines
5.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Remove an environment in reverse dependency order.
|
|
#
|
|
# Default scope removes only application and one-shot operation resources.
|
|
# Stateful data, Vault, namespaces, CRDs, and shared operators require explicit
|
|
# opt-in flags.
|
|
|
|
set -Eeuo pipefail
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
# shellcheck source=../lib/common.sh
|
|
. "$SCRIPT_DIR/../lib/common.sh"
|
|
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
GITOPS_ROOT="$REPO_ROOT/gitops"
|
|
NAMESPACE="mnt"
|
|
VSO_NAMESPACE="${VSO_NAMESPACE:-vault-secrets-operator-system}"
|
|
VSO_RELEASE="${VSO_RELEASE:-vault-secrets-operator}"
|
|
MINIO_OPERATOR_NAMESPACE="${MINIO_OPERATOR_NAMESPACE:-minio-operator}"
|
|
MINIO_OPERATOR_RELEASE="${MINIO_OPERATOR_RELEASE:-minio-operator}"
|
|
NAMESPACE_DELETE_INCOMPLETE=0
|
|
|
|
usage() {
|
|
cat >&2 <<'EOF'
|
|
Usage: scripts/bin/teardown.sh <lab|staging|prod>
|
|
|
|
Default:
|
|
Remove stages 50-apps and 40-operations only.
|
|
|
|
Options:
|
|
DELETE_DATA=yes Also remove data, VSO CRs, Vault, and app namespace
|
|
TEARDOWN_PLATFORM=yes Also remove shared Helm operators and stage 00
|
|
(requires DELETE_DATA=yes)
|
|
FORCE_FINALIZERS=yes Last-resort namespace finalizer removal
|
|
(requires DELETE_DATA=yes)
|
|
ALLOW_PROD_DESTRUCTIVE=yes Required for prod
|
|
CONFIRM=yes Non-interactive confirmation
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
delete_entrypoint() {
|
|
local label="$1"
|
|
local entrypoint="$2"
|
|
[[ -f "$entrypoint/kustomization.yaml" ]] || {
|
|
log "[$label] entrypoint 없음: skip"
|
|
return 0
|
|
}
|
|
|
|
log "[$label] delete"
|
|
kubectl delete -k "$entrypoint" \
|
|
--ignore-not-found \
|
|
--wait=true \
|
|
--timeout=300s
|
|
}
|
|
|
|
delete_application_scope() {
|
|
delete_entrypoint "50-apps" "$CLUSTER_ROOT/stages/50-apps"
|
|
delete_entrypoint "40-operations" "$CLUSTER_ROOT/stages/40-operations"
|
|
}
|
|
|
|
delete_data_scope() {
|
|
[[ "${DELETE_DATA:-}" == "yes" ]] || {
|
|
log "DELETE_DATA 미지정: data / secrets / Vault / namespace 보존"
|
|
return 0
|
|
}
|
|
|
|
delete_entrypoint "35-registry" "$CLUSTER_ROOT/stages/35-registry"
|
|
delete_entrypoint "30-data" "$CLUSTER_ROOT/stages/30-data"
|
|
delete_entrypoint "20-secrets" "$CLUSTER_ROOT/stages/20-secrets"
|
|
delete_entrypoint "10-vault" "$CLUSTER_ROOT/stages/10-vault"
|
|
|
|
log "namespace/$NAMESPACE 삭제"
|
|
if ! kubectl delete namespace "$NAMESPACE" \
|
|
--ignore-not-found \
|
|
--wait=true \
|
|
--timeout=300s; then
|
|
warn "namespace 삭제가 제한 시간 안에 완료되지 않았습니다."
|
|
NAMESPACE_DELETE_INCOMPLETE=1
|
|
fi
|
|
}
|
|
|
|
force_finalize_if_requested() {
|
|
[[ "${FORCE_FINALIZERS:-}" == "yes" ]] || return 0
|
|
[[ "${DELETE_DATA:-}" == "yes" ]] \
|
|
|| die "FORCE_FINALIZERS=yes 는 DELETE_DATA=yes 와 함께만 사용할 수 있습니다."
|
|
ns_exists "$NAMESPACE" || return 0
|
|
|
|
warn "FORCE_FINALIZERS=yes: orphaned volume/controller state가 생길 수 있습니다."
|
|
confirm "namespace/$NAMESPACE finalizer를 강제로 제거합니까?" || die "사용자 취소"
|
|
strip_finalizers_all_ns_resources "$NAMESPACE"
|
|
force_finalize_namespace "$NAMESPACE"
|
|
wait_namespace_gone "$NAMESPACE" 120 \
|
|
|| die "namespace/$NAMESPACE 강제 finalize 후에도 남아 있습니다."
|
|
NAMESPACE_DELETE_INCOMPLETE=0
|
|
}
|
|
|
|
delete_platform_scope() {
|
|
[[ "${TEARDOWN_PLATFORM:-}" == "yes" ]] || {
|
|
log "TEARDOWN_PLATFORM 미지정: 공유 operator / CRD / stage 00 보존"
|
|
return 0
|
|
}
|
|
[[ "${DELETE_DATA:-}" == "yes" ]] \
|
|
|| die "TEARDOWN_PLATFORM=yes 는 DELETE_DATA=yes 와 함께만 사용할 수 있습니다."
|
|
|
|
warn "공유 controller와 cluster-scoped 리소스를 제거합니다."
|
|
confirm "이 클러스터가 다른 환경과 공유되지 않음을 확인했습니까?" || die "사용자 취소"
|
|
|
|
helm -n "$VSO_NAMESPACE" uninstall "$VSO_RELEASE" --wait --timeout=5m \
|
|
2>/dev/null || warn "VSO Helm release가 없거나 uninstall에 실패했습니다."
|
|
helm -n "$MINIO_OPERATOR_NAMESPACE" uninstall "$MINIO_OPERATOR_RELEASE" --wait --timeout=5m \
|
|
2>/dev/null || warn "MinIO Operator Helm release가 없거나 uninstall에 실패했습니다."
|
|
|
|
delete_entrypoint "00-platform" "$CLUSTER_ROOT/stages/00-platform"
|
|
kubectl delete namespace "$VSO_NAMESPACE" "$MINIO_OPERATOR_NAMESPACE" \
|
|
--ignore-not-found \
|
|
--wait=true \
|
|
--timeout=300s \
|
|
|| warn "operator namespace 삭제가 완료되지 않았습니다."
|
|
}
|
|
|
|
main() {
|
|
ENV_NAME="${1:-}"
|
|
case "$ENV_NAME" in
|
|
lab | staging | prod) ;;
|
|
*) usage ;;
|
|
esac
|
|
|
|
CLUSTER_ROOT="$GITOPS_ROOT/clusters/$ENV_NAME/main"
|
|
[[ -f "$CLUSTER_ROOT/all/kustomization.yaml" ]] \
|
|
|| die "클러스터 entrypoint가 없습니다: $CLUSTER_ROOT"
|
|
|
|
require_cmd kubectl helm jq
|
|
require_kube_context "$ENV_NAME"
|
|
require_production_gate "$ENV_NAME" "$NAMESPACE"
|
|
|
|
local scope="apps + one-shot operations"
|
|
[[ "${DELETE_DATA:-}" == "yes" ]] && scope="$scope + data + Vault + namespace"
|
|
[[ "${TEARDOWN_PLATFORM:-}" == "yes" ]] && scope="$scope + shared platform"
|
|
|
|
log "Project-Infra teardown: env=$ENV_NAME context=$KUBE_CONTEXT_LOCKED"
|
|
confirm "삭제 범위: $scope. 계속합니까?" || die "사용자 취소"
|
|
|
|
delete_application_scope
|
|
delete_data_scope
|
|
force_finalize_if_requested
|
|
delete_platform_scope
|
|
|
|
if ((NAMESPACE_DELETE_INCOMPLETE == 1)) && ns_exists "$NAMESPACE"; then
|
|
die "$ENV_NAME teardown 미완료: namespace/$NAMESPACE 가 남아 있습니다."
|
|
fi
|
|
|
|
log "$ENV_NAME teardown 완료: $scope"
|
|
}
|
|
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
main "$@"
|
|
fi
|