Files
tia-love/internal/stack/scanner.go
T

100 lines
2.3 KiB
Go

package stack
import (
"os"
"path/filepath"
"sort"
"strings"
"gitea.oxpoe.qzz.io/oxpoe/tia-love/internal/docker"
)
// ComposeFileNames — nama file compose yang diterima (REA modul 2 — Dockge).
var ComposeFileNames = []string{"compose.yaml", "docker-compose.yaml", "docker-compose.yml", "compose.yml"}
// Status — status stack (nilai mengikuti referensi Dockge).
type Status int
const (
StatusUnknown Status = iota
StatusCreatedFile
StatusCreatedStack
StatusRunning
StatusExited
)
// Stack — satu stack terkelola di direktori stack.
type Stack struct {
Name string
Dir string
ComposeFile string
Status Status
}
// ScanFS — daftar stack dari disk: setiap subfolder yang berisi file compose.
// Folder tidak ada → daftar kosong, bukan error (belum onboarding).
func ScanFS(dir string) ([]Stack, error) {
entries, err := os.ReadDir(dir)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
var out []Stack
for _, e := range entries {
if !e.IsDir() {
continue
}
stackDir := filepath.Join(dir, e.Name())
if f := findComposeFile(stackDir); f != "" {
out = append(out, Stack{
Name: e.Name(),
Dir: stackDir,
ComposeFile: f,
Status: StatusCreatedFile,
})
}
}
sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name })
return out, nil
}
func findComposeFile(dir string) string {
for _, name := range ComposeFileNames {
p := filepath.Join(dir, name)
if st, err := os.Stat(p); err == nil && !st.IsDir() {
return p
}
}
return ""
}
// Reconcile — overlay status dari `docker compose ls` (parity Dockge:
// nama project compose = nama folder stack).
func Reconcile(stacks []Stack, projects []docker.ComposeProject) []Stack {
byName := make(map[string]Status, len(projects))
for _, p := range projects {
byName[p.Name] = parseComposeStatus(p.Status)
}
for i := range stacks {
if s, ok := byName[stacks[i].Name]; ok {
stacks[i].Status = s
}
}
return stacks
}
func parseComposeStatus(s string) Status {
switch {
case strings.HasPrefix(s, "running"):
return StatusRunning
case strings.HasPrefix(s, "exited"):
return StatusExited
case strings.HasPrefix(s, "created"):
return StatusCreatedStack
default:
return StatusUnknown
}
}