# Tema 2 · 2 · S3: versionado, URL firmada y sincronización Presentación del Tema 2: «Laboratorio almacenamiento de objetos - 2» y «Laboratorio de objetos 2 · paso a paso». Duración: unos 30 minutos. Coste: céntimos. > **¿Dudas con un script?** Todos los scripts de esta carpeta traen su propia ayuda: `./descargar-datos.sh --ayuda` · `python3 vaciar-bucket.py --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.** Todo recurso que crees a mano (máquina, volumen, bucket, base de datos, tabla, función...) ponle estas etiquetas, al crearlo (apartado *Tags* / *Etiquetas*) o después desde su pestaña de etiquetas: `curso` = `G214`, `universidad` = `CUNEF` y `actividad` = `02.02-s3versionadoysync`. Si algún día hay que borrar recursos a mano, se localizan todos de golpe con `aws resourcegroupstaggingapi get-resources --region eu-north-1 --tag-filters Key=actividad,Values=02.02-s3versionadoysync`. 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 Sobre el bucket de la carpeta anterior, practicar tres cosas que distinguen a S3 de un disco: el **versionado** (cada sobrescritura guarda la versión antigua), las **URL firmadas que caducan** (compartir sin abrir el bucket) y la **sincronización incremental** (`sync` solo sube lo que cambia). Terminas **vaciando un bucket con versiones**, que es más difícil de lo que parece. ## Qué se crea en AWS Nada nuevo: usas el bucket `g214-apellido-objetos` del [laboratorio 1](../02.01-s3primerbucket/README.md). Si lo borraste, créalo de nuevo y vuelve a subir `dataset.csv` (paso 1). ## Qué contiene esta carpeta | Fichero | Para qué sirve | Se usa en | |---|---|---| | `carpeta/` | Cinco ficheros pequeños (uno en `carpeta/sub/`) | Paso 5 (`aws s3 sync`) | | `descargar-datos.sh` | Descarga el padrón del INE (`dataset.csv`, 26 MB) con reintentos y validación; también `estado` y `eliminar` | Paso 1, solo si ya no lo tienes | | `vaciar-bucket.py` | Borra **todas** las versiones, los *delete markers* y las subidas multiparte a medias de un bucket y, si quieres, el bucket. Solo necesita Python 3 y la CLI | Paso 7 | ## Antes de empezar - [ ] Has hecho [`02.01-s3primerbucket`](../02.01-s3primerbucket/README.md) y conservas el bucket con `dataset.csv`. - [ ] CloudShell abierto en **eu-north-1** (o Git Bash con la CLI y un usuario IAM; ver el README del 02.01). - [ ] Sube esta carpeta a CloudShell (*Actions → Upload file* con el zip de `02.02-s3versionadoysync`) y entra: ```bash unzip -o 02.02-s3versionadoysync.zip cd 02.02-s3versionadoysync chmod -R u+rwX . && chmod +x *.sh ``` > Si ya subiste `g214-materiales.zip` (README principal), no necesitas este zip: entra con `cd ~/g214-materiales/tema2/02.02-s3versionadoysync` y, si algún fichero da `Permission denied`, ejecuta allí `chmod -R u+rwX . && chmod +x *.sh`. Si en CloudShell ya tenías el `dataset.csv` del laboratorio 1 en otra carpeta, cópialo aquí; si no, descárgalo otra vez (paso 1). ## Paso a paso En los comandos, cambia `g214-apellido-objetos` por tu bucket. ### Paso 1 · Ten a mano el CSV original ```bash ./descargar-datos.sh padron # solo si no conservas dataset.csv ``` ### Paso 2 · Activa el versionado y sube dos versiones ```bash aws s3api put-bucket-versioning --bucket g214-apellido-objetos --versioning-configuration Status=Enabled mv dataset.csv dataset_ine.csv # guarda el original: vas a sobrescribir dataset.csv con textos pequeños echo "version,uno" > dataset.csv ; aws s3 cp dataset.csv s3://g214-apellido-objetos/ --content-type text/csv echo "version,dos,distinto" > dataset.csv ; aws s3 cp dataset.csv s3://g214-apellido-objetos/ --content-type text/csv aws s3api list-object-versions --bucket g214-apellido-objetos --prefix dataset.csv ``` **Qué verás:** **tres versiones, no dos**. El `dataset.csv` del laboratorio 1 se subió antes de activar el versionado y conserva `VersionId: null`; las dos subidas nuevas son las otras dos. Solo la última lleva `IsLatest: true`. Cada versión ocupa y factura por separado. ### Paso 3 · Recupera la versión anterior Por consola: abre el objeto, pestaña **Versions** (o, en la pestaña *Objects*, el interruptor **Show versions**) y descarga la anterior. Por CLI, con el `VersionId` de la versión antigua: ```bash aws s3api get-object --bucket g214-apellido-objetos --key dataset.csv --version-id anterior.csv cat anterior.csv ``` **Qué verás:** el contenido de esa versión (`version,uno` si elegiste la primera de las nuevas). ### Paso 4 · Comparte con una URL que caduca ```bash aws s3 presign s3://g214-apellido-objetos/dataset.csv --expires-in 300 ``` Ábrela en el navegador y **repite pasados 5 minutos**. **Qué verás:** a los 5 minutos, `AccessDenied` / `Request has expired`: la firma caduca y el bucket sigue privado. Una URL firmada generada **antes** de subir versiones nuevas sigue sirviendo la **versión más reciente**: la firma identifica la clave, no una versión concreta. ### Paso 5 · Sincroniza una carpeta dos veces Usa un **prefijo nuevo** (`sync/`). Sobre `lote/` la primera ejecución no transferiría nada, porque ya lo llenó `cp --recursive` en el laboratorio 1. **Antes, una vez:** los ficheros de un zip creado en Windows pueden aparecer en CloudShell con una fecha **posterior a la actual** (el zip no guarda la zona horaria). `sync` compara fechas y, si cree que el fichero local es más nuevo, lo vuelve a subir siempre. Ponles la fecha de ahora: ```bash find carpeta -type f -exec touch {} + ``` Ahora sí: ```bash aws s3 sync ./carpeta s3://g214-apellido-objetos/sync/ # imprime 5 líneas "upload: ..." aws s3 sync ./carpeta s3://g214-apellido-objetos/sync/ # NO imprime nada: no hay nada que transferir echo $? # 0: terminó bien touch carpeta/parte1.csv # cambia la fecha de un fichero aws s3 sync ./carpeta s3://g214-apellido-objetos/sync/ # sube solo parte1.csv ``` **Qué verás:** la segunda ejecución no imprime nada (`sync` compara tamaño y fecha) y `echo $?` da `0`. Tras el `touch`, solo sube `parte1.csv`. ### Paso 6 · Mide lo que ocupa ```bash aws s3 ls s3://g214-apellido-objetos --recursive --summarize --human-readable ``` **Qué verás:** `ls --recursive --summarize` **solo cuenta las versiones actuales**: oculta los 26,1 MiB de la versión `null`. Las versiones no actuales se ven con `list-object-versions` y pesan en *Metrics* y en la factura. ### Paso 7 · Borra el bucket con versiones (importante) `aws s3 rb s3://bucket --force` **falla** con `BucketNotEmpty ... You must delete all versions in the bucket` y, antes de fallar, añade un delete marker por cada objeto. Se hace así: o desde la consola (*Show versions* → seleccionar todo → *Delete*), o con el script de esta carpeta: ```bash python3 vaciar-bucket.py g214-apellido-objetos --borrar # pide que escribas el nombre del bucket ``` **Qué verás:** el script te pide confirmación (comprueba bien el nombre del bucket: es **irreversible**, no hay papelera) y borra todas las versiones, todos los delete markers y, con `--borrar`, el bucket. Comprueba con `aws s3 ls | grep g214` (no debe salir ningún bucket tuyo). Otras opciones (probadas en AWS real; con `--borrar` sobre un bucket que ya no existe termina bien: es repetible): `--si` (o `-y`) no pregunta, y es obligatoria si no hay terminal; `--estado` solo cuenta las versiones y no borra nada; `--region R` si el bucket no está en eu-north-1; `--ayuda`. Reintenta solo ante errores pasajeros de red, y si lo cortas con Ctrl+C puedes repetirlo: continúa donde lo dejó. ## Errores frecuentes | Qué ves | Causa | Solución | |---|---|---| | `sync` no imprime nada | No hay nada que transferir (es lo normal en la segunda ejecución) | Comprueba con `echo $?` (0) y cambia un fichero para ver que sube | | `sync` vuelve a subir los 5 ficheros en la segunda ejecución | Los ficheros del zip tienen fecha futura (ver el paso 5) | `find carpeta -type f -exec touch {} +` y repite | | `rb --force` termina con `BucketNotEmpty` | Hay versiones o delete markers | `python3 vaciar-bucket.py BUCKET --borrar` | | Solo ves dos versiones | El `dataset.csv` anterior no se subió, o lo subiste con otro nombre | Es normal si empezaste con un bucket nuevo: la versión `null` solo existe si había un objeto antes de activar el versionado | | `Unable to locate credentials` | Terminal sin credenciales | Usa CloudShell | ## Cómo sabes que has terminado - [ ] Has visto **tres versiones** de `dataset.csv` y recuperado la anterior con `get-object --version-id`. - [ ] La URL firmada funcionó antes de 5 minutos y falló después. - [ ] Sabes explicar por qué la segunda ejecución de `sync` no imprime nada y por qué `ls --summarize` no cuenta las versiones antiguas. - [ ] El bucket está borrado (`aws s3 ls | grep g214` no muestra nada tuyo). Anterior: [`02.01-s3primerbucket`](../02.01-s3primerbucket/README.md) · Siguiente: [`02.03-EBSWindowsFormatearDisco.md`](../02.03-EBSWindowsFormatearDisco.md)