Subir archivos a "/"
This commit is contained in:
104
README.md
Normal file
104
README.md
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
# Cloud Conversion
|
||||||
|
|
||||||
|
Cloud Conversion es un proyecto Python para apoyar evaluaciones de migracion cloud. Descarga y transforma catalogos de precios de AWS y OCI, compara inventarios de servidores contra shapes cloud, genera archivos `MATCH-*` con recomendaciones y costos, y ofrece una interfaz grafica local en Streamlit para operar el pipeline sin depender de comandos manuales.
|
||||||
|
|
||||||
|
La ruta recomendada para arquitectos es la interfaz grafica. Los scripts CLI siguen disponibles para automatizacion, troubleshooting o ejecuciones controladas.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
1. Crear y activar ambiente virtual:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3.12 -m venv .venv
|
||||||
|
source .venv/bin/activate
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Configurar variables opcionales:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Abrir la interfaz grafica:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
streamlit run cloud_conversion_ui/Home.py
|
||||||
|
```
|
||||||
|
|
||||||
|
4. En la GUI:
|
||||||
|
|
||||||
|
- Selecciona o sube un inventario en `Inventario`.
|
||||||
|
- Actualiza catalogos en `Catalogos` si necesitas precios recientes.
|
||||||
|
- Ejecuta `AWS Match` y `OCI Match` en `Ejecucion`.
|
||||||
|
- Revisa costos y cobertura en `Dashboard`.
|
||||||
|
- Descarga CSVs, EDA y logs en `Logs y Artefactos`.
|
||||||
|
|
||||||
|
## Flujo Operativo
|
||||||
|
|
||||||
|
### Interfaz grafica
|
||||||
|
|
||||||
|
La aplicacion Streamlit vive en `cloud_conversion_ui/` y usa `cloud_conversion_ui/Home.py` como entrada. Es el camino recomendado para uso diario porque agrupa inventarios, catalogos, ejecucion, resultados y descargas en una sola consola local.
|
||||||
|
|
||||||
|
Al ejecutar matching desde la GUI, los inventarios no se archivan automaticamente. Internamente la GUI llama los pipelines con `move_to_done=False`; si quieres archivar un inventario, hazlo desde la pagina `Inventario`.
|
||||||
|
|
||||||
|
### Scripts CLI
|
||||||
|
|
||||||
|
Los scripts estan en `scripts/`. El pipeline AWS tipico es:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python scripts/aws_fetch_offer.py
|
||||||
|
python scripts/aws_eda.py
|
||||||
|
python scripts/aws_match.py --inventory input/inventario.xlsx --skip-llm
|
||||||
|
```
|
||||||
|
|
||||||
|
El pipeline OCI tipico es:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python scripts/oci_fetch_offer.py
|
||||||
|
python scripts/oci_match.py --inventory input/inventario.xlsx --skip-llm
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentacion
|
||||||
|
|
||||||
|
- [Despliegue Local/VM](docs/DEPLOYMENT.md)
|
||||||
|
- [Guia de la Interfaz Grafica](docs/UI_GUIDE.md)
|
||||||
|
- [Scripts y Comandos](docs/SCRIPTS.md)
|
||||||
|
- [Diccionario de Datos](docs/DATA_DICTIONARY.md)
|
||||||
|
- [Estructura de Directorios](docs/DIRECTORY_STRUCTURE.md)
|
||||||
|
|
||||||
|
## Comandos Utiles
|
||||||
|
|
||||||
|
| Comando | Uso |
|
||||||
|
| --- | --- |
|
||||||
|
| `streamlit run cloud_conversion_ui/Home.py` | Inicia la GUI local. |
|
||||||
|
| `python scripts/aws_match.py --help` | Muestra parametros de AWS Match. |
|
||||||
|
| `python scripts/oci_match.py --help` | Muestra parametros de OCI Match. |
|
||||||
|
| `python scripts/cloud-chat.py --ask "Cuanto cuesta m7a.xlarge en virginia?"` | Consulta el catalogo AWS desde CLI. |
|
||||||
|
| `python scripts/whatsapp_chatbot.py` | Inicia webhook Flask para WhatsApp Cloud Chat. |
|
||||||
|
| `python -m pytest -q` | Ejecuta la suite de pruebas. |
|
||||||
|
|
||||||
|
## Datos y Seguridad
|
||||||
|
|
||||||
|
- `.env` contiene secretos locales y no debe subirse.
|
||||||
|
- `.env.example` es la plantilla segura para compartir.
|
||||||
|
- Los datos actuales se conservan para uso interno, pero antes de publicar el repo se debe revisar sensibilidad de inventarios, clientes, precios y logs.
|
||||||
|
- `data/` puede ser grande; en este workspace pesa aproximadamente 8 GB.
|
||||||
|
- `logs/`, `.venv/`, caches y archivos temporales estan ignorados por Git.
|
||||||
|
|
||||||
|
## Validacion antes de Compartir
|
||||||
|
|
||||||
|
Ejecuta:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m pytest -q
|
||||||
|
python scripts/aws_match.py --help
|
||||||
|
python scripts/oci_match.py --help
|
||||||
|
python scripts/aws_eda.py --help
|
||||||
|
python scripts/cloud-chat.py --help
|
||||||
|
python scripts/whatsapp_send.py --help
|
||||||
|
streamlit run cloud_conversion_ui/Home.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Para validar Streamlit en una VM, confirma que el navegador abre la pagina inicial y que el sidebar muestra `Inventario`, `Catalogos`, `Ejecucion`, `Dashboard` y `Logs y Artefactos`.
|
||||||
|
|
||||||
9
requirements.txt
Normal file
9
requirements.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
pandas==2.2.3
|
||||||
|
openpyxl==3.1.5
|
||||||
|
pydantic==2.10.6
|
||||||
|
requests==2.32.3
|
||||||
|
langchain-ollama==1.1.0
|
||||||
|
flask==3.1.3
|
||||||
|
twilio==9.10.9
|
||||||
|
python-dotenv==1.2.2
|
||||||
|
streamlit==1.57.0
|
||||||
20
send.py
Normal file
20
send.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import os
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from twilio.rest import Client
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
account_sid = os.environ["TWILIO_ACCOUNT_SID"]
|
||||||
|
auth_token = os.environ["TWILIO_AUTH_TOKEN"]
|
||||||
|
from_whatsapp = os.environ["TWILIO_WHATSAPP_FROM"]
|
||||||
|
to_whatsapp = os.environ["MY_WHATSAPP_TO"]
|
||||||
|
|
||||||
|
client = Client(account_sid, auth_token)
|
||||||
|
message = client.messages.create(
|
||||||
|
from_=from_whatsapp,
|
||||||
|
to=to_whatsapp,
|
||||||
|
body="Hola mundo desde Python usando Twilio WhatsApp."
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Mensaje enviado correctamente.")
|
||||||
|
print("SID:", message.sid)
|
||||||
|
print("Estado:", message.status)
|
||||||
45
server.py
Normal file
45
server.py
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import os
|
||||||
|
from flask import Flask, request, abort, Response
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from twilio.request_validator import RequestValidator
|
||||||
|
from twilio.twiml.messaging_response import MessagingResponse
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
twilio_auth_token = os.environ["TWILIO_AUTH_TOKEN"]
|
||||||
|
public_webhook_url = os.environ["PUBLIC_WEBHOOK_URL"]
|
||||||
|
|
||||||
|
validator = RequestValidator(twilio_auth_token)
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/whatsapp")
|
||||||
|
def whatsapp_webhook():
|
||||||
|
signature = request.headers.get("X-Twilio-Signature", "")
|
||||||
|
|
||||||
|
is_valid = validator.validate(
|
||||||
|
public_webhook_url,
|
||||||
|
request.form.to_dict(),
|
||||||
|
signature
|
||||||
|
)
|
||||||
|
|
||||||
|
if not is_valid:
|
||||||
|
print("Firma inválida. Request rechazado.")
|
||||||
|
abort(403)
|
||||||
|
|
||||||
|
incoming_message = request.form.get("Body", "")
|
||||||
|
sender = request.form.get("From", "")
|
||||||
|
|
||||||
|
print("Mensaje recibido desde WhatsApp")
|
||||||
|
print("De:", sender)
|
||||||
|
print("Texto:", incoming_message)
|
||||||
|
|
||||||
|
response = MessagingResponse()
|
||||||
|
response.message(f"Hola. Recibí tu mensaje: {incoming_message}")
|
||||||
|
|
||||||
|
return Response(str(response), mimetype="text/xml")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(port=3000, debug=True)
|
||||||
Reference in New Issue
Block a user