feat: 10 funciones infra Docker y 2 tipos — operaciones de contenedores e imagenes

Funciones Docker: list/start/stop/remove containers, list/pull/remove images,
inspect, logs, run. Tipos: ContainerInfo e ImageInfo. Pre-existentes en el
dominio infra, ahora registrados.
This commit is contained in:
2026-03-28 03:58:43 +01:00
parent 2f95dcc076
commit 0402e0fdbe
25 changed files with 799 additions and 0 deletions
+23
View File
@@ -0,0 +1,23 @@
package infra
import (
"fmt"
"os/exec"
"strconv"
)
// DockerContainerLogs obtiene los logs de un contenedor. tail limita las últimas N líneas (0 = todas).
func DockerContainerLogs(nameOrID string, tail int) (string, error) {
args := []string{"logs"}
if tail > 0 {
args = append(args, "--tail", strconv.Itoa(tail))
}
args = append(args, nameOrID)
out, err := exec.Command("docker", args...).CombinedOutput()
if err != nil {
return "", fmt.Errorf("docker logs %s: %w", nameOrID, err)
}
return string(out), nil
}
+32
View File
@@ -0,0 +1,32 @@
---
name: docker_container_logs
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func DockerContainerLogs(nameOrID string, tail int) (string, error)"
description: "Obtiene los logs de un contenedor Docker. El parámetro tail limita a las últimas N líneas (0 devuelve todos los logs)."
tags: [docker, container, logs, infra]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, os/exec, strconv]
tested: false
tests: []
test_file_path: ""
file_path: "functions/infra/docker_container_logs.go"
---
## Ejemplo
```go
// Últimas 100 líneas
logs, err := DockerContainerLogs("my-app", 100)
if err != nil {
log.Fatal(err)
}
fmt.Println(logs)
```
@@ -0,0 +1,26 @@
package infra
import (
"encoding/json"
"fmt"
"os/exec"
)
// DockerInspectContainer devuelve los detalles completos de un contenedor como JSON genérico.
func DockerInspectContainer(nameOrID string) (map[string]any, error) {
out, err := exec.Command("docker", "inspect", nameOrID).Output()
if err != nil {
return nil, fmt.Errorf("docker inspect %s: %w", nameOrID, err)
}
var result []map[string]any
if err := json.Unmarshal(out, &result); err != nil {
return nil, fmt.Errorf("parsing inspect output: %w", err)
}
if len(result) == 0 {
return nil, fmt.Errorf("container %s not found", nameOrID)
}
return result[0], nil
}
@@ -0,0 +1,35 @@
---
name: docker_inspect_container
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func DockerInspectContainer(nameOrID string) (map[string]any, error)"
description: "Devuelve los detalles completos de un contenedor Docker como mapa JSON genérico. Útil para inspeccionar configuración, red, volumes, etc."
tags: [docker, container, inspect, infra]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [encoding/json, fmt, os/exec]
tested: false
tests: []
test_file_path: ""
file_path: "functions/infra/docker_inspect_container.go"
---
## Ejemplo
```go
info, err := DockerInspectContainer("my-app")
if err != nil {
log.Fatal(err)
}
fmt.Println(info["State"])
```
## Notas
Devuelve `map[string]any` en vez de un struct tipado para maximizar flexibilidad. El caller puede navegar el JSON libremente.
+104
View File
@@ -0,0 +1,104 @@
package infra
import (
"encoding/json"
"fmt"
"os/exec"
)
// DockerListContainers lista contenedores Docker. Si all es true, incluye los detenidos.
func DockerListContainers(all bool) ([]ContainerInfo, error) {
args := []string{"ps", "--format", "{{json .}}", "--no-trunc"}
if all {
args = append(args, "-a")
}
out, err := exec.Command("docker", args...).Output()
if err != nil {
return nil, fmt.Errorf("docker ps: %w", err)
}
if len(out) == 0 {
return nil, nil
}
var containers []ContainerInfo
for _, line := range splitLines(out) {
if len(line) == 0 {
continue
}
var raw struct {
ID string `json:"ID"`
Names string `json:"Names"`
Image string `json:"Image"`
Status string `json:"Status"`
State string `json:"State"`
Ports string `json:"Ports"`
Created string `json:"CreatedAt"`
Labels string `json:"Labels"`
}
if err := json.Unmarshal(line, &raw); err != nil {
continue
}
containers = append(containers, ContainerInfo{
ID: raw.ID[:12],
Name: raw.Names,
Image: raw.Image,
Status: raw.Status,
State: raw.State,
Ports: raw.Ports,
Created: raw.Created,
Labels: parseLabels(raw.Labels),
})
}
return containers, nil
}
// splitLines divide bytes en líneas individuales.
func splitLines(data []byte) [][]byte {
var lines [][]byte
start := 0
for i, b := range data {
if b == '\n' {
lines = append(lines, data[start:i])
start = i + 1
}
}
if start < len(data) {
lines = append(lines, data[start:])
}
return lines
}
// parseLabels convierte "key=val,key2=val2" en map.
func parseLabels(s string) map[string]string {
m := make(map[string]string)
if s == "" {
return m
}
for _, part := range splitByComma(s) {
for i := 0; i < len(part); i++ {
if part[i] == '=' {
m[part[:i]] = part[i+1:]
break
}
}
}
return m
}
func splitByComma(s string) []string {
var parts []string
start := 0
for i := 0; i < len(s); i++ {
if s[i] == ',' {
parts = append(parts, s[start:i])
start = i + 1
}
}
if start < len(s) {
parts = append(parts, s[start:])
}
return parts
}
+37
View File
@@ -0,0 +1,37 @@
---
name: docker_list_containers
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func DockerListContainers(all bool) ([]ContainerInfo, error)"
description: "Lista contenedores Docker locales. Si all es true incluye contenedores detenidos. Parsea la salida JSON de docker ps."
tags: [docker, container, list, infra]
uses_functions: []
uses_types: [container_info_go_infra]
returns: [container_info_go_infra]
returns_optional: false
error_type: "error_go_core"
imports: [encoding/json, fmt, os/exec]
tested: false
tests: []
test_file_path: ""
file_path: "functions/infra/docker_list_containers.go"
---
## Ejemplo
```go
containers, err := DockerListContainers(true)
if err != nil {
log.Fatal(err)
}
for _, c := range containers {
fmt.Printf("%s %s %s\n", c.ID, c.Name, c.Status)
}
```
## Notas
Usa `docker ps --format '{{json .}}'` para parsear la salida de forma confiable. Incluye helpers internos `splitLines` y `parseLabels`.
+45
View File
@@ -0,0 +1,45 @@
package infra
import (
"encoding/json"
"fmt"
"os/exec"
)
// DockerListImages lista las imágenes Docker locales.
func DockerListImages() ([]ImageInfo, error) {
out, err := exec.Command("docker", "images", "--format", "{{json .}}", "--no-trunc").Output()
if err != nil {
return nil, fmt.Errorf("docker images: %w", err)
}
if len(out) == 0 {
return nil, nil
}
var images []ImageInfo
for _, line := range splitLines(out) {
if len(line) == 0 {
continue
}
var raw struct {
ID string `json:"ID"`
Repository string `json:"Repository"`
Tag string `json:"Tag"`
Size string `json:"Size"`
Created string `json:"CreatedAt"`
}
if err := json.Unmarshal(line, &raw); err != nil {
continue
}
images = append(images, ImageInfo{
ID: raw.ID,
Repository: raw.Repository,
Tag: raw.Tag,
Size: raw.Size,
Created: raw.Created,
})
}
return images, nil
}
+33
View File
@@ -0,0 +1,33 @@
---
name: docker_list_images
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func DockerListImages() ([]ImageInfo, error)"
description: "Lista las imágenes Docker disponibles localmente. Parsea la salida JSON de docker images."
tags: [docker, image, list, infra]
uses_functions: []
uses_types: [image_info_go_infra]
returns: [image_info_go_infra]
returns_optional: false
error_type: "error_go_core"
imports: [encoding/json, fmt, os/exec]
tested: false
tests: []
test_file_path: ""
file_path: "functions/infra/docker_list_images.go"
---
## Ejemplo
```go
images, err := DockerListImages()
if err != nil {
log.Fatal(err)
}
for _, img := range images {
fmt.Printf("%s:%s (%s)\n", img.Repository, img.Tag, img.Size)
}
```
+16
View File
@@ -0,0 +1,16 @@
package infra
import (
"fmt"
"os/exec"
"strings"
)
// DockerPullImage descarga una imagen Docker del registry remoto.
func DockerPullImage(image string) error {
out, err := exec.Command("docker", "pull", image).CombinedOutput()
if err != nil {
return fmt.Errorf("docker pull %s: %s", image, strings.TrimSpace(string(out)))
}
return nil
}
+30
View File
@@ -0,0 +1,30 @@
---
name: docker_pull_image
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func DockerPullImage(image string) error"
description: "Descarga una imagen Docker desde el registry remoto (Docker Hub u otro configurado). Acepta formato image:tag."
tags: [docker, image, pull, infra]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, os/exec, strings]
tested: false
tests: []
test_file_path: ""
file_path: "functions/infra/docker_pull_image.go"
---
## Ejemplo
```go
err := DockerPullImage("nginx:latest")
if err != nil {
log.Fatal(err)
}
```
@@ -0,0 +1,22 @@
package infra
import (
"fmt"
"os/exec"
"strings"
)
// DockerRemoveContainer elimina un contenedor Docker. Si force es true, fuerza la eliminación de contenedores en ejecución.
func DockerRemoveContainer(nameOrID string, force bool) error {
args := []string{"rm"}
if force {
args = append(args, "-f")
}
args = append(args, nameOrID)
out, err := exec.Command("docker", args...).CombinedOutput()
if err != nil {
return fmt.Errorf("docker rm %s: %s", nameOrID, strings.TrimSpace(string(out)))
}
return nil
}
@@ -0,0 +1,31 @@
---
name: docker_remove_container
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func DockerRemoveContainer(nameOrID string, force bool) error"
description: "Elimina un contenedor Docker. Con force=true puede eliminar contenedores en ejecución (equivale a docker rm -f)."
tags: [docker, container, remove, infra]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, os/exec, strings]
tested: false
tests: []
test_file_path: ""
file_path: "functions/infra/docker_remove_container.go"
---
## Ejemplo
```go
// Eliminar contenedor detenido
err := DockerRemoveContainer("old-app", false)
// Forzar eliminación
err = DockerRemoveContainer("stuck-app", true)
```
+22
View File
@@ -0,0 +1,22 @@
package infra
import (
"fmt"
"os/exec"
"strings"
)
// DockerRemoveImage elimina una imagen Docker local. Si force es true, fuerza la eliminación.
func DockerRemoveImage(image string, force bool) error {
args := []string{"rmi"}
if force {
args = append(args, "-f")
}
args = append(args, image)
out, err := exec.Command("docker", args...).CombinedOutput()
if err != nil {
return fmt.Errorf("docker rmi %s: %s", image, strings.TrimSpace(string(out)))
}
return nil
}
+30
View File
@@ -0,0 +1,30 @@
---
name: docker_remove_image
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func DockerRemoveImage(image string, force bool) error"
description: "Elimina una imagen Docker local. Con force=true fuerza la eliminación incluso si hay contenedores que la usan."
tags: [docker, image, remove, infra]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, os/exec, strings]
tested: false
tests: []
test_file_path: ""
file_path: "functions/infra/docker_remove_image.go"
---
## Ejemplo
```go
err := DockerRemoveImage("nginx:latest", false)
if err != nil {
log.Fatal(err)
}
```
+55
View File
@@ -0,0 +1,55 @@
package infra
import (
"fmt"
"os/exec"
"strings"
)
// DockerRunOpts opciones para ejecutar un contenedor Docker.
type DockerRunOpts struct {
Name string // Nombre del contenedor (opcional)
Ports []string // Mapeo de puertos, ej: ["8080:80", "443:443"]
Env map[string]string // Variables de entorno
Volumes []string // Bind mounts, ej: ["/host/path:/container/path"]
Detach bool // Ejecutar en background
Remove bool // Eliminar al terminar (--rm)
Network string // Red Docker (opcional)
}
// DockerRunContainer ejecuta un contenedor Docker nuevo con la imagen y opciones dadas.
// Devuelve el ID del contenedor creado.
func DockerRunContainer(image string, opts DockerRunOpts) (string, error) {
args := []string{"run"}
if opts.Detach {
args = append(args, "-d")
}
if opts.Remove {
args = append(args, "--rm")
}
if opts.Name != "" {
args = append(args, "--name", opts.Name)
}
if opts.Network != "" {
args = append(args, "--network", opts.Network)
}
for _, p := range opts.Ports {
args = append(args, "-p", p)
}
for k, v := range opts.Env {
args = append(args, "-e", k+"="+v)
}
for _, vol := range opts.Volumes {
args = append(args, "-v", vol)
}
args = append(args, image)
out, err := exec.Command("docker", args...).CombinedOutput()
if err != nil {
return "", fmt.Errorf("docker run %s: %s", image, strings.TrimSpace(string(out)))
}
return strings.TrimSpace(string(out)), nil
}
+40
View File
@@ -0,0 +1,40 @@
---
name: docker_run_container
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func DockerRunContainer(image string, opts DockerRunOpts) (string, error)"
description: "Ejecuta un contenedor Docker nuevo a partir de una imagen. Soporta puertos, env vars, volumes, network, detach y auto-remove. Devuelve el ID del contenedor."
tags: [docker, container, run, infra]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, os/exec, strings]
tested: false
tests: []
test_file_path: ""
file_path: "functions/infra/docker_run_container.go"
---
## Ejemplo
```go
id, err := DockerRunContainer("nginx:latest", DockerRunOpts{
Name: "web-server",
Ports: []string{"8080:80"},
Env: map[string]string{"NGINX_HOST": "localhost"},
Detach: true,
})
if err != nil {
log.Fatal(err)
}
fmt.Println("Container ID:", id)
```
## Notas
`DockerRunOpts` es un struct de opciones definido en el mismo archivo. No se registra como tipo del registry porque es específico de esta función.
+16
View File
@@ -0,0 +1,16 @@
package infra
import (
"fmt"
"os/exec"
"strings"
)
// DockerStartContainer inicia un contenedor existente por nombre o ID.
func DockerStartContainer(nameOrID string) error {
out, err := exec.Command("docker", "start", nameOrID).CombinedOutput()
if err != nil {
return fmt.Errorf("docker start %s: %s", nameOrID, strings.TrimSpace(string(out)))
}
return nil
}
+30
View File
@@ -0,0 +1,30 @@
---
name: docker_start_container
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func DockerStartContainer(nameOrID string) error"
description: "Inicia un contenedor Docker existente que está detenido. Recibe nombre o ID del contenedor."
tags: [docker, container, start, infra]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, os/exec, strings]
tested: false
tests: []
test_file_path: ""
file_path: "functions/infra/docker_start_container.go"
---
## Ejemplo
```go
err := DockerStartContainer("my-app")
if err != nil {
log.Fatal(err)
}
```
+23
View File
@@ -0,0 +1,23 @@
package infra
import (
"fmt"
"os/exec"
"strconv"
"strings"
)
// DockerStopContainer detiene un contenedor Docker. timeoutSecs indica el tiempo de gracia antes de SIGKILL.
func DockerStopContainer(nameOrID string, timeoutSecs int) error {
args := []string{"stop"}
if timeoutSecs > 0 {
args = append(args, "-t", strconv.Itoa(timeoutSecs))
}
args = append(args, nameOrID)
out, err := exec.Command("docker", args...).CombinedOutput()
if err != nil {
return fmt.Errorf("docker stop %s: %s", nameOrID, strings.TrimSpace(string(out)))
}
return nil
}
+30
View File
@@ -0,0 +1,30 @@
---
name: docker_stop_container
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func DockerStopContainer(nameOrID string, timeoutSecs int) error"
description: "Detiene un contenedor Docker en ejecución. timeoutSecs controla el tiempo de gracia antes de SIGKILL (0 usa el default de Docker)."
tags: [docker, container, stop, infra]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, os/exec, strconv, strings]
tested: false
tests: []
test_file_path: ""
file_path: "functions/infra/docker_stop_container.go"
---
## Ejemplo
```go
err := DockerStopContainer("my-app", 10)
if err != nil {
log.Fatal(err)
}
```
+22
View File
@@ -0,0 +1,22 @@
package infra
// ContainerInfo representa la información básica de un contenedor Docker.
type ContainerInfo struct {
ID string
Name string
Image string
Status string
State string
Ports string
Created string
Labels map[string]string
}
// ImageInfo representa la información básica de una imagen Docker local.
type ImageInfo struct {
ID string
Repository string
Tag string
Size string
Created string
}
+13
View File
@@ -0,0 +1,13 @@
package infra
// ContainerInfo representa la información básica de un contenedor Docker.
type ContainerInfo struct {
ID string // ID corto del contenedor
Name string // Nombre del contenedor
Image string // Imagen usada
Status string // Estado actual (running, exited, etc.)
State string // Estado detallado
Ports string // Mapeo de puertos
Created string // Fecha de creación
Labels map[string]string // Labels del contenedor
}
+39
View File
@@ -0,0 +1,39 @@
---
name: container_info
lang: go
domain: infra
version: "1.0.0"
algebraic: product
definition: |
type ContainerInfo struct {
ID string
Name string
Image string
Status string
State string
Ports string
Created string
Labels map[string]string
}
description: "Información básica de un contenedor Docker: ID, nombre, imagen, estado, puertos, labels."
tags: [docker, container, infra]
uses_types: []
file_path: "types/infra/container_info.go"
---
## Ejemplo
```go
c := ContainerInfo{
ID: "abc123",
Name: "my-app",
Image: "nginx:latest",
Status: "Up 2 hours",
State: "running",
Ports: "0.0.0.0:8080->80/tcp",
}
```
## Notas
Tipo product que modela la salida de `docker ps`. Los campos mapean directamente a las columnas del formato JSON de Docker.
+10
View File
@@ -0,0 +1,10 @@
package infra
// ImageInfo representa la información básica de una imagen Docker local.
type ImageInfo struct {
ID string // ID corto de la imagen
Repository string // Nombre del repositorio
Tag string // Tag de la imagen
Size string // Tamaño legible (ej: "142MB")
Created string // Fecha de creación
}
+35
View File
@@ -0,0 +1,35 @@
---
name: image_info
lang: go
domain: infra
version: "1.0.0"
algebraic: product
definition: |
type ImageInfo struct {
ID string
Repository string
Tag string
Size string
Created string
}
description: "Información básica de una imagen Docker local: ID, repositorio, tag, tamaño, fecha."
tags: [docker, image, infra]
uses_types: []
file_path: "types/infra/image_info.go"
---
## Ejemplo
```go
img := ImageInfo{
ID: "sha256:abc123",
Repository: "nginx",
Tag: "latest",
Size: "142MB",
Created: "2 weeks ago",
}
```
## Notas
Tipo product que modela la salida de `docker images`. Los campos mapean al formato JSON de Docker.