- Introduced Aggregator.sol for Chainlink-compatible oracle functionality, including round-based updates and access control. - Added OracleWithCCIP.sol to extend Aggregator with CCIP cross-chain messaging capabilities. - Created .gitmodules to include OpenZeppelin contracts as a submodule. - Developed a comprehensive deployment guide in NEXT_STEPS_COMPLETE_GUIDE.md for Phase 2 and smart contract deployment. - Implemented Vite configuration for the orchestration portal, supporting both Vue and React frameworks. - Added server-side logic for the Multi-Cloud Orchestration Portal, including API endpoints for environment management and monitoring. - Created scripts for resource import and usage validation across non-US regions. - Added tests for CCIP error handling and integration to ensure robust functionality. - Included various new files and directories for the orchestration portal and deployment scripts.
176 lines
5.1 KiB
Python
176 lines
5.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Multi-Cloud Orchestration Portal
|
|
Web-based UI for managing deployments across all environments
|
|
"""
|
|
|
|
import os
|
|
import yaml
|
|
import json
|
|
from flask import Flask, render_template, request, jsonify, redirect, url_for
|
|
from flask_cors import CORS
|
|
import subprocess
|
|
from datetime import datetime
|
|
from typing import Dict, List, Any
|
|
|
|
app = Flask(__name__)
|
|
CORS(app)
|
|
|
|
# Configuration
|
|
ENVIRONMENTS_FILE = os.path.join(os.path.dirname(__file__), '../../config/environments.yaml')
|
|
DEPLOYMENT_LOG_DIR = os.path.join(os.path.dirname(__file__), '../../logs/deployments')
|
|
|
|
os.makedirs(DEPLOYMENT_LOG_DIR, exist_ok=True)
|
|
|
|
|
|
def load_environments() -> Dict[str, Any]:
|
|
"""Load environments configuration from YAML file"""
|
|
try:
|
|
with open(ENVIRONMENTS_FILE, 'r') as f:
|
|
config = yaml.safe_load(f)
|
|
return config.get('environments', [])
|
|
except Exception as e:
|
|
print(f"Error loading environments: {e}")
|
|
return []
|
|
|
|
|
|
def get_environment_by_name(name: str) -> Dict[str, Any]:
|
|
"""Get environment configuration by name"""
|
|
environments = load_environments()
|
|
for env in environments:
|
|
if env.get('name') == name:
|
|
return env
|
|
return {}
|
|
|
|
|
|
def get_deployment_status(environment_name: str) -> Dict[str, Any]:
|
|
"""Get deployment status for an environment"""
|
|
# This would query Terraform state, Kubernetes clusters, etc.
|
|
# For now, return mock data
|
|
return {
|
|
'status': 'deployed',
|
|
'last_deployed': '2024-01-15T10:30:00Z',
|
|
'cluster_health': 'healthy',
|
|
'node_count': 3,
|
|
'pods_running': 12,
|
|
'pods_total': 12
|
|
}
|
|
|
|
|
|
@app.route('/')
|
|
def index():
|
|
"""Main dashboard"""
|
|
environments = load_environments()
|
|
|
|
# Group by provider
|
|
by_provider = {}
|
|
for env in environments:
|
|
provider = env.get('provider', 'unknown')
|
|
if provider not in by_provider:
|
|
by_provider[provider] = []
|
|
by_provider[provider].append(env)
|
|
|
|
# Get status for each environment
|
|
env_statuses = {}
|
|
for env in environments:
|
|
if env.get('enabled'):
|
|
env_statuses[env['name']] = get_deployment_status(env['name'])
|
|
|
|
return render_template('index.html',
|
|
environments=environments,
|
|
by_provider=by_provider,
|
|
env_statuses=env_statuses)
|
|
|
|
|
|
@app.route('/api/environments')
|
|
def api_environments():
|
|
"""API endpoint for environments"""
|
|
environments = load_environments()
|
|
return jsonify(environments)
|
|
|
|
|
|
@app.route('/api/environments/<name>')
|
|
def api_environment(name: str):
|
|
"""API endpoint for a specific environment"""
|
|
env = get_environment_by_name(name)
|
|
if not env:
|
|
return jsonify({'error': 'Environment not found'}), 404
|
|
|
|
status = get_deployment_status(name)
|
|
return jsonify({
|
|
'config': env,
|
|
'status': status
|
|
})
|
|
|
|
|
|
@app.route('/api/environments/<name>/deploy', methods=['POST'])
|
|
def api_deploy(name: str):
|
|
"""Deploy to a specific environment"""
|
|
env = get_environment_by_name(name)
|
|
if not env:
|
|
return jsonify({'error': 'Environment not found'}), 404
|
|
|
|
if not env.get('enabled'):
|
|
return jsonify({'error': 'Environment is disabled'}), 400
|
|
|
|
# Trigger deployment
|
|
deployment_id = f"{name}-{datetime.now().strftime('%Y%m%d%H%M%S')}"
|
|
|
|
# In production, this would trigger Terraform/CI-CD pipeline
|
|
# For now, log the deployment request
|
|
log_file = os.path.join(DEPLOYMENT_LOG_DIR, f"{deployment_id}.log")
|
|
with open(log_file, 'w') as f:
|
|
f.write(f"Deployment requested for {name} at {datetime.now().isoformat()}\n")
|
|
f.write(f"Environment config: {json.dumps(env, indent=2)}\n")
|
|
|
|
return jsonify({
|
|
'deployment_id': deployment_id,
|
|
'status': 'queued',
|
|
'environment': name,
|
|
'message': 'Deployment queued successfully'
|
|
})
|
|
|
|
|
|
@app.route('/api/environments/<name>/status')
|
|
def api_status(name: str):
|
|
"""Get deployment status for an environment"""
|
|
status = get_deployment_status(name)
|
|
return jsonify(status)
|
|
|
|
|
|
@app.route('/api/deployments')
|
|
def api_deployments():
|
|
"""List all deployments"""
|
|
deployments = []
|
|
|
|
if os.path.exists(DEPLOYMENT_LOG_DIR):
|
|
for filename in os.listdir(DEPLOYMENT_LOG_DIR):
|
|
if filename.endswith('.log'):
|
|
deployment_id = filename[:-4]
|
|
deployments.append({
|
|
'id': deployment_id,
|
|
'environment': deployment_id.split('-')[0],
|
|
'timestamp': os.path.getmtime(os.path.join(DEPLOYMENT_LOG_DIR, filename))
|
|
})
|
|
|
|
deployments.sort(key=lambda x: x['timestamp'], reverse=True)
|
|
return jsonify(deployments)
|
|
|
|
|
|
@app.route('/environment/<name>')
|
|
def environment_detail(name: str):
|
|
"""Environment detail page"""
|
|
env = get_environment_by_name(name)
|
|
if not env:
|
|
return "Environment not found", 404
|
|
|
|
status = get_deployment_status(name)
|
|
return render_template('environment.html',
|
|
environment=env,
|
|
status=status)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
app.run(debug=True, host='0.0.0.0', port=5000)
|
|
|