docs: CLAUDE.md actualizado con fn run, tipos Go en functions/, bash functions
Documentación de fn run para todos los lenguajes, nueva ubicación de tipos Go, sección de uso por agentes. Añadidas funciones Bash del registry (shell, infra, core, pipelines). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: assert_docker_container_running
|
||||
kind: function
|
||||
lang: bash
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "assert_docker_container_running(container_name: string) -> void"
|
||||
description: "Verifica que un contenedor Docker está corriendo. Sale con exit code 1 si no está activo, con mensaje a stderr."
|
||||
tags: [assert, docker, container, running, validation, infra, bash]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "bash/functions/infra/assert_docker_container_running.sh"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```bash
|
||||
source functions/infra/assert_docker_container_running.sh
|
||||
|
||||
assert_docker_container_running metabase
|
||||
echo "Contenedor activo, continuando..."
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
Usa `docker ps --format '{{.Names}}'` con grep anclado (`^name$`) para evitar matches parciales (ej: "metabase" no matchea "metabase-test").
|
||||
|
||||
Output limpio: void en éxito. El mensaje de error en stderr no incluye lista de contenedores activos — eso es responsabilidad del pipeline/caller.
|
||||
|
||||
Requiere que `docker` esté en PATH. Combinar con `assert_command_exists` antes de llamar.
|
||||
@@ -0,0 +1,19 @@
|
||||
# assert_docker_container_running
|
||||
# --------------------------------
|
||||
# Verifica que un contenedor Docker está corriendo.
|
||||
# No produce output a stdout en caso de éxito.
|
||||
# Sale con exit code 1 si el contenedor no está corriendo,
|
||||
# con mensaje descriptivo a stderr.
|
||||
#
|
||||
# USO (sourced):
|
||||
# source assert_docker_container_running.sh
|
||||
# assert_docker_container_running metabase
|
||||
|
||||
assert_docker_container_running() {
|
||||
local container_name="$1"
|
||||
|
||||
if ! docker ps --format '{{.Names}}' | grep -q "^${container_name}$"; then
|
||||
echo "assert_docker_container_running: el contenedor '$container_name' no está corriendo" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
name: docker_cp_file
|
||||
kind: function
|
||||
lang: bash
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "docker_cp_file(local_path: string, container_name: string, dest_path: string) -> string"
|
||||
description: "Copia un archivo local a un contenedor Docker y verifica que el tamaño coincide. Imprime JSON con local_size y remote_size a stdout. Sale con exit code 1 si docker cp falla o los tamaños difieren."
|
||||
tags: [docker, cp, copy, file, container, transfer, infra, bash]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "bash/functions/infra/docker_cp_file.sh"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```bash
|
||||
source functions/infra/docker_cp_file.sh
|
||||
|
||||
result=$(docker_cp_file /home/lucas/fn_registry/registry.db metabase /registry.db)
|
||||
echo "$result"
|
||||
# {"local_size":524288,"remote_size":524288}
|
||||
|
||||
local_size=$(echo "$result" | grep -o '"local_size":[0-9]*' | cut -d: -f2)
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
La verificación de tamaño usa `docker exec stat -c%s` sobre el contenedor destino. Si `stat` no está disponible en el contenedor, `remote_size` será -1 y la función fallará.
|
||||
|
||||
Output a stdout: JSON minificado con campos `local_size` y `remote_size` (enteros, bytes).
|
||||
|
||||
Usa `printf` en lugar de `echo` para garantizar que no haya newline extra en el JSON.
|
||||
@@ -0,0 +1,33 @@
|
||||
# docker_cp_file
|
||||
# --------------
|
||||
# Copia un archivo local a un contenedor Docker y verifica que el tamaño coincide.
|
||||
# Imprime JSON con local_size y remote_size a stdout si la copia es exitosa.
|
||||
# Sale con exit code 1 si docker cp falla o si los tamaños no coinciden.
|
||||
#
|
||||
# USO (sourced):
|
||||
# source docker_cp_file.sh
|
||||
# result=$(docker_cp_file /ruta/local.db metabase /dest/path.db)
|
||||
|
||||
docker_cp_file() {
|
||||
local local_path="$1"
|
||||
local container_name="$2"
|
||||
local dest_path="$3"
|
||||
|
||||
if ! docker cp "$local_path" "${container_name}:${dest_path}" 2>/dev/null; then
|
||||
echo "docker_cp_file: fallo al copiar '$local_path' a '${container_name}:${dest_path}'" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local local_size
|
||||
local_size=$(stat -c%s "$local_path")
|
||||
|
||||
local remote_size
|
||||
remote_size=$(docker exec "$container_name" stat -c%s "$dest_path" 2>/dev/null || echo "-1")
|
||||
|
||||
if [ "$local_size" != "$remote_size" ]; then
|
||||
echo "docker_cp_file: tamaños no coinciden (local=${local_size}, remoto=${remote_size})" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf '{"local_size":%s,"remote_size":%s}' "$local_size" "$remote_size"
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
name: setup_metabase_volume
|
||||
kind: pipeline
|
||||
lang: bash
|
||||
domain: pipelines
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "setup_metabase_volume([registry_db_path: string], [container_name: string], [dest_path: string]) -> void"
|
||||
description: "Copia registry.db al contenedor Docker de Metabase verificando existencia del archivo, disponibilidad de docker, estado del contenedor y coincidencia de tamaños. Todos los argumentos son opcionales con defaults razonables."
|
||||
tags: [metabase, docker, setup, launcher, pipeline, bash, infra]
|
||||
uses_functions:
|
||||
- assert_file_exists_bash_shell
|
||||
- assert_command_exists_bash_shell
|
||||
- assert_docker_container_running_bash_infra
|
||||
- docker_cp_file_bash_infra
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "bash/functions/pipelines/setup_metabase_volume.sh"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```bash
|
||||
# Con defaults
|
||||
./functions/pipelines/setup_metabase_volume.sh
|
||||
|
||||
# Con argumentos explícitos
|
||||
./functions/pipelines/setup_metabase_volume.sh \
|
||||
/home/lucas/fn_registry/registry.db \
|
||||
metabase \
|
||||
/registry.db
|
||||
```
|
||||
|
||||
## Flujo
|
||||
|
||||
1. `assert_file_exists` — verifica que `registry.db` existe localmente y obtiene su tamaño
|
||||
2. `assert_command_exists` — verifica que `docker` está disponible en PATH
|
||||
3. `assert_docker_container_running` — verifica que el contenedor destino está activo; si falla, muestra lista de contenedores activos
|
||||
4. `docker_cp_file` — ejecuta `docker cp` y verifica que los tamaños local y remoto coinciden
|
||||
|
||||
## Notas
|
||||
|
||||
El pipeline usa `set -euo pipefail` — cualquier fallo en una función individual detiene la ejecución.
|
||||
|
||||
Las funciones individuales se sourcean desde sus rutas en el registry, relativas a `REGISTRY_ROOT` detectado automáticamente desde la ubicación del script.
|
||||
|
||||
Defaults:
|
||||
- `REGISTRY_DB_PATH`: `/home/lucas/fn_registry/registry.db`
|
||||
- `CONTAINER_NAME`: `metabase`
|
||||
- `DEST_PATH`: `/registry.db`
|
||||
|
||||
Nota de persistencia: `docker cp` copia al contenedor en ejecución. Si el contenedor se reinicia, el archivo se pierde. Para persistencia real, montar el directorio como volumen en docker-compose:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- /home/lucas/fn_registry:/fn_registry:ro
|
||||
```
|
||||
|
||||
Y usar `--registry-db-path /fn_registry/registry.db`.
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env bash
|
||||
# setup_metabase_volume
|
||||
# ---------------------
|
||||
# Copia registry.db al contenedor Docker de Metabase.
|
||||
# Compone: assert_file_exists + assert_command_exists +
|
||||
# assert_docker_container_running + docker_cp_file
|
||||
#
|
||||
# USO:
|
||||
# ./setup_metabase_volume.sh [REGISTRY_DB_PATH] [CONTAINER_NAME] [DEST_PATH]
|
||||
#
|
||||
# ARGUMENTOS (opcionales, con defaults):
|
||||
# REGISTRY_DB_PATH Ruta local al registry.db
|
||||
# Default: /home/lucas/fn_registry/registry.db
|
||||
# CONTAINER_NAME Nombre del contenedor Docker de Metabase
|
||||
# Default: metabase
|
||||
# DEST_PATH Ruta destino dentro del contenedor
|
||||
# Default: /registry.db
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REGISTRY_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||
|
||||
source "$REGISTRY_ROOT/bash/functions/shell/assert_file_exists.sh"
|
||||
source "$REGISTRY_ROOT/bash/functions/shell/assert_command_exists.sh"
|
||||
source "$REGISTRY_ROOT/bash/functions/infra/assert_docker_container_running.sh"
|
||||
source "$REGISTRY_ROOT/bash/functions/infra/docker_cp_file.sh"
|
||||
|
||||
REGISTRY_DB_PATH="${1:-/home/lucas/fn_registry/registry.db}"
|
||||
CONTAINER_NAME="${2:-metabase}"
|
||||
DEST_PATH="${3:-/registry.db}"
|
||||
|
||||
echo "[setup_metabase_volume] Configuracion:"
|
||||
echo " registry.db local : $REGISTRY_DB_PATH"
|
||||
echo " contenedor Docker : $CONTAINER_NAME"
|
||||
echo " ruta en contenedor : $DEST_PATH"
|
||||
echo ""
|
||||
|
||||
# 1. Verificar archivo local
|
||||
local_size=$(assert_file_exists "$REGISTRY_DB_PATH")
|
||||
echo "[setup_metabase_volume] Archivo local encontrado: ${local_size} bytes"
|
||||
|
||||
# 2. Verificar que docker esta disponible
|
||||
assert_command_exists docker
|
||||
echo "[setup_metabase_volume] docker disponible en PATH."
|
||||
|
||||
# 3. Verificar que el contenedor esta corriendo
|
||||
if ! assert_docker_container_running "$CONTAINER_NAME"; then
|
||||
echo "" >&2
|
||||
echo "Contenedores activos:" >&2
|
||||
docker ps --format " {{.Names}}\t{{.Status}}\t{{.Image}}" >&2
|
||||
echo "" >&2
|
||||
echo "Si el contenedor se llama diferente, pasa el nombre como segundo argumento:" >&2
|
||||
echo " ./setup_metabase_volume.sh $REGISTRY_DB_PATH <nombre_contenedor>" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "[setup_metabase_volume] Contenedor '$CONTAINER_NAME' encontrado y activo."
|
||||
|
||||
# 4. Copiar archivo y verificar tamaños
|
||||
echo "[setup_metabase_volume] Copiando $REGISTRY_DB_PATH -> ${CONTAINER_NAME}:${DEST_PATH} ..."
|
||||
result=$(docker_cp_file "$REGISTRY_DB_PATH" "$CONTAINER_NAME" "$DEST_PATH")
|
||||
|
||||
remote_size=$(echo "$result" | grep -o '"remote_size":[0-9]*' | cut -d: -f2)
|
||||
echo "[setup_metabase_volume] OK Copia completada y verificada."
|
||||
echo "[setup_metabase_volume] Tamanio: ${local_size} bytes (local) = ${remote_size} bytes (remoto)"
|
||||
|
||||
echo ""
|
||||
echo "---------------------------------------------------------------------"
|
||||
echo "registry.db disponible en el contenedor como: $DEST_PATH"
|
||||
echo ""
|
||||
echo "Ahora ejecuta main.py con:"
|
||||
echo ""
|
||||
echo " METABASE_ADMIN_PASSWORD=<password> \\"
|
||||
echo " REGISTRY_DB_PATH=${DEST_PATH} \\"
|
||||
echo " python apps/metabase_registry/main.py"
|
||||
echo ""
|
||||
echo "O bien:"
|
||||
echo ""
|
||||
echo " python apps/metabase_registry/main.py \\"
|
||||
echo " --admin-password <password> \\"
|
||||
echo " --registry-db-path ${DEST_PATH}"
|
||||
echo "---------------------------------------------------------------------"
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
name: assert_command_exists
|
||||
kind: function
|
||||
lang: bash
|
||||
domain: shell
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "assert_command_exists(command_name: string) -> void"
|
||||
description: "Verifica que un comando está disponible en el PATH. Sale con exit code 1 si no se encuentra, con mensaje a stderr."
|
||||
tags: [assert, command, exists, validation, shell, bash, path]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "bash/functions/shell/assert_command_exists.sh"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```bash
|
||||
source functions/shell/assert_command_exists.sh
|
||||
|
||||
assert_command_exists docker
|
||||
assert_command_exists jq
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
Usa `command -v` (POSIX) con redirección `&>/dev/null` para suprimir output. No produce nada a stdout en caso de éxito.
|
||||
|
||||
Output limpio: void en éxito, mensaje a stderr en fallo.
|
||||
@@ -0,0 +1,18 @@
|
||||
# assert_command_exists
|
||||
# ---------------------
|
||||
# Verifica que un comando está disponible en el PATH.
|
||||
# No produce output a stdout.
|
||||
# Sale con exit code 1 si el comando no se encuentra.
|
||||
#
|
||||
# USO (sourced):
|
||||
# source assert_command_exists.sh
|
||||
# assert_command_exists docker
|
||||
|
||||
assert_command_exists() {
|
||||
local command_name="$1"
|
||||
|
||||
if ! command -v "$command_name" &>/dev/null; then
|
||||
echo "assert_command_exists: comando no encontrado en PATH: $command_name" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: assert_file_exists
|
||||
kind: function
|
||||
lang: bash
|
||||
domain: shell
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "assert_file_exists(file_path: string) -> string"
|
||||
description: "Verifica que un archivo existe en el filesystem. Imprime su tamaño en bytes a stdout. Sale con exit code 1 si el archivo no existe."
|
||||
tags: [assert, file, exists, validation, shell, bash]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "bash/functions/shell/assert_file_exists.sh"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```bash
|
||||
source functions/shell/assert_file_exists.sh
|
||||
|
||||
size=$(assert_file_exists /home/lucas/fn_registry/registry.db)
|
||||
echo "Tamaño: $size bytes"
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
La función se sourcea, no se ejecuta directamente. Usa `stat -c%s` para obtener el tamaño en bytes (compatible con GNU coreutils / Linux).
|
||||
|
||||
Output limpio: solo el número de bytes a stdout. Los errores van a stderr.
|
||||
|
||||
No usa `set -e` internamente — el caller controla el flujo con el exit code de retorno.
|
||||
@@ -0,0 +1,20 @@
|
||||
# assert_file_exists
|
||||
# ------------------
|
||||
# Verifica que un archivo existe en el filesystem.
|
||||
# Imprime su tamaño en bytes a stdout.
|
||||
# Sale con exit code 1 si el archivo no existe.
|
||||
#
|
||||
# USO (sourced):
|
||||
# source assert_file_exists.sh
|
||||
# size=$(assert_file_exists /ruta/al/archivo)
|
||||
|
||||
assert_file_exists() {
|
||||
local file_path="$1"
|
||||
|
||||
if [ ! -f "$file_path" ]; then
|
||||
echo "assert_file_exists: archivo no encontrado: $file_path" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
stat -c%s "$file_path"
|
||||
}
|
||||
Reference in New Issue
Block a user