143 lines
4.8 KiB
YAML

{{/*
ConfigMap containing the API backend Python script
Handles POST requests to /api/status and updates the status.json file
*/}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "gitops-status-server.fullname" . }}-api
labels:
{{- include "gitops-status-server.labels" . | nindent 4 }}
data:
app.py: |
#!/usr/bin/env python3
"""
Simple Flask API for updating status.json
Listens on port 5000 and handles POST requests to /api/status
"""
import os
import json
import logging
from flask import Flask, request, jsonify
from datetime import datetime
app = Flask(__name__)
# Configuration
STATUS_FILE = '/usr/share/nginx/html/status.json'
API_PORT = int(os.environ.get('API_PORT', 5000))
API_HOST = os.environ.get('API_HOST', '127.0.0.1')
# Setup logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
def load_status():
"""Load the current status from file"""
try:
if os.path.exists(STATUS_FILE):
with open(STATUS_FILE, 'r') as f:
return json.load(f)
else:
# Default status if file doesn't exist
return {
"repo": "unknown",
"server": "unknown",
"sync_status": "UNKNOWN",
"drift_count": 0,
"files": [],
"last_check": ""
}
except Exception as e:
logger.error(f"Error loading status: {e}")
return {}
def save_status(status):
"""Save the status to file"""
try:
# Ensure directory exists (should already exist from mount)
os.makedirs(os.path.dirname(STATUS_FILE), exist_ok=True)
# Write with proper formatting
with open(STATUS_FILE, 'w') as f:
json.dump(status, f, indent=2)
logger.info(f"Status saved successfully: {status['repo']}/{status['server']} -> {status['sync_status']}")
return True
except Exception as e:
logger.error(f"Error saving status: {e}")
return False
@app.route('/api/status', methods=['GET', 'POST', 'OPTIONS'])
def api_status():
"""
GET: Retrieve current status
POST: Update status with new data
"""
if request.method == 'OPTIONS':
return '', 204
if request.method == 'GET':
status = load_status()
return jsonify(status), 200
if request.method == 'POST':
try:
# Parse incoming JSON
incoming_data = request.get_json()
if not incoming_data:
return jsonify({"error": "No JSON data provided"}), 400
# Load current status
status = load_status()
# Update with incoming data (merge)
status.update(incoming_data)
# Ensure required fields exist
if 'last_check' not in status or not status['last_check']:
status['last_check'] = datetime.utcnow().isoformat() + 'Z'
# Save updated status
if save_status(status):
return jsonify({
"success": True,
"message": "Status updated successfully",
"status": status
}), 200
else:
return jsonify({
"error": "Failed to save status"
}), 500
except json.JSONDecodeError:
return jsonify({"error": "Invalid JSON"}), 400
except Exception as e:
logger.error(f"Error processing POST request: {e}")
return jsonify({"error": str(e)}), 500
@app.route('/health', methods=['GET'])
def health():
"""Health check endpoint"""
return jsonify({"status": "healthy"}), 200
@app.route('/ready', methods=['GET'])
def ready():
"""Readiness check - verify status file is accessible"""
try:
status = load_status()
if status:
return jsonify({"status": "ready"}), 200
else:
return jsonify({"status": "not_ready", "reason": "status file empty"}), 503
except Exception as e:
return jsonify({"status": "not_ready", "error": str(e)}), 503
if __name__ == '__main__':
logger.info(f"Starting gitops-status-server API on {API_HOST}:{API_PORT}")
logger.info(f"Status file: {STATUS_FILE}")
app.run(host=API_HOST, port=API_PORT, debug=False)