Back

2_compute_deploy

#  AMI    : Latest Ubuntu Server LTS
#  TYPE   : t3.micro (Free Tier eligible)
#  USER   : ubuntu
#  RUN    : chmod +x 2_compute_deploy.sh && ./2_compute_deploy.sh
#  DELETE : ./2_compute_cleanup.sh
#  STATE  : $HOME/aws_state_compute.txt
# ================================================================
set -euo pipefail

REGION="ap-south-1"
AMI_ID=$(aws ec2 describe-images --owners 099720109477 \
  --filters "Name=name,Values=ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*" \
  --region "$REGION" --query "sort_by(Images, &CreationDate)[-1].ImageId" --output text)
INSTANCE_TYPE="t3.micro"
KEY_NAME="Practical-KeyPair"
SG_NAME="Practical-FirstEC2-SG"
INST_NAME="First-EC2-Instance"
STATE_FILE="$HOME/aws_state_compute.txt"

G='\033[0;32m'; B='\033[0;34m'; Y='\033[1;33m'; NC='\033[0m'
info()    { echo -e "${B}[INFO]${NC}  $*"; }
success() { echo -e "${G}[OK]${NC}    $*"; }
banner()  { echo -e "\n${Y}══════════════════════════════════════════${NC}"; \
            echo -e "${Y}  $*${NC}"; \
            echo -e "${Y}══════════════════════════════════════════${NC}\n"; }

banner "AWS COMPUTE — Launch EC2 Instance"
echo "  AMI    : $AMI_ID (Ubuntu 24.04 LTS)"
echo "  Type   : $INSTANCE_TYPE (2 vCPU, 8 GB)"
echo "  Region : $REGION"
echo ""

# ── Step 1: Key Pair ─────────────────────────────────────────
info "Step 1 — Key Pair: $KEY_NAME"
if aws ec2 describe-key-pairs --key-names "$KEY_NAME" --region "$REGION" >/dev/null 2>&1; then
  info "  Key Pair '$KEY_NAME' already exists. Using it."
else
  info "  Creating Key Pair: $KEY_NAME"
  aws ec2 create-key-pair --key-name "$KEY_NAME" --region "$REGION" \
    --query "KeyMaterial" --output text > "$HOME/${KEY_NAME}.pem"
  chmod 400 "$HOME/${KEY_NAME}.pem"
  success "Key Pair created → $HOME/${KEY_NAME}.pem"
fi

# ── Step 2: Networking (Independence & "From Scratch" logic) ───
info "Step 2 — Networking: VPC Discovery"
VPC_ID=$(aws ec2 describe-vpcs --filters "Name=tag:Name,Values=Practical-VPC" --query "Vpcs[0].VpcId" --output text --region "$REGION" 2>/dev/null || echo "None")
if [[ "$VPC_ID" == "None" || "$VPC_ID" == "null" ]]; then
  VPC_ID=$(aws ec2 describe-vpcs --filters "Name=isDefault,Values=true" --region "$REGION" --query "Vpcs[0].VpcId" --output text 2>/dev/null || echo "None")
fi

if [[ "$VPC_ID" == "None" || "$VPC_ID" == "null" ]]; then
  info "  No suitable VPC found. Creating 'Practical-Compute-VPC'..."
  VPC_ID=$(aws ec2 create-vpc --cidr-block "10.20.0.0/16" --region "$REGION" --query "Vpc.VpcId" --output text)
  aws ec2 create-tags --resources "$VPC_ID" --region "$REGION" --tags Key=Name,Value="Practical-Compute-VPC"
  aws ec2 modify-vpc-attribute --vpc-id "$VPC_ID" --enable-dns-hostnames --region "$REGION"
  aws ec2 modify-vpc-attribute --vpc-id "$VPC_ID" --enable-dns-support --region "$REGION"
  IGW_ID=$(aws ec2 create-internet-gateway --region "$REGION" --query "InternetGateway.InternetGatewayId" --output text)
  aws ec2 attach-internet-gateway --internet-gateway-id "$IGW_ID" --vpc-id "$VPC_ID" --region "$REGION"
  # Route Table
  RT_ID=$(aws ec2 create-route-table --vpc-id "$VPC_ID" --region "$REGION" --query "RouteTable.RouteTableId" --output text)
  aws ec2 create-route --route-table-id "$RT_ID" --destination-cidr-block "0.0.0.0/0" --gateway-id "$IGW_ID" --region "$REGION" > /dev/null
fi

