iac_modules/scripts/run.sh

290 lines
8.3 KiB
Bash
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
set -e
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$PROJECT_ROOT"
# ========== 默认参数 ==========
DEFAULT_ENV="sit"
DEFAULT_CONFIG="${PROJECT_ROOT}/config"
# ========== 模块路径 ==========
PULUMI_DIR="${PROJECT_ROOT}/iac_modules/pulumi"
TERRAFORM_DIR="${PROJECT_ROOT}/iac_modules/terraform"
ANSIBLE_DIR="${PROJECT_ROOT}/ansible"
# ================================
# ✅ 自动加载 Pulumi passphrase
# ================================
export PULUMI_CONFIG_PASSPHRASE_FILE="${PULUMI_CONFIG_PASSPHRASE_FILE:-$HOME/.pulumi-passphrase}"
if [ ! -f "$PULUMI_CONFIG_PASSPHRASE_FILE" ]; then
echo "⚠️ 未检测到 Pulumi 密码文件: $PULUMI_CONFIG_PASSPHRASE_FILE"
echo "请先创建该文件并写入 passphrase例如"
echo " echo 'changeme123' > ~/.pulumi-passphrase && chmod 600 ~/.pulumi-passphrase"
exit 1
else
echo "🔐 Pulumi 密码文件已加载: $PULUMI_CONFIG_PASSPHRASE_FILE"
fi
# ========== 参数解析 ==========
if [[ -n "$1" && "$1" != up && "$1" != down && "$1" != delete && "$1" != export && "$1" != import && "$1" != init && "$1" != ansible && "$1" != help ]]; then
STACK_ENV="$1"
ACTION="${2:-up}"
else
STACK_ENV="${STACK_ENV:-$DEFAULT_ENV}"
ACTION="${1:-help}"
fi
STACK_NAME="${STACK_NAME:-$STACK_ENV}"
CONFIG_PATH="${CONFIG_PATH:-${DEFAULT_CONFIG}/${STACK_ENV}}"
# ========== 配置目录检查 ==========
if [ ! -d "$CONFIG_PATH" ] || [ -z "$(find "$CONFIG_PATH" -maxdepth 1 -name '*.yml' -o -name '*.yaml')" ]; then
echo "⚠️ 配置目录为空:$CONFIG_PATH,跳过部署"
exit 0
fi
# ========== 帮助信息 ==========
print_help() {
echo ""
echo "🧰 iac_cli - 多环境自动化管理器 (IaC + Ansible + GitOps)"
echo ""
echo "用法:"
echo " ./scripts/run.sh [env] [命令]"
echo " STACK_ENV=prod CONFIG_PATH=config/prod ./scripts/run.sh up"
echo ""
echo "🌍 当前环境: $STACK_ENV"
echo "📁 当前配置路径: $CONFIG_PATH"
echo ""
echo "支持命令:"
echo " init ⚙️ 初始化依赖"
echo " up 🚀 部署资源"
echo " down 🔥 销毁资源"
echo " export 📤 导出 stack 状态"
echo " import 📥 导入 stack 状态"
echo " ansible 🧪 执行 ansible-playbook"
echo " help 📖 显示帮助"
echo ""
}
# ========== 检查 Pulumi ==========
ensure_pulumi() {
if ! command -v pulumi &> /dev/null; then
echo "📦 未检测到 Pulumi正在自动安装..."
case "$(uname | tr '[:upper:]' '[:lower:]')" in
linux)
curl -fsSL https://get.pulumi.com | sh
export PATH="$HOME/.pulumi/bin:$PATH"
;;
darwin)
brew install pulumi || (curl -fsSL https://get.pulumi.com | sh && export PATH="$HOME/.pulumi/bin:$PATH")
;;
msys*|mingw*|cygwin*)
echo "👉 Windows 用户请手动安装 Pulumihttps://www.pulumi.com/docs/get-started/install/"
exit 1
;;
*)
echo "❌ 当前平台不支持自动安装 Pulumi"
exit 1
;;
esac
fi
echo "✅ Pulumi 版本: $(pulumi version)"
}
# ========== 检查 Ansible ==========
ensure_ansible() {
if ! command -v ansible &> /dev/null; then
echo "❌ 未检测到 Ansible请手动安装"
case "$(uname | tr '[:upper:]' '[:lower:]')" in
linux)
echo "👉 Ubuntu/Debian: sudo apt install ansible"
echo "👉 RHEL/CentOS: sudo yum install ansible"
;;
darwin)
echo "👉 macOS: brew install ansible"
;;
msys*|mingw*|cygwin*)
echo "👉 Windows 用户请参考官方安装指南https://docs.ansible.com/"
;;
*)
echo "👉 其他平台请参考https://docs.ansible.com/"
;;
esac
exit 1
else
echo "✅ Ansible 已安装: $(ansible --version | head -n 1)"
fi
}
# ========== 检查 Terraform ==========
ensure_terraform() {
if ! command -v terraform &> /dev/null; then
echo "❌ 未检测到 Terraform请手动安装"
echo "👉 https://developer.hashicorp.com/terraform/install"
exit 1
fi
echo "✅ Terraform 已安装: $(terraform version | head -n1)"
}
# ========== 环境初始化检查 ==========
init_env() {
echo "⚙️ 初始化 Pulumi + Ansible 环境..."
# 1⃣ 检查 Pulumi
ensure_pulumi
# 2⃣ 安装 Python 依赖
mkdir -p ~/.pip
cat > ~/.pip/pip.conf <<EOF
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
EOF
if [ -f "requirements.txt" ]; then
echo "📦 安装 Python 依赖..."
# 1. 创建虚拟环境
python3 -m venv .venv
# 2. 激活虚拟环境zsh/bash
source .venv/bin/activate
# 3. 安装依赖
"$PYTHON_BIN" -m pip install -r "$PROJECT_ROOT/requirements.txt"
fi
# 3⃣ 检查 Ansible
ensure_ansible
# 4⃣ 检查 Terraform可选
if [ -d "$TERRAFORM_DIR" ]; then
ensure_terraform
fi
# 5⃣ 初始化 Pulumi Stack
cd "$PULUMI_DIR"
pulumi login --local > /dev/null
if ! pulumi stack ls | grep -q "$STACK_NAME"; then
pulumi stack init "$STACK_NAME"
else
echo "✅ Stack 已存在:$STACK_NAME"
fi
echo "✅ 初始化完成 ✅"
}
# ========== 执行 Pulumi ==========
pulumi_run() {
cd "$PULUMI_DIR"
# 设置 Python 虚拟环境路径
VENV_DIR="$PROJECT_ROOT/.venv"
PYTHON_BIN="$VENV_DIR/bin/python"
# 1. 激活虚拟环境
echo "✅ 激活虚拟环境: $VENV_DIR"
# 如果没有虚拟环境就创建并安装依赖
if [ ! -d "$VENV_DIR" ]; then
echo "📦 创建 Python 虚拟环境: $VENV_DIR"
python3 -m venv "$VENV_DIR"
source "$VENV_DIR/bin/activate"
python3 -m pip install -r requirements.txt
else
echo "✅ 虚拟环境已存在,直接激活"
source "$VENV_DIR/bin/activate"
fi
source "$VENV_DIR/bin/activate"
# 2. 确保 pulumi 安装在虚拟环境中
if ! "$PYTHON_BIN" -c "import pulumi" &> /dev/null; then
echo "⚠️ Pulumi SDK 未安装,正在安装..."
"$PYTHON_BIN" -m pip install --upgrade pip
"$PYTHON_BIN" -m pip install pulumi pulumi-aws PyYAML
else
echo "✅ Pulumi SDK 已就绪"
fi
# 3. 告诉 Pulumi 使用这个 Python
export PULUMI_PYTHON_CMD="$PYTHON_BIN"
# ✅ 明确选择 stack若不存在则创建避免交互式提示
pulumi stack select "$STACK_NAME" 2>/dev/null || pulumi stack init "$STACK_NAME"
# ✅ 自动从 config 读取 region 并设置 pulumi config防止 provider 报错)
if [ -f "$CONFIG_PATH/base.yaml" ]; then
region=$(grep '^ *region:' "$CONFIG_PATH/base.yaml" | awk '{print $2}')
if [ -n "$region" ]; then
pulumi config set aws:region "$region" --stack "$STACK_NAME" --non-interactive
echo "✅ Pulumi config 中设置 aws:region=$region"
fi
fi
if [ ! -d "$CONFIG_PATH" ] || [ -z "$(find "$CONFIG_PATH" -maxdepth 1 -name '*.yml' -o -name '*.yaml')" ]; then
echo "⚠️ 配置目录为空:$CONFIG_PATH,跳过部署"
exit 0
fi
case "$ACTION" in
up)
echo "🚀 正在部署 stack: $STACK_NAME"
pulumi up --yes
;;
down)
echo "⚠️ 先执行 destroy 确保资源干净"
pulumi destroy --yes
echo "🔄 执行 refresh 同步状态..."
pulumi refresh --yes
echo "🗑️ 正式删除 Stack..."
pulumi stack rm "$STACK_NAME" --yes
;;
export)
echo "📤 导出 stack 状态"
pulumi stack export --file stack-export.json
;;
import)
echo "📥 导入 stack 状态"
pulumi stack import --file stack-export.json
;;
init)
init_env
;;
*)
print_help
;;
esac
}
# ========== 执行 Ansible ==========
run_ansible() {
if [ ! -f scripts/dynamic_inventory.py ]; then
echo "❌ 未找到 scripts/dynamic_inventory.py"
exit 1
fi
echo "🧪 执行 Ansible Playbook"
ansible-playbook -i scripts/dynamic_inventory.py ansible/playbooks/common_setup.yml -D
ansible-playbook -i scripts/dynamic_inventory.py ansible/playbooks/vpn-wireguard-site.yaml -D -l slave-1,master-1
ansible-playbook -i scripts/dynamic_inventory.py ansible/playbooks/vpn-overlay.yaml -D -l slave-1,master-1
ansible-playbook -i scripts/dynamic_inventory.py ansible/playbooks/k3s-cluster.yaml -D -l slave-1,master-1
}
# ========== 分发 ==========
case "$ACTION" in
up|down|delete|export|import|init)
export CONFIG_PATH
export STACK_ENV
pulumi_run
;;
ansible)
run_ansible
;;
help|*)
print_help
;;
esac