#!/bin/bash # ============================================================================= # Script para Adicionar Novo Cliente # ============================================================================= # # Este script provisiona um novo cliente com: # - n8n em namespace separado (cliente-n8n) # - Organização no Gitea compartilhado (opcional) # # Uso: # ./add-client.sh # # Exemplo: # ./add-client.sh acme # -> Cria namespace acme-n8n com n8n # -> Cria organização /acme no Gitea (se disponível) # # Pré-requisitos: # - ./setup.sh já executado (gera .env com configurações) # - kubectl configurado # - Helm instalado # # ============================================================================= set -e # Cores para output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[OK]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERRO]${NC} $1"; } SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" CLIENT=$1 # ============================================================================= # CARREGAR CONFIGURAÇÃO # ============================================================================= if [[ ! -f "$SCRIPT_DIR/.env" ]]; then log_error "Arquivo .env não encontrado!" log_error "Execute ./setup.sh primeiro para configurar o ambiente." exit 1 fi source "$SCRIPT_DIR/.env" # Suporte ao novo formato (N8N_HOST) e legado (DOMAIN) if [[ -n "$N8N_HOST" && -z "$DOMAIN" ]]; then # Extrair DOMAIN do N8N_HOST (ex: n8n.kube.quest → kube.quest) DOMAIN=$(echo "$N8N_HOST" | sed 's/^[^.]*\.//') fi if [[ -z "$DOMAIN" ]]; then log_error "Variável DOMAIN ou N8N_HOST não definida no .env" log_error "Execute ./setup.sh novamente." exit 1 fi # Carregar configuração do Gitea se disponível GITEA_HOST="" if [[ -f "$SCRIPT_DIR/../aula-10/.env" ]]; then source "$SCRIPT_DIR/../aula-10/.env" fi # ============================================================================= # VALIDAÇÕES # ============================================================================= if [ -z "$CLIENT" ]; then echo "Uso: $0 " echo "" echo "Exemplo:" echo " $0 acme" echo "" echo "Configuração atual (de .env):" echo " Domínio: ${DOMAIN}" echo " CloudFlare: ${USE_CLOUDFLARE}" echo " Let's Encrypt: ${USE_LETSENCRYPT}" echo "" echo "Isso vai criar:" echo " - Namespace: acme-n8n" PROTOCOL="https" [[ "$USE_CLOUDFLARE" == "false" && "$USE_LETSENCRYPT" == "false" ]] && PROTOCOL="http" echo " - n8n em: ${PROTOCOL}://acme-n8n.${DOMAIN}" if [[ -n "$GITEA_HOST" ]]; then echo " - Gitea organização: https://${GITEA_HOST}/acme/ (se configurado)" fi exit 1 fi # Validar nome do cliente (só letras minúsculas, números e hífens) if ! [[ "$CLIENT" =~ ^[a-z0-9-]+$ ]]; then log_error "Nome do cliente inválido: $CLIENT" log_error "Use apenas letras minúsculas, números e hífens" exit 1 fi log_info "Verificando pré-requisitos..." if ! command -v kubectl &> /dev/null; then log_error "kubectl não encontrado" exit 1 fi if ! command -v helm &> /dev/null; then log_error "Helm não encontrado" exit 1 fi if ! kubectl cluster-info &> /dev/null; then log_error "Não foi possível conectar ao cluster" exit 1 fi log_success "Pré-requisitos OK" echo "" echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" echo -e "${CYAN} Adicionando Cliente: $CLIENT${NC}" echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" echo "" # ============================================================================= # 1. CRIAR NAMESPACE PARA N8N # ============================================================================= log_info "Criando namespace ${CLIENT}-n8n..." kubectl create namespace ${CLIENT}-n8n --dry-run=client -o yaml | kubectl apply -f - log_success "Namespace criado" # ============================================================================= # 2. INSTALAR N8N # ============================================================================= log_info "Instalando n8n para ${CLIENT}..." # Verificar se base-n8n-values.yaml existe if [ ! -f "$SCRIPT_DIR/base-n8n-values.yaml" ]; then log_error "Arquivo base-n8n-values.yaml não encontrado em $SCRIPT_DIR" exit 1 fi # Adicionar repo se necessário helm repo add community-charts https://community-charts.github.io/helm-charts 2>/dev/null || true helm repo update # Construir argumentos do Helm dinamicamente HELM_ARGS="" # Configurar host do ingress HELM_ARGS="$HELM_ARGS --set ingress.enabled=true" HELM_ARGS="$HELM_ARGS --set ingress.className=nginx" HELM_ARGS="$HELM_ARGS --set ingress.hosts[0].host=${CLIENT}-n8n.${DOMAIN}" HELM_ARGS="$HELM_ARGS --set ingress.hosts[0].paths[0].path=/" HELM_ARGS="$HELM_ARGS --set ingress.hosts[0].paths[0].pathType=Prefix" # Configurar webhook URL if [[ "$USE_CLOUDFLARE" == "true" || "$USE_LETSENCRYPT" == "true" ]]; then HELM_ARGS="$HELM_ARGS --set webhook.url=https://${CLIENT}-n8n.${DOMAIN}" else HELM_ARGS="$HELM_ARGS --set webhook.url=http://${CLIENT}-n8n.${DOMAIN}" fi # Configurar TLS (se Let's Encrypt) if [[ "$USE_LETSENCRYPT" == "true" ]]; then HELM_ARGS="$HELM_ARGS --set ingress.annotations.cert-manager\\.io/cluster-issuer=letsencrypt" HELM_ARGS="$HELM_ARGS --set ingress.tls[0].hosts[0]=${CLIENT}-n8n.${DOMAIN}" HELM_ARGS="$HELM_ARGS --set ingress.tls[0].secretName=${CLIENT}-n8n-tls" fi # Configurar N8N_SECURE_COOKIE (se HTTPS) if [[ "$USE_CLOUDFLARE" == "true" || "$USE_LETSENCRYPT" == "true" ]]; then HELM_ARGS="$HELM_ARGS --set main.extraEnvVars.N8N_SECURE_COOKIE=true" HELM_ARGS="$HELM_ARGS --set worker.extraEnvVars.N8N_SECURE_COOKIE=true" HELM_ARGS="$HELM_ARGS --set webhook.extraEnvVars.N8N_SECURE_COOKIE=true" fi # Instalar n8n eval helm upgrade --install ${CLIENT}-n8n community-charts/n8n \ --namespace ${CLIENT}-n8n \ -f "$SCRIPT_DIR/base-n8n-values.yaml" \ $HELM_ARGS \ --wait \ --timeout 5m log_success "n8n instalado" # ============================================================================= # 3. CRIAR ORGANIZAÇÃO NO GITEA (opcional) # ============================================================================= log_info "Verificando Gitea..." # Obter token do Gitea if [ -z "$GITEA_TOKEN" ]; then GITEA_TOKEN=$(kubectl get secret gitea-admin-secret \ -n gitea \ -o jsonpath='{.data.password}' 2>/dev/null | base64 -d || echo "") fi if [ -z "$GITEA_TOKEN" ]; then log_warn "Gitea não encontrado ou não configurado" log_warn "Pule esta etapa ou crie a organização manualmente" else log_info "Criando organização no Gitea..." # Usar GITEA_HOST se disponível (da aula-10/.env) if [[ -n "$GITEA_HOST" ]]; then GITEA_URL="https://${GITEA_HOST}" else GITEA_URL="https://gitea.${DOMAIN}" fi # Criar organização via API RESULT=$(curl -s --request POST "${GITEA_URL}/api/v1/orgs" \ --header "Authorization: token ${GITEA_TOKEN}" \ --header "Content-Type: application/json" \ --data "{\"username\":\"${CLIENT}\",\"visibility\":\"private\"}" \ --write-out "%{http_code}" \ --output /tmp/gitea-org-result.json 2>/dev/null || echo "000") if [ "$RESULT" == "201" ]; then log_success "Organização criada no Gitea" elif [ "$RESULT" == "422" ]; then log_warn "Organização já existe ou erro de validação" else log_warn "Não foi possível criar organização (HTTP $RESULT)" log_warn "Crie manualmente em ${GITEA_URL}/-/admin/orgs" fi fi # ============================================================================= # RESUMO # ============================================================================= # Obter IP do LoadBalancer LB_IP=$(kubectl get svc ingress-nginx-controller \ -n ingress-nginx \ -o jsonpath='{.status.loadBalancer.ingress[0].ip}' 2>/dev/null || echo "") # Determinar protocolo PROTOCOL="https" [[ "$USE_CLOUDFLARE" == "false" && "$USE_LETSENCRYPT" == "false" ]] && PROTOCOL="http" echo "" echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" echo -e "${GREEN} Cliente $CLIENT Provisionado!${NC}" echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" echo "" echo "Serviços:" echo -e " n8n: ${GREEN}${PROTOCOL}://${CLIENT}-n8n.${DOMAIN}${NC}" if [ -n "$GITEA_TOKEN" ]; then if [[ -n "$GITEA_HOST" ]]; then echo -e " Gitea: ${GREEN}https://${GITEA_HOST}/${CLIENT}/${NC}" else echo -e " Gitea: ${GREEN}https://gitea.${DOMAIN}/${CLIENT}/${NC}" fi fi echo "" if [[ "$USE_CLOUDFLARE" == "true" ]]; then echo "Configure no CloudFlare:" echo -e " ${YELLOW}Tipo:${NC} A" echo -e " ${YELLOW}Nome:${NC} ${CLIENT}-n8n" echo -e " ${YELLOW}Conteúdo:${NC} ${GREEN}${LB_IP}${NC}" echo -e " ${YELLOW}Proxy:${NC} ✓ (ícone laranja)" echo "" echo "(Ou use o wildcard *.${DOMAIN} se já configurado)" else echo "Configure o DNS:" echo -e " ${YELLOW}Tipo:${NC} A" echo -e " ${YELLOW}Nome:${NC} ${CLIENT}-n8n" echo -e " ${YELLOW}Valor:${NC} ${GREEN}${LB_IP}${NC}" echo "" echo "(Ou use o wildcard *.${DOMAIN} se já configurado)" fi if [ -n "$GITEA_TOKEN" ]; then echo "" echo "Git clone:" if [[ -n "$GITEA_HOST" ]]; then echo " git clone git@${GITEA_HOST}:${CLIENT}/meu-projeto.git" else echo " git clone git@gitea.${DOMAIN}:${CLIENT}/meu-projeto.git" fi fi echo "" echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"