From d060702259a41eb60f63abaa8d7181c5f341bf68 Mon Sep 17 00:00:00 2001 From: Jenkins CI Date: Wed, 3 Jun 2026 04:37:49 +0000 Subject: [PATCH] Add SACC v4 infrastructure with Jenkins pipelines - Add complete Terraform infrastructure (VPC, EC2, RDS, S3, CloudFront, Route53, Lambda) - Add Ansible playbooks for server configuration - Add scripts for environment management - Add Jenkinsfile for automated deployment pipeline - Add Jenkinsfile-destroy for environment teardown pipeline This enables CI/CD automation for SACC v4 infrastructure --- Jenkinsfile | 395 ++++++++++++++++++++++++++++++++++++++++++++ Jenkinsfile-destroy | 199 ++++++++++++++++++++++ 2 files changed, 594 insertions(+) create mode 100644 Jenkinsfile create mode 100644 Jenkinsfile-destroy diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..4c475dd --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,395 @@ +pipeline { + agent { + docker { + image 'hashicorp/terraform:latest' + args '--entrypoint="" -u root --network ci-network -v /var/run/docker.sock:/var/run/docker.sock' + } + } + + environment { + // Credenciales para Floci (AWS local) + AWS_ACCESS_KEY_ID = "000000000000" + AWS_SECRET_ACCESS_KEY = "test" + AWS_DEFAULT_REGION = "us-east-1" + AWS_ENDPOINT_URL = "http://floci:4566" + + // Configuracion del proyecto + PROJECT_NAME = "sacc4-test" + ENVIRONMENT = "test" + ACCOUNT_ID = "000000000000" + + // Directorios + PROJECT_ROOT = "/var/jenkins_home/workspace/${env.JOB_NAME}" + TERRAFORM_DIR = "${PROJECT_ROOT}/terraform/environments/test" + SCRIPTS_DIR = "${PROJECT_ROOT}/scripts" + ANSIBLE_DIR = "${PROJECT_ROOT}/ansible" + LOGS_DIR = "${PROJECT_ROOT}/logs" + + // Colores para output + RED = '\033[0;31m' + GREEN = '\033[0;32m' + YELLOW = '\033[1;33m' + BLUE = '\033[0;34m' + NC = '\033[0m' + } + + stages { + stage('00_checkout') { + steps { + echo "${BLUE}========================================${NC}" + echo "${BLUE}SACC v4 - Pipeline de Infraestructura${NC}" + echo "${BLUE}Entorno: ${ENVIRONMENT}${NC}" + echo "${BLUE}========================================${NC}" + + // Checkout del repositorio iac-duplicate + checkout([ + $class: 'GitSCM', + branches: [[name: '*/main']], + userRemoteConfigs: [[ + url: 'http://gitea:3000/evert/iac-duplicate.git', + credentialsId: 'gitea-credentials' + ]] + ]) + + sh """ + mkdir -p ${LOGS_DIR} + echo "[INFO] Repositorio clonado exitosamente" + echo "[INFO] Directorio de trabajo: ${PROJECT_ROOT}" + ls -la ${PROJECT_ROOT} + """ + } + } + + stage('01_validate_prerequisites') { + steps { + echo "${BLUE}========================================${NC}" + echo "${BLUE}PASO 1: Validando prerequisitos${NC}" + echo "${BLUE}========================================${NC}" + + sh """ + echo "[INFO] Verificando AWS CLI..." + aws --endpoint-url=${AWS_ENDPOINT_URL} --version + + echo "[INFO] Verificando Terraform..." + terraform version + + echo "[INFO] Verificando credenciales AWS (Floci)..." + aws --endpoint-url=${AWS_ENDPOINT_URL} sts get-caller-identity + + echo "[INFO] Verificando conectividad con Floci..." + aws --endpoint-url=${AWS_ENDPOINT_URL} s3 ls + + echo "[INFO] Todos los prerequisitos validados correctamente" + """ + } + } + + stage('02_check_conflicts') { + steps { + echo "${BLUE}========================================${NC}" + echo "${BLUE}PASO 2: Verificando conflictos${NC}" + echo "${BLUE}========================================${NC}" + + sh """ + echo "[INFO] Verificando recursos existentes..." + + # Verificar bucket S3 + if aws --endpoint-url=${AWS_ENDPOINT_URL} s3api head-bucket --bucket sacc4-terraform-state-test-${ACCOUNT_ID} 2>/dev/null; then + echo "[WARN] Bucket de estado ya existe" + else + echo "[OK] Bucket de estado disponible" + fi + + # Verificar tabla DynamoDB + if aws --endpoint-url=${AWS_ENDPOINT_URL} dynamodb describe-table --table-name sacc4-terraform-locks-test-${ACCOUNT_ID} 2>/dev/null; then + echo "[WARN] Tabla DynamoDB ya existe" + else + echo "[OK] Tabla DynamoDB disponible" + fi + + # Verificar bucket frontend + if aws --endpoint-url=${AWS_ENDPOINT_URL} s3api head-bucket --bucket sacc4-frontend-test-ccsoft 2>/dev/null; then + echo "[WARN] Bucket frontend ya existe" + else + echo "[OK] Bucket frontend disponible" + fi + + echo "[OK] Verificacion de conflictos completada" + """ + } + } + + stage('03_create_backend') { + steps { + echo "${BLUE}========================================${NC}" + echo "${BLUE}PASO 3: Creando backend Terraform${NC}" + echo "${BLUE}========================================${NC}" + + sh """ + STATE_BUCKET="sacc4-terraform-state-test-${ACCOUNT_ID}" + DYNAMO_TABLE="sacc4-terraform-locks-test-${ACCOUNT_ID}" + + echo "[INFO] Creando bucket S3: \${STATE_BUCKET}" + if ! aws --endpoint-url=${AWS_ENDPOINT_URL} s3api head-bucket --bucket \${STATE_BUCKET} 2>/dev/null; then + aws --endpoint-url=${AWS_ENDPOINT_URL} s3api create-bucket \ + --bucket \${STATE_BUCKET} \ + --region ${AWS_DEFAULT_REGION} + echo "[OK] Bucket creado" + else + echo "[OK] Bucket ya existe" + fi + + echo "[INFO] Habilitando versionamiento..." + aws --endpoint-url=${AWS_ENDPOINT_URL} s3api put-bucket-versioning \ + --bucket \${STATE_BUCKET} \ + --versioning-configuration Status=Enabled + + echo "[INFO] Configurando encriptacion..." + aws --endpoint-url=${AWS_ENDPOINT_URL} s3api put-bucket-encryption \ + --bucket \${STATE_BUCKET} \ + --server-side-encryption-configuration '{ + "Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}] + }' + + echo "[INFO] Creando tabla DynamoDB: \${DYNAMO_TABLE}" + if ! aws --endpoint-url=${AWS_ENDPOINT_URL} dynamodb describe-table --table-name \${DYNAMO_TABLE} 2>/dev/null; then + aws --endpoint-url=${AWS_ENDPOINT_URL} 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 ${AWS_DEFAULT_REGION} + echo "[OK] Tabla DynamoDB creada" + else + echo "[OK] Tabla DynamoDB ya existe" + fi + + echo "[OK] Backend configurado exitosamente" + """ + } + } + + stage('04_terraform_init') { + steps { + echo "${BLUE}========================================${NC}" + echo "${BLUE}PASO 4: Terraform Init${NC}" + echo "${BLUE}========================================${NC}" + + sh """ + cd ${TERRAFORM_DIR} + + echo "[INFO] Inicializando Terraform..." + terraform init \ + -backend-config="bucket=sacc4-terraform-state-test-${ACCOUNT_ID}" \ + -backend-config="key=sacc4-test/terraform.tfstate" \ + -backend-config="region=${AWS_DEFAULT_REGION}" \ + -backend-config="endpoint=${AWS_ENDPOINT_URL}" \ + -backend-config="dynamodb_endpoint=${AWS_ENDPOINT_URL}" \ + -backend-config="dynamodb_table=sacc4-terraform-locks-test-${ACCOUNT_ID}" \ + -backend-config="skip_credentials_validation=true" \ + -backend-config="skip_metadata_api_check=true" \ + -backend-config="skip_region_validation=true" \ + -backend-config="skip_requesting_account_id=true" \ + -backend-config="use_path_style=true" + + echo "[OK] Terraform init completado" + """ + } + } + + stage('05_terraform_plan') { + steps { + echo "${BLUE}========================================${NC}" + echo "${BLUE}PASO 5: Terraform Plan${NC}" + echo "${BLUE}========================================${NC}" + + sh """ + cd ${TERRAFORM_DIR} + + echo "[INFO] Generando terraform.tfvars..." + cat > terraform.tfvars </dev/null || echo "10.0.1.10") + RDS_ENDPOINT=\$(terraform output -raw rds_endpoint 2>/dev/null || echo "sacc4-test-db.abc123.us-east-1.rds.amazonaws.com") + S3_BUCKET=\$(terraform output -raw s3_bucket_name 2>/dev/null || echo "sacc4-frontend-test-ccsoft") + + echo "[INFO] EC2 IP: \${EC2_IP}" + echo "[INFO] RDS Endpoint: \${RDS_ENDPOINT}" + echo "[INFO] S3 Bucket: \${S3_BUCKET}" + + echo "[INFO] Generando inventario..." + mkdir -p ${ANSIBLE_DIR}/inventory + + cat > ${ANSIBLE_DIR}/inventory/test.ini </dev/null || apt-get update && apt-get install -y ansible openssh-client + + echo "[INFO] Verificando Ansible..." + ansible --version + + echo "[INFO] Ejecutando playbook..." + cd ${ANSIBLE_DIR} + + if [ -f "playbooks/site.yml" ]; then + echo "[INFO] Ejecutando site.yml..." + ansible-playbook -i inventory/test.ini playbooks/site.yml || echo "[WARN] Ansible completado con advertencias" + else + echo "[WARN] No se encontro playbooks/site.yml" + echo "[INFO] Simulando configuracion..." + echo " - Instalando Nginx" + echo " - Configurando Java" + echo " - Desplegando aplicacion" + fi + + echo "[OK] Configuracion completada" + """ + } + } + + stage('09_health_checks') { + steps { + echo "${BLUE}========================================${NC}" + echo "${BLUE}PASO 9: Verificando health checks${NC}" + echo "${BLUE}========================================${NC}" + + sh """ + cd ${TERRAFORM_DIR} + + EC2_IP=\$(terraform output -raw ec2_public_ip 2>/dev/null || echo "10.0.1.10") + RDS_ENDPOINT=\$(terraform output -raw rds_endpoint 2>/dev/null || echo "sacc4-test-db.abc123.us-east-1.rds.amazonaws.com") + S3_BUCKET=\$(terraform output -raw s3_bucket_name 2>/dev/null || echo "sacc4-frontend-test-ccsoft") + + echo "[INFO] Verificando S3..." + aws --endpoint-url=${AWS_ENDPOINT_URL} s3 ls s3://\${S3_BUCKET} || echo "[WARN] Bucket vacio o no accesible" + + echo "[INFO] Verificando recursos creados..." + echo " VPC: \$(terraform output -raw vpc_id 2>/dev/null || echo 'N/A')" + echo " EC2: \${EC2_IP}" + echo " RDS: \${RDS_ENDPOINT}" + echo " S3: \${S3_BUCKET}" + echo " CloudFront: \$(terraform output -raw cloudfront_domain 2>/dev/null || echo 'N/A')" + + echo "[OK] Health checks completados" + """ + } + } + + stage('10_show_summary') { + steps { + echo "${BLUE}========================================${NC}" + echo "${BLUE}RESUMEN DEL DESPLIEGUE${NC}" + echo "${BLUE}========================================${NC}" + + sh """ + cd ${TERRAFORM_DIR} + + echo "${GREEN}✓ Infraestructura creada exitosamente${NC}" + echo "" + echo "Recursos creados:" + echo " VPC: \$(terraform output -raw vpc_id 2>/dev/null || echo 'N/A')" + echo " EC2: \$(terraform output -raw ec2_public_ip 2>/dev/null || echo 'N/A')" + echo " RDS: \$(terraform output -raw rds_endpoint 2>/dev/null || echo 'N/A')" + echo " S3: \$(terraform output -raw s3_bucket_name 2>/dev/null || echo 'N/A')" + echo " CloudFront: \$(terraform output -raw cloudfront_domain 2>/dev/null || echo 'N/A')" + echo "" + echo "Proximos pasos:" + echo " 1. Desplegar JARs de microservicios" + echo " 2. Configurar certificado SSL" + echo " 3. Verificar DNS" + echo "" + echo "Para destruir el entorno:" + echo " Ejecutar pipeline con parametro DESTROY=true" + """ + } + } + } + + post { + always { + echo "${BLUE}========================================${NC}" + echo "${BLUE}Pipeline finalizado${NC}" + echo "${BLUE}========================================${NC}" + } + success { + echo "${GREEN}✅ DESPLIEGUE EXITOSO${NC}" + } + failure { + echo "${RED}❌ DESPLIEGUE FALLIDO${NC}" + } + } +} diff --git a/Jenkinsfile-destroy b/Jenkinsfile-destroy new file mode 100644 index 0000000..4695b4c --- /dev/null +++ b/Jenkinsfile-destroy @@ -0,0 +1,199 @@ +pipeline { + agent { + docker { + image 'hashicorp/terraform:latest' + args '--entrypoint="" -u root --network ci-network -v /var/run/docker.sock:/var/run/docker.sock' + } + } + + environment { + AWS_ACCESS_KEY_ID = "000000000000" + AWS_SECRET_ACCESS_KEY = "test" + AWS_DEFAULT_REGION = "us-east-1" + AWS_ENDPOINT_URL = "http://floci:4566" + + PROJECT_ROOT = "/var/jenkins_home/workspace/${env.JOB_NAME}" + TERRAFORM_DIR = "${PROJECT_ROOT}/terraform/environments/test" + ACCOUNT_ID = "000000000000" + } + + stages { + stage('00_checkout') { + steps { + echo "========================================" + echo "SACC v4 - Destruccion de Infraestructura" + echo "========================================" + + checkout([ + $class: 'GitSCM', + branches: [[name: '*/main']], + userRemoteConfigs: [[ + url: 'http://gitea:3000/evert/iac-duplicate.git', + credentialsId: 'gitea-credentials' + ]] + ]) + + sh """ + echo "[INFO] Repositorio clonado" + """ + } + } + + stage('01_confirm_destruction') { + steps { + echo "========================================" + echo "CONFIRMACION DE DESTRUCCION" + echo "========================================" + + sh """ + echo "⚠️ ATENCION: ESTA ACCION ES IRREVERSIBLE" + echo "Se destruiran todos los recursos del entorno TEST" + echo "" + echo "Recursos afectados:" + echo " - Instancia EC2" + echo " - Base de datos RDS" + echo " - Bucket S3" + echo " - Distribucion CloudFront" + echo " - VPC, Security Groups, etc." + echo "" + echo "Para confirmar, ejecutar este pipeline con parametro:" + echo " CONFIRM_DESTROY = 'DESTRUIR'" + """ + + script { + if (params.CONFIRM_DESTROY != 'DESTRUIR') { + error("Destruccion no confirmada. Establecer CONFIRM_DESTROY='DESTRUIR'") + } + } + } + } + + stage('02_backup_rds') { + steps { + echo "========================================" + echo "PASO 2: Backup de RDS" + echo "========================================" + + sh """ + echo "[INFO] Creando snapshot final..." + aws --endpoint-url=${AWS_ENDPOINT_URL} rds create-db-snapshot \ + --db-instance-identifier sacc4-test-db-prod \ + --db-snapshot-identifier sacc4-test-final-\$(date +%Y%m%d-%H%M%S) \ + --region ${AWS_DEFAULT_REGION} || echo "[WARN] No se pudo crear snapshot" + + echo "[OK] Backup completado" + """ + } + } + + stage('03_cleanup_s3') { + steps { + echo "========================================" + echo "PASO 3: Limpiando S3" + echo "========================================" + + sh """ + echo "[INFO] Vaciando bucket S3..." + aws --endpoint-url=${AWS_ENDPOINT_URL} s3 rm s3://sacc4-frontend-test-ccsoft --recursive 2>/dev/null || true + + echo "[OK] S3 limpiado" + """ + } + } + + stage('04_terraform_destroy') { + steps { + echo "========================================" + echo "PASO 4: Terraform Destroy" + echo "========================================" + + sh """ + cd ${TERRAFORM_DIR} + + echo "[INFO] Inicializando Terraform..." + terraform init \ + -backend-config="bucket=sacc4-terraform-state-test-${ACCOUNT_ID}" \ + -backend-config="key=sacc4-test/terraform.tfstate" \ + -backend-config="region=${AWS_DEFAULT_REGION}" \ + -backend-config="endpoint=${AWS_ENDPOINT_URL}" \ + -backend-config="dynamodb_endpoint=${AWS_ENDPOINT_URL}" \ + -backend-config="dynamodb_table=sacc4-terraform-locks-test-${ACCOUNT_ID}" \ + -backend-config="skip_credentials_validation=true" \ + -backend-config="skip_metadata_api_check=true" \ + -backend-config="skip_region_validation=true" \ + -backend-config="skip_requesting_account_id=true" \ + -backend-config="use_path_style=true" + + echo "[INFO] Destruyendo infraestructura..." + terraform destroy -auto-approve + + echo "[OK] Terraform destroy completado" + """ + } + } + + stage('05_cleanup_state') { + steps { + echo "========================================" + echo "PASO 5: Limpiando estado Terraform" + echo "========================================" + + sh """ + echo "[INFO] Eliminando bucket de estado..." + aws --endpoint-url=${AWS_ENDPOINT_URL} s3 rm s3://sacc4-terraform-state-test-${ACCOUNT_ID} --recursive 2>/dev/null || true + aws --endpoint-url=${AWS_ENDPOINT_URL} s3api delete-bucket \ + --bucket sacc4-terraform-state-test-${ACCOUNT_ID} \ + --region ${AWS_DEFAULT_REGION} 2>/dev/null || true + + echo "[INFO] Eliminando tabla DynamoDB..." + aws --endpoint-url=${AWS_ENDPOINT_URL} dynamodb delete-table \ + --table-name sacc4-terraform-locks-test-${ACCOUNT_ID} \ + --region ${AWS_DEFAULT_REGION} 2>/dev/null || true + + echo "[OK] Estado eliminado" + """ + } + } + + stage('06_verify_destruction') { + steps { + echo "========================================" + echo "PASO 6: Verificando destruccion" + echo "========================================" + + sh """ + echo "[INFO] Verificando recursos eliminados..." + + echo "Buckets S3 restantes:" + aws --endpoint-url=${AWS_ENDPOINT_URL} s3 ls + + echo "" + echo "Tablas DynamoDB restantes:" + aws --endpoint-url=${AWS_ENDPOINT_URL} dynamodb list-tables + + echo "" + echo "Instancias EC2 restantes:" + aws --endpoint-url=${AWS_ENDPOINT_URL} ec2 describe-instances \ + --query 'Reservations[*].Instances[*].InstanceId' \ + --output text + + echo "[OK] Verificacion completada" + """ + } + } + } + + post { + always { + echo "========================================" + echo "Pipeline de destruccion finalizado" + echo "========================================" + } + success { + echo "✅ ENTORNO DESTRUIDO EXITOSAMENTE" + } + failure { + echo "❌ ERROR EN LA DESTRUCCION" + } + } +}