Initial commit: File Transformer S3 project with React dashboard and Knative functions

This commit is contained in:
greg
2025-07-04 08:01:46 -07:00
commit fd9abd0210
54 changed files with 5584 additions and 0 deletions

30
api-gateway/Dockerfile Normal file
View File

@@ -0,0 +1,30 @@
FROM python:3.11-slim
# Set working directory
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y \
gcc \
&& rm -rf /var/lib/apt/lists/*
# Copy requirements and install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application code
COPY app.py .
# Create non-root user
RUN useradd --create-home --shell /bin/bash app && chown -R app:app /app
USER app
# Expose port
EXPOSE 8080
# Health check
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1
# Run the application
CMD ["gunicorn", "--bind", "0.0.0.0:8080", "--workers", "4", "--timeout", "300", "app:app"]

165
api-gateway/app.py Normal file
View File

@@ -0,0 +1,165 @@
import os
import requests
from flask import Flask, request, jsonify
from flask_cors import CORS
import logging
app = Flask(__name__)
CORS(app)
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Function service URLs
UPLOAD_SERVICE_URL = os.getenv('UPLOAD_SERVICE_URL', 'http://function-upload:5000')
TRANSFORM_SERVICE_URL = os.getenv('TRANSFORM_SERVICE_URL', 'http://function-transform:5000')
DOWNLOAD_SERVICE_URL = os.getenv('DOWNLOAD_SERVICE_URL', 'http://function-download:5000')
METADATA_SERVICE_URL = os.getenv('METADATA_SERVICE_URL', 'http://function-metadata:5000')
@app.route('/health', methods=['GET'])
def health_check():
"""Health check endpoint."""
return jsonify({'status': 'healthy', 'service': 'api-gateway'})
@app.route('/files/upload', methods=['POST'])
def upload_file():
"""Route file upload requests to upload service."""
try:
response = requests.post(
f"{UPLOAD_SERVICE_URL}/upload",
files=request.files,
data=request.form,
timeout=300
)
return jsonify(response.json()), response.status_code
except requests.exceptions.RequestException as e:
logger.error(f"Upload service error: {e}")
return jsonify({'error': 'Upload service unavailable'}), 503
@app.route('/files/<file_id>/transform', methods=['POST'])
def transform_file(file_id):
"""Route transformation requests to transform service."""
try:
response = requests.post(
f"{TRANSFORM_SERVICE_URL}/transform/{file_id}",
json=request.get_json(),
timeout=300
)
return jsonify(response.json()), response.status_code
except requests.exceptions.RequestException as e:
logger.error(f"Transform service error: {e}")
return jsonify({'error': 'Transform service unavailable'}), 503
@app.route('/files/<file_id>/download', methods=['GET'])
def download_file(file_id):
"""Route download requests to download service."""
try:
response = requests.get(
f"{DOWNLOAD_SERVICE_URL}/download/{file_id}",
timeout=300
)
return response.content, response.status_code, response.headers.items()
except requests.exceptions.RequestException as e:
logger.error(f"Download service error: {e}")
return jsonify({'error': 'Download service unavailable'}), 503
@app.route('/files/<file_id>/metadata', methods=['GET'])
def get_file_metadata(file_id):
"""Route metadata requests to metadata service."""
try:
response = requests.get(
f"{METADATA_SERVICE_URL}/files/{file_id}/metadata",
timeout=30
)
return jsonify(response.json()), response.status_code
except requests.exceptions.RequestException as e:
logger.error(f"Metadata service error: {e}")
return jsonify({'error': 'Metadata service unavailable'}), 503
@app.route('/files/<file_id>/metadata', methods=['PUT'])
def update_file_metadata(file_id):
"""Route metadata update requests to metadata service."""
try:
response = requests.put(
f"{METADATA_SERVICE_URL}/files/{file_id}/metadata",
json=request.get_json(),
timeout=30
)
return jsonify(response.json()), response.status_code
except requests.exceptions.RequestException as e:
logger.error(f"Metadata service error: {e}")
return jsonify({'error': 'Metadata service unavailable'}), 503
@app.route('/files', methods=['GET'])
def get_files():
"""Route file listing requests to metadata service."""
try:
response = requests.get(
f"{METADATA_SERVICE_URL}/files",
params=request.args,
timeout=30
)
return jsonify(response.json()), response.status_code
except requests.exceptions.RequestException as e:
logger.error(f"Metadata service error: {e}")
return jsonify({'error': 'Metadata service unavailable'}), 503
@app.route('/transformations', methods=['GET'])
def get_transformations():
"""Route transformation listing requests to metadata service."""
try:
response = requests.get(
f"{METADATA_SERVICE_URL}/transformations",
params=request.args,
timeout=30
)
return jsonify(response.json()), response.status_code
except requests.exceptions.RequestException as e:
logger.error(f"Metadata service error: {e}")
return jsonify({'error': 'Metadata service unavailable'}), 503
@app.route('/dashboard/stats', methods=['GET'])
def get_dashboard_stats():
"""Route dashboard stats requests to metadata service."""
try:
response = requests.get(
f"{METADATA_SERVICE_URL}/stats",
timeout=30
)
return jsonify(response.json()), response.status_code
except requests.exceptions.RequestException as e:
logger.error(f"Metadata service error: {e}")
return jsonify({'error': 'Metadata service unavailable'}), 503
@app.route('/buckets', methods=['GET'])
def get_buckets():
"""Route bucket requests to metadata service."""
try:
response = requests.get(
f"{METADATA_SERVICE_URL}/buckets",
timeout=30
)
return jsonify(response.json()), response.status_code
except requests.exceptions.RequestException as e:
logger.error(f"Metadata service error: {e}")
return jsonify({'error': 'Metadata service unavailable'}), 503
# Auth endpoints (placeholder for now)
@app.route('/auth/login', methods=['POST'])
def login():
"""Placeholder login endpoint."""
return jsonify({'token': 'dummy-token', 'user': {'id': 1, 'username': 'admin'}}), 200
@app.route('/auth/logout', methods=['POST'])
def logout():
"""Placeholder logout endpoint."""
return jsonify({'message': 'Logged out successfully'}), 200
@app.route('/auth/profile', methods=['GET'])
def get_profile():
"""Placeholder profile endpoint."""
return jsonify({'id': 1, 'username': 'admin', 'email': 'admin@example.com'}), 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080, debug=False)

View File

@@ -0,0 +1,11 @@
# Core dependencies
flask==2.3.3
flask-cors==4.0.0
gunicorn==21.2.0
python-dotenv==1.0.0
# HTTP requests
requests==2.31.0
# Logging
structlog==23.1.0