feat: metabase_setup Python, fix list_databases, volumen Docker en init_metabase
Nueva función metabase_setup para setup inicial via API. Fix list_databases que no extraía data del response wrapper. Pipeline init_metabase soporta --mb-volumes para montar SQLite como volumen con fix de permisos automático. Añadido .env a gitignore. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,13 +30,17 @@ file_path: "functions/pipelines/init_metabase/main.go"
|
||||
## Ejemplo
|
||||
|
||||
```bash
|
||||
# Básico
|
||||
go run functions/pipelines/init_metabase/main.go \
|
||||
--project analytics \
|
||||
--metabase-port 3000 \
|
||||
--pg-port 5432 \
|
||||
--pg-user metabase \
|
||||
--pg-password metabase \
|
||||
--pg-database metabase
|
||||
--pg-password metabase
|
||||
|
||||
# Con volume para registry.db (detecta cambios en vivo)
|
||||
go run functions/pipelines/init_metabase/main.go \
|
||||
--project fn_registry \
|
||||
--mb-volumes "/home/lucas/fn_registry/registry.db:/data/registry.db"
|
||||
```
|
||||
|
||||
Salida JSON:
|
||||
@@ -60,7 +64,8 @@ El pipeline orquesta 5 pasos secuenciales:
|
||||
2. **Pull** — descarga `postgres:16` y `metabase/metabase:latest`
|
||||
3. **Postgres** — inicia con volume persistente (named volume por defecto o bind mount con `--pg-volume`)
|
||||
4. **Health check** — retry exponencial (hasta ~34 min) con `pg_isready` dentro del contenedor
|
||||
5. **Metabase** — conecta a Postgres via red interna, expone en puerto configurable
|
||||
5. **Metabase** — conecta a Postgres via red interna, expone en puerto configurable. Con `--mb-volumes` monta volumes adicionales (ej: registry.db para SQLite)
|
||||
6. **Permisos** — ajusta ownership de directorios montados para el usuario `metabase` (UID 2000) dentro del contenedor
|
||||
|
||||
Reutiliza conceptualmente `docker_create_network`, `docker_pull_image`, `docker_run_container`, `docker_inspect_container` y `retry_with_backoff`, reimplementadas inline por ser un ejecutable independiente.
|
||||
|
||||
|
||||
@@ -28,7 +28,8 @@ func main() {
|
||||
pgUser := flag.String("pg-user", "metabase", "Usuario Postgres")
|
||||
pgPass := flag.String("pg-password", "metabase", "Password Postgres")
|
||||
pgDB := flag.String("pg-database", "metabase", "Base de datos Postgres")
|
||||
pgVolume := flag.String("pg-volume", "", "Path host para persistencia (default: docker named volume)")
|
||||
pgVolume := flag.String("pg-volume", "", "Path host para persistencia Postgres (default: docker named volume)")
|
||||
mbVolumes := flag.String("mb-volumes", "", "Volumes adicionales para Metabase, separados por coma (ej: /host/path:/container/path,/otro:/dest)")
|
||||
flag.Parse()
|
||||
|
||||
if *project == "" {
|
||||
@@ -37,7 +38,12 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
result, err := initMetabase(*project, *mbPort, *pgPort, *pgUser, *pgPass, *pgDB, *pgVolume)
|
||||
var extraVolumes []string
|
||||
if *mbVolumes != "" {
|
||||
extraVolumes = strings.Split(*mbVolumes, ",")
|
||||
}
|
||||
|
||||
result, err := initMetabase(*project, *mbPort, *pgPort, *pgUser, *pgPass, *pgDB, *pgVolume, extraVolumes)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
os.Exit(1)
|
||||
@@ -48,7 +54,7 @@ func main() {
|
||||
enc.Encode(result)
|
||||
}
|
||||
|
||||
func initMetabase(project, mbPort, pgPort, pgUser, pgPass, pgDB, pgVolume string) (*MetabaseResult, error) {
|
||||
func initMetabase(project, mbPort, pgPort, pgUser, pgPass, pgDB, pgVolume string, mbExtraVolumes []string) (*MetabaseResult, error) {
|
||||
networkName := project + "-net"
|
||||
pgName := project + "-postgres"
|
||||
mbName := project + "-metabase"
|
||||
@@ -118,13 +124,36 @@ func initMetabase(project, mbPort, pgPort, pgUser, pgPass, pgDB, pgVolume string
|
||||
"-e", "MB_DB_USER=" + pgUser,
|
||||
"-e", "MB_DB_PASS=" + pgPass,
|
||||
"-e", "MB_DB_HOST=" + pgName,
|
||||
"metabase/metabase:latest",
|
||||
}
|
||||
for _, v := range mbExtraVolumes {
|
||||
mbArgs = append(mbArgs, "-v", strings.TrimSpace(v))
|
||||
}
|
||||
mbArgs = append(mbArgs, "metabase/metabase:latest")
|
||||
mbID, err := dockerCmd(mbArgs...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("starting metabase: %w", err)
|
||||
}
|
||||
|
||||
// 6. Fix permisos para volumes SQLite — Metabase corre como UID 2000
|
||||
for _, v := range mbExtraVolumes {
|
||||
parts := strings.SplitN(strings.TrimSpace(v), ":", 2)
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
destPath := parts[1]
|
||||
// Si es un archivo, fix el directorio padre; si es directorio, fix directo
|
||||
dir := destPath
|
||||
if strings.Contains(destPath, ".") {
|
||||
// Probablemente un archivo, usar dirname
|
||||
idx := strings.LastIndex(destPath, "/")
|
||||
if idx > 0 {
|
||||
dir = destPath[:idx]
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, " Fijando permisos de %s para usuario metabase...\n", dir)
|
||||
dockerCmd("exec", "-u", "root", mbName, "chown", "metabase:metabase", dir)
|
||||
}
|
||||
|
||||
mbURL := fmt.Sprintf("http://localhost:%s", mbPort)
|
||||
fmt.Fprintf(os.Stderr, "\nStack listo. Metabase disponible en %s\n", mbURL)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user