336 lines
7.7 KiB
Markdown
336 lines
7.7 KiB
Markdown
# ScriptsManager - Sistema de Proxy Interno
|
|
|
|
## 🚀 Nueva Arquitectura Implementada
|
|
|
|
El ScriptsManager ahora incluye un **sistema de proxy interno** que permite ejecutar scripts Flask de forma más elegante y escalable.
|
|
|
|
### ✨ Características Principales
|
|
|
|
- **Un solo puerto expuesto** (5002/5003) para toda la aplicación
|
|
- **Puertos internos gestionados automáticamente** (5200-5400)
|
|
- **Soporte para múltiples proyectos por usuario**
|
|
- **Aislamiento completo** entre ejecuciones de diferentes usuarios
|
|
- **Limpieza automática** de procesos inactivos
|
|
- **Monitoreo en tiempo real** del estado de los scripts
|
|
|
|
## 🏗️ Arquitectura
|
|
|
|
```
|
|
Usuario External → ScriptsManager (puerto 5002/5003)
|
|
↓
|
|
/project/{project_id}/script/{script_id}/user/{user_id}/*
|
|
↓
|
|
http://localhost:{puerto_interno}/*
|
|
```
|
|
|
|
### Flujo de Ejecución
|
|
|
|
1. **Usuario solicita ejecutar un script** a través de la interfaz web
|
|
2. **ScriptsManager asigna un puerto interno** (ej: 5234)
|
|
3. **Script se ejecuta como Flask app** en ese puerto interno
|
|
4. **Proxy redirige peticiones** de la URL pública al puerto interno
|
|
5. **Usuario accede al script** a través de URL amigable
|
|
|
|
## 📁 Estructura de URLs
|
|
|
|
### URLs de Acceso a Scripts
|
|
```bash
|
|
# Página principal del script
|
|
/project/{project_id}/script/{script_id}/user/{user_id}/
|
|
|
|
# Cualquier ruta del script
|
|
/project/{project_id}/script/{script_id}/user/{user_id}/dashboard
|
|
/project/{project_id}/script/{script_id}/user/{user_id}/api/data
|
|
/project/{project_id}/script/{script_id}/user/{user_id}/results
|
|
```
|
|
|
|
### URLs de Control
|
|
```bash
|
|
# Iniciar script
|
|
POST /project/{project_id}/script/{script_id}/user/{user_id}/_control/start
|
|
|
|
# Detener script
|
|
POST /project/{project_id}/script/{script_id}/user/{user_id}/_control/stop
|
|
|
|
# Estado del script
|
|
GET /project/{project_id}/script/{script_id}/user/{user_id}/_control/status
|
|
```
|
|
|
|
### URLs Administrativas
|
|
```bash
|
|
# Estadísticas del proxy (solo admin)
|
|
GET /project/_admin/stats
|
|
```
|
|
|
|
## 💻 Desarrollo de Scripts
|
|
|
|
### Estructura de Script Flask
|
|
|
|
Los scripts ahora deben seguir esta estructura:
|
|
|
|
```python
|
|
"""
|
|
Mi Script Flask para ScriptsManager
|
|
"""
|
|
|
|
# Variables automáticas disponibles:
|
|
# - WORKSPACE_PATH: directorio de trabajo del script
|
|
# - PARAMETERS: parámetros pasados al script
|
|
# - ENVIRONMENT: variables de entorno
|
|
# - app: instancia Flask configurada
|
|
|
|
from flask import render_template, request, jsonify
|
|
import os
|
|
|
|
@app.route('/')
|
|
def index():
|
|
"""Página principal del script"""
|
|
return render_template_string("""
|
|
<h1>Mi Script</h1>
|
|
<p>Workspace: {{ workspace }}</p>
|
|
<p>Parámetros: {{ parameters }}</p>
|
|
""", workspace=WORKSPACE_PATH, parameters=PARAMETERS)
|
|
|
|
@app.route('/api/data')
|
|
def get_data():
|
|
"""API endpoint del script"""
|
|
return jsonify({
|
|
'status': 'ok',
|
|
'data': 'Mi data personalizada'
|
|
})
|
|
|
|
@app.route('/process', methods=['POST'])
|
|
def process_data():
|
|
"""Procesar datos"""
|
|
data = request.get_json()
|
|
# Procesar...
|
|
return jsonify({'result': 'processed'})
|
|
```
|
|
|
|
### Variables Disponibles
|
|
|
|
Cada script tiene acceso a:
|
|
|
|
- `WORKSPACE_PATH`: Directorio de trabajo aislado
|
|
- `PARAMETERS`: Diccionario con parámetros del usuario
|
|
- `ENVIRONMENT`: Variables de entorno (USER_LEVEL, PROJECT_NAME, etc.)
|
|
- `app`: Instancia Flask pre-configurada
|
|
- `PROJECT_WORKSPACE`: Alias para WORKSPACE_PATH
|
|
|
|
### Health Check Automático
|
|
|
|
Cada script **debe responder** en `/health`:
|
|
|
|
```python
|
|
@app.route('/health')
|
|
def health_check():
|
|
return {'status': 'ok', 'workspace': WORKSPACE_PATH}, 200
|
|
```
|
|
|
|
## 🔧 Uso desde Python
|
|
|
|
### Ejecutar Script con Proxy
|
|
|
|
```python
|
|
from app.services.script_executor import ScriptExecutor
|
|
|
|
executor = ScriptExecutor()
|
|
|
|
# Ejecutar script usando el nuevo sistema de proxy
|
|
result = executor.execute_script_with_proxy(
|
|
script_id=1,
|
|
user_id=1,
|
|
project_id=1,
|
|
parameters={'sample_size': 1000, 'mode': 'advanced'},
|
|
environment={'DEBUG': 'true'}
|
|
)
|
|
|
|
if result['success']:
|
|
print(f"Script disponible en: {result['proxy_url']}")
|
|
print(f"Puerto interno: {result['internal_port']}")
|
|
else:
|
|
print(f"Error: {result['error']}")
|
|
```
|
|
|
|
### Control de Scripts
|
|
|
|
```python
|
|
# Detener script
|
|
stop_result = executor.stop_script_proxy(
|
|
script_id=1, user_id=1, project_id=1
|
|
)
|
|
|
|
# Obtener estado
|
|
status = executor.get_script_proxy_status(
|
|
script_id=1, user_id=1, project_id=1
|
|
)
|
|
```
|
|
|
|
## 🌐 APIs REST
|
|
|
|
### Iniciar Script
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5003/project/1/script/1/user/1/_control/start \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"parameters": {"mode": "test"}, "environment": {"DEBUG": "true"}}'
|
|
```
|
|
|
|
**Respuesta:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"proxy_url": "/project/1/script/1/user/1/",
|
|
"internal_port": 5234,
|
|
"message": "Script iniciado correctamente",
|
|
"script_key": "1_1_1"
|
|
}
|
|
```
|
|
|
|
### Estado del Script
|
|
|
|
```bash
|
|
curl http://localhost:5003/project/1/script/1/user/1/_control/status
|
|
```
|
|
|
|
**Respuesta:**
|
|
```json
|
|
{
|
|
"script_key": "1_1_1",
|
|
"running": true,
|
|
"proxy_service_info": {
|
|
"status": "running",
|
|
"port": 5234,
|
|
"started_at": "2025-09-13T10:30:00",
|
|
"last_activity": "2025-09-13T10:35:00"
|
|
},
|
|
"database_info": {
|
|
"id": 42,
|
|
"status": "running",
|
|
"workspace_path": "/app/workspaces/user_1/project_1/script_1"
|
|
}
|
|
}
|
|
```
|
|
|
|
## 📊 Monitoreo y Administración
|
|
|
|
### Estadísticas del Proxy
|
|
|
|
```bash
|
|
curl http://localhost:5003/project/_admin/stats
|
|
```
|
|
|
|
**Respuesta:**
|
|
```json
|
|
{
|
|
"total_scripts": 3,
|
|
"used_ports": 3,
|
|
"available_ports": 197,
|
|
"port_range": "5200-5400",
|
|
"scripts_by_status": {
|
|
"running": 2,
|
|
"starting": 1,
|
|
"stopping": 0,
|
|
"error": 0
|
|
}
|
|
}
|
|
```
|
|
|
|
## 🗄️ Base de Datos
|
|
|
|
### Nuevas Tablas
|
|
|
|
#### `script_proxy_executions`
|
|
- Registra scripts ejecutándose en el proxy
|
|
- Relaciona project_id, script_id, user_id con puertos internos
|
|
- Tracking de actividad y estado
|
|
|
|
#### `execution_logs` (actualizada)
|
|
- Nuevas columnas: `project_id`, `proxy_port`, `proxy_url`, `execution_mode`
|
|
- Soporte para logging de ejecuciones proxy
|
|
|
|
### Migración
|
|
|
|
Para aplicar los cambios de base de datos:
|
|
|
|
```bash
|
|
python scripts/migrate_proxy_system.py
|
|
```
|
|
|
|
## 🚦 Testing
|
|
|
|
### Script de Prueba Automático
|
|
|
|
```bash
|
|
./test_proxy_system.sh
|
|
```
|
|
|
|
Este script prueba:
|
|
- Inicio de scripts
|
|
- Proxy de peticiones
|
|
- APIs internas
|
|
- Detención de scripts
|
|
- Estadísticas del sistema
|
|
|
|
### Script de Ejemplo
|
|
|
|
Incluido en `data/script_groups/examples/example_flask_app.py`:
|
|
- Interfaz web completa
|
|
- Generación de datos
|
|
- Creación de gráficos
|
|
- Explorador de archivos
|
|
- APIs REST
|
|
|
|
## 🔄 Migración desde Sistema Anterior
|
|
|
|
### Para Desarrolladores
|
|
|
|
1. **Scripts existentes**: Mantienen compatibilidad
|
|
2. **Nuevos scripts**: Usar formato Flask con variables automáticas
|
|
3. **APIs**: Cambiar de puertos directos a URLs proxy
|
|
|
|
### Beneficios del Nuevo Sistema
|
|
|
|
- ✅ **Seguridad**: No más puertos expuestos
|
|
- ✅ **Escalabilidad**: Pool de puertos gestionado
|
|
- ✅ **Aislamiento**: Workspaces separados por proyecto/usuario
|
|
- ✅ **Monitoreo**: Estado en tiempo real
|
|
- ✅ **Limpieza**: Procesos inactivos eliminados automáticamente
|
|
- ✅ **URLs amigables**: Rutas semánticas y organizadas
|
|
|
|
## 🛠️ Configuración
|
|
|
|
### Variables de Entorno
|
|
|
|
```bash
|
|
# Rango de puertos internos
|
|
PORT_RANGE_START=5200
|
|
PORT_RANGE_END=5400
|
|
|
|
# Timeout de inactividad (segundos)
|
|
SCRIPT_TIMEOUT=3600
|
|
|
|
# Intervalo de limpieza (segundos)
|
|
CLEANUP_INTERVAL=300
|
|
```
|
|
|
|
### Docker Compose
|
|
|
|
Los nuevos volúmenes incluidos:
|
|
|
|
```yaml
|
|
volumes:
|
|
- ./workspaces:/app/workspaces # Workspaces aislados
|
|
```
|
|
|
|
## 🎯 Próximos Pasos
|
|
|
|
- [ ] Dashboard de monitoreo en tiempo real
|
|
- [ ] WebSocket para logs en vivo
|
|
- [ ] Límites de recursos por script
|
|
- [ ] Backup automático de workspaces
|
|
- [ ] Métricas de performance
|
|
|
|
---
|
|
|
|
**¡El nuevo sistema de proxy está listo para usar!** 🚀 |