amo-server/scripts/docker_setup.py
Maxim Snesarev 33d6bb7ebd Refactor AMO CRM Data Collection Service to use PostgreSQL
- Updated database configuration to switch from SQLite to PostgreSQL, including changes to alembic.ini, Docker Compose, and environment settings.
- Refactored application code to utilize PostgreSQL database adapters, ensuring compatibility with the new database structure.
- Enhanced API routes and data handling to support the new database, including adjustments in data models and query logic.
- Introduced new job processing mechanisms for full synchronization of AMO CRM entities, leveraging FastStream for background tasks.
- Improved logging and error handling across the application to facilitate better monitoring and debugging.
- Removed obsolete SQLite adapter files and migrations, streamlining the project structure for PostgreSQL integration.
2025-11-05 00:38:37 +03:00

258 lines
7.4 KiB
Python

#!/usr/bin/env python3
"""
Docker setup script for AMO CRM service with FastStream.
This script helps set up and manage Docker containers for the AMO CRM service
with FastStream workers.
"""
import subprocess
import sys
import os
import logging
import argparse
from pathlib import Path
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def run_command(command: str, capture_output: bool = False) -> subprocess.CompletedProcess:
"""
Run a shell command.
Args:
command: Command to execute
capture_output: Whether to capture output
Returns:
CompletedProcess result
"""
logger.info(f"Running: {command}")
return subprocess.run(
command.split(),
capture_output=capture_output,
text=True
)
def check_docker() -> bool:
"""
Check if Docker is installed and running.
Returns:
True if Docker is available, False otherwise
"""
try:
result = run_command("docker --version", capture_output=True)
if result.returncode == 0:
logger.info(f"Docker found: {result.stdout.strip()}")
# Check if Docker daemon is running
result = run_command("docker info", capture_output=True)
if result.returncode == 0:
logger.info("Docker daemon is running")
return True
else:
logger.error("Docker daemon is not running")
return False
else:
logger.error("Docker not found")
return False
except FileNotFoundError:
logger.error("Docker not installed")
return False
def check_docker_compose() -> bool:
"""
Check if Docker Compose is installed.
Returns:
True if Docker Compose is available, False otherwise
"""
try:
result = run_command("docker-compose --version", capture_output=True)
if result.returncode == 0:
logger.info(f"Docker Compose found: {result.stdout.strip()}")
return True
else:
# Try docker compose (newer syntax)
result = run_command("docker compose version", capture_output=True)
if result.returncode == 0:
logger.info(f"Docker Compose found: {result.stdout.strip()}")
return True
else:
logger.error("Docker Compose not found")
return False
except FileNotFoundError:
logger.error("Docker Compose not installed")
return False
def create_env_file() -> None:
"""Create .env file from template if it doesn't exist."""
env_file = Path(".env")
env_example = Path("env.example")
if not env_file.exists() and env_example.exists():
logger.info("Creating .env file from template")
env_file.write_text(env_example.read_text())
logger.warning("Please edit .env file with your configuration")
elif not env_file.exists():
logger.warning(".env file not found and no template available")
def create_directories() -> None:
"""Create necessary directories."""
directories = ["data", "credentials", "ssl"]
for directory in directories:
path = Path(directory)
if not path.exists():
logger.info(f"Creating directory: {directory}")
path.mkdir(exist_ok=True)
def build_images() -> bool:
"""
Build Docker images.
Returns:
True if successful, False otherwise
"""
logger.info("Building Docker images...")
result = run_command("docker-compose build")
return result.returncode == 0
def start_services(mode: str = "dev") -> bool:
"""
Start Docker services.
Args:
mode: Deployment mode (dev or prod)
Returns:
True if successful, False otherwise
"""
if mode == "prod":
logger.info("Starting services in production mode...")
result = run_command("docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d")
else:
logger.info("Starting services in development mode...")
result = run_command("docker-compose up -d")
return result.returncode == 0
def stop_services() -> bool:
"""
Stop Docker services.
Returns:
True if successful, False otherwise
"""
logger.info("Stopping services...")
result = run_command("docker-compose down")
return result.returncode == 0
def show_logs(service: str = None, follow: bool = False) -> None:
"""
Show service logs.
Args:
service: Specific service to show logs for
follow: Whether to follow logs
"""
if service:
command = f"docker-compose logs {'--follow' if follow else ''} {service}"
else:
command = f"docker-compose logs {'--follow' if follow else ''}"
run_command(command)
def show_status() -> None:
"""Show status of all services."""
logger.info("Service status:")
run_command("docker-compose ps")
logger.info("\nService health:")
run_command("docker-compose exec app python -c \"import requests; print('API:', requests.get('http://localhost:8000/health').json())\"")
def main() -> None:
"""Main function."""
parser = argparse.ArgumentParser(description="Docker setup for AMO CRM service")
parser.add_argument("action", choices=["setup", "start", "stop", "restart", "logs", "status", "build"],
help="Action to perform")
parser.add_argument("--mode", choices=["dev", "prod"], default="dev",
help="Deployment mode")
parser.add_argument("--service", help="Specific service for logs")
parser.add_argument("--follow", action="store_true", help="Follow logs")
args = parser.parse_args()
# Check prerequisites
if not check_docker():
logger.error("Docker is required but not available")
sys.exit(1)
if not check_docker_compose():
logger.error("Docker Compose is required but not available")
sys.exit(1)
# Execute action
if args.action == "setup":
logger.info("Setting up AMO CRM service with FastStream...")
create_env_file()
create_directories()
if build_images():
logger.info("Setup completed successfully!")
logger.info("Next steps:")
logger.info("1. Edit .env file with your configuration")
logger.info("2. Run: python scripts/docker_setup.py start")
else:
logger.error("Setup failed during image build")
sys.exit(1)
elif args.action == "build":
if not build_images():
logger.error("Build failed")
sys.exit(1)
elif args.action == "start":
if not start_services(args.mode):
logger.error("Failed to start services")
sys.exit(1)
logger.info("Services started successfully!")
logger.info("API available at: http://localhost:8000")
logger.info("API documentation: http://localhost:8000/docs")
elif args.action == "stop":
if not stop_services():
logger.error("Failed to stop services")
sys.exit(1)
elif args.action == "restart":
logger.info("Restarting services...")
stop_services()
if not start_services(args.mode):
logger.error("Failed to restart services")
sys.exit(1)
elif args.action == "logs":
show_logs(args.service, args.follow)
elif args.action == "status":
show_status()
if __name__ == "__main__":
main()