# Deployment Guide

Deploy Sonora in production environments.

# Docker Deployment

# Basic Setup

FROM python:3.11-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .
RUN pip install -e .

EXPOSE 8080
CMD ["python", "-m", "sonora.cli", "start"]

# Multi-stage Build

# Build stage
FROM python:3.11 as builder
WORKDIR /app
COPY pyproject.toml .
RUN pip install build && python -m build

# Runtime stage
FROM python:3.11-slim as runtime
COPY --from=builder /app/dist/*.whl .
RUN pip install *.whl

CMD ["sonoractl", "start"]

# Docker Compose

version: '3.8'
services:
  sonora:
    build: .
    environment:
      - LAVALINK_HOST=lavalink
      - DISCORD_TOKEN=${DISCORD_TOKEN}
    depends_on:
      - lavalink

  lavalink:
    image: fredboat/lavalink:4.0.1
    volumes:
      - ./application.yml:/opt/Lavalink/application.yml
    ports:
      - "2333:2333"

# Kubernetes Deployment

# Deployment Manifest

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sonora
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sonora
  template:
    metadata:
      labels:
        app: sonora
    spec:
      containers:
      - name: sonora
        image: code-xon/sonora:latest
        env:
        - name: LAVALINK_HOST
          value: "lavalink-service"
        - name: DISCORD_TOKEN
          valueFrom:
            secretKeyRef:
              name: discord-secret
              key: token
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"

# Service Configuration

apiVersion: v1
kind: Service
metadata:
  name: sonora-service
spec:
  selector:
    app: sonora
  ports:
  - port: 80
    targetPort: 8080
  type: LoadBalancer

# Cloud Deployment

# AWS ECS

{
  "family": "sonora-task",
  "containerDefinitions": [
    {
      "name": "sonora",
      "image": "code-xon/sonora:latest",
      "essential": true,
      "environment": [
        {"name": "LAVALINK_HOST", "value": "lavalink.example.com"},
        {"name": "DISCORD_TOKEN", "value": "${DISCORD_TOKEN}"}
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/sonora",
          "awslogs-region": "us-east-1"
        }
      }
    }
  ]
}

# Google Cloud Run

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: sonora
spec:
  template:
    spec:
      containers:
      - image: gcr.io/project/sonora:latest
        env:
        - name: LAVALINK_HOST
          value: "lavalink.example.com"
        - name: DISCORD_TOKEN
          valueFrom:
            secretKeyRef:
              name: discord-token
              key: latest
        resources:
          limits:
            memory: "512Mi"
            cpu: "1000m"

# Configuration Management

# Environment Variables

# Application config
export SONORA_ENV=production
export SONORA_DEBUG=false
export SONORA_LOG_LEVEL=INFO

# Lavalink config
export LAVALINK_HOST=lavalink.example.com
export LAVALINK_PORT=2333
export LAVALINK_PASSWORD=secure_password

# Discord config
export DISCORD_TOKEN=bot_token
export DISCORD_SHARD_COUNT=2

# Database config
export DATABASE_URL=postgresql://user:pass@host:5432/db

# Configuration Files

# config.py
import os

config = {
    'environment': os.getenv('SONORA_ENV', 'development'),
    'debug': os.getenv('SONORA_DEBUG', 'false').lower() == 'true',
    'lavalink': {
        'host': os.getenv('LAVALINK_HOST', 'localhost'),
        'port': int(os.getenv('LAVALINK_PORT', 2333)),
        'password': os.getenv('LAVALINK_PASSWORD'),
    },
    'discord': {
        'token': os.getenv('DISCORD_TOKEN'),
        'shard_count': int(os.getenv('DISCORD_SHARD_COUNT', 1)),
    },
    'database': {
        'url': os.getenv('DATABASE_URL'),
    }
}

# Monitoring & Logging

# Structured Logging

import structlog

# Configure structured logging
structlog.configure(
    processors=[
        structlog.stdlib.filter_by_level,
        structlog.stdlib.add_logger_name,
        structlog.stdlib.add_log_level,
        structlog.stdlib.PositionalArgumentsFormatter(),
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.StackInfoRenderer(),
        structlog.processors.format_exc_info,
        structlog.processors.UnicodeDecoder(),
        structlog.processors.JSONRenderer()
    ],
    context_class=dict,
    logger_factory=structlog.stdlib.LoggerFactory(),
    wrapper_class=structlog.stdlib.BoundLogger,
    cache_logger_on_first_use=True,
)

# Health Checks

from fastapi import FastAPI

app = FastAPI()

@app.get("/health")
async def health_check():
    return {
        "status": "healthy",
        "version": "1.2.8",
        "uptime": get_uptime(),
        "players": len(client.players),
        "nodes": len(client.nodes)
    }

@app.get("/metrics")
async def metrics():
    return {
        "cpu_usage": psutil.cpu_percent(),
        "memory_usage": psutil.virtual_memory().percent,
        "active_connections": len(client.players)
    }

# Scaling Strategies

# Auto-scaling

# Kubernetes HPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: sonora-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: sonora
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

# Load Balancing

# Application load balancer
from sonora.loadbalancer import LoadBalancer

lb = LoadBalancer()
lb.add_backend("node1:2333")
lb.add_backend("node2:2333")

# Route requests
node = lb.get_backend()
track = await node.load_track(query)

# Backup & Recovery

# Automated Backups

#!/bin/bash
# backup.sh
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups"

# Create backup
sonoractl snapshot save "backup_$DATE"

# Upload to cloud
aws s3 cp "$BACKUP_DIR/backup_$DATE.json" "s3://sonora-backups/"

# Cleanup old backups
find $BACKUP_DIR -name "backup_*.json" -mtime +7 -delete

# Disaster Recovery

# Recovery plan
apiVersion: v1
kind: ConfigMap
metadata:
  name: disaster-recovery
data:
  recovery.sh: |
    #!/bin/bash
    # Stop current deployment
    kubectl scale deployment sonora --replicas=0

    # Restore from backup
    sonoractl snapshot restore latest

    # Start new deployment
    kubectl scale deployment sonora --replicas=3

# Security Hardening

# Container Security

# Use non-root user
RUN useradd --create-home --shell /bin/bash sonora
USER sonora

# Minimize attack surface
RUN apt-get remove -y curl wget && \
    apt-get autoremove -y && \
    apt-get clean

# Security scanning
FROM aquasec/trivy:latest as scanner
COPY --from=builder /app/dist/*.whl .
RUN trivy filesystem --exit-code 1 --no-progress .

# Network Security

# Network policies
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: sonora-network-policy
spec:
  podSelector:
    matchLabels:
      app: sonora
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: lavalink
    ports:
    - protocol: TCP
      port: 2333
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: lavalink
    ports:
    - protocol: TCP
      port: 2333

This deployment guide covers production-ready setups for Sonora.