288 lines
11 KiB
Bash
Executable File
288 lines
11 KiB
Bash
Executable File
#!/bin/bash
|
|
# MPR Deploy Script
|
|
#
|
|
# Usage: ./ctrl/deploy.sh <command> [options]
|
|
#
|
|
# Commands:
|
|
# rsync [--restart] [--dry-run] Sync to remote server via rsync
|
|
# aws Deploy AWS infrastructure (Lambda, Step Functions, S3)
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
cd "$PROJECT_ROOT"
|
|
|
|
source "$SCRIPT_DIR/.env" 2>/dev/null || true
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
# ─── Rsync Deploy ─────────────────────────────────────────────────────────────
|
|
|
|
deploy_rsync() {
|
|
if [ -z "${SERVER:-}" ] || [ -z "${REMOTE_PATH:-}" ]; then
|
|
echo -e "${RED}Error: SERVER and REMOTE_PATH must be set in ctrl/.env${NC}"
|
|
echo "Example:"
|
|
echo " SERVER=user@host"
|
|
echo " REMOTE_PATH=~/mpr"
|
|
exit 1
|
|
fi
|
|
|
|
RESTART=false
|
|
DRY_RUN=""
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--restart) RESTART=true; shift ;;
|
|
--dry-run) DRY_RUN="--dry-run"; shift ;;
|
|
*) echo "Unknown option: $1"; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
echo -e "${GREEN}=== Deploying MPR to $SERVER:$REMOTE_PATH ===${NC}"
|
|
|
|
echo -e "${YELLOW}Syncing files...${NC}"
|
|
rsync -avz --delete $DRY_RUN \
|
|
--filter=':- .gitignore' \
|
|
--exclude='.git' \
|
|
--exclude='media/*' \
|
|
--exclude='ctrl/.env' \
|
|
"$PROJECT_ROOT/" "$SERVER:$REMOTE_PATH/"
|
|
|
|
if [ -n "$DRY_RUN" ]; then
|
|
echo -e "${YELLOW}Dry run - no changes made${NC}"
|
|
exit 0
|
|
fi
|
|
|
|
ssh "$SERVER" "[ -f $REMOTE_PATH/ctrl/.env ] || cp $REMOTE_PATH/ctrl/.env.template $REMOTE_PATH/ctrl/.env"
|
|
|
|
if [ "$RESTART" = true ]; then
|
|
echo -e "${YELLOW}Restarting services...${NC}"
|
|
ssh "$SERVER" "cd $REMOTE_PATH/ctrl && docker compose down && docker compose up -d --build"
|
|
fi
|
|
|
|
echo -e "${GREEN}Done!${NC}"
|
|
}
|
|
|
|
# ─── AWS Deploy ────────────────────────────────────────────────────────────────
|
|
|
|
deploy_aws() {
|
|
REGION="${AWS_REGION:-us-east-1}"
|
|
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
|
|
PROJECT="mpr"
|
|
|
|
# S3
|
|
BUCKET_IN="${S3_BUCKET_IN:-mpr-media-in}"
|
|
BUCKET_OUT="${S3_BUCKET_OUT:-mpr-media-out}"
|
|
|
|
# ECR
|
|
ECR_REPO="${PROJECT}-transcode"
|
|
ECR_URI="${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/${ECR_REPO}"
|
|
|
|
# Lambda
|
|
LAMBDA_NAME="${PROJECT}-transcode"
|
|
LAMBDA_TIMEOUT=900
|
|
LAMBDA_MEMORY=2048
|
|
|
|
# Step Functions
|
|
SFN_NAME="${PROJECT}-transcode"
|
|
|
|
# IAM
|
|
LAMBDA_ROLE_NAME="${PROJECT}-lambda-role"
|
|
SFN_ROLE_NAME="${PROJECT}-sfn-role"
|
|
|
|
# Callback
|
|
CALLBACK_URL="${CALLBACK_URL:-https://mpr.mcrn.ar/api}"
|
|
CALLBACK_API_KEY="${CALLBACK_API_KEY:-changeme}"
|
|
|
|
echo -e "${GREEN}=== Deploying MPR to AWS ($REGION, account $ACCOUNT_ID) ===${NC}"
|
|
|
|
# ─── S3 Buckets ───────────────────────────────────────────────────────
|
|
|
|
echo -e "${YELLOW}Creating S3 buckets...${NC}"
|
|
for bucket in "$BUCKET_IN" "$BUCKET_OUT"; do
|
|
if ! aws s3api head-bucket --bucket "$bucket" 2>/dev/null; then
|
|
aws s3api create-bucket \
|
|
--bucket "$bucket" \
|
|
--region "$REGION" \
|
|
--create-bucket-configuration LocationConstraint="$REGION"
|
|
echo " Created $bucket"
|
|
else
|
|
echo " $bucket already exists"
|
|
fi
|
|
done
|
|
|
|
# ─── IAM Roles ────────────────────────────────────────────────────────
|
|
|
|
echo -e "${YELLOW}Creating IAM roles...${NC}"
|
|
|
|
if ! aws iam get-role --role-name "$LAMBDA_ROLE_NAME" 2>/dev/null; then
|
|
aws iam create-role \
|
|
--role-name "$LAMBDA_ROLE_NAME" \
|
|
--assume-role-policy-document '{
|
|
"Version": "2012-10-17",
|
|
"Statement": [{
|
|
"Effect": "Allow",
|
|
"Principal": {"Service": "lambda.amazonaws.com"},
|
|
"Action": "sts:AssumeRole"
|
|
}]
|
|
}'
|
|
aws iam attach-role-policy \
|
|
--role-name "$LAMBDA_ROLE_NAME" \
|
|
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
|
|
aws iam put-role-policy \
|
|
--role-name "$LAMBDA_ROLE_NAME" \
|
|
--policy-name "${PROJECT}-s3-access" \
|
|
--policy-document '{
|
|
"Version": "2012-10-17",
|
|
"Statement": [{
|
|
"Effect": "Allow",
|
|
"Action": ["s3:GetObject", "s3:PutObject"],
|
|
"Resource": [
|
|
"arn:aws:s3:::'"$BUCKET_IN"'/*",
|
|
"arn:aws:s3:::'"$BUCKET_OUT"'/*"
|
|
]
|
|
}]
|
|
}'
|
|
echo " Created $LAMBDA_ROLE_NAME"
|
|
echo " Waiting for role to propagate..."
|
|
sleep 10
|
|
else
|
|
echo " $LAMBDA_ROLE_NAME already exists"
|
|
fi
|
|
LAMBDA_ROLE_ARN=$(aws iam get-role --role-name "$LAMBDA_ROLE_NAME" --query Role.Arn --output text)
|
|
|
|
if ! aws iam get-role --role-name "$SFN_ROLE_NAME" 2>/dev/null; then
|
|
aws iam create-role \
|
|
--role-name "$SFN_ROLE_NAME" \
|
|
--assume-role-policy-document '{
|
|
"Version": "2012-10-17",
|
|
"Statement": [{
|
|
"Effect": "Allow",
|
|
"Principal": {"Service": "states.amazonaws.com"},
|
|
"Action": "sts:AssumeRole"
|
|
}]
|
|
}'
|
|
aws iam put-role-policy \
|
|
--role-name "$SFN_ROLE_NAME" \
|
|
--policy-name "${PROJECT}-sfn-invoke-lambda" \
|
|
--policy-document '{
|
|
"Version": "2012-10-17",
|
|
"Statement": [{
|
|
"Effect": "Allow",
|
|
"Action": "lambda:InvokeFunction",
|
|
"Resource": "arn:aws:lambda:'"$REGION"':'"$ACCOUNT_ID"':function:'"$LAMBDA_NAME"'"
|
|
}]
|
|
}'
|
|
echo " Created $SFN_ROLE_NAME"
|
|
sleep 10
|
|
else
|
|
echo " $SFN_ROLE_NAME already exists"
|
|
fi
|
|
SFN_ROLE_ARN=$(aws iam get-role --role-name "$SFN_ROLE_NAME" --query Role.Arn --output text)
|
|
|
|
# ─── ECR Repository ──────────────────────────────────────────────────
|
|
|
|
echo -e "${YELLOW}Setting up ECR...${NC}"
|
|
if ! aws ecr describe-repositories --repository-names "$ECR_REPO" --region "$REGION" 2>/dev/null; then
|
|
aws ecr create-repository --repository-name "$ECR_REPO" --region "$REGION"
|
|
echo " Created ECR repo $ECR_REPO"
|
|
else
|
|
echo " ECR repo $ECR_REPO already exists"
|
|
fi
|
|
|
|
# ─── Build & Push Lambda Image ───────────────────────────────────────
|
|
|
|
echo -e "${YELLOW}Building Lambda container image...${NC}"
|
|
|
|
docker build -f ctrl/lambda/Dockerfile -t "${ECR_REPO}:latest" .
|
|
|
|
echo -e "${YELLOW}Pushing to ECR...${NC}"
|
|
aws ecr get-login-password --region "$REGION" | \
|
|
docker login --username AWS --password-stdin "${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com"
|
|
|
|
docker tag "${ECR_REPO}:latest" "${ECR_URI}:latest"
|
|
docker push "${ECR_URI}:latest"
|
|
|
|
# ─── Lambda Function ─────────────────────────────────────────────────
|
|
|
|
echo -e "${YELLOW}Deploying Lambda function...${NC}"
|
|
LAMBDA_ARN="arn:aws:lambda:${REGION}:${ACCOUNT_ID}:function:${LAMBDA_NAME}"
|
|
|
|
if aws lambda get-function --function-name "$LAMBDA_NAME" --region "$REGION" 2>/dev/null; then
|
|
aws lambda update-function-code \
|
|
--function-name "$LAMBDA_NAME" \
|
|
--image-uri "${ECR_URI}:latest" \
|
|
--region "$REGION"
|
|
echo " Updated $LAMBDA_NAME"
|
|
else
|
|
aws lambda create-function \
|
|
--function-name "$LAMBDA_NAME" \
|
|
--package-type Image \
|
|
--code ImageUri="${ECR_URI}:latest" \
|
|
--role "$LAMBDA_ROLE_ARN" \
|
|
--timeout "$LAMBDA_TIMEOUT" \
|
|
--memory-size "$LAMBDA_MEMORY" \
|
|
--environment "Variables={S3_BUCKET_IN=${BUCKET_IN},S3_BUCKET_OUT=${BUCKET_OUT},AWS_REGION=${REGION}}" \
|
|
--region "$REGION"
|
|
echo " Created $LAMBDA_NAME"
|
|
fi
|
|
|
|
# ─── Step Functions ───────────────────────────────────────────────────
|
|
|
|
echo -e "${YELLOW}Deploying Step Functions state machine...${NC}"
|
|
|
|
SFN_DEFINITION=$(sed "s|\${TranscodeLambdaArn}|${LAMBDA_ARN}|g" ctrl/state-machine.json)
|
|
|
|
SFN_ARN="arn:aws:states:${REGION}:${ACCOUNT_ID}:stateMachine:${SFN_NAME}"
|
|
if aws stepfunctions describe-state-machine --state-machine-arn "$SFN_ARN" --region "$REGION" 2>/dev/null; then
|
|
aws stepfunctions update-state-machine \
|
|
--state-machine-arn "$SFN_ARN" \
|
|
--definition "$SFN_DEFINITION" \
|
|
--region "$REGION"
|
|
echo " Updated $SFN_NAME"
|
|
else
|
|
aws stepfunctions create-state-machine \
|
|
--name "$SFN_NAME" \
|
|
--definition "$SFN_DEFINITION" \
|
|
--role-arn "$SFN_ROLE_ARN" \
|
|
--region "$REGION"
|
|
echo " Created $SFN_NAME"
|
|
fi
|
|
|
|
# ─── Summary ──────────────────────────────────────────────────────────
|
|
|
|
echo ""
|
|
echo -e "${GREEN}Deployment complete!${NC}"
|
|
echo ""
|
|
echo "Add these to your .env:"
|
|
echo " MPR_EXECUTOR=lambda"
|
|
echo " STEP_FUNCTION_ARN=${SFN_ARN}"
|
|
echo " LAMBDA_FUNCTION_ARN=${LAMBDA_ARN}"
|
|
echo " S3_BUCKET_IN=${BUCKET_IN}"
|
|
echo " S3_BUCKET_OUT=${BUCKET_OUT}"
|
|
echo " CALLBACK_URL=${CALLBACK_URL}"
|
|
echo " CALLBACK_API_KEY=${CALLBACK_API_KEY}"
|
|
}
|
|
|
|
# ─── Main ──────────────────────────────────────────────────────────────────────
|
|
|
|
COMMAND="${1:-}"
|
|
shift || true
|
|
|
|
case "$COMMAND" in
|
|
rsync) deploy_rsync "$@" ;;
|
|
aws) deploy_aws "$@" ;;
|
|
*)
|
|
echo "Usage: ./ctrl/deploy.sh <command> [options]"
|
|
echo ""
|
|
echo "Commands:"
|
|
echo " rsync [--restart] [--dry-run] Sync to remote server"
|
|
echo " aws Deploy AWS infrastructure"
|
|
exit 1
|
|
;;
|
|
esac
|