From 4db1285f883265c490e88fb7866db31348eb0586 Mon Sep 17 00:00:00 2001 From: pratik Date: Wed, 22 Oct 2025 13:19:06 -0500 Subject: [PATCH] add simple deploy --- .claude/settings.local.json | 3 +- deploy-chunked-simple.sh | 322 ++++++++++++++++++++++++++++++++++++ 2 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 deploy-chunked-simple.sh diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 22d13f2..2b2b1ef 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -8,7 +8,8 @@ "Bash(./gradlew clean build:*)", "Bash(jar:*)", "Bash(git log:*)", - "Bash(dir /B *.sh *.md)" + "Bash(dir /B *.sh *.md)", + "Bash(chmod:*)" ], "deny": [], "ask": [] diff --git a/deploy-chunked-simple.sh b/deploy-chunked-simple.sh new file mode 100644 index 0000000..aa2c399 --- /dev/null +++ b/deploy-chunked-simple.sh @@ -0,0 +1,322 @@ +#!/bin/bash + +############################################################################# +# CF Deployer - Simple Chunked Upload Deployment Script +# +# This script deploys a Java application to Cloud Foundry using chunked +# uploads to bypass nginx size restrictions and async deployment to avoid +# timeout issues. +# +# This is a simplified version without cert/key/header authentication. +# +# Usage: +# ./deploy-chunked-simple.sh +# +# Configuration: +# Edit the variables below to match your environment +############################################################################# + +set -e # Exit on error + +############################################################################# +# CONFIGURATION - Update these values for your deployment +############################################################################# + +# API endpoint +API_BASE="http://localhost:8080/api/cf" + +# Files to deploy +JAR_FILE="./app.jar" +MANIFEST_FILE="./manifest.yml" + +# Chunk size (bytes) +# Recommended: 1MB (1048576) for Tanzu with memory constraints +# Options: 512KB (524288), 1MB (1048576), 2MB (2097152), 5MB (5242880) +CHUNK_SIZE=1048576 # 1MB + +# Cloud Foundry configuration +CF_API_ENDPOINT="https://api.cf.example.com" +CF_USERNAME="your-username" +CF_PASSWORD="your-password" +CF_ORGANIZATION="your-org" +CF_SPACE="your-space" +CF_APP_NAME="your-app" +CF_SKIP_SSL="false" # Use "true" for self-signed certificates + +# Polling configuration +POLL_INTERVAL=5 # seconds between status checks +MAX_WAIT=600 # maximum wait time in seconds (10 minutes) + +# Debug mode (set to "true" to see curl commands and responses) +DEBUG_MODE="false" + +############################################################################# +# SCRIPT - Do not modify below this line +############################################################################# + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Helper functions +log_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +log_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +log_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +# Check if files exist +if [ ! -f "$JAR_FILE" ]; then + log_error "JAR file not found: $JAR_FILE" + exit 1 +fi + +if [ ! -f "$MANIFEST_FILE" ]; then + log_error "Manifest file not found: $MANIFEST_FILE" + exit 1 +fi + +# Check if curl is available +if ! command -v curl &> /dev/null; then + log_error "curl is not installed. Please install curl to use this script." + exit 1 +fi + +# Build CF configuration JSON +CF_CONFIG=$(cat < "$TEMP_JSON" + +# Execute curl command +if [ "$DEBUG_MODE" = "true" ]; then + INIT_RESPONSE=$(curl -v -X POST "$API_BASE/upload/init" \ + -H "Content-Type: application/json" \ + -d @"$TEMP_JSON") +else + INIT_RESPONSE=$(curl -s -X POST "$API_BASE/upload/init" \ + -H "Content-Type: application/json" \ + -d @"$TEMP_JSON") +fi + +# Clean up temporary file +rm -f "$TEMP_JSON" + +CURL_EXIT_CODE=$? +if [ "$DEBUG_MODE" = "true" ]; then + echo "DEBUG: Curl exit code: $CURL_EXIT_CODE" + echo "DEBUG: Response:" + echo "$INIT_RESPONSE" +fi + +if [ $CURL_EXIT_CODE -ne 0 ]; then + log_error "Failed to initialize upload session (curl exit code: $CURL_EXIT_CODE)" + echo "$INIT_RESPONSE" + exit 1 +fi + +# Debug output +if [ -z "$INIT_RESPONSE" ]; then + log_error "Empty response from server" + exit 1 +fi + +SESSION_ID=$(echo "$INIT_RESPONSE" | grep -o '"uploadSessionId":"[^"]*' | cut -d'"' -f4) + +if [ -z "$SESSION_ID" ]; then + log_error "Failed to get session ID from response:" + echo "$INIT_RESPONSE" + exit 1 +fi + +log_success "Upload session created: $SESSION_ID" +echo "" + +############################################################################# +# FUNCTION: Upload file in chunks +############################################################################# +upload_file_in_chunks() { + local file_path=$1 + local file_type=$2 + local file_name=$(basename "$file_path") + + # Get file size (cross-platform) + if [[ "$OSTYPE" == "darwin"* ]]; then + local file_size=$(stat -f%z "$file_path") + else + local file_size=$(stat -c%s "$file_path") + fi + + local total_chunks=$(( ($file_size + $CHUNK_SIZE - 1) / $CHUNK_SIZE )) + local file_size_mb=$(awk "BEGIN {printf \"%.2f\", $file_size / 1048576}") + + log_info "Uploading $file_type: $file_name (${file_size_mb}MB, $total_chunks chunks)" + + # Create temporary directory for chunks + local temp_dir=$(mktemp -d) + + # Split file into chunks + split -b $CHUNK_SIZE "$file_path" "$temp_dir/chunk_" + + local chunk_index=0 + for chunk_file in "$temp_dir"/chunk_*; do + printf " Chunk %3d/%3d... " "$((chunk_index + 1))" "$total_chunks" + + RESPONSE=$(curl -s -X POST "$API_BASE/upload/chunk" \ + -F "uploadSessionId=$SESSION_ID" \ + -F "fileType=$file_type" \ + -F "chunkIndex=$chunk_index" \ + -F "totalChunks=$total_chunks" \ + -F "fileName=$file_name" \ + -F "chunk=@$chunk_file") + + SUCCESS=$(echo "$RESPONSE" | grep -o '"success":[^,}]*' | cut -d':' -f2) + + if [ "$SUCCESS" != "true" ]; then + echo -e "${RED}FAILED${NC}" + log_error "Failed to upload chunk $((chunk_index + 1))/$total_chunks" + echo "$RESPONSE" + rm -rf "$temp_dir" + exit 1 + fi + + echo -e "${GREEN}OK${NC}" + chunk_index=$((chunk_index + 1)) + done + + # Cleanup temporary directory + rm -rf "$temp_dir" + log_success "$file_type upload completed ($total_chunks chunks)" + echo "" +} + +############################################################################# +# STEP 2: Upload JAR file +############################################################################# +log_info "Step 2/5: Uploading JAR file..." +upload_file_in_chunks "$JAR_FILE" "jarFile" + +############################################################################# +# STEP 3: Upload manifest file +############################################################################# +log_info "Step 3/5: Uploading manifest file..." +upload_file_in_chunks "$MANIFEST_FILE" "manifest" + +############################################################################# +# STEP 4: Start async deployment +############################################################################# +log_info "Step 4/5: Starting async deployment..." + +FINALIZE_RESPONSE=$(curl -s -X POST "$API_BASE/upload/finalize?uploadSessionId=$SESSION_ID&async=true" \ + -H "Content-Length: 0") + +STATUS=$(echo "$FINALIZE_RESPONSE" | grep -o '"status":"[^"]*' | cut -d'"' -f4) + +if [ "$STATUS" != "IN_PROGRESS" ]; then + log_error "Failed to start deployment. Status: $STATUS" + echo "$FINALIZE_RESPONSE" + exit 1 +fi + +log_success "Deployment started successfully" +log_info "Step 5/5: Polling deployment status (max wait: ${MAX_WAIT}s)..." +echo "" + +############################################################################# +# STEP 5: Poll deployment status +############################################################################# +elapsed=0 +last_message="" + +while [ $elapsed -lt $MAX_WAIT ]; do + sleep $POLL_INTERVAL + elapsed=$((elapsed + POLL_INTERVAL)) + + STATUS_RESPONSE=$(curl -s "$API_BASE/deployment/status/$SESSION_ID" 2>/dev/null) + + if [ $? -ne 0 ]; then + log_warning "Failed to fetch status, retrying..." + continue + fi + + CURRENT_STATUS=$(echo "$STATUS_RESPONSE" | grep -o '"status":"[^"]*' | cut -d'"' -f4) + MESSAGE=$(echo "$STATUS_RESPONSE" | grep -o '"message":"[^"]*' | cut -d'"' -f4) + PROGRESS=$(echo "$STATUS_RESPONSE" | grep -o '"progress":[0-9]*' | cut -d':' -f2) + + # Only print if message changed to reduce clutter + if [ "$MESSAGE" != "$last_message" ]; then + printf " [%3ds] Status: %-15s Progress: %3s%% - %s\n" \ + "$elapsed" "$CURRENT_STATUS" "${PROGRESS:-0}" "$MESSAGE" + last_message="$MESSAGE" + fi + + # Check if deployment completed + if [ "$CURRENT_STATUS" = "COMPLETED" ]; then + echo "" + log_success "Deployment completed successfully!" + echo "" + log_info "Deployment details:" + echo "$STATUS_RESPONSE" | python -m json.tool 2>/dev/null || echo "$STATUS_RESPONSE" + exit 0 + fi + + # Check if deployment failed + if [ "$CURRENT_STATUS" = "FAILED" ]; then + echo "" + log_error "Deployment failed!" + echo "" + log_info "Error details:" + echo "$STATUS_RESPONSE" | python -m json.tool 2>/dev/null || echo "$STATUS_RESPONSE" + exit 1 + fi +done + +# Timeout reached +echo "" +log_warning "Deployment timeout reached after ${MAX_WAIT}s" +log_info "The deployment may still be running. Check status manually:" +echo " curl $API_BASE/deployment/status/$SESSION_ID" +exit 1