# Tema 3 · 4 · Web app propia en una EC2 y ejercicio 3 (exportar e importar) Presentación del Tema 3: «Utilización de una WebApp propia» (con `estudiantes.php` y `estudiantes-nota.php`) y «Ejercicios 3 y 3B» (insertar, exportar y restaurar en otro servidor). Duración: unos 10 minutos para crear la máquina (el script lo hace todo) más 15-20 minutos para el ejercicio 3. Coste: una máquina `t3.small` (céntimos por hora; se apaga sola a las 4 horas); la RDS MySQL del ejercicio 3B, si la haces con RDS, factura por hora mientras exista (con `--servidor-mysql` no cuesta nada más). > **¿Dudas con un script?** Todos los scripts de esta carpeta traen su propia ayuda: `./gestionar-webapp.sh --ayuda` (también vale `--help` o `-h`) explica los pasos y las opciones. Este `README.md` es el paso a paso de la actividad: tenlo a mano y consúltalo antes de preguntar. > **Etiquetas de lo que creas.** `./gestionar-webapp.sh crear` etiqueta la máquina, su disco, el Security Group y el bucket temporal con `curso` = `G214`, `universidad` = `CUNEF`, `actividad` = `03.04-webappexportar` y `script` = `gestionar-webapp.sh`. Lo que crees a mano (la segunda RDS del 3B, si la haces) etiquétalo con las tres primeras. Si hiciera falta borrar a mano, todo se localiza con `aws resourcegroupstaggingapi get-resources --region eu-north-1 --tag-filters Key=actividad,Values=03.04-webappexportar`. Más detalle (cómo etiquetar con la CLI, cómo buscar y qué hacer en una emergencia): [README principal](../../README.md), sección «Etiquetas». ## Qué vas a hacer Vas a ejecutar, en **una máquina EC2 propia** que crea un script (sin instalar nada en tu PC y sin copiar ni pegar ficheros), una pequeña web en PHP que se conecta a tu RDS y hace altas, cambios y bajas sobre la tabla `estudiantes`. Después, con esa web y con Adminer, harás el ejercicio 3: insertar alumnos, **exportar** la base a un `.sql` y **restaurarla** en un servidor MySQL distinto (ejercicio 3B). ``` Tu navegador ──http://IP/estudiantes.php──> EC2 «webapp» (Apache + PHP) ──puerto 3306──> tu RDS (base universidad) Adminer: Export (estudiantes.sql) ──Import──> segundo servidor MySQL (RDS MySQL, o MySQL en la propia EC2 «webapp») ``` **Qué se crea en AWS:** una EC2 `webapp` (Amazon Linux 2023, `t3.small`), un Security Group (puertos 22 y 80) y un bucket temporal con los ficheros de la actividad (el script lo borra con `eliminar`). Con `--rds` se añade la regla que deja a la máquina llegar a tu RDS. Todo lleva las etiquetas del curso y **se apaga solo a las 4 horas** (se para, no se borra: volver a ejecutar `crear` la arranca y renueva el plazo). Esta actividad es independiente de la [03.05](../03.05-paiseseuribor/README.md), que crea su propia máquina. ## Qué contiene esta carpeta | Fichero | Para qué sirve | En qué paso se usa | |---|---|---| | `gestionar-webapp.sh` | Script único: crea la EC2 con la web PHP (`index.php`, `estudiantes.php`, `estudiantes-nota.php`), con los ficheros ya dentro (no hay que copiar ni pegar nada), la apaga sola, la consulta y la borra | Pasos 1 y 9 | | `index.php` | Página de inicio de la máquina: dos botones, uno a cada versión de la web (y a Adminer del 3B si usaste `--servidor-mysql`). Copia de referencia del que lleva el script | Paso 2 | | `estudiantes.php` | CRUD sobre `estudiantes` (id, nombre, apellidos, grupo, nº de convocatoria, derecho a examen). Copia de referencia del que lleva el script (`./gestionar-webapp.sh extraer` los escribe) | Pasos 2 y 3 | | `estudiantes-nota.php` | La misma web con una columna más, `nota` (0 a 10, con valor por defecto 5). Es la versión de la presentación | Paso 4 | | `ejercicios.txt` | Las comprobaciones del ejercicio 3 y el `CREATE DATABASE` del servidor de destino del 3B | Pasos 5 a 8 | | `README.md` | Esta guía | Siempre | ## Antes de empezar - [ ] La base `universidad` cargada con `tema3_estudiantes.sql` en tu RDS ([03.03](../03.03-sqlestudiantes/README.md)) y hechos los ejercicios 1 y 2 de esa actividad (para que las cifras del ejercicio 3 cuadren). - [ ] Tu RDS es **MariaDB 10.11** (no la 11.x): esta web no cifra la conexión y las MariaDB 11.x la exigen ([03.01](../03.01-RDSMariaDB.md)). - [ ] El **nombre (DB identifier)** de tu RDS, tal como sale en la consola de RDS: se lo das al script con `--rds`. No hace falta que la RDS sea pública ni abrir su Security Group a tu IP: el script deja pasar solo a la máquina de la web (de Security Group a Security Group). - [ ] CloudShell abierto con la región **eu-north-1 (Estocolmo)**. No hay variables de entorno que configurar: host, usuario y contraseña se escriben en el formulario de la propia web. - [ ] Adminer funcionando ([03.02](../03.02-adminer/README.md)) para la parte de exportar e importar. ## Cómo llevar los ficheros a donde toque Todo se hace desde **CloudShell** (la web corre en la EC2, no en tu PC). En tu PC comprime la carpeta `03.04-webappexportar` (clic derecho > *Comprimir en ZIP*), en CloudShell usa **Actions > Upload file** y descomprime: ```bash unzip -o 03.04-webappexportar.zip cd 03.04-webappexportar chmod -R u+rwX . && chmod +x gestionar-webapp.sh ./gestionar-webapp.sh --ayuda ``` > Si ya subiste `g214-materiales.zip` (README principal), no necesitas este zip: entra con `cd ~/g214-materiales/tema3/03.04-webappexportar` y, si algún fichero da `Permission denied`, ejecuta allí `chmod -R u+rwX . && chmod +x *.sh`. No hay que llevar `estudiantes.php` ni ningún otro fichero a la máquina: el script los lleva dentro y se los entrega solo. Los ficheros `.sql` que exportes con Adminer se guardan en tu PC. ## Paso a paso **Paso 1. Crear la máquina de la web.** En CloudShell, dentro de esta carpeta (con el nombre de **tu** RDS): ```bash ./gestionar-webapp.sh crear --rds nombre-de-tu-rds --servidor-mysql ``` `--servidor-mysql` instala además un MySQL en la misma máquina, que usarás como «segundo servidor» del ejercicio 3B (paso 7, opción B). Si vas a hacer el 3B con una segunda RDS, puedes omitirlo. Qué verás: el Security Group creado, los ficheros subidos al bucket temporal, la máquina lanzada, `Apagado automático: se apagará a las HH:MM UTC (dentro de 4 h 0 min)`, el aviso `Tu máquina ya puede conectar con la RDS ...` y, al final, un recuadro **Tu web de estudiantes** con las direcciones (la página de inicio `http://IP/`, `http://IP/estudiantes.php` y `http://IP/estudiantes-nota.php`) y, con `--servidor-mysql`, la dirección de su Adminer y la contraseña de `root`. Tarda unos 3 minutos; el MySQL, si lo pediste, puede tardar 1-3 minutos más en responder (`./gestionar-webapp.sh estado` te dice si ya responden). Es seguro repetir el comando: lo que ya existe se reutiliza. **Paso 2. Abrir la web y conectar.** Abre `http://IP/` (la IP del recuadro): verás dos botones, **Estudiantes** y **Estudiantes con nota**. Pulsa el primero (`http://IP/estudiantes.php`). 1. Formulario `Conectar a MySQL`: **Host** = el endpoint de tu RDS, **Base de datos** = `universidad` (ya viene rellenada), **Usuario** = `admin`, **Contraseña** = la tuya. Pulsa **Guardar conexión**. 2. La página se recarga con la tarjeta `Conexión activa` (host, base y usuario) y, debajo, `Añadir estudiante` y `Listado de estudiantes` con los registros de tu tabla. Campos del alta: nombre, apellidos, grupo (A, B o C), nº de convocatoria (1 a 3) y la casilla `Derecho a examen`. Cada fila del listado tiene **Guardar** y **Eliminar**. 3. Si la tabla `estudiantes` no existe, verás `La tabla no existe todavía`; el botón `Crear/verificar tabla "estudiantes"` la crea, pero lo normal es haber cargado antes `tema3_estudiantes.sql`. 4. Las credenciales se guardan en cookies del navegador durante 7 días. **Cambiar conexión** las borra. Es un ejemplo de docencia: la web va por HTTP, no metas credenciales que no sean de prueba. 5. Si la conexión falla, sale un aviso rojo `Error de conexión: ...` con el motivo y no aparecen ni el alta ni el listado: pulsa **Cambiar conexión** y revisa los datos (ver «Errores frecuentes»). **Paso 3. Probar altas, cambios y bajas** desde la web (esto prepara el ejercicio 3, paso 5). **Paso 4. `estudiantes-nota.php`.** Es la misma web con la columna `nota`. Abre `http://IP/estudiantes-nota.php`. Necesita que la tabla `estudiantes` tenga esa columna: ejecuta antes en Adminer el `ALTER` de la presentación (o el bloque `Columna nota` de [03.03](../03.03-sqlestudiantes/README.md)), o pulsa el botón `Crear/verificar tabla "estudiantes"` dentro de `estudiantes-nota.php`, que intenta añadirla. Sin la columna, el listado y las altas y modificaciones de esa versión fallan. Este es el ejemplo de la presentación: si cambia la base de datos, hay que actualizar las aplicaciones que la consumen. Respuesta de referencia a «¿qué ventajas y desventajas ves?»: ventaja, una interfaz a medida para usuarios que no saben SQL (alta, baja y edición con botones); desventaja, está atada al esquema: si cambia (por ejemplo, la columna `nota`), `estudiantes.php` no la muestra y `estudiantes-nota.php` falla en una tabla que no la tiene hasta que se actualice la aplicación. **Paso 5. Ejercicio 3: insertar.** Este ejercicio se hace desde la interfaz (la web `estudiantes.php` y Adminer): inserta los dos alumnos nuevos que pide la presentación (para que las cifras de abajo cuadren, ponlos en el grupo A). Comprobación (en Adminer, **SQL command**; viene en `ejercicios.txt`): ```sql USE universidad; SELECT COUNT(*) FROM estudiantes; SELECT grupo, COUNT(*) AS alumnos FROM estudiantes GROUP BY grupo; ``` Qué verás: tras los ejercicios anteriores la tabla tiene **50 filas** (A 14, B 13, C 23, si los dos alumnos nuevos son del grupo A; sin el id 2, id más alto 51, o 52 si antes ejecutaste el bloque `nota` con `ROLLBACK` (el `INSERT` deshecho gasta el id 50), y Ana con `derecho_a_examen` vacío). **Paso 6. Exportar desde Adminer (ejercicio 3).** En Adminer, con la base `universidad` elegida: **Export** > *Output* `save`, *Format* `SQL`, marca *Table* y *Data* > **Export**. El *Output* por defecto es `open` (se muestra en pantalla, no se descarga). Se descarga `estudiantes.sql` (el nombre de la tabla; si exportas varias tablas, el nombre de la base), con `DROP TABLE IF EXISTS`, `CREATE TABLE` y los `INSERT`, y **sin** `CREATE DATABASE` ni `USE`. Por eso, en el servidor de destino hay que crear la base vacía y elegirla **antes** de importar (paso 8). **Paso 7. Ejercicio 3B: el segundo servidor.** Hay dos formas; las dos sirven para el objetivo del ejercicio (restaurar el `.sql` en un servidor distinto). *Opción A: segunda RDS MySQL.* Se crea como la primera ([03.01](../03.01-RDSMariaDB.md)): MySQL 8.x, `db.t3.micro`, gp3 de 20 GiB, sin Multi-AZ, acceso público y el Security Group `BaseDeDatos` (en la misma VPC). Etiquétala con `curso`, `universidad` y `actividad` y bórrala al terminar. **Si AWS no te deja crear la segunda RDS.** Con una cuenta del plan gratuito, `create-db-instance` o la consola responden `InstanceQuotaExceeded: You reached the maximum number of instances available with free plan accounts` cuando la cuenta ya tiene cierto número de instancias: es un límite del plan gratuito, no de la API. El número exacto depende de tu cuenta y de lo que ya tengas creado (se ha visto con dos instancias en la cuenta, una propia y otra ajena): si solo tienes la MariaDB, prueba primero a crear la de MySQL. Si da el error, tienes dos salidas: 1. **Borrar antes la RDS MariaDB.** Ya tienes `estudiantes.sql` exportado en tu PC: borra la MariaDB (limpieza de [03.01](../03.01-RDSMariaDB.md); los datos se pierden, pero el `.sql` los conserva), crea la RDS MySQL y restaura en ella. Después, para seguir con el resto del tema, vuelve a crear la MariaDB y recarga `tema3_estudiantes.sql`. 2. **La opción B** (sin RDS y sin coste añadido). *Opción B: MySQL en la propia máquina de la web (recomendada si no puedes crear otra RDS).* Es el MySQL que instaló `--servidor-mysql` en el paso 1. Abre `http://IP/adminer-3b.php` (también está enlazado en la página de inicio `http://IP/`) y entra con **Servidor** `localhost`, **Usuario** `root` y la contraseña que mostró `crear` (queda guardada en el fichero `.gestionar-webapp.mysql` de tu carpeta de CloudShell: `cat .gestionar-webapp.mysql`). Si creaste la máquina sin esa opción, bórrala y créala otra vez (tu RDS no se toca): ```bash ./gestionar-webapp.sh eliminar ./gestionar-webapp.sh crear --rds nombre-de-tu-rds --servidor-mysql ``` **Paso 8. Restaurar en el segundo servidor.** Crea la base vacía y elígela ANTES de importar (viene en `ejercicios.txt`): ```sql CREATE DATABASE IF NOT EXISTS universidad; USE universidad; ``` Después: **Import** > `estudiantes.sql` > **Execute**, y comprueba `SELECT COUNT(*) FROM estudiantes;`. En la opción A usa tu Adminer de [03.02](../03.02-adminer/README.md) con el endpoint de la nueva RDS; en la B, el Adminer de la propia máquina (`adminer-3b.php`). Qué verás: **50 filas**, A 14 / B 13 / C 23: el destino debe dar lo mismo que el origen. El mismo `.sql` de MariaDB 10.11 entra en MySQL 8 sin cambios (puede salir un aviso por el alias `utf8`). **Paso 9. Limpieza.** Al terminar esta actividad: ```bash ./gestionar-webapp.sh eliminar ``` Borra la máquina, su disco, el Security Group, la regla que le daba acceso a tu RDS, el bucket temporal y la contraseña guardada del MySQL local. Es repetible: si algo falla, vuelve a ejecutarlo. Si hiciste la opción A, borra además la segunda RDS (limpieza de [03.01](../03.01-RDSMariaDB.md)). ## Errores frecuentes | Síntoma | Causa | Solución | |---|---|---| | La página no carga (se queda esperando) | La máquina aún está instalando, está apagada, o tu red bloquea el acceso por IP directa o por puertos distintos del 80 | `./gestionar-webapp.sh estado` (si está parada, `crear` la arranca); espera 2-3 minutos tras crear; prueba desde otra red (por ejemplo, el móvil como punto de acceso) | | `http://IP/estudiantes.php` da 404 | La máquina arrancó pero no descargó los ficheros (fallo raro de red al crearla) | `./gestionar-webapp.sh eliminar` y vuelve a crear | | El script dice `No encuentro la RDS` | El nombre de `--rds` no coincide con el *DB identifier* de la consola de RDS | Cópialo tal cual de la consola de RDS (columna *DB identifier*) | | `Error de conexión` con tiempo agotado | No diste `--rds` (la máquina no puede llegar a la RDS) o el endpoint está mal | `./gestionar-webapp.sh crear --rds NOMBRE` (añade el acceso sin crear nada duplicado) y revisa el endpoint | | `SQLSTATE[HY000] [3159] Connections using insecure transport are prohibited while --require_secure_transport=ON` | Tu RDS es MariaDB 11.x, que exige cifrado, y la web PHP se conecta sin cifrar | Crea la RDS con MariaDB 10.11 ([03.01](../03.01-RDSMariaDB.md)). Adminer y el visor del Euribor sí funcionan con la 11.x | | `SQLSTATE[HY000] [1045] Access denied for user 'admin'` aunque la contraseña sea correcta | Tu RDS exige conexión cifrada (MariaDB 11.x, o `require_secure_transport=1`): en una 10.11 con TLS obligatorio el síntoma es este y no el `[3159]` | Crea la RDS con MariaDB 10.11 ([03.01](../03.01-RDSMariaDB.md)) | | `Error de conexión` de acceso denegado | Usuario o contraseña incorrectos | Pulsa **Cambiar conexión** y reintenta | | `Error de conexión` de base de datos desconocida | La base `universidad` no existe en tu RDS | Carga antes `tema3_estudiantes.sql` ([03.03](../03.03-sqlestudiantes/README.md)) o escribe el nombre correcto | | `estudiantes-nota.php` falla al listar o al guardar | La tabla no tiene la columna `nota` | `ALTER` de la presentación o el botón `Crear/verificar tabla "estudiantes"` | | El export de Adminer no descarga nada, solo muestra el SQL en pantalla | *Output* está en `open` | Cambia *Output* a `save` | | Al importar en el destino: error de base de datos no elegida | El `.sql` exportado no lleva `CREATE DATABASE` ni `USE` | Crea la base y elígela antes (paso 8) | | `InstanceQuotaExceeded: You reached the maximum number of instances available with free plan accounts` al crear la segunda RDS | Límite del plan gratuito de AWS | Borra antes la RDS MariaDB o usa la opción B (paso 7) | | `crear` dice que la máquina «ya existe y se creó sin el servidor MySQL» | Pediste `--servidor-mysql` con una máquina creada sin esa opción (el MySQL solo se instala al crearla) | `./gestionar-webapp.sh eliminar` y `./gestionar-webapp.sh crear --rds NOMBRE --servidor-mysql` | ## Cómo sabes que has terminado - [ ] `estudiantes.php` conecta con tu RDS y muestra el listado de `estudiantes`; has probado alta, cambio y baja. - [ ] Has visto `estudiantes-nota.php` con la columna `nota` y sabes por qué falla sin ella. - [ ] Tras el ejercicio 3, `universidad.estudiantes` tiene 50 filas (A 14, B 13, C 23). - [ ] Has exportado `estudiantes.sql` y lo has restaurado en un segundo servidor (RDS MySQL o MySQL en tu máquina) con las mismas 50 filas. - [ ] Has ejecutado `./gestionar-webapp.sh eliminar` (y borrado la segunda RDS, si la creaste) y `./gestionar-webapp.sh estado` dice que no queda nada. La RDS MariaDB y Adminer **no** se borran aquí: se borran al final del tema (Adminer en [03.02](../03.02-adminer/README.md), la RDS en [03.01](../03.01-RDSMariaDB.md), después de la actividad 03.09). Anterior: [03.03 · SQL con la tabla de estudiantes](../03.03-sqlestudiantes/README.md) · Siguiente: [03.05 · Ejercicios 4 y 5: países y Euribor](../03.05-paiseseuribor/README.md)