#!/bin/bash # ============================================================================= # SACC v4 - Script de Creacion de Entorno TEST # ============================================================================= # Cuenta AWS: 668889063715 # Region: mx-central-1 # # Este script: # 1. Valida prerequisitos (AWS CLI, Terraform, credenciales) # 2. Verifica que no existan recursos con conflictos de nombres # 3. Crea backend S3/DynamoDB para estado Terraform # 4. Ejecuta terraform init/plan/apply # 5. Genera inventario Ansible # 6. Ejecuta playbooks de Ansible # 7. Verifica health checks # # USO: # export AWS_ACCESS_KEY_ID=... # export AWS_SECRET_ACCESS_KEY=... # export AWS_SESSION_TOKEN=... # export AWS_DEFAULT_REGION=mx-central-1 # ./create-test-environment.sh # # IMPORTANTE: NO ejecutar en produccion # ============================================================================= set -euo pipefail # Colores para output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # ============================================================================= # CONFIGURACION # ============================================================================= SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" TERRAFORM_DIR="$PROJECT_ROOT/terraform/environments/test" ANSIBLE_DIR="$PROJECT_ROOT/ansible" LOG_FILE="$PROJECT_ROOT/logs/create-test-$(date +%Y%m%d-%H%M%S).log" ACCOUNT_ID="668889063715" REGION="mx-central-1" # Crear directorio de logs mkdir -p "$(dirname "$LOG_FILE")" # ============================================================================= # FUNCIONES DE UTILIDAD # ============================================================================= log() { echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] INFO:${NC} $1" | tee -a "$LOG_FILE" } warn() { echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] WARN:${NC} $1" | tee -a "$LOG_FILE" } error() { echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] ERROR:${NC} $1" | tee -a "$LOG_FILE" exit 1 } info() { echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')] INFO:${NC} $1" | tee -a "$LOG_FILE" } # ============================================================================= # PASO 1: VALIDAR PREREQUISITOS # ============================================================================= validate_prerequisites() { info "========================================" info "PASO 1: Validando prerequisitos" info "========================================" # Validar AWS CLI if ! command -v aws &> /dev/null; then error "AWS CLI no esta instalado. Instalar desde: https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html" fi log "AWS CLI: $(aws --version | head -1)" # Validar Terraform if ! command -v terraform &> /dev/null; then error "Terraform no esta instalado. Instalar desde: https://developer.hashicorp.com/terraform/downloads" fi log "Terraform: $(terraform version | head -1)" # Validar Ansible if ! command -v ansible-playbook &> /dev/null; then warn "Ansible no esta instalado. Se omitira el paso de Ansible." ANSIBLE_AVAILABLE=false else log "Ansible: $(ansible-playbook --version | head -1)" ANSIBLE_AVAILABLE=true fi # Validar credenciales AWS info "Verificando credenciales AWS..." if ! aws sts get-caller-identity &> /dev/null; then error "No se pueden validar las credenciales AWS. Asegurate de configurar:\n export AWS_ACCESS_KEY_ID=...\n export AWS_SECRET_ACCESS_KEY=...\n export AWS_SESSION_TOKEN=...\n export AWS_DEFAULT_REGION=mx-central-1" fi local caller_identity caller_identity=$(aws sts get-caller-identity --output json) local account_id account_id=$(echo "$caller_identity" | jq -r '.Account') local arn arn=$(echo "$caller_identity" | jq -r '.Arn') if [ "$account_id" != "$ACCOUNT_ID" ]; then error "Cuenta AWS incorrecta. Esperada: $ACCOUNT_ID, Actual: $account_id" fi log "Credenciales AWS validas" log " Cuenta: $account_id" log " ARN: $arn" log " Region: $REGION" # Validar region local current_region current_region=$(aws configure get region 2>/dev/null || echo "$AWS_DEFAULT_REGION") if [ "$current_region" != "$REGION" ]; then warn "Region actual ($current_region) diferente de la esperada ($REGION)" warn "Estableciendo AWS_DEFAULT_REGION=$REGION" export AWS_DEFAULT_REGION="$REGION" fi # Validar archivo de variables if [ ! -f "$TERRAFORM_DIR/terraform.tfvars" ]; then error "No existe $TERRAFORM_DIR/terraform.tfvars\nCopiar desde terraform.tfvars.example y completar los valores." fi log "Archivo terraform.tfvars encontrado" # Validar llaves SSH if [ ! -f "$HOME/.ssh/sacc4-test-key.pem" ]; then warn "No existe ~/.ssh/sacc4-test-key.pem" warn "Generar con: ssh-keygen -t ed25519 -f ~/.ssh/sacc4-test-key -C 'sacc4-test'" warn "Subir la llave publica a AWS: aws ec2 import-key-pair ..." fi } # ============================================================================= # PASO 2: VERIFICAR CONFLICTOS DE NOMBRES # ============================================================================= check_conflicts() { info "========================================" info "PASO 2: Verificando conflictos de nombres" info "========================================" local conflicts_found=0 # Verificar bucket S3 local bucket_name bucket_name=$(grep "frontend_bucket_name" "$TERRAFORM_DIR/terraform.tfvars" | cut -d'=' -f2 | tr -d ' "') log "Verificando bucket S3: $bucket_name" if aws s3api head-bucket --bucket "$bucket_name" 2>/dev/null; then warn "Bucket S3 '$bucket_name' ya existe" conflicts_found=$((conflicts_found + 1)) else log "Bucket S3 disponible" fi # Verificar instancia RDS local rds_id="sacc4-test-db-prod" log "Verificando RDS: $rds_id" if aws rds describe-db-instances --db-instance-identifier "$rds_id" 2>/dev/null; then warn "RDS '$rds_id' ya existe" conflicts_found=$((conflicts_found + 1)) else log "RDS disponible" fi # Verificar VPC con mismo CIDR local vpc_cidr vpc_cidr=$(grep "vpc_cidr" "$TERRAFORM_DIR/terraform.tfvars" | head -1 | cut -d'=' -f2 | tr -d ' "') log "Verificando VPC CIDR: $vpc_cidr" local existing_vpcs existing_vpcs=$(aws ec2 describe-vpcs --filters "Name=cidr,Values=$vpc_cidr" --query 'Vpcs[*].VpcId' --output text) if [ -n "$existing_vpcs" ] && [ "$existing_vpcs" != "None" ]; then warn "VPC con CIDR $vpc_cidr ya existe: $existing_vpcs" conflicts_found=$((conflicts_found + 1)) else log "VPC CIDR disponible" fi # Verificar tabla DynamoDB para locks local dynamo_table="sacc4-terraform-locks-test-668889063715" log "Verificando DynamoDB: $dynamo_table" if aws dynamodb describe-table --table-name "$dynamo_table" 2>/dev/null; then warn "Tabla DynamoDB '$dynamo_table' ya existe" conflicts_found=$((conflicts_found + 1)) else log "Tabla DynamoDB disponible" fi # Verificar bucket de estado Terraform local state_bucket="sacc4-terraform-state-test-668889063715" log "Verificando bucket de estado: $state_bucket" if aws s3api head-bucket --bucket "$state_bucket" 2>/dev/null; then warn "Bucket de estado '$state_bucket' ya existe" conflicts_found=$((conflicts_found + 1)) else log "Bucket de estado disponible" fi if [ $conflicts_found -gt 0 ]; then warn "Se encontraron $conflicts_found conflictos. Revisar antes de continuar." read -p "Continuar de todos modos? (yes/no): " confirm if [ "$confirm" != "yes" ]; then error "Abortado por el usuario" fi else log "No se encontraron conflictos" fi } # ============================================================================= # PASO 3: CREAR BACKEND TERRAFORM (S3 + DynamoDB) # ============================================================================= create_backend() { info "========================================" info "PASO 3: Creando backend para estado Terraform" info "========================================" local state_bucket="sacc4-terraform-state-test-668889063715" local dynamo_table="sacc4-terraform-locks-test-668889063715" # Crear bucket S3 log "Creando bucket S3: $state_bucket" if ! aws s3api head-bucket --bucket "$state_bucket" 2>/dev/null; then aws s3api create-bucket \ --bucket "$state_bucket" \ --region "$REGION" \ --create-bucket-configuration LocationConstraint="$REGION" log "Bucket creado" else log "Bucket ya existe" fi # Habilitar versionamiento log "Habilitando versionamiento en bucket" aws s3api put-bucket-versioning \ --bucket "$state_bucket" \ --versioning-configuration Status=Enabled # Encriptacion log "Configurando encriptacion del bucket" aws s3api put-bucket-encryption \ --bucket "$state_bucket" \ --server-side-encryption-configuration '{ "Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}] }' # Crear tabla DynamoDB log "Creando tabla DynamoDB: $dynamo_table" if ! aws dynamodb describe-table --table-name "$dynamo_table" 2>/dev/null; then aws dynamodb create-table \ --table-name "$dynamo_table" \ --attribute-definitions AttributeName=LockID,AttributeType=S \ --key-schema AttributeName=LockID,KeyType=HASH \ --billing-mode PAY_PER_REQUEST \ --region "$REGION" log "Tabla DynamoDB creada" else log "Tabla DynamoDB ya existe" fi } # ============================================================================= # PASO 4: TERRAFORM INIT / PLAN / APPLY # ============================================================================= run_terraform() { info "========================================" info "PASO 4: Ejecutando Terraform" info "========================================" cd "$TERRAFORM_DIR" log "Inicializando Terraform..." terraform init log "Ejecutando terraform plan..." terraform plan -out=tfplan -var-file=terraform.tfvars info "Revisar el plan anterior. Se crearan los recursos listados arriba." read -p "Aplicar cambios? (yes/no): " confirm if [ "$confirm" != "yes" ]; then error "Abortado por el usuario" fi log "Aplicando infraestructura (esto puede tomar 10-15 minutos)..." terraform apply tfplan log "Terraform apply completado" } # ============================================================================= # PASO 5: GENERAR INVENTARIO ANSIBLE # ============================================================================= generate_ansible_inventory() { info "========================================" info "PASO 5: Generando inventario Ansible" info "========================================" cd "$TERRAFORM_DIR" local ec2_ip ec2_ip=$(terraform output -raw ec2_public_ip) local rds_endpoint rds_endpoint=$(terraform output -raw rds_endpoint) local s3_bucket s3_bucket=$(terraform output -raw frontend_bucket_name) mkdir -p "$ANSIBLE_DIR/inventory" cat > "$ANSIBLE_DIR/inventory/test.ini" << EOF [sacc4-test] $ec2_ip ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/sacc4-test-key.pem ansible_python_interpreter=/usr/bin/python3 [sacc4-test:vars] environment=test db_endpoint=$rds_endpoint s3_bucket=$s3_bucket EOF log "Inventario Ansible generado: $ANSIBLE_DIR/inventory/test.ini" cat "$ANSIBLE_DIR/inventory/test.ini" } # ============================================================================= # PASO 6: EJECUTAR ANSIBLE # ============================================================================= run_ansible() { info "========================================" info "PASO 6: Configurando servidor con Ansible" info "========================================" if [ "$ANSIBLE_AVAILABLE" != "true" ]; then warn "Ansible no disponible. Omitiendo configuracion." info "Para ejecutar manualmente despues:" info " cd $ANSIBLE_DIR" info " ansible-playbook -i inventory/test.ini playbooks/site.yml" return fi cd "$ANSIBLE_DIR" log "Ejecutando playbook Ansible..." ansible-playbook -i inventory/test.ini playbooks/site.yml log "Ansible completado" } # ============================================================================= # PASO 7: VERIFICAR HEALTH CHECKS # ============================================================================= verify_health_checks() { info "========================================" info "PASO 7: Verificando health checks" info "========================================" cd "$TERRAFORM_DIR" local ec2_ip ec2_ip=$(terraform output -raw ec2_public_ip) log "Verificando conectividad SSH..." if ssh -i ~/.ssh/sacc4-test-key.pem -o StrictHostKeyChecking=no -o ConnectTimeout=10 ubuntu@"$ec2_ip" "echo 'OK'" > /dev/null 2>&1; then log "SSH: OK" else warn "SSH: No responde (la instancia puede estar inicializando)" fi log "Verificando Nginx..." if ssh -i ~/.ssh/sacc4-test-key.pem -o StrictHostKeyChecking=no ubuntu@"$ec2_ip" "sudo systemctl is-active nginx" 2>/dev/null; then log "Nginx: Activo" else warn "Nginx: No activo (esperar a que Ansible termine)" fi log "Verificando servicios en puertos 8080-8085..." for port in 8080 8081 8082 8083 8084 8085; do if ssh -i ~/.ssh/sacc4-test-key.pem -o StrictHostKeyChecking=no ubuntu@"$ec2_ip" "curl -s -o /dev/null -w '%{http_code}' http://localhost:$port/actuator/health 2>/dev/null || echo '000'" 2>/dev/null | grep -q "200"; then log "Puerto $port: OK" else warn "Puerto $port: No responde (esperar despliegue de JARs)" fi done log "Verificando RDS..." local rds_endpoint rds_endpoint=$(terraform output -raw rds_endpoint) if ssh -i ~/.ssh/sacc4-test-key.pem -o StrictHostKeyChecking=no ubuntu@"$ec2_ip" "mysql -h $rds_endpoint -u sacc_app_user -p -e 'SELECT 1;' 2>/dev/null" > /dev/null 2>&1; then log "RDS: Conexion exitosa" else warn "RDS: No se pudo conectar (verificar credenciales y security groups)" fi log "Verificando S3..." local s3_bucket s3_bucket=$(terraform output -raw frontend_bucket_name) if aws s3 ls "s3://$s3_bucket" >/dev/null 2>&1; then log "S3: Bucket accesible" else warn "S3: No se pudo acceder al bucket" fi } # ============================================================================= # PASO 8: MOSTRAR RESUMEN # ============================================================================= show_summary() { info "========================================" info "RESUMEN DEL DESPLIEGUE" info "========================================" cd "$TERRAFORM_DIR" info "Outputs de Terraform:" terraform output info "" info "Recursos creados en cuenta $ACCOUNT_ID:" info " VPC: $(terraform output -raw vpc_id 2>/dev/null || echo 'N/A')" info " EC2: $(terraform output -raw ec2_public_ip 2>/dev/null || echo 'N/A')" info " RDS: $(terraform output -raw rds_endpoint 2>/dev/null || echo 'N/A')" info " S3: $(terraform output -raw frontend_bucket_name 2>/dev/null || echo 'N/A')" info " CloudFront: $(terraform output -raw cloudfront_domain_name 2>/dev/null || echo 'N/A')" info "" info "Proximos pasos:" info " 1. Desplegar JARs de microservicios a /opt/sacc4/*/current/" info " 2. Configurar certificado SSL (Let's Encrypt o ACM)" info " 3. Verificar DNS: $(terraform output -raw api_subdomain 2>/dev/null || echo 'N/A')" info " 4. Ejecutar: $SCRIPT_DIR/validate-environment.sh" info "" info "Para destruir el entorno:" info " $SCRIPT_DIR/destroy-test-environment.sh" } # ============================================================================= # MAIN # ============================================================================= main() { info "========================================" info "SACC v4 - Creacion de Entorno TEST" info "Cuenta: $ACCOUNT_ID" info "Region: $REGION" info "========================================" info "" info "IMPORTANTE:" info " - Este script creara recursos AWS que generan costos" info " - Verificar que las credenciales sean de la cuenta correcta" info " - No ejecutar en produccion" info "" read -p "Continuar? (yes/no): " confirm if [ "$confirm" != "yes" ]; then error "Abortado por el usuario" fi validate_prerequisites check_conflicts create_backend run_terraform generate_ansible_inventory run_ansible verify_health_checks show_summary log "Proceso completado exitosamente" log "Log guardado en: $LOG_FILE" } main "$@"