Lab 2: Sitio Secundario (Fallback)

Lab 2: Sitio Secundario – Página de Mantenimiento

El sitio secundario es la página de contingencia que verán los usuarios cuando el sitio primario no esté disponible. Debe ser estática, altamente disponible y serverless.

Usuario → AWS Amplify Hosting   → "Página de Mantenimiento"  (default)
       → CloudFront + S3 (alt.) → "Página de Mantenimiento"

Cargar variables de entorno

source ~/global.env

Opción A: CloudFormation (Base) — AWS Amplify (Recomendado)

AWS Amplify Hosting es la opción más simple: sin buckets S3, sin distribuciones CloudFront, sin esperas de propagación. El sitio queda disponible en menos de 2 minutos con HTTPS automático.

1. Crear el template CloudFormation

cat > /tmp/secondary-site.yaml << 'TEMPLATE_EOF'
AWSTemplateFormatVersion: '2010-09-09'
Description: 'roLearning - Route53 ARC Workshop - Sitio Secundario (AWS Amplify)'

Resources:
  FallbackAmplifyApp:
    Type: AWS::Amplify::App
    Properties:
      Name: route53-arc-fallback
      Description: "Sitio de mantenimiento - roLearning Workshop"
      Platform: WEB
      BuildSpec: |
        version: 1
        frontend:
          phases:
            build:
              commands: []
          artifacts:
            baseDirectory: /
            files:
              - '**/*'
      Tags:
        - { Key: Workshop, Value: route53-arc }

  FallbackAmplifyBranch:
    Type: AWS::Amplify::Branch
    Properties:
      AppId: !GetAtt FallbackAmplifyApp.AppId
      BranchName: main
      Stage: PRODUCTION
      EnableAutoBuild: false
      Tags:
        - { Key: Workshop, Value: route53-arc }

Outputs:
  AmplifyAppId:
    Value: !GetAtt FallbackAmplifyApp.AppId
    Export: { Name: route53-arc-amplify-app-id }
  AmplifyDefaultDomain:
    Value: !GetAtt FallbackAmplifyApp.DefaultDomain
    Export: { Name: route53-arc-amplify-domain }
TEMPLATE_EOF

2. Desplegar Stack y subir el contenido

aws cloudformation deploy \
  --template-file /tmp/secondary-site.yaml \
  --stack-name route53-arc-secondary \
  --capabilities CAPABILITY_IAM \
  --region $AWS_REGION

export AMPLIFY_APP_ID=$(aws cloudformation describe-stacks \
  --stack-name route53-arc-secondary --region $AWS_REGION \
  --query 'Stacks[0].Outputs[?OutputKey==`AmplifyAppId`].OutputValue' --output text)

export AMPLIFY_DOMAIN=$(aws cloudformation describe-stacks \
  --stack-name route53-arc-secondary --region $AWS_REGION \
  --query 'Stacks[0].Outputs[?OutputKey==`AmplifyDefaultDomain`].OutputValue' --output text)

