Fix docker
This commit is contained in:
@@ -15,27 +15,32 @@ class Settings(BaseSettings):
|
||||
DEBUG: bool = os.getenv("DEBUG", "False").lower() == "true"
|
||||
LOG_LEVEL: str = os.getenv("LOG_LEVEL", "INFO")
|
||||
|
||||
# CORS settings
|
||||
CORS_ORIGINS: List[str] = os.getenv("CORS_ORIGINS", "http://localhost:3000,http://localhost:3001").split(",")
|
||||
# CORS settings - FIXED: Remove List[str] type and parse manually
|
||||
CORS_ORIGINS: str = "http://localhost:3000,http://localhost:3001"
|
||||
|
||||
# Service URLs
|
||||
AUTH_SERVICE_URL: str = os.getenv("AUTH_SERVICE_URL", "http://auth-service:8000")
|
||||
TRAINING_SERVICE_URL: str = os.getenv("TRAINING_SERVICE_URL", "http://training-service:8000")
|
||||
FORECASTING_SERVICE_URL: str = os.getenv("FORECASTING_SERVICE_URL", "http://forecasting-service:8000")
|
||||
DATA_SERVICE_URL: str = os.getenv("DATA_SERVICE_URL", "http://data-service:8000")
|
||||
TENANT_SERVICE_URL: str = os.getenv("TENANT_SERVICE_URL", "http://tenant-service:8000")
|
||||
NOTIFICATION_SERVICE_URL: str = os.getenv("NOTIFICATION_SERVICE_URL", "http://notification-service:8000")
|
||||
AUTH_SERVICE_URL: str = "http://auth-service:8000"
|
||||
TRAINING_SERVICE_URL: str = "http://training-service:8000"
|
||||
FORECASTING_SERVICE_URL: str = "http://forecasting-service:8000"
|
||||
DATA_SERVICE_URL: str = "http://data-service:8000"
|
||||
TENANT_SERVICE_URL: str = "http://tenant-service:8000"
|
||||
NOTIFICATION_SERVICE_URL: str = "http://notification-service:8000"
|
||||
|
||||
# Redis settings
|
||||
REDIS_URL: str = os.getenv("REDIS_URL", "redis://redis:6379/6")
|
||||
REDIS_URL: str = "redis://redis:6379/6"
|
||||
|
||||
# Rate limiting
|
||||
RATE_LIMIT_REQUESTS: int = int(os.getenv("RATE_LIMIT_REQUESTS", "100"))
|
||||
RATE_LIMIT_WINDOW: int = int(os.getenv("RATE_LIMIT_WINDOW", "60"))
|
||||
RATE_LIMIT_REQUESTS: int = 100
|
||||
RATE_LIMIT_WINDOW: int = 60
|
||||
|
||||
# JWT settings
|
||||
JWT_SECRET_KEY: str = os.getenv("JWT_SECRET_KEY", "your-secret-key-change-in-production")
|
||||
JWT_ALGORITHM: str = os.getenv("JWT_ALGORITHM", "HS256")
|
||||
JWT_SECRET_KEY: str = "your-secret-key-change-in-production"
|
||||
JWT_ALGORITHM: str = "HS256"
|
||||
|
||||
@property
|
||||
def CORS_ORIGINS_LIST(self) -> List[str]:
|
||||
"""Parse CORS origins from string to list"""
|
||||
return [origin.strip() for origin in self.CORS_ORIGINS.split(",") if origin.strip()]
|
||||
|
||||
@property
|
||||
def SERVICES(self) -> Dict[str, str]:
|
||||
@@ -49,4 +54,7 @@ class Settings(BaseSettings):
|
||||
"notification": self.NOTIFICATION_SERVICE_URL
|
||||
}
|
||||
|
||||
class Config:
|
||||
env_file = ".env"
|
||||
|
||||
settings = Settings()
|
||||
@@ -40,10 +40,10 @@ metrics_collector = MetricsCollector("gateway")
|
||||
# Service discovery
|
||||
service_discovery = ServiceDiscovery()
|
||||
|
||||
# CORS middleware
|
||||
# CORS middleware - FIXED: Use the parsed list property
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=settings.CORS_ORIGINS,
|
||||
allow_origins=settings.CORS_ORIGINS_LIST,
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
|
||||
66
gateway/app/routes/data.py
Normal file
66
gateway/app/routes/data.py
Normal file
@@ -0,0 +1,66 @@
|
||||
"""
|
||||
Data routes for gateway
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter, Request, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
import httpx
|
||||
import logging
|
||||
|
||||
from app.core.config import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter()
|
||||
|
||||
@router.post("/upload")
|
||||
async def upload_sales_data(request: Request):
|
||||
"""Proxy data upload to data service"""
|
||||
try:
|
||||
body = await request.body()
|
||||
auth_header = request.headers.get("Authorization")
|
||||
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(
|
||||
f"{settings.DATA_SERVICE_URL}/upload",
|
||||
content=body,
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": auth_header
|
||||
}
|
||||
)
|
||||
|
||||
return JSONResponse(
|
||||
status_code=response.status_code,
|
||||
content=response.json()
|
||||
)
|
||||
|
||||
except httpx.RequestError as e:
|
||||
logger.error(f"Data service unavailable: {e}")
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Data service unavailable"
|
||||
)
|
||||
|
||||
@router.get("/sales")
|
||||
async def get_sales_data(request: Request):
|
||||
"""Get sales data"""
|
||||
try:
|
||||
auth_header = request.headers.get("Authorization")
|
||||
|
||||
async with httpx.AsyncClient(timeout=10.0) as client:
|
||||
response = await client.get(
|
||||
f"{settings.DATA_SERVICE_URL}/sales",
|
||||
headers={"Authorization": auth_header}
|
||||
)
|
||||
|
||||
return JSONResponse(
|
||||
status_code=response.status_code,
|
||||
content=response.json()
|
||||
)
|
||||
|
||||
except httpx.RequestError as e:
|
||||
logger.error(f"Data service unavailable: {e}")
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Data service unavailable"
|
||||
)
|
||||
66
gateway/app/routes/forecasting.py
Normal file
66
gateway/app/routes/forecasting.py
Normal file
@@ -0,0 +1,66 @@
|
||||
"""
|
||||
Forecasting routes for gateway
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter, Request, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
import httpx
|
||||
import logging
|
||||
|
||||
from app.core.config import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter()
|
||||
|
||||
@router.post("/predict")
|
||||
async def create_forecast(request: Request):
|
||||
"""Proxy forecast request to forecasting service"""
|
||||
try:
|
||||
body = await request.body()
|
||||
auth_header = request.headers.get("Authorization")
|
||||
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(
|
||||
f"{settings.FORECASTING_SERVICE_URL}/predict",
|
||||
content=body,
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": auth_header
|
||||
}
|
||||
)
|
||||
|
||||
return JSONResponse(
|
||||
status_code=response.status_code,
|
||||
content=response.json()
|
||||
)
|
||||
|
||||
except httpx.RequestError as e:
|
||||
logger.error(f"Forecasting service unavailable: {e}")
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Forecasting service unavailable"
|
||||
)
|
||||
|
||||
@router.get("/forecasts")
|
||||
async def get_forecasts(request: Request):
|
||||
"""Get forecasts"""
|
||||
try:
|
||||
auth_header = request.headers.get("Authorization")
|
||||
|
||||
async with httpx.AsyncClient(timeout=10.0) as client:
|
||||
response = await client.get(
|
||||
f"{settings.FORECASTING_SERVICE_URL}/forecasts",
|
||||
headers={"Authorization": auth_header}
|
||||
)
|
||||
|
||||
return JSONResponse(
|
||||
status_code=response.status_code,
|
||||
content=response.json()
|
||||
)
|
||||
|
||||
except httpx.RequestError as e:
|
||||
logger.error(f"Forecasting service unavailable: {e}")
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Forecasting service unavailable"
|
||||
)
|
||||
66
gateway/app/routes/notification.py
Normal file
66
gateway/app/routes/notification.py
Normal file
@@ -0,0 +1,66 @@
|
||||
"""
|
||||
Notification routes for gateway
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter, Request, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
import httpx
|
||||
import logging
|
||||
|
||||
from app.core.config import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter()
|
||||
|
||||
@router.post("/send")
|
||||
async def send_notification(request: Request):
|
||||
"""Proxy notification request to notification service"""
|
||||
try:
|
||||
body = await request.body()
|
||||
auth_header = request.headers.get("Authorization")
|
||||
|
||||
async with httpx.AsyncClient(timeout=10.0) as client:
|
||||
response = await client.post(
|
||||
f"{settings.NOTIFICATION_SERVICE_URL}/send",
|
||||
content=body,
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": auth_header
|
||||
}
|
||||
)
|
||||
|
||||
return JSONResponse(
|
||||
status_code=response.status_code,
|
||||
content=response.json()
|
||||
)
|
||||
|
||||
except httpx.RequestError as e:
|
||||
logger.error(f"Notification service unavailable: {e}")
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Notification service unavailable"
|
||||
)
|
||||
|
||||
@router.get("/history")
|
||||
async def get_notification_history(request: Request):
|
||||
"""Get notification history"""
|
||||
try:
|
||||
auth_header = request.headers.get("Authorization")
|
||||
|
||||
async with httpx.AsyncClient(timeout=10.0) as client:
|
||||
response = await client.get(
|
||||
f"{settings.NOTIFICATION_SERVICE_URL}/history",
|
||||
headers={"Authorization": auth_header}
|
||||
)
|
||||
|
||||
return JSONResponse(
|
||||
status_code=response.status_code,
|
||||
content=response.json()
|
||||
)
|
||||
|
||||
except httpx.RequestError as e:
|
||||
logger.error(f"Notification service unavailable: {e}")
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Notification service unavailable"
|
||||
)
|
||||
66
gateway/app/routes/tenant.py
Normal file
66
gateway/app/routes/tenant.py
Normal file
@@ -0,0 +1,66 @@
|
||||
"""
|
||||
Tenant routes for gateway
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter, Request, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
import httpx
|
||||
import logging
|
||||
|
||||
from app.core.config import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter()
|
||||
|
||||
@router.post("/")
|
||||
async def create_tenant(request: Request):
|
||||
"""Proxy tenant creation to tenant service"""
|
||||
try:
|
||||
body = await request.body()
|
||||
auth_header = request.headers.get("Authorization")
|
||||
|
||||
async with httpx.AsyncClient(timeout=10.0) as client:
|
||||
response = await client.post(
|
||||
f"{settings.TENANT_SERVICE_URL}/tenants",
|
||||
content=body,
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": auth_header
|
||||
}
|
||||
)
|
||||
|
||||
return JSONResponse(
|
||||
status_code=response.status_code,
|
||||
content=response.json()
|
||||
)
|
||||
|
||||
except httpx.RequestError as e:
|
||||
logger.error(f"Tenant service unavailable: {e}")
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Tenant service unavailable"
|
||||
)
|
||||
|
||||
@router.get("/")
|
||||
async def get_tenants(request: Request):
|
||||
"""Get tenants"""
|
||||
try:
|
||||
auth_header = request.headers.get("Authorization")
|
||||
|
||||
async with httpx.AsyncClient(timeout=10.0) as client:
|
||||
response = await client.get(
|
||||
f"{settings.TENANT_SERVICE_URL}/tenants",
|
||||
headers={"Authorization": auth_header}
|
||||
)
|
||||
|
||||
return JSONResponse(
|
||||
status_code=response.status_code,
|
||||
content=response.json()
|
||||
)
|
||||
|
||||
except httpx.RequestError as e:
|
||||
logger.error(f"Tenant service unavailable: {e}")
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Tenant service unavailable"
|
||||
)
|
||||
@@ -11,3 +11,4 @@ python-json-logger==2.0.4
|
||||
email-validator==2.0.0
|
||||
aio-pika==9.3.0
|
||||
pytz==2023.3
|
||||
python-logstash==0.4.8
|
||||
@@ -4,3 +4,6 @@ Messaging service for training service
|
||||
|
||||
from shared.messaging.rabbitmq import RabbitMQClient
|
||||
from app.core.config import settings
|
||||
|
||||
# Global message publisher
|
||||
message_publisher = RabbitMQClient(settings.RABBITMQ_URL)
|
||||
Reference in New Issue
Block a user