123 lines
3.9 KiB
Go
123 lines
3.9 KiB
Go
package minio
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/example/storage-appliance/internal/infra/osexec"
|
|
)
|
|
|
|
type Adapter struct {
|
|
Runner osexec.Runner
|
|
EnvPath string
|
|
}
|
|
|
|
func NewAdapter(runner osexec.Runner, envPath string) *Adapter {
|
|
if envPath == "" {
|
|
envPath = "/etc/minio/minio.env"
|
|
}
|
|
return &Adapter{Runner: runner, EnvPath: envPath}
|
|
}
|
|
|
|
type Settings struct {
|
|
AccessKey string `json:"access_key"`
|
|
SecretKey string `json:"secret_key"`
|
|
DataPath string `json:"data_path"`
|
|
Port int `json:"port"`
|
|
TLS bool `json:"tls"`
|
|
}
|
|
|
|
// WriteEnv writes environment file used by MinIO service
|
|
func (a *Adapter) WriteEnv(ctx context.Context, s Settings) error {
|
|
dir := filepath.Dir(a.EnvPath)
|
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
return err
|
|
}
|
|
// env lines
|
|
lines := []string{
|
|
fmt.Sprintf("MINIO_ROOT_USER=%s", s.AccessKey),
|
|
fmt.Sprintf("MINIO_ROOT_PASSWORD=%s", s.SecretKey),
|
|
fmt.Sprintf("MINIO_VOLUMES=%s", s.DataPath),
|
|
}
|
|
if s.Port != 0 {
|
|
lines = append(lines, fmt.Sprintf("MINIO_OPTS=--address :%d", s.Port))
|
|
}
|
|
content := strings.Join(lines, "\n") + "\n"
|
|
tmp := filepath.Join(dir, ".minio.env.tmp")
|
|
if err := os.WriteFile(tmp, []byte(content), 0600); err != nil {
|
|
return err
|
|
}
|
|
if err := os.Rename(tmp, a.EnvPath); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Reload reloads minio service to pick up new env; prefer systemctl reload
|
|
func (a *Adapter) Reload(ctx context.Context) error {
|
|
_, stderr, _, err := osexec.ExecWithRunner(a.Runner, ctx, "systemctl", "reload", "minio")
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
// fallback to restart
|
|
_, stderr, _, err = osexec.ExecWithRunner(a.Runner, ctx, "systemctl", "restart", "minio")
|
|
if err != nil {
|
|
return fmt.Errorf("minio reload/restart failed: %s", stderr)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ConfigureMC configures mc alias to point to the MinIO service using given settings
|
|
func (a *Adapter) ConfigureMC(ctx context.Context, alias string, settings Settings) error {
|
|
secure := "--insecure"
|
|
if settings.TLS {
|
|
secure = ""
|
|
}
|
|
// mc alias set <alias> <endpoint> <access> <secret> [--api S3v4]
|
|
endpoint := fmt.Sprintf("http://127.0.0.1:%d", settings.Port)
|
|
if settings.TLS {
|
|
endpoint = fmt.Sprintf("https://127.0.0.1:%d", settings.Port)
|
|
}
|
|
_, stderr, _, err := osexec.ExecWithRunner(a.Runner, ctx, "mc", "alias", "set", alias, endpoint, settings.AccessKey, settings.SecretKey, secure)
|
|
if err != nil {
|
|
return fmt.Errorf("mc alias set failed: %s", stderr)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ListBuckets uses mc to list buckets via alias
|
|
func (a *Adapter) ListBuckets(ctx context.Context, alias string) ([]string, error) {
|
|
out, stderr, _, err := osexec.ExecWithRunner(a.Runner, ctx, "mc", "ls", "--json", alias)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("mc ls failed: %s", stderr)
|
|
}
|
|
// parse JSON lines, each contains a 'key' or 'name' - in mc, `ls --json` returns 'key'
|
|
var buckets []string
|
|
lines := strings.Split(strings.TrimSpace(out), "\n")
|
|
for _, l := range lines {
|
|
var obj map[string]any
|
|
if err := json.Unmarshal([]byte(l), &obj); err != nil {
|
|
continue
|
|
}
|
|
if otype, ok := obj["type"].(string); ok && otype == "bucket" {
|
|
if name, ok := obj["key"].(string); ok {
|
|
buckets = append(buckets, name)
|
|
}
|
|
}
|
|
}
|
|
return buckets, nil
|
|
}
|
|
|
|
// CreateBucket uses mc to create a new bucket alias/<name>
|
|
func (a *Adapter) CreateBucket(ctx context.Context, alias, name string) error {
|
|
_, stderr, _, err := osexec.ExecWithRunner(a.Runner, ctx, "mc", "mb", alias+"/"+name)
|
|
if err != nil {
|
|
return fmt.Errorf("mc mb failed: %s", stderr)
|
|
}
|
|
return nil
|
|
}
|