# Crear la página de mantenimiento HTML
cat > /tmp/fallback-index.html << 'HTML'
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <title>Mantenimiento – roLearning</title>
  <style>
    * { margin:0; padding:0; box-sizing:border-box; }
    body { font-family:'Segoe UI',Arial,sans-serif; background:#0f172a; color:#e2e8f0; display:flex; align-items:center; justify-content:center; min-height:100vh; }
    .container { text-align:center; padding:40px 60px; background:#1e293b; border-radius:16px; box-shadow:0 8px 32px rgba(0,0,0,.5); max-width:600px; width:90%; }
    h1 { font-size:2em; color:#f59e0b; margin-bottom:12px; }
    p { color:#94a3b8; line-height:1.6; margin-bottom:8px; }
    .badge { display:inline-block; background:#f59e0b; color:#0f172a; padding:6px 20px; border-radius:20px; font-weight:bold; font-size:.85em; margin:16px 0; }
  </style>
</head>
<body>
  <div class="container">
    <h1>⚠️ Sitio en Mantenimiento</h1>
    <div class="badge">MANTENIMIENTO PROGRAMADO</div>
    <p>Estamos realizando tareas de mantenimiento para mejorar nuestros servicios.</p>
    <p><strong>Por favor, inténtelo de nuevo en unos minutos.</strong></p>
    <p style="margin-top:20px; font-size:0.8em; color:#475569;">roLearning – AWS Route 53 ARC Workshop (CloudFormation + Amplify)</p>
  </div>
</body>
</html>
HTML

# Crear el HTML directamente como index.html y empaquetar en un único ZIP
cat > /tmp/index.html << 'HTML'
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <title>Mantenimiento – roLearning</title>
  <style>
    * { margin:0; padding:0; box-sizing:border-box; }
    body { font-family:'Segoe UI',Arial,sans-serif; background:#0f172a; color:#e2e8f0; display:flex; align-items:center; justify-content:center; min-height:100vh; }
    .container { text-align:center; padding:40px 60px; background:#1e293b; border-radius:16px; box-shadow:0 8px 32px rgba(0,0,0,.5); max-width:600px; width:90%; }
    h1 { font-size:2em; color:#f59e0b; margin-bottom:12px; }
    p { color:#94a3b8; line-height:1.6; margin-bottom:8px; }
    .badge { display:inline-block; background:#f59e0b; color:#0f172a; padding:6px 20px; border-radius:20px; font-weight:bold; font-size:.85em; margin:16px 0; }
  </style>
</head>
<body>
  <div class="container">
    <h1>⚠️ Sitio en Mantenimiento</h1>
    <div class="badge">MANTENIMIENTO PROGRAMADO</div>
    <p>Estamos realizando tareas de mantenimiento para mejorar nuestros servicios.</p>
    <p><strong>Por favor, inténtelo de nuevo en unos minutos.</strong></p>
    <p style="margin-top:20px; font-size:0.8em; color:#475569;">roLearning – AWS Route 53 ARC Workshop (CloudFormation + Amplify)</p>
  </div>
</body>
</html>
HTML

cd /tmp && zip -q fallback-site.zip index.html

# Iniciar un deployment manual en Amplify
DEPLOY_RESULT=$(aws amplify create-deployment \
  --app-id $AMPLIFY_APP_ID \
  --branch-name main \
  --region $AWS_REGION \
  --output json)

UPLOAD_URL=$(echo $DEPLOY_RESULT | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['zipUploadUrl'])")
JOB_ID=$(echo $DEPLOY_RESULT | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['jobId'])")

echo "📤 Subiendo contenido al deployment Amplify..."
curl -s -X PUT -H "Content-Type: application/zip" --data-binary @/tmp/fallback-site.zip "$UPLOAD_URL"

# Iniciar el deployment
aws amplify start-deployment \
  --app-id $AMPLIFY_APP_ID \
  --branch-name main \
  --job-id $JOB_ID \
  --region $AWS_REGION

echo "⏳ Esperando que el deployment de Amplify finalice..."
for i in {1..12}; do
  STATUS=$(aws amplify get-job \
    --app-id $AMPLIFY_APP_ID \
    --branch-name main \
    --job-id $JOB_ID \
    --region $AWS_REGION \
    --query 'job.summary.status' --output text 2>/dev/null)
  echo "  [$i/12] Estado del deployment: $STATUS"
  [ "$STATUS" = "SUCCEED" ] && break
  [ "$STATUS" = "FAILED" ] && echo "❌ Deployment falló" && break
  sleep 10
done

export FALLBACK_DOMAIN="https://main.${AMPLIFY_DOMAIN}"
echo "🌐 Sitio Fallback (Amplify): $FALLBACK_DOMAIN"

# Persistir en global.env para que esté disponible en labs siguientes
if grep -q "FALLBACK_DOMAIN" ~/global.env 2>/dev/null; then
  sed -i '' "s|.*FALLBACK_DOMAIN.*|export FALLBACK_DOMAIN=\"${FALLBACK_DOMAIN}\"|" ~/global.env 2>/dev/null || \
  sed -i "s|.*FALLBACK_DOMAIN.*|export FALLBACK_DOMAIN=\"${FALLBACK_DOMAIN}\"|" ~/global.env
else
  echo "export FALLBACK_DOMAIN=\"${FALLBACK_DOMAIN}\"" >> ~/global.env
fi

# Persistir AMPLIFY_APP_ID para re-deploys manuales si fuera necesario
if grep -q "AMPLIFY_APP_ID" ~/global.env 2>/dev/null; then
  sed -i '' "s|.*AMPLIFY_APP_ID.*|export AMPLIFY_APP_ID=\"${AMPLIFY_APP_ID}\"|" ~/global.env 2>/dev/null || \
  sed -i "s|.*AMPLIFY_APP_ID.*|export AMPLIFY_APP_ID=\"${AMPLIFY_APP_ID}\"|" ~/global.env
else
  echo "export AMPLIFY_APP_ID=\"${AMPLIFY_APP_ID}\"" >> ~/global.env
fi
echo "✅ FALLBACK_DOMAIN y AMPLIFY_APP_ID guardados en ~/global.env"

Opción A Alternativa: CloudFormation — S3 + CloudFront

Aviso

⏱️ Tiempo de espera: La distribución CloudFront tarda entre 15 y 20 minutos en propagarse globalmente. Durante ese tiempo, la verificación devolverá 403 o timeout — esto es normal. No avances al Lab 3 hasta confirmar que el sitio responde con HTTP 200.

Esta opción despliega un bucket S3 privado protegido con Origin Access Control (OAC) y una distribución global de CloudFront.

1. Crear el template CloudFormation

cat > /tmp/secondary-site-cf.yaml << 'TEMPLATE_EOF'
AWSTemplateFormatVersion: '2010-09-09'
Description: 'roLearning - Route53 ARC Workshop - Sitio Secundario (S3 + CloudFront)'

Parameters:
  BucketName:
    Type: String
    Description: "Nombre único del bucket S3"

Resources:
  FallbackBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref BucketName
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      Tags: [{ Key: Workshop, Value: route53-arc }]

  CloudFrontOAC:
    Type: AWS::CloudFront::OriginAccessControl
    Properties:
      OriginAccessControlConfig:
        Name: route53-arc-fallback-oac-cfn
        OriginAccessControlOriginType: s3
        SigningBehavior: always
        SigningProtocol: sigv4

  FallbackBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref FallbackBucket
      PolicyDocument:
        Statement:
          - Sid: AllowCloudFrontServicePrincipal
            Effect: Allow
            Principal: { Service: cloudfront.amazonaws.com }
            Action: s3:GetObject
            Resource: !Sub "${FallbackBucket.Arn}/*"
            Condition:
              StringEquals:
                "AWS:SourceArn": !Sub "arn:aws:cloudfront::${AWS::AccountId}:distribution/${FallbackDistribution}"

  FallbackDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Enabled: true
        DefaultRootObject: index.html
        Comment: "roLearning Route53 ARC Fallback Site"
        HttpVersion: http2
        Origins:
          - Id: S3FallbackOrigin
            DomainName: !GetAtt FallbackBucket.RegionalDomainName
            OriginAccessControlId: !Ref CloudFrontOAC
            S3OriginConfig: { OriginAccessIdentity: "" }
        DefaultCacheBehavior:
          ViewerProtocolPolicy: redirect-to-https
          TargetOriginId: S3FallbackOrigin
          CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6
          AllowedMethods: [GET, HEAD]
          CachedMethods: [GET, HEAD]
        CustomErrorResponses:
          - ErrorCode: 403
            ResponseCode: 200
            ResponsePagePath: /index.html
          - ErrorCode: 404
            ResponseCode: 200
            ResponsePagePath: /index.html
        Tags: [{ Key: Workshop, Value: route53-arc }]

Outputs:
  FallbackBucketName:
    Value: !Ref FallbackBucket
    Export: { Name: route53-arc-fallback-bucket }
  CloudFrontDomain:
    Value: !GetAtt FallbackDistribution.DomainName
    Export: { Name: route53-arc-cf-domain }
  CloudFrontDistributionId:
    Value: !Ref FallbackDistribution
    Export: { Name: route53-arc-cf-distribution-id }
TEMPLATE_EOF

2. Desplegar Stack y subir HTML

export BUCKET_NAME="route53-arc-fallback-${AWS_ACCOUNT_ID}"

aws cloudformation deploy \
  --template-file /tmp/secondary-site-cf.yaml \
  --stack-name route53-arc-secondary \
  --capabilities CAPABILITY_IAM \
  --region $AWS_REGION \
  --parameter-overrides BucketName=$BUCKET_NAME

export CF_DOMAIN=$(aws cloudformation describe-stacks \
  --stack-name route53-arc-secondary --region $AWS_REGION \
  --query 'Stacks[0].Outputs[?OutputKey==`CloudFrontDomain`].OutputValue' --output text)

cat > /tmp/fallback-index.html << 'HTML'
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <title>Mantenimiento – roLearning</title>
  <style>
    * { margin:0; padding:0; box-sizing:border-box; }
    body { font-family:'Segoe UI',Arial,sans-serif; background:#0f172a; color:#e2e8f0; display:flex; align-items:center; justify-content:center; min-height:100vh; }
    .container { text-align:center; padding:40px 60px; background:#1e293b; border-radius:16px; box-shadow:0 8px 32px rgba(0,0,0,.5); max-width:600px; width:90%; }
    h1 { font-size:2em; color:#f59e0b; margin-bottom:12px; }
    p { color:#94a3b8; line-height:1.6; margin-bottom:8px; }
    .badge { display:inline-block; background:#f59e0b; color:#0f172a; padding:6px 20px; border-radius:20px; font-weight:bold; font-size:.85em; margin:16px 0; }
  </style>
</head>
<body>
  <div class="container">
    <h1>⚠️ Sitio en Mantenimiento</h1>
    <div class="badge">MANTENIMIENTO PROGRAMADO</div>
    <p>Estamos realizando tareas de mantenimiento para mejorar nuestros servicios.</p>
    <p><strong>Por favor, inténtelo de nuevo en unos minutos.</strong></p>
    <p style="margin-top:20px; font-size:0.8em; color:#475569;">roLearning – AWS Route 53 ARC Workshop (CloudFormation + CloudFront)</p>
  </div>
</body>
</html>
HTML

aws s3 cp /tmp/fallback-index.html s3://$BUCKET_NAME/index.html --content-type "text/html" --region $AWS_REGION
export FALLBACK_DOMAIN="https://$CF_DOMAIN"
echo "🌐 Sitio Fallback (CloudFront): $FALLBACK_DOMAIN"
echo "⏳ Recordá que CloudFront puede tardar 15-20 min en propagarse. Avanzá al Lab 3 y volvé a verificar."

Opción B: Terraform — AWS Amplify (Recomendado)

Detalles

🚫 Opción B requiere terminal local — no uses CloudShell con Terraform. Ver Lab 0 para más detalles.

1. Configurar el módulo Terraform

cd ~/route53-arc-tf/02_secondary

# variables.tf
cat > variables.tf << 'EOF'
variable "aws_region"   { type = string; default = "us-east-1" }
variable "project_tag"  { type = string; default = "route53-arc" }
EOF

# main.tf
cat > main.tf << 'EOF'
terraform {
  required_version = ">= 1.5"
  required_providers {
    aws = { source = "hashicorp/aws", version = "~> 5.0" }
  }
}

provider "aws" {
  region = var.aws_region
  default_tags { tags = { Workshop = var.project_tag, ManagedBy = "Terraform" } }
}

resource "aws_amplify_app" "fallback" {
  name        = "route53-arc-fallback"
  description = "Sitio de mantenimiento - roLearning Workshop"
  platform    = "WEB"
  build_spec  = <<-YAML
    version: 1
    frontend:
      phases:
        build:
          commands: []
      artifacts:
        baseDirectory: /
        files: ['**/*']
  YAML
}

resource "aws_amplify_branch" "main" {
  app_id            = aws_amplify_app.fallback.id
  branch_name       = "main"
  stage             = "PRODUCTION"
  enable_auto_build = false
}
EOF

# outputs.tf
cat > outputs.tf << 'EOF'
output "amplify_app_id" {
  value = aws_amplify_app.fallback.id
}
output "fallback_domain" {
  value = "https://main.${aws_amplify_app.fallback.default_domain}"
}
EOF

2. Aplicar Terraform y desplegar el contenido

terraform init
terraform apply -auto-approve

export AMPLIFY_APP_ID=$(terraform output -raw amplify_app_id)
export FALLBACK_DOMAIN=$(terraform output -raw fallback_domain)

# Crear la página de mantenimiento HTML
cat > /tmp/index.html << 'HTML'
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <title>Mantenimiento - roLearning Workshop</title>
  <style>
    * { margin:0; padding:0; box-sizing:border-box; }
    body { font-family:'Segoe UI',Arial,sans-serif; background:#0f172a; color:#e2e8f0; display:flex; align-items:center; justify-content:center; min-height:100vh; }
    .container { text-align:center; padding:40px 60px; background:#1e293b; border-radius:16px; box-shadow:0 8px 32px rgba(0,0,0,.5); max-width:600px; width:90%; }
    h1 { font-size:2em; color:#f59e0b; margin-bottom:12px; }
    p { color:#94a3b8; line-height:1.6; margin-bottom:8px; }
    .badge { display:inline-block; background:#f59e0b; color:#0f172a; padding:6px 20px; border-radius:20px; font-weight:bold; font-size:.85em; margin:16px 0; }
  </style>
</head>
<body>
  <div class="container">
    <h1>⚠️ Sitio en Mantenimiento</h1>
    <div class="badge">MANTENIMIENTO PROGRAMADO</div>
    <p>Estamos realizando tareas de mantenimiento para mejorar nuestros servicios.</p>
    <p><strong>Por favor, inténtelo de nuevo en unos minutos.</strong></p>
    <p style="margin-top:20px; font-size:0.8em; color:#475569;">roLearning – AWS Route 53 ARC Workshop (Terraform + Amplify)</p>
  </div>
</body>
</html>
HTML

# Empaquetar y subir el contenido al branch de Amplify
cd /tmp && zip -q fallback-site.zip index.html

echo "📤 Creando deployment en Amplify..."
DEPLOY_RESULT=$(aws amplify create-deployment \
  --app-id $AMPLIFY_APP_ID \
  --branch-name main \
  --region $AWS_REGION \
  --output json)

UPLOAD_URL=$(echo $DEPLOY_RESULT | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['zipUploadUrl'])")
JOB_ID=$(echo $DEPLOY_RESULT | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['jobId'])")

curl -s -X PUT -H "Content-Type: application/zip" --data-binary @/tmp/fallback-site.zip "$UPLOAD_URL"
echo "✅ ZIP subido"

aws amplify start-deployment \
  --app-id $AMPLIFY_APP_ID \
  --branch-name main \
  --job-id $JOB_ID \
  --region $AWS_REGION

echo "⏳ Esperando que el deployment finalice..."
for i in {1..12}; do
  STATUS=$(aws amplify get-job \
    --app-id $AMPLIFY_APP_ID \
    --branch-name main \
    --job-id $JOB_ID \
    --region $AWS_REGION \
    --query 'job.summary.status' --output text 2>/dev/null)
  echo "  [$i/12] Estado: $STATUS"
  [ "$STATUS" = "SUCCEED" ] && break
  [ "$STATUS" = "FAILED" ] && echo "❌ Deployment falló" && break
  sleep 10
done

echo "🌐 Sitio Fallback (Amplify): $FALLBACK_DOMAIN"

# Persistir en global.env para que esté disponible en labs siguientes
if grep -q "FALLBACK_DOMAIN" ~/global.env 2>/dev/null; then
  sed -i '' "s|.*FALLBACK_DOMAIN.*|export FALLBACK_DOMAIN=\"${FALLBACK_DOMAIN}\"|" ~/global.env 2>/dev/null || \
  sed -i "s|.*FALLBACK_DOMAIN.*|export FALLBACK_DOMAIN=\"${FALLBACK_DOMAIN}\"|" ~/global.env
else
  echo "export FALLBACK_DOMAIN=\"${FALLBACK_DOMAIN}\"" >> ~/global.env
fi

if grep -q "AMPLIFY_APP_ID" ~/global.env 2>/dev/null; then
  sed -i '' "s|.*AMPLIFY_APP_ID.*|export AMPLIFY_APP_ID=\"${AMPLIFY_APP_ID}\"|" ~/global.env 2>/dev/null || \
  sed -i "s|.*AMPLIFY_APP_ID.*|export AMPLIFY_APP_ID=\"${AMPLIFY_APP_ID}\"|" ~/global.env
else
  echo "export AMPLIFY_APP_ID=\"${AMPLIFY_APP_ID}\"" >> ~/global.env
fi
echo "✅ FALLBACK_DOMAIN y AMPLIFY_APP_ID guardados en ~/global.env"

Opción B Alternativa: Terraform — S3 + CloudFront

Aviso

⏱️ Tiempo de espera: La distribución CloudFront tarda entre 15 y 20 minutos en propagarse. La verificación devolverá 403 durante ese tiempo — es normal. No avances al Lab 3 hasta confirmar HTTP 200.

cd ~/route53-arc-tf/02_secondary

cat > main.tf << 'EOF'
terraform {
  required_version = ">= 1.5"
  required_providers {
    aws = { source = "hashicorp/aws", version = "~> 5.0" }
  }
}

provider "aws" {
  region = var.aws_region
  default_tags { tags = { Workshop = var.project_tag, ManagedBy = "Terraform" } }
}

data "aws_caller_identity" "current" {}

resource "aws_s3_bucket" "fallback" {
  bucket        = "route53-arc-fallback-${data.aws_caller_identity.current.account_id}"
  force_destroy = true
}

resource "aws_s3_bucket_public_access_block" "fallback" {
  bucket                  = aws_s3_bucket.fallback.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_cloudfront_origin_access_control" "fallback" {
  name                              = "route53-arc-fallback-oac-tf"
  origin_access_control_origin_type = "s3"
  signing_behavior                  = "always"
  signing_protocol                  = "sigv4"
}

resource "aws_cloudfront_distribution" "fallback" {
  enabled             = true
  default_root_object = "index.html"
  comment             = "roLearning Route53 ARC Fallback Site"
  http_version        = "http2"

  origin {
    domain_name              = aws_s3_bucket.fallback.bucket_regional_domain_name
    origin_id                = "S3FallbackOrigin"
    origin_access_control_id = aws_cloudfront_origin_access_control.fallback.id
  }

  default_cache_behavior {
    target_origin_id       = "S3FallbackOrigin"
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods        = ["GET", "HEAD"]
    cached_methods         = ["GET", "HEAD"]
    cache_policy_id        = "658327ea-f89d-4fab-a63d-7e88639e58f6"
  }

  custom_error_response {
    error_code         = 403
    response_code      = 200
    response_page_path = "/index.html"
  }

  restrictions {
    geo_restriction { restriction_type = "none" }
  }

  viewer_certificate { cloudfront_default_certificate = true }
}

resource "aws_s3_bucket_policy" "fallback" {
  bucket = aws_s3_bucket.fallback.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Sid       = "AllowCloudFrontServicePrincipal"
      Effect    = "Allow"
      Principal = { Service = "cloudfront.amazonaws.com" }
      Action    = "s3:GetObject"
      Resource  = "${aws_s3_bucket.fallback.arn}/*"
      Condition = { StringEquals = { "AWS:SourceArn" = aws_cloudfront_distribution.fallback.arn } }
    }]
  })
}
EOF

cat > outputs.tf << 'EOF'
output "fallback_domain"   { value = "https://${aws_cloudfront_distribution.fallback.domain_name}" }
output "fallback_bucket"   { value = aws_s3_bucket.fallback.id }
output "cf_distribution_id"{ value = aws_cloudfront_distribution.fallback.id }
EOF

terraform init && terraform apply -auto-approve
export FALLBACK_DOMAIN=$(terraform output -raw fallback_domain)
BUCKET_NAME=$(terraform output -raw fallback_bucket)

# Subir el HTML al bucket
cat > /tmp/fallback-index.html << 'HTML'
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <title>Mantenimiento – roLearning</title>
  <style>
    * { margin:0; padding:0; box-sizing:border-box; }
    body { font-family:'Segoe UI',Arial,sans-serif; background:#0f172a; color:#e2e8f0; display:flex; align-items:center; justify-content:center; min-height:100vh; }
    .container { text-align:center; padding:40px 60px; background:#1e293b; border-radius:16px; box-shadow:0 8px 32px rgba(0,0,0,.5); max-width:600px; width:90%; }
    h1 { font-size:2em; color:#f59e0b; margin-bottom:12px; }
    p { color:#94a3b8; line-height:1.6; margin-bottom:8px; }
    .badge { display:inline-block; background:#f59e0b; color:#0f172a; padding:6px 20px; border-radius:20px; font-weight:bold; font-size:.85em; margin:16px 0; }
  </style>
</head>
<body>
  <div class="container">
    <h1>⚠️ Sitio en Mantenimiento</h1>
    <div class="badge">MANTENIMIENTO PROGRAMADO</div>
    <p>Estamos realizando tareas de mantenimiento para mejorar nuestros servicios.</p>
    <p><strong>Por favor, inténtelo de nuevo en unos minutos.</strong></p>
    <p style="margin-top:20px; font-size:0.8em; color:#475569;">roLearning – AWS Route 53 ARC Workshop (Terraform + CloudFront)</p>
  </div>
</body>
</html>
HTML

aws s3 cp /tmp/fallback-index.html s3://$BUCKET_NAME/index.html --content-type "text/html" --region $AWS_REGION
echo "🌐 Sitio Fallback (CloudFront): $FALLBACK_DOMAIN"
echo "⏳ CloudFront puede tardar 15-20 min en propagarse."

✅ Verificación del Lab 2

echo "=== Verificación Lab 2: Sitio Secundario ==="
echo "Probando endpoint fallback: $FALLBACK_DOMAIN"

STATUS=$(curl -s -o /dev/null -w "%{http_code}" $FALLBACK_DOMAIN)
[ "$STATUS" = "200" ] \
  && echo "✅ Sitio fallback HTTPS responde: HTTP $STATUS" \
  || echo "⚠️  Estado HTTP: $STATUS — si usaste CloudFront, esperá 15-20 min y re-ejecutá esta verificación"

Siguiente paso → Lab 3: Route 53 ARC