| |
| """ |
| Production Deployment Setup - Simplified Version |
| Advanced Workflow Automation - Production Readiness |
| |
| This script sets up production deployment with: |
| - Configuration management |
| - Directory structure |
| - Security setup |
| - Monitoring configuration |
| - Deployment scripts |
| """ |
|
|
| from datetime import datetime |
| import json |
| import os |
| from pathlib import Path |
| import subprocess |
| import sys |
| import uuid |
|
|
| print("🚀 PRODUCTION DEPLOYMENT SETUP") |
| print("=" * 80) |
| print("Setting up production environment for Advanced Workflow Automation") |
| print("=" * 80) |
|
|
| |
| if os.name == 'posix' and os.geteuid() != 0: |
| print("⚠️ Note: This script is best run with sudo for full functionality") |
| print(" Some directory creation may require elevated privileges") |
| print(" Continuing with current user privileges...") |
| print() |
|
|
| |
| BASE_PATH = Path("/opt/atom") |
| PROD_PATH = BASE_PATH / "production" |
| CONFIG_PATH = PROD_PATH / "config" |
| LOGS_PATH = PROD_PATH / "logs" |
| BACKUPS_PATH = PROD_PATH / "backups" |
| SCRIPTS_PATH = PROD_PATH / "scripts" |
| SSL_PATH = PROD_PATH / "ssl" |
|
|
| try: |
| print("\n📁 Creating Production Directory Structure...") |
| print("-" * 50) |
| |
| |
| directories = [ |
| BASE_PATH, |
| PROD_PATH, |
| CONFIG_PATH, |
| LOGS_PATH, |
| BACKUPS_PATH, |
| SCRIPTS_PATH, |
| SSL_PATH, |
| PROD_PATH / "data", |
| PROD_PATH / "temp", |
| PROD_PATH / "static", |
| PROD_PATH / "venv" |
| ] |
| |
| for directory in directories: |
| try: |
| directory.mkdir(parents=True, exist_ok=True) |
| print(f" ✅ Created: {directory}") |
| except PermissionError: |
| print(f" ⚠️ Permission denied for: {directory}") |
| print(f" Run with sudo to create system directories") |
| except Exception as e: |
| print(f" ❌ Error creating {directory}: {str(e)}") |
| |
| print("\n⚙️ Generating Configuration Files...") |
| print("-" * 50) |
| |
| |
| prod_config = { |
| "environment": "production", |
| "debug": False, |
| "log_level": "INFO", |
| "timezone": "UTC", |
| |
| |
| "database": { |
| "host": "localhost", |
| "port": 5432, |
| "name": "atom_production", |
| "user": "atom_user", |
| "password": "CHANGE_THIS_PASSWORD", |
| "pool_size": 20, |
| "max_overflow": 30, |
| "ssl_mode": "require" |
| }, |
| |
| |
| "redis": { |
| "host": "localhost", |
| "port": 6379, |
| "db": 0, |
| "password": "CHANGE_THIS_REDIS_PASSWORD", |
| "max_connections": 100 |
| }, |
| |
| |
| "websocket": { |
| "host": "0.0.0.0", |
| "port": 8765, |
| "ssl_enabled": True, |
| "cert_file": f"{SSL_PATH}/cert.pem", |
| "key_file": f"{SSL_PATH}/key.pem" |
| }, |
| |
| |
| "api": { |
| "host": "0.0.0.0", |
| "port": 8000, |
| "ssl_enabled": True, |
| "workers": 4, |
| "worker_class": "uvicorn.workers.UvicornWorker" |
| }, |
| |
| |
| "security": { |
| "secret_key": str(uuid.uuid4()), |
| "jwt_secret_key": str(uuid.uuid4()), |
| "jwt_expiration_hours": 24, |
| "session_timeout_minutes": 30, |
| "password_min_length": 12, |
| "max_login_attempts": 5, |
| "lockout_duration_minutes": 15 |
| }, |
| |
| |
| "performance": { |
| "max_concurrent_workflows": 1000, |
| "workflow_timeout_minutes": 60, |
| "task_queue_max_size": 10000, |
| "cache_ttl_seconds": 3600, |
| "connection_pool_size": 100 |
| }, |
| |
| |
| "monitoring": { |
| "prometheus_enabled": True, |
| "prometheus_port": 9090, |
| "health_check_port": 8080, |
| "metrics_collection_enabled": True, |
| "log_analytics_enabled": True |
| }, |
| |
| |
| "backup": { |
| "enabled": True, |
| "schedule_hours": 24, |
| "retention_days": 30, |
| "auto_recovery_enabled": True, |
| "backup_path": str(BACKUPS_PATH) |
| }, |
| |
| |
| "email": { |
| "smtp_server": "smtp.gmail.com", |
| "smtp_port": 587, |
| "smtp_use_tls": True, |
| "smtp_username": "noreply@atom.com", |
| "smtp_password": "CHANGE_EMAIL_PASSWORD", |
| "from_email": "noreply@atom.com" |
| } |
| } |
| |
| |
| config_file = CONFIG_PATH / "production.json" |
| with open(config_file, 'w') as f: |
| json.dump(prod_config, f, indent=2) |
| print(f" ✅ Created: {config_file}") |
| |
| |
| env_content = f""" |
| # Production Environment Variables |
| export ATOM_ENV=production |
| export ATOM_DEBUG=false |
| export ATOM_LOG_LEVEL=INFO |
| |
| # Database |
| export DATABASE_URL=postgresql://{prod_config['database']['user']}:{prod_config['database']['password']}@{prod_config['database']['host']}:{prod_config['database']['port']}/{prod_config['database']['name']} |
| export DATABASE_POOL_SIZE={prod_config['database']['pool_size']} |
| |
| # Redis |
| export REDIS_URL=redis://:{prod_config['redis']['password']}@{prod_config['redis']['host']}:{prod_config['redis']['port']}/{prod_config['redis']['db']} |
| |
| # Security |
| export SECRET_KEY={prod_config['security']['secret_key']} |
| export JWT_SECRET_KEY={prod_config['security']['jwt_secret_key']} |
| |
| # WebSocket |
| export WEBSOCKET_HOST={prod_config['websocket']['host']} |
| export WEBSOCKET_PORT={prod_config['websocket']['port']} |
| export WEBSOCKET_SSL_ENABLED={prod_config['websocket']['ssl_enabled']} |
| |
| # API |
| export API_HOST={prod_config['api']['host']} |
| export API_PORT={prod_config['api']['port']} |
| |
| # Performance |
| export MAX_CONCURRENT_WORKFLOWS={prod_config['performance']['max_concurrent_workflows']} |
| export WORKFLOW_TIMEOUT_MINUTES={prod_config['performance']['workflow_timeout_minutes']} |
| |
| # Monitoring |
| export PROMETHEUS_ENABLED={prod_config['monitoring']['prometheus_enabled']} |
| export PROMETHEUS_PORT={prod_config['monitoring']['prometheus_port']} |
| export HEALTH_CHECK_PORT={prod_config['monitoring']['health_check_port']} |
| |
| # Email |
| export SMTP_SERVER={prod_config['email']['smtp_server']} |
| export SMTP_PORT={prod_config['email']['smtp_port']} |
| export SMTP_USERNAME={prod_config['email']['smtp_username']} |
| export SMTP_PASSWORD={prod_config['email']['smtp_password']} |
| """ |
| |
| env_file = CONFIG_PATH / ".env" |
| with open(env_file, 'w') as f: |
| f.write(env_content.strip()) |
| print(f" ✅ Created: {env_file}") |
| |
| print("\n🔒 Setting Up Security Configuration...") |
| print("-" * 50) |
| |
| |
| security_policies = { |
| "authentication": { |
| "password_policy": { |
| "min_length": 12, |
| "require_uppercase": True, |
| "require_lowercase": True, |
| "require_numbers": True, |
| "require_symbols": True, |
| "max_age_days": 90, |
| "prevent_reuse": True, |
| "reuse_count": 5 |
| }, |
| "session_policy": { |
| "timeout_minutes": 30, |
| "max_concurrent_sessions": 3, |
| "require_reauth_minutes": 60, |
| "secure_cookies": True, |
| "http_only_cookies": True |
| }, |
| "lockout_policy": { |
| "max_attempts": 5, |
| "lockout_duration_minutes": 15, |
| "progressive_lockout": True, |
| "ip_based_lockout": True |
| } |
| }, |
| "authorization": { |
| "rbac_enabled": True, |
| "default_roles": ["user", "admin", "operator"], |
| "principle_of_least_privilege": True, |
| "role_hierarchy": { |
| "user": [], |
| "operator": ["user"], |
| "admin": ["user", "operator"] |
| } |
| }, |
| "api_security": { |
| "rate_limiting": { |
| "enabled": True, |
| "requests_per_minute": 100, |
| "requests_per_hour": 1000, |
| "burst_size": 20, |
| "per_user_limiting": True |
| }, |
| "cors": { |
| "allowed_origins": ["https://localhost"], |
| "allowed_methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"], |
| "allowed_headers": ["Authorization", "Content-Type", "X-Requested-With"], |
| "max_age_seconds": 3600, |
| "credentials_allowed": True |
| }, |
| "request_validation": { |
| "max_request_size_mb": 10, |
| "max_header_size_kb": 8, |
| "validate_content_type": True, |
| "sanitize_inputs": True |
| } |
| }, |
| "encryption": { |
| "at_rest": { |
| "database_encryption": True, |
| "file_encryption": True, |
| "key_rotation_days": 90 |
| }, |
| "in_transit": { |
| "tls_version": "1.2", |
| "cipher_suites": ["ECDHE-RSA-AES256-GCM-SHA512", "ECDHE-RSA-AES256-GCM-SHA384"], |
| "hsts_enabled": True, |
| "hsts_max_age_seconds": 31536000 |
| } |
| } |
| } |
| |
| security_file = CONFIG_PATH / "security_policies.json" |
| with open(security_file, 'w') as f: |
| json.dump(security_policies, f, indent=2) |
| print(f" ✅ Created: {security_file}") |
| |
| print("\n📊 Setting Up Monitoring Configuration...") |
| print("-" * 50) |
| |
| |
| prometheus_config = { |
| "global": { |
| "scrape_interval": "15s", |
| "evaluation_interval": "15s" |
| }, |
| "rule_files": [f"{CONFIG_PATH}/workflow_alerts.yml"], |
| "scrape_configs": [ |
| { |
| "job_name": "atom-api", |
| "static_configs": [{"targets": ["localhost:8000"]}], |
| "metrics_path": "/metrics", |
| "scrape_interval": "30s" |
| }, |
| { |
| "job_name": "atom-websocket", |
| "static_configs": [{"targets": ["localhost:8765"]}], |
| "metrics_path": "/metrics", |
| "scrape_interval": "30s" |
| }, |
| { |
| "job_name": "atom-health", |
| "static_configs": [{"targets": ["localhost:8080"]}], |
| "metrics_path": "/metrics", |
| "scrape_interval": "60s" |
| }, |
| { |
| "job_name": "node-exporter", |
| "static_configs": [{"targets": ["localhost:9100"]}], |
| "scrape_interval": "30s" |
| } |
| ] |
| } |
| |
| prometheus_file = CONFIG_PATH / "prometheus.yml" |
| with open(prometheus_file, 'w') as f: |
| json.dump(prometheus_config, f, indent=2) |
| print(f" ✅ Created: {prometheus_file}") |
| |
| |
| alert_rules = { |
| "groups": [ |
| { |
| "name": "atom_workflow_alerts", |
| "rules": [ |
| { |
| "alert": "WorkflowExecutionFailure", |
| "expr": "workflow_execution_failures_total > 0", |
| "for": "5m", |
| "labels": {"severity": "warning"}, |
| "annotations": { |
| "summary": "Workflow execution failed", |
| "description": "Workflow {{ $labels.workflow_id }} has failed {{ $value }} times in last 5 minutes" |
| } |
| }, |
| { |
| "alert": "HighWorkflowExecutionTime", |
| "expr": "workflow_execution_duration_seconds > 300", |
| "for": "10m", |
| "labels": {"severity": "warning"}, |
| "annotations": { |
| "summary": "High workflow execution time", |
| "description": "Workflow {{ $labels.workflow_id }} has been running for {{ $value }} seconds" |
| } |
| }, |
| { |
| "alert": "WebSocketConnectionFailure", |
| "expr": "websocket_connection_errors_total > 10", |
| "for": "2m", |
| "labels": {"severity": "critical"}, |
| "annotations": { |
| "summary": "High WebSocket connection errors", |
| "description": "{{ $value }} WebSocket connection errors in last 2 minutes" |
| } |
| }, |
| { |
| "alert": "HighMemoryUsage", |
| "expr": "(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes > 0.8", |
| "for": "5m", |
| "labels": {"severity": "warning"}, |
| "annotations": { |
| "summary": "High memory usage", |
| "description": "Memory usage is {{ $value | humanizePercentage }}" |
| } |
| }, |
| { |
| "alert": "HighCPUUsage", |
| "expr": "100 - (avg by(instance) (rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100) > 80", |
| "for": "10m", |
| "labels": {"severity": "warning"}, |
| "annotations": { |
| "summary": "High CPU usage", |
| "description": "CPU usage is {{ $value | humanizePercentage }}" |
| } |
| } |
| ] |
| } |
| ] |
| } |
| |
| alerts_file = CONFIG_PATH / "workflow_alerts.yml" |
| with open(alerts_file, 'w') as f: |
| json.dump(alert_rules, f, indent=2) |
| print(f" ✅ Created: {alerts_file}") |
| |
| print("\n🚀 Creating Deployment Scripts...") |
| print("-" * 50) |
| |
| |
| deploy_script = f"""#!/bin/bash |
| # Atom Workflow Automation Deployment Script |
| |
| set -e |
| |
| DEPLOYMENT_PATH="{PROD_PATH}" |
| LOG_FILE="$DEPLOYMENT_PATH/logs/deploy.log" |
| |
| echo "🚀 Starting Atom Workflow Automation Deployment..." |
| echo "$(date): Deployment started" >> $LOG_FILE |
| |
| log() {{ |
| echo "$1" |
| echo "$(date): $1" >> $LOG_FILE |
| }} |
| |
| # Stop existing services |
| log "🛑 Stopping existing services..." |
| systemctl stop atom-workflow-api || true |
| systemctl stop atom-websocket-server || true |
| systemctl stop atom-scheduler || true |
| |
| # Update application code |
| log "📥 Updating application code..." |
| cd $DEPLOYMENT_PATH |
| |
| # Install dependencies |
| log "📦 Installing Python dependencies..." |
| if [ -d "venv" ]; then |
| source venv/bin/activate |
| else |
| python3 -m venv venv |
| source venv/bin/activate |
| fi |
| |
| pip install --upgrade pip |
| pip install -r requirements.txt |
| |
| # Run database migrations |
| log "🗄️ Running database migrations..." |
| python -c " |
| import psycopg2 |
| import os |
| |
| db_config = {json.dumps(prod_config['database'])} |
| try: |
| conn = psycopg2.connect( |
| host=db_config['host'], |
| port=db_config['port'], |
| database='postgres', |
| user=db_config['user'], |
| password=db_config['password'] |
| ) |
| conn.autocommit = True |
| cursor = conn.cursor() |
| cursor.execute(f'CREATE DATABASE {{db_config["name"]}}') |
| print('Database created or already exists') |
| except Exception as e: |
| print(f'Database creation skipped: {{e}}') |
| |
| # Create tables (simplified) |
| import uuid |
| from datetime import datetime |
| conn = psycopg2.connect( |
| host=db_config['host'], |
| port=db_config['port'], |
| database=db_config['name'], |
| user=db_config['user'], |
| password=db_config['password'] |
| ) |
| cursor = conn.cursor() |
| |
| # Create workflows table |
| cursor.execute(''' |
| CREATE TABLE IF NOT EXISTS workflows ( |
| id UUID PRIMARY KEY DEFAULT gen_random_uuid(), |
| name VARCHAR(255) NOT NULL, |
| description TEXT, |
| category VARCHAR(100), |
| user_id UUID NOT NULL, |
| parameters JSONB DEFAULT '{{}}', |
| template_id UUID, |
| created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), |
| updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), |
| version INTEGER DEFAULT 1 |
| ) |
| ''') |
| |
| # Create workflow_executions table |
| cursor.execute(''' |
| CREATE TABLE IF NOT EXISTS workflow_executions ( |
| id UUID PRIMARY KEY DEFAULT gen_random_uuid(), |
| workflow_id UUID NOT NULL REFERENCES workflows(id), |
| status VARCHAR(50) NOT NULL, |
| input_data JSONB DEFAULT '{{}}', |
| output_data JSONB DEFAULT '{{}}', |
| error_message TEXT, |
| execution_time_seconds DECIMAL, |
| created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), |
| started_at TIMESTAMP WITH TIME ZONE, |
| completed_at TIMESTAMP WITH TIME ZONE, |
| user_id UUID NOT NULL |
| ) |
| ''') |
| |
| # Create workflow_steps table |
| cursor.execute(''' |
| CREATE TABLE IF NOT EXISTS workflow_steps ( |
| id UUID PRIMARY KEY DEFAULT gen_random_uuid(), |
| execution_id UUID NOT NULL REFERENCES workflow_executions(id), |
| step_order INTEGER NOT NULL, |
| service VARCHAR(100) NOT NULL, |
| action VARCHAR(100) NOT NULL, |
| parameters JSONB DEFAULT '{{}}', |
| status VARCHAR(50) NOT NULL, |
| result JSONB, |
| error_message TEXT, |
| execution_time_seconds DECIMAL, |
| started_at TIMESTAMP WITH TIME ZONE, |
| completed_at TIMESTAMP WITH TIME ZONE |
| ) |
| ''') |
| |
| # Create users table |
| cursor.execute(''' |
| CREATE TABLE IF NOT EXISTS users ( |
| id UUID PRIMARY KEY DEFAULT gen_random_uuid(), |
| username VARCHAR(100) UNIQUE NOT NULL, |
| email VARCHAR(255) UNIQUE NOT NULL, |
| password_hash VARCHAR(255) NOT NULL, |
| is_active BOOLEAN DEFAULT TRUE, |
| is_admin BOOLEAN DEFAULT FALSE, |
| last_login TIMESTAMP WITH TIME ZONE, |
| created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), |
| updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() |
| ) |
| ''') |
| |
| # Create integration_catalog table |
| cursor.execute(''' |
| CREATE TABLE IF NOT EXISTS integration_catalog ( |
| id TEXT PRIMARY KEY, |
| name TEXT NOT NULL, |
| description TEXT, |
| category TEXT NOT NULL, |
| icon TEXT, |
| color TEXT DEFAULT '#6366F1', |
| auth_type TEXT DEFAULT 'none', |
| native_id TEXT, |
| triggers JSONB DEFAULT '[]', |
| actions JSONB DEFAULT '[]', |
| popular BOOLEAN DEFAULT FALSE, |
| created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), |
| updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() |
| ) |
| ''') |
| |
| conn.commit() |
| cursor.close() |
| conn.close() |
| print('Database migrations completed') |
| " |
| |
| # Start services |
| log "🚀 Starting services..." |
| |
| # Note: In a real deployment, you would install and configure systemd services |
| # For this demo, we'll use nohup to run services in background |
| |
| # Start WebSocket server |
| log "🌐 Starting WebSocket server..." |
| cd $DEPLOYMENT_PATH |
| nohup python setup_websocket_server.py > logs/websocket.log 2>&1 & |
| echo $! > logs/websocket.pid |
| |
| # Start health check server |
| log "🏥 Starting health check server..." |
| nohup python -c " |
| import aiohttp.web |
| import asyncio |
| from datetime import datetime |
| |
| async def health_check(request): |
| return aiohttp.web.json_response({{ |
| 'status': 'healthy', |
| 'timestamp': datetime.now().isoformat(), |
| 'version': '1.0.0' |
| }}) |
| |
| app = aiohttp.web.Application() |
| app.add_routes([aiohttp.web.get('/health', health_check)]) |
| aiohttp.web.run_app(app, host='localhost', port=8080) |
| " > logs/health_check.log 2>&1 & |
| echo $! > logs/health_check.pid |
| |
| # Test services |
| log "🧪 Testing services..." |
| sleep 5 |
| |
| if curl -f http://localhost:8080/health > /dev/null 2>&1; then |
| log "✅ Health check passed" |
| else |
| log "❌ Health check failed" |
| fi |
| |
| log "🎉 Deployment completed successfully!" |
| echo "$(date): Deployment completed" >> $LOG_FILE |
| |
| echo "" |
| echo "📊 Service Status:" |
| echo "WebSocket Server: http://localhost:8765" |
| echo "Health Check: http://localhost:8080/health" |
| echo "Logs: $DEPLOYMENT_PATH/logs/" |
| echo "" |
| echo "🔍 To check logs:" |
| echo "tail -f $DEPLOYMENT_PATH/logs/websocket.log" |
| echo "tail -f $DEPLOYMENT_PATH/logs/deploy.log" |
| echo "" |
| echo "🛑 To stop services:" |
| echo "kill \$(cat $DEPLOYMENT_PATH/logs/websocket.pid)" |
| echo "kill \$(cat $DEPLOYMENT_PATH/logs/health_check.pid)" |
| """ |
| |
| deploy_file = SCRIPTS_PATH / "deploy.sh" |
| with open(deploy_file, 'w') as f: |
| f.write(deploy_script) |
| |
| |
| try: |
| os.chmod(deploy_file, 0o755) |
| print(f" ✅ Created: {deploy_file} (executable)") |
| except: |
| print(f" ✅ Created: {deploy_file} (run: chmod +x to make executable)") |
| |
| |
| monitor_script = f"""#!/bin/bash |
| # Atom Workflow Automation Monitoring Script |
| |
| DEPLOYMENT_PATH="{PROD_PATH}" |
| LOG_FILE="$DEPLOYMENT_PATH/logs/monitoring.log" |
| |
| log() {{ |
| echo "$1" |
| echo "$(date): $1" >> $LOG_FILE |
| }} |
| |
| check_service() {{ |
| local service_name=$1 |
| local port=$2 |
| |
| if curl -f http://localhost:$port/health > /dev/null 2>&1; then |
| log "✅ $service_name is healthy" |
| return 0 |
| else |
| log "❌ $service_name is unhealthy" |
| return 1 |
| fi |
| }} |
| |
| check_resources() {{ |
| # CPU usage |
| CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{{print $2}}' | cut -d'%' -f1) |
| if (( $(echo "$CPU_USAGE > 80" | bc -l) )); then |
| log "⚠️ High CPU usage: $CPU_USAGE%" |
| fi |
| |
| # Memory usage |
| MEMORY_USAGE=$(free | grep Mem | awk '{{printf("%.0f", $3/$2 * 100.0)}}') |
| if [ $MEMORY_USAGE -gt 80 ]; then |
| log "⚠️ High memory usage: $MEMORY_USAGE%" |
| fi |
| |
| # Disk usage |
| DISK_USAGE=$(df / | awk 'NR==2 {{print $5}}' | sed 's/%//') |
| if [ $DISK_USAGE -gt 80 ]; then |
| log "⚠️ High disk usage: $DISK_USAGE%" |
| fi |
| }} |
| |
| check_database() {{ |
| # Simplified database check |
| if pgrep -f "postgres" > /dev/null; then |
| log "✅ PostgreSQL is running" |
| else |
| log "❌ PostgreSQL is not running" |
| fi |
| }} |
| |
| log "🔍 Starting system monitoring..." |
| |
| # Check services |
| check_service "WebSocket Server" 8765 |
| check_service "Health Check" 8080 |
| |
| # Check system resources |
| check_resources |
| |
| # Check database |
| check_database |
| |
| log "✅ Monitoring completed" |
| """ |
| |
| monitor_file = SCRIPTS_PATH / "monitor.sh" |
| with open(monitor_file, 'w') as f: |
| f.write(monitor_script) |
| |
| try: |
| os.chmod(monitor_file, 0o755) |
| print(f" ✅ Created: {monitor_file} (executable)") |
| except: |
| print(f" ✅ Created: {monitor_file} (run: chmod +x to make executable)") |
| |
| |
| backup_script = f"""#!/bin/bash |
| # Atom Workflow Automation Backup Script |
| |
| DEPLOYMENT_PATH="{PROD_PATH}" |
| BACKUP_PATH="{BACKUPS_PATH}" |
| LOG_FILE="$DEPLOYMENT_PATH/logs/backup.log" |
| |
| log() {{ |
| echo "$1" |
| echo "$(date): $1" >> $LOG_FILE |
| }} |
| |
| backup_database() {{ |
| log "🗄️ Creating database backup..." |
| TIMESTAMP=$(date +%Y%m%d_%H%M%S) |
| |
| # Create database backup (simplified) |
| pg_dump -h {prod_config['database']['host']} -p {prod_config['database']['port']} -U {prod_config['database']['user']} -d {prod_config['database']['name']} | gzip > "$BACKUP_PATH/db_backup_$TIMESTAMP.sql.gz" 2>/dev/null || log "⚠️ Database backup failed" |
| }} |
| |
| backup_config() {{ |
| log "⚙️ Creating configuration backup..." |
| TIMESTAMP=$(date +%Y%m%d_%H%M%S) |
| |
| tar -czf "$BACKUP_PATH/config_backup_$TIMESTAMP.tar.gz" "$DEPLOYMENT_PATH/config" 2>/dev/null || log "⚠️ Config backup failed" |
| }} |
| |
| cleanup_old_backups() {{ |
| log "🧹 Cleaning up old backups..." |
| find "$BACKUP_PATH" -name "*.gz" -mtime +{prod_config['backup']['retention_days']} -delete 2>/dev/null || true |
| }} |
| |
| log "📦 Starting backup process..." |
| |
| # Create backup directory |
| mkdir -p "$BACKUP_PATH" |
| |
| # Run backups |
| backup_database |
| backup_config |
| |
| # Cleanup old backups |
| cleanup_old_backups |
| |
| log "✅ Backup completed" |
| log "📊 Backup location: $BACKUP_PATH" |
| """ |
| |
| backup_file = SCRIPTS_PATH / "backup.sh" |
| with open(backup_file, 'w') as f: |
| f.write(backup_script) |
| |
| try: |
| os.chmod(backup_file, 0o755) |
| print(f" ✅ Created: {backup_file} (executable)") |
| except: |
| print(f" ✅ Created: {backup_file} (run: chmod +x to make executable)") |
| |
| print("\n📝 Creating Documentation...") |
| print("-" * 50) |
| |
| |
| readme_content = f"""# Atom Workflow Automation - Production Deployment |
| |
| ## Overview |
| This is the production deployment setup for the Atom Workflow Automation system. |
| |
| ## Directory Structure |
| ``` |
| {PROD_PATH}/ |
| ├── config/ # Configuration files |
| ├── logs/ # Log files |
| ├── backups/ # Backup files |
| ├── scripts/ # Deployment and management scripts |
| ├── ssl/ # SSL certificates |
| ├── data/ # Application data |
| ├── temp/ # Temporary files |
| ├── static/ # Static assets |
| └── venv/ # Python virtual environment |
| ``` |
| |
| ## Configuration |
| - Main config: `{CONFIG_PATH}/production.json` |
| - Environment variables: `{CONFIG_PATH}/.env` |
| - Security policies: `{CONFIG_PATH}/security_policies.json` |
| |
| ## Services |
| - WebSocket Server: http://localhost:8765 |
| - Health Check: http://localhost:8080/health |
| - API Server: http://localhost:8000 (when deployed) |
| |
| ## Management Scripts |
| |
| ### Deployment |
| ```bash |
| {SCRIPTS_PATH}/deploy.sh |
| ``` |
| |
| ### Monitoring |
| ```bash |
| {SCRIPTS_PATH}/monitor.sh |
| ``` |
| |
| ### Backup |
| ```bash |
| {SCRIPTS_PATH}/backup.sh |
| ``` |
| |
| ## Environment Setup |
| 1. Install dependencies: |
| ```bash |
| cd {PROD_PATH} |
| source venv/bin/activate |
| pip install -r requirements.txt |
| ``` |
| |
| 2. Configure environment: |
| ```bash |
| # Edit {CONFIG_PATH}/.env with your settings |
| vim {CONFIG_PATH}/.env |
| ``` |
| |
| 3. Set up database: |
| ```bash |
| # PostgreSQL should be installed and running |
| # Create database and user as specified in config |
| ``` |
| |
| 4. Start services: |
| ```bash |
| {SCRIPTS_PATH}/deploy.sh |
| ``` |
| |
| ## Monitoring |
| - Health checks: http://localhost:8080/health |
| - Logs: {LOGS_PATH}/ |
| - Prometheus: http://localhost:9090 (if configured) |
| |
| ## Backup Schedule |
| - Automatic backups: Every {prod_config['backup']['schedule_hours']} hours |
| - Retention: {prod_config['backup']['retention_days']} days |
| - Location: {BACKUPS_PATH}/ |
| |
| ## Security |
| - All passwords should be changed from defaults |
| - SSL certificates should be installed in {SSL_PATH}/ |
| - Review security policies in {CONFIG_PATH}/security_policies.json |
| |
| ## Troubleshooting |
| 1. Check logs: `tail -f {LOGS_PATH}/deploy.log` |
| 2. Verify services: `{SCRIPTS_PATH}/monitor.sh` |
| 3. Check health: `curl http://localhost:8080/health` |
| |
| ## Support |
| For issues, check the logs or contact the system administrator. |
| """ |
| |
| readme_file = PROD_PATH / "README.md" |
| with open(readme_file, 'w') as f: |
| f.write(readme_content) |
| print(f" ✅ Created: {readme_file}") |
| |
| print("\n🎉 PRODUCTION SETUP COMPLETED!") |
| print("=" * 80) |
| print("✅ Production environment is ready for deployment") |
| print("=" * 80) |
| |
| print("\n📋 NEXT STEPS:") |
| print("-" * 50) |
| print("1. Configure environment variables:") |
| print(f" 📝 Edit: {CONFIG_PATH}/.env") |
| print(" 🔒 Change all default passwords and keys") |
| print() |
| print("2. Set up database:") |
| print(" 🗄️ Install PostgreSQL") |
| print(" 👤 Create database and user") |
| print(" 🔐 Configure security settings") |
| print() |
| print("3. Install SSL certificates:") |
| print(f" 🔒 Place certificates in: {SSL_PATH}/") |
| print(" 📄 cert.pem and key.pem") |
| print() |
| print("4. Deploy application:") |
| print(f" 🚀 Run: {SCRIPTS_PATH}/deploy.sh") |
| print() |
| print("5. Verify deployment:") |
| print(" 🏥 Health check: http://localhost:8080/health") |
| print(" 🌐 WebSocket: http://localhost:8765") |
| print() |
| print("6. Set up monitoring:") |
| print(f" 📊 Monitor: {SCRIPTS_PATH}/monitor.sh") |
| print(f" 📦 Backup: {SCRIPTS_PATH}/backup.sh") |
| |
| print("\n🔧 MANAGEMENT COMMANDS:") |
| print("-" * 50) |
| print(f"📂 Deployment Path: {PROD_PATH}") |
| print(f"⚙️ Configuration: {CONFIG_PATH}/") |
| print(f"📄 Logs: {LOGS_PATH}/") |
| print(f"💾 Backups: {BACKUPS_PATH}/") |
| print(f"🚀 Deploy: {SCRIPTS_PATH}/deploy.sh") |
| print(f"🔍 Monitor: {SCRIPTS_PATH}/monitor.sh") |
| print(f"📦 Backup: {SCRIPTS_PATH}/backup.sh") |
| |
| print("\n📊 SERVICE ENDPOINTS:") |
| print("-" * 50) |
| print("🌐 WebSocket Server: ws://localhost:8765") |
| print("🏥 Health Check: http://localhost:8080/health") |
| print("📊 API Server: http://localhost:8000 (when deployed)") |
| print("📈 Prometheus: http://localhost:9090 (if configured)") |
| |
| print("\n" + "=" * 80) |
| print("🎊 PRODUCTION ENVIRONMENT SETUP COMPLETED SUCCESSFULLY! 🎊") |
| print("🏭 System is ready for production deployment") |
| print("=" * 80) |
| |
| |
| setup_summary = { |
| "setup_completed": True, |
| "deployment_path": str(PROD_PATH), |
| "config_path": str(CONFIG_PATH), |
| "logs_path": str(LOGS_PATH), |
| "backups_path": str(BACKUPS_PATH), |
| "scripts_path": str(SCRIPTS_PATH), |
| "ssl_path": str(SSL_PATH), |
| "created_at": datetime.now().isoformat(), |
| "configuration": { |
| "main_config": str(config_file), |
| "env_file": str(env_file), |
| "security_policies": str(security_file), |
| "prometheus_config": str(prometheus_file), |
| "alerts_config": str(alerts_file) |
| }, |
| "scripts": { |
| "deploy_script": str(deploy_file), |
| "monitor_script": str(monitor_file), |
| "backup_script": str(backup_file) |
| }, |
| "documentation": str(readme_file), |
| "next_steps": [ |
| "Configure environment variables", |
| "Set up database", |
| "Install SSL certificates", |
| "Deploy application", |
| "Verify deployment", |
| "Set up monitoring" |
| ], |
| "service_endpoints": { |
| "websocket": "ws://localhost:8765", |
| "health_check": "http://localhost:8080/health", |
| "api": "http://localhost:8000" |
| } |
| } |
| |
| summary_file = CONFIG_PATH / "setup_summary.json" |
| with open(summary_file, 'w') as f: |
| json.dump(setup_summary, f, indent=2) |
| |
| print(f"\n📄 Setup summary saved to: {summary_file}") |
|
|
| except Exception as e: |
| print(f"\n❌ Setup failed with error: {str(e)}") |
| import traceback |
| traceback.print_exc() |
| sys.exit(1) |