Files
tia-love/internal/docker/client.go
T
2026-10-15 09:48:39 +07:00

101 lines
2.5 KiB
Go

// Package docker — lapisan tipis di atas Docker SDK untuk core tia.
// Bebas UI: dipakai bersama oleh TUI dan CLI (F-028).
package docker
import (
"context"
"fmt"
"strings"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
)
// Client — pembungkus Docker SDK dengan negosiasi versi API
// (mendukung Docker Engine 20.10+, PRD §9).
type Client struct {
cli *client.Client
}
// New membaca konfigurasi dari env (DOCKER_HOST dll) atau default socket.
func New() (*Client, error) {
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return nil, fmt.Errorf("docker: create client: %w", err)
}
return &Client{cli: cli}, nil
}
func (c *Client) Close() error { return c.cli.Close() }
// Info — ringkasan daemon untuk dashboard, doctor, dan status bar.
type Info struct {
ServerVersion string
APIVersion string
Containers int
Running int
Images int
MemoryTotal int64
CPUs int
}
func (c *Client) Info(ctx context.Context) (Info, error) {
i, err := c.cli.Info(ctx)
if err != nil {
return Info{}, fmt.Errorf("docker: info: %w", err)
}
return Info{
ServerVersion: i.ServerVersion,
APIVersion: c.cli.ClientVersion(), // hasil negosiasi API
Containers: i.Containers,
Running: i.ContainersRunning,
Images: i.Images,
MemoryTotal: i.MemTotal,
CPUs: i.NCPU,
}, nil
}
// Ping — cek daemon hidup (dipakai doctor).
func (c *Client) Ping(ctx context.Context) error {
if _, err := c.cli.Ping(ctx); err != nil {
return fmt.Errorf("docker: ping: %w", err)
}
return nil
}
// Container — ringkasan kontainer untuk sidebar/dashboard.
type Container struct {
ID string
Name string
Image string
State string // running, exited, paused, restarting, created, dead
Status string // "Up 2 hours (healthy)"
}
// ListContainers mengembalikan semua kontainer (termasuk yang berhenti).
func (c *Client) ListContainers(ctx context.Context) ([]Container, error) {
list, err := c.cli.ContainerList(ctx, container.ListOptions{All: true})
if err != nil {
return nil, fmt.Errorf("docker: container list: %w", err)
}
out := make([]Container, 0, len(list))
for _, ct := range list {
name := ""
if len(ct.Names) > 0 {
name = strings.TrimPrefix(ct.Names[0], "/")
}
id := ct.ID
if len(id) > 12 {
id = id[:12]
}
out = append(out, Container{
ID: id,
Name: name,
Image: ct.Image,
State: ct.State,
Status: ct.Status,
})
}
return out, nil
}