SUBNET_ID=$(aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPC_ID" --region "$REGION" --query "Subnets[0].SubnetId" --output text 2>/dev/null || echo "None")
if [[ "$SUBNET_ID" == "None" || "$SUBNET_ID" == "null" ]]; then
  info "  Creating subnet..."
  SUBNET_ID=$(aws ec2 create-subnet --vpc-id "$VPC_ID" --cidr-block "10.20.1.0/24" --region "$REGION" --query "Subnet.SubnetId" --output text 2>/dev/null || \
           aws ec2 create-default-subnet --region "$REGION" --query "Subnet.SubnetId" --output text)
fi
success "VPC: $VPC_ID | Subnet: $SUBNET_ID"

SG_ID=$(aws ec2 describe-security-groups --group-names "$SG_NAME" --region "$REGION" \
  --query "SecurityGroups[0].GroupId" --output text 2>/dev/null || echo "NOT_FOUND")

if [[ "$SG_ID" == "NOT_FOUND" ]]; then
  info "  Creating Security Group..."
  SG_ID=$(aws ec2 create-security-group \
    --group-name "$SG_NAME" \
    --description "Allow SSH Access" \
    --vpc-id "$VPC_ID" \
    --region "$REGION" \
    --query "GroupId" --output text)
  aws ec2 create-tags --resources "$SG_ID" \
    --tags Key=Name,Value="$SG_NAME" --region "$REGION"
  success "Security Group created: $SG_ID"
else
  info "  Security Group '$SG_NAME' already exists ($SG_ID). Using it."
fi

# ── Step 3: SSH Inbound Rule ──────────────────────────────────
info "Step 3 — Adding SSH inbound rule (port 22)"
aws ec2 authorize-security-group-ingress \
  --group-id "$SG_ID" --protocol tcp --port 22 --cidr "0.0.0.0/0" \
  --region "$REGION" 2>/dev/null || true
success "SSH (port 22) rule checked/added."

# ── Step 4: Launch EC2 ───────────────────────────────────────
info "Step 4 — Compute Instance: $INST_NAME"
INSTANCE_ID=$(aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=$INST_NAME" "Name=instance-state-name,Values=running" \
  --region "$REGION" --query "Reservations[0].Instances[0].InstanceId" --output text 2>/dev/null || echo "None")

if [[ "$INSTANCE_ID" == "None" || "$INSTANCE_ID" == "null" ]]; then
  info "  Launching new instance..."
  INSTANCE_ID=$(aws ec2 run-instances \
    --image-id "$AMI_ID" \
    --instance-type "$INSTANCE_TYPE" \
    --key-name "$KEY_NAME" \
    --security-group-ids "$SG_ID" \
    --subnet-id "$SUBNET_ID" \
    --region "$REGION" \
    --count 1 \
    --tag-specifications \
      "ResourceType=instance,Tags=[
        {Key=Name,Value=$INST_NAME},
        {Key=AMI,Value=$AMI_ID}]" \
    --query "Instances[0].InstanceId" \
    --output text)
  success "Instance launched: $INSTANCE_ID"
else
  info "  Running instance 'EC2-ComputeNode' already exists ($INSTANCE_ID). Using it."
fi

# ── Step 5: Wait ──────────────────────────────────────────────
info "Step 5 — Waiting for 'running' state..."
aws ec2 wait instance-running \
  --instance-ids "$INSTANCE_ID" --region "$REGION"
success "Instance is RUNNING."

# ── Step 6: Fetch Details ─────────────────────────────────────
info "Step 6 — Fetching instance details"
aws ec2 describe-instances \
  --instance-ids "$INSTANCE_ID" --region "$REGION" \
  --query "Reservations[0].Instances[0].{
      ID:InstanceId, State:State.Name,
      Type:InstanceType, PublicIP:PublicIpAddress,
      PrivateIP:PrivateIpAddress, AZ:Placement.AvailabilityZone,
      AMI:ImageId}" \
  --output table

PUBLIC_IP=$(aws ec2 describe-instances \
  --instance-ids "$INSTANCE_ID" --region "$REGION" \
  --query "Reservations[0].Instances[0].PublicIpAddress" --output text)

# ── Save state ────────────────────────────────────────────────
cat > "$STATE_FILE" <<EOF
REGION=$REGION
INSTANCE_ID=$INSTANCE_ID
SG_ID=$SG_ID
SG_NAME=$SG_NAME
VPC_ID=$VPC_ID
KEY_NAME=$KEY_NAME
PUBLIC_IP=$PUBLIC_IP
AMI_ID=$AMI_ID
INSTANCE_TYPE=$INSTANCE_TYPE
EOF

banner "AWS COMPUTE — COMPLETE SUMMARY"
cat <<SUMMARY
  ╔════════════════════════════════════════════════════════════════════════════════╗
  ║              RESOURCES DEPLOYED                                                ║
  ╠═══════════════════════╦════════════════════════════════════════════════════════╣
  ║ Resource              ║ Value                                                  ║
  ╠═══════════════════════╬════════════════════════════════════════════════════════╣
  ║ EC2 Instance ID       ║ $INSTANCE_ID                                           ║
  ║ Public IP             ║ $PUBLIC_IP                                             ║
  ║ Key Pair Name         ║ $KEY_NAME                                              ║
  ║ Key File Location     ║ $HOME/${KEY_NAME}.pem                                  ║
  ║ Security Group ID     ║ $SG_ID                                                 ║
  ║ Security Group Name   ║ $SG_NAME                                               ║
  ║ VPC ID                ║ $VPC_ID                                                ║
  ║ AMI Used              ║ $AMI_ID                                                ║
  ║ Instance Type         ║ $INSTANCE_TYPE                                         ║
  ║ Region                ║ $REGION                                                ║
  ╠═══════════════════════╩════════════════════════════════════════════════════════╣
  ║              DETAILS NEEDED TO CLEANUP                                         ║
  ╠════════════════════════════════════════════════════════════════════════════════╣
  ║  Instance ID  : $INSTANCE_ID                                                   ║
  ║  SG ID        : $SG_ID                                                         ║
  ║  Key Pair     : $KEY_NAME                                                      ║
  ║  Region       : $REGION                                                        ║
  ║  State File   : $STATE_FILE                                                    ║
  ╠════════════════════════════════════════════════════════════════════════════════╣
  ║  Run: ./2_compute_cleanup.sh  (reads state file automatically)                 ║
  ╚════════════════════════════════════════════════════════════════════════════════╝

  Connect to Instance:
  EC2 Console → Instances → $INSTANCE_ID → Connect → EC2 Instance Connect
SUMMARY