#!/usr/bin/env bash # 🚀 RxMinder Template-based Kubernetes Deployment Script # This script processes template files and applies them to Kubernetes set -euo pipefail # Script configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" K8S_DIR="$(dirname "$SCRIPT_DIR")/k8s" ENV_FILE="$(dirname "$SCRIPT_DIR")/.env" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color print_status() { echo -e "${BLUE}$1${NC}" } print_success() { echo -e "${GREEN}✅ $1${NC}" } print_warning() { echo -e "${YELLOW}⚠️ $1${NC}" } print_error() { echo -e "${RED}❌ $1${NC}" } # Function to load environment variables load_env() { if [[ -f "$ENV_FILE" ]]; then print_status "Loading environment variables from .env..." # Export variables from .env file set -a source "$ENV_FILE" set +a print_success "Environment variables loaded" else print_warning ".env file not found at $ENV_FILE" print_warning "Using default values. Copy .env.example to .env and customize." fi } # Function to substitute environment variables in templates substitute_template() { local template_file="$1" local output_file="$2" print_status "Processing template: $template_file" # Use envsubst to substitute environment variables if command -v envsubst >/dev/null 2>&1; then envsubst < "$template_file" > "$output_file" else print_error "envsubst not found. Please install gettext package." exit 1 fi print_success "Generated: $output_file" } # Function to apply Kubernetes resources apply_k8s_resource() { local resource_file="$1" if [[ -f "$resource_file" ]]; then print_status "Applying Kubernetes resource: $resource_file" if kubectl apply -f "$resource_file"; then print_success "Applied: $resource_file" else print_error "Failed to apply: $resource_file" return 1 fi else print_warning "Resource file not found: $resource_file" fi } # Function to validate required environment variables validate_env() { local required_vars=( "APP_NAME" "DOCKER_IMAGE" "COUCHDB_USER" "COUCHDB_PASSWORD" "INGRESS_HOST" "STORAGE_CLASS" "STORAGE_SIZE" ) local missing_vars=() for var in "${required_vars[@]}"; do if [[ -z "${!var:-}" ]]; then missing_vars+=("$var") fi done if [[ ${#missing_vars[@]} -gt 0 ]]; then print_error "Missing required environment variables:" for var in "${missing_vars[@]}"; do echo -e " ${RED}- $var${NC}" done print_warning "Please update your .env file with these variables." exit 1 fi print_success "All required environment variables are set" } # Function to process all templates process_templates() { local temp_dir="/tmp/rxminder-k8s-$$" mkdir -p "$temp_dir" print_status "Processing Kubernetes templates..." # Find all template files local template_files=( "$K8S_DIR/couchdb-secret.yaml.template" "$K8S_DIR/ingress.yaml.template" ) # Add any additional template files for template_file in "$K8S_DIR"/*.template; do if [[ -f "$template_file" ]]; then template_files+=("$template_file") fi done # Process each template for template_file in "${template_files[@]}"; do if [[ -f "$template_file" ]]; then local base_name base_name="$(basename "$template_file" .template)" local output_file="$temp_dir/$base_name" substitute_template "$template_file" "$output_file" fi done echo "$temp_dir" } # Function to deploy resources in correct order deploy_resources() { local resource_dir="$1" print_status "Deploying Kubernetes resources..." # Deploy in specific order for dependencies local deployment_order=( "couchdb-secret.yaml" "couchdb-pvc.yaml" "couchdb-service.yaml" "couchdb-statefulset.yaml" "configmap.yaml" "frontend-deployment.yaml" "frontend-service.yaml" "ingress.yaml" "$K8S_DIR/network-policy.yaml" "$K8S_DIR/hpa.yaml" ) for resource in "${deployment_order[@]}"; do if [[ "$resource" == *.yaml ]]; then # Check if it's a template-generated file if [[ -f "$resource_dir/$(basename "$resource")" ]]; then apply_k8s_resource "$resource_dir/$(basename "$resource")" else # Apply directly from k8s directory apply_k8s_resource "$resource" fi fi done } # Function to run database seeding job run_db_seed() { print_status "Running database seed job..." # Apply the db-seed-job (which uses environment variables from secret) if kubectl apply -f "$K8S_DIR/db-seed-job.yaml"; then print_success "Database seed job submitted" # Wait for job completion print_status "Waiting for database seed job to complete..." if kubectl wait --for=condition=complete --timeout=300s job/db-seed-job; then print_success "Database seeding completed successfully" else print_warning "Database seed job may have failed. Check logs:" echo "kubectl logs job/db-seed-job" fi else print_error "Failed to apply database seed job" return 1 fi } # Function to display deployment status show_status() { print_status "Deployment Status:" echo print_status "Pods:" kubectl get pods -l app="${APP_NAME:-rxminder}" echo print_status "Services:" kubectl get services -l app="${APP_NAME:-rxminder}" echo print_status "Ingress:" kubectl get ingress echo if [[ -n "${INGRESS_HOST:-}" ]]; then print_success "Application should be available at: http://${INGRESS_HOST}" fi } # Function to cleanup temporary files cleanup() { if [[ -n "${temp_dir:-}" && -d "$temp_dir" ]]; then rm -rf "$temp_dir" fi } # Main deployment function main() { local command="${1:-deploy}" case "$command" in "deploy"|"apply") print_status "🚀 Starting RxMinder Kubernetes deployment..." echo # Set default values for required variables export APP_NAME="${APP_NAME:-rxminder}" export DOCKER_IMAGE="${DOCKER_IMAGE:-gitea-http.taildb3494.ts.net/will/meds:latest}" export COUCHDB_USER="${COUCHDB_USER:-admin}" export COUCHDB_PASSWORD="${COUCHDB_PASSWORD:-change-this-secure-password}" export INGRESS_HOST="${INGRESS_HOST:-rxminder.local}" export STORAGE_CLASS="${STORAGE_CLASS:-longhorn}" export STORAGE_SIZE="${STORAGE_SIZE:-5Gi}" load_env validate_env # Process templates temp_dir=$(process_templates) trap cleanup EXIT # Deploy resources deploy_resources "$temp_dir" # Run database seeding run_db_seed # Show status echo show_status print_success "🎉 RxMinder deployment completed!" ;; "status") load_env show_status ;; "delete"|"cleanup") print_status "🗑️ Cleaning up RxMinder deployment..." kubectl delete all,pvc,secret,configmap,ingress -l app="${APP_NAME:-rxminder}" || true kubectl delete job db-seed-job || true print_success "Cleanup completed" ;; "help"|"-h"|"--help") echo "RxMinder Kubernetes Deployment Script" echo echo "Usage: $0 [command]" echo echo "Commands:" echo " deploy Deploy RxMinder to Kubernetes (default)" echo " status Show deployment status" echo " delete Delete all RxMinder resources" echo " help Show this help message" echo echo "Environment variables (set in .env):" echo " APP_NAME Application name (default: rxminder)" echo " DOCKER_IMAGE Container image to deploy" echo " COUCHDB_USER Database username (default: admin)" echo " COUCHDB_PASSWORD Database password (required)" echo " INGRESS_HOST Ingress hostname (required)" echo " STORAGE_CLASS Storage class for PVCs (default: longhorn)" echo " STORAGE_SIZE Storage size for database (default: 5Gi)" ;; *) print_error "Unknown command: $command" echo "Use '$0 help' for usage information" exit 1 ;; esac } # Check if kubectl is available if ! command -v kubectl >/dev/null 2>&1; then print_error "kubectl not found. Please install kubectl and configure it to connect to your cluster." exit 1 fi # Check if envsubst is available if ! command -v envsubst >/dev/null 2>&1; then print_error "envsubst not found. Please install the gettext package:" echo " Ubuntu/Debian: sudo apt-get install gettext" echo " macOS: brew install gettext" echo " RHEL/CentOS: sudo yum install gettext" exit 1 fi # Run main function main "$@"