#!/bin/bash # MongoDB Connection Test Script for Release Environment # Tests connectivity, database operations, and index validation set -euo pipefail # Configuration readonly MONGODB_HOST="${MONGODB_HOST:-192.168.0.100}" readonly MONGODB_PORT="${MONGODB_PORT:-27017}" readonly DATABASE_NAME="${DATABASE_NAME:-BCardsDB}" readonly CONNECTION_STRING="mongodb://${MONGODB_HOST}:${MONGODB_PORT}/${DATABASE_NAME}" readonly TIMEOUT=30 # Colors for output readonly RED='\033[0;31m' readonly GREEN='\033[0;32m' readonly YELLOW='\033[1;33m' readonly BLUE='\033[0;34m' readonly NC='\033[0m' # No Color # Logging functions log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # Test basic TCP connectivity test_tcp_connection() { log_info "Testing TCP connection to $MONGODB_HOST:$MONGODB_PORT..." if timeout $TIMEOUT bash -c "/dev/null; then log_success "TCP connection successful" return 0 else log_error "TCP connection failed" return 1 fi } # Test MongoDB connectivity using mongosh if available test_mongodb_with_mongosh() { if ! command -v mongosh >/dev/null 2>&1; then log_warning "mongosh not available, skipping MongoDB shell tests" return 1 fi log_info "Testing MongoDB connection with mongosh..." # Test basic connection local test_output=$(timeout $TIMEOUT mongosh "$CONNECTION_STRING" --quiet --eval "db.runCommand({ping: 1})" 2>/dev/null || echo "FAILED") if [[ "$test_output" == *"ok"* ]]; then log_success "MongoDB ping successful" else log_error "MongoDB ping failed" return 1 fi # Test database access log_info "Testing database operations..." local db_test=$(timeout $TIMEOUT mongosh "$CONNECTION_STRING" --quiet --eval " try { // Test basic database operations db.connection_test.insertOne({test: true, timestamp: new Date()}); var result = db.connection_test.findOne({test: true}); db.connection_test.deleteOne({test: true}); print('DATABASE_ACCESS_OK'); } catch (e) { print('DATABASE_ACCESS_FAILED: ' + e.message); } " 2>/dev/null || echo "DATABASE_ACCESS_FAILED") if [[ "$db_test" == *"DATABASE_ACCESS_OK"* ]]; then log_success "Database operations test passed" else log_error "Database operations test failed: $db_test" return 1 fi return 0 } # Test MongoDB connectivity using Python if available test_mongodb_with_python() { if ! command -v python3 >/dev/null 2>&1; then log_warning "Python3 not available, skipping Python MongoDB tests" return 1 fi log_info "Testing MongoDB connection with Python..." python3 << EOF import sys try: import pymongo from pymongo import MongoClient import socket # Test connection client = MongoClient("$CONNECTION_STRING", serverSelectionTimeoutMS=$((TIMEOUT * 1000))) # Test ping client.admin.command('ping') print("MongoDB ping successful (Python)") # Test database access db = client["$DATABASE_NAME"] # Insert test document test_collection = db.connection_test result = test_collection.insert_one({"test": True, "source": "python"}) # Read test document doc = test_collection.find_one({"_id": result.inserted_id}) if doc: print("Database read/write test passed (Python)") # Cleanup test_collection.delete_one({"_id": result.inserted_id}) client.close() print("PYTHON_TEST_SUCCESS") except ImportError: print("PyMongo not installed, skipping Python tests") sys.exit(1) except Exception as e: print(f"Python MongoDB test failed: {e}") sys.exit(1) EOF local python_result=$? if [ $python_result -eq 0 ]; then log_success "Python MongoDB test passed" return 0 else log_error "Python MongoDB test failed" return 1 fi } # Test using Docker MongoDB client test_mongodb_with_docker() { if ! command -v docker >/dev/null 2>&1; then log_warning "Docker not available, skipping Docker MongoDB tests" return 1 fi log_info "Testing MongoDB connection using Docker MongoDB client..." # Use official MongoDB image to test connection local docker_test=$(timeout $TIMEOUT docker run --rm mongo:7.0 mongosh "$CONNECTION_STRING" --quiet --eval " try { db.runCommand({ping: 1}); db.connection_test.insertOne({test: true, source: 'docker', timestamp: new Date()}); var doc = db.connection_test.findOne({source: 'docker'}); db.connection_test.deleteOne({source: 'docker'}); print('DOCKER_TEST_SUCCESS'); } catch (e) { print('DOCKER_TEST_FAILED: ' + e.message); } " 2>/dev/null || echo "DOCKER_TEST_FAILED") if [[ "$docker_test" == *"DOCKER_TEST_SUCCESS"* ]]; then log_success "Docker MongoDB test passed" return 0 else log_error "Docker MongoDB test failed: $docker_test" return 1 fi } # Test MongoDB from application container test_from_application_container() { local container_name="bcards-staging" if ! docker ps --format "{{.Names}}" | grep -q "^${container_name}$"; then log_warning "Application container '$container_name' not running, skipping application test" return 1 fi log_info "Testing MongoDB connection from application container..." # Test connection from the application container local app_test=$(docker exec "$container_name" timeout 10 bash -c " # Test TCP connection if timeout 5 bash -c '/dev/null; then echo 'APP_TCP_OK' else echo 'APP_TCP_FAILED' exit 1 fi # Test HTTP health endpoint if available if curl -f -s http://localhost:8080/health >/dev/null 2>&1; then echo 'APP_HEALTH_OK' else echo 'APP_HEALTH_FAILED' fi " 2>/dev/null || echo "APP_TEST_FAILED") if [[ "$app_test" == *"APP_TCP_OK"* ]]; then log_success "Application container can connect to MongoDB" if [[ "$app_test" == *"APP_HEALTH_OK"* ]]; then log_success "Application health check passed" else log_warning "Application health check failed - app may still be starting" fi return 0 else log_error "Application container cannot connect to MongoDB" return 1 fi } # Check MongoDB server status and version check_mongodb_status() { log_info "Checking MongoDB server status..." # Try multiple methods to check status local status_checked=false # Method 1: Using mongosh if command -v mongosh >/dev/null 2>&1; then local server_status=$(timeout $TIMEOUT mongosh "$CONNECTION_STRING" --quiet --eval " try { var status = db.runCommand({serverStatus: 1}); print('MongoDB Version: ' + status.version); print('Uptime: ' + status.uptime + ' seconds'); print('Connections: ' + status.connections.current + '/' + status.connections.available); print('STATUS_CHECK_OK'); } catch (e) { print('STATUS_CHECK_FAILED: ' + e.message); } " 2>/dev/null || echo "STATUS_CHECK_FAILED") if [[ "$server_status" == *"STATUS_CHECK_OK"* ]]; then echo "$server_status" | grep -v "STATUS_CHECK_OK" log_success "MongoDB server status check passed" status_checked=true fi fi # Method 2: Using Docker if mongosh failed if [ "$status_checked" = false ] && command -v docker >/dev/null 2>&1; then local docker_status=$(timeout $TIMEOUT docker run --rm mongo:7.0 mongosh "$CONNECTION_STRING" --quiet --eval " try { var status = db.runCommand({serverStatus: 1}); print('MongoDB Version: ' + status.version); print('STATUS_CHECK_OK'); } catch (e) { print('STATUS_CHECK_FAILED: ' + e.message); } " 2>/dev/null || echo "STATUS_CHECK_FAILED") if [[ "$docker_status" == *"STATUS_CHECK_OK"* ]]; then echo "$docker_status" | grep -v "STATUS_CHECK_OK" log_success "MongoDB server status check passed (via Docker)" status_checked=true fi fi if [ "$status_checked" = false ]; then log_warning "Could not retrieve MongoDB server status" return 1 fi return 0 } # Test BCards specific collections and indexes test_bcards_collections() { if ! command -v mongosh >/dev/null 2>&1 && ! command -v docker >/dev/null 2>&1; then log_warning "Cannot test BCards collections - no MongoDB client available" return 1 fi log_info "Testing BCards specific collections and indexes..." local mongo_cmd="mongosh" local docker_prefix="" if ! command -v mongosh >/dev/null 2>&1; then mongo_cmd="docker run --rm mongo:7.0 mongosh" docker_prefix="timeout $TIMEOUT " fi local collections_test=$(${docker_prefix}${mongo_cmd} "$CONNECTION_STRING" --quiet --eval " try { // Check required collections var collections = db.listCollectionNames(); var requiredCollections = ['users', 'userpages', 'categories']; var missingCollections = []; requiredCollections.forEach(function(collection) { if (collections.indexOf(collection) === -1) { missingCollections.push(collection); } }); if (missingCollections.length > 0) { print('Missing collections: ' + missingCollections.join(', ')); } else { print('All required collections exist'); } // Check indexes on userpages collection if (collections.indexOf('userpages') !== -1) { var indexes = db.userpages.getIndexes(); print('UserPages collection has ' + indexes.length + ' indexes'); // Check for important compound index var hasCompoundIndex = indexes.some(function(index) { return index.key && index.key.category && index.key.slug; }); if (hasCompoundIndex) { print('Required compound index (category, slug) exists'); } else { print('WARNING: Compound index (category, slug) is missing'); } } print('COLLECTIONS_TEST_OK'); } catch (e) { print('COLLECTIONS_TEST_FAILED: ' + e.message); } " 2>/dev/null || echo "COLLECTIONS_TEST_FAILED") if [[ "$collections_test" == *"COLLECTIONS_TEST_OK"* ]]; then echo "$collections_test" | grep -v "COLLECTIONS_TEST_OK" log_success "BCards collections test passed" return 0 else log_warning "BCards collections test had issues: $collections_test" return 1 fi } # Performance test test_mongodb_performance() { log_info "Running basic performance test..." if ! command -v mongosh >/dev/null 2>&1; then log_warning "mongosh not available, skipping performance test" return 1 fi local perf_test=$(timeout $TIMEOUT mongosh "$CONNECTION_STRING" --quiet --eval " try { var start = new Date(); // Insert test documents var docs = []; for (var i = 0; i < 100; i++) { docs.push({test: true, index: i, timestamp: new Date()}); } db.performance_test.insertMany(docs); // Read test var count = db.performance_test.countDocuments({test: true}); // Update test db.performance_test.updateMany({test: true}, {\$set: {updated: true}}); // Delete test db.performance_test.deleteMany({test: true}); var end = new Date(); var duration = end - start; print('Performance test completed in ' + duration + 'ms'); print('Operations: 100 inserts, 1 count, 100 updates, 100 deletes'); if (duration < 5000) { print('PERFORMANCE_TEST_OK'); } else { print('PERFORMANCE_TEST_SLOW'); } } catch (e) { print('PERFORMANCE_TEST_FAILED: ' + e.message); } " 2>/dev/null || echo "PERFORMANCE_TEST_FAILED") if [[ "$perf_test" == *"PERFORMANCE_TEST_OK"* ]]; then echo "$perf_test" | grep -v "PERFORMANCE_TEST_OK" log_success "Performance test passed" return 0 elif [[ "$perf_test" == *"PERFORMANCE_TEST_SLOW"* ]]; then echo "$perf_test" | grep -v "PERFORMANCE_TEST_SLOW" log_warning "Performance test completed but was slow" return 0 else log_error "Performance test failed: $perf_test" return 1 fi } # Display connection summary display_summary() { echo "" log_info "MongoDB Connection Test Summary" echo "==================================================" echo "🏠 Host: $MONGODB_HOST:$MONGODB_PORT" echo "🗄️ Database: $DATABASE_NAME" echo "🔗 Connection String: $CONNECTION_STRING" echo "⏱️ Timeout: ${TIMEOUT}s" echo "📊 Tests completed: $(date)" echo "==================================================" } # Main test function main() { log_info "Starting MongoDB connection tests for Release environment" local test_results=() local overall_success=true # Run all tests if test_tcp_connection; then test_results+=("✅ TCP Connection") else test_results+=("❌ TCP Connection") overall_success=false fi if test_mongodb_with_mongosh; then test_results+=("✅ MongoDB Shell") elif test_mongodb_with_docker; then test_results+=("✅ MongoDB Docker") elif test_mongodb_with_python; then test_results+=("✅ MongoDB Python") else test_results+=("❌ MongoDB Client") overall_success=false fi if test_from_application_container; then test_results+=("✅ Application Container") else test_results+=("⚠️ Application Container") fi if check_mongodb_status; then test_results+=("✅ Server Status") else test_results+=("⚠️ Server Status") fi if test_bcards_collections; then test_results+=("✅ BCards Collections") else test_results+=("⚠️ BCards Collections") fi if test_mongodb_performance; then test_results+=("✅ Performance Test") else test_results+=("⚠️ Performance Test") fi # Display results display_summary echo "" log_info "Test Results:" for result in "${test_results[@]}"; do echo " $result" done echo "" if [ "$overall_success" = true ]; then log_success "All critical MongoDB tests passed!" exit 0 else log_error "Some critical MongoDB tests failed!" exit 1 fi } # Run main function main "$@"