// Package opsconnect implements the connection strategy shared by every
// admin frontend (gitfed-tui, gitfed-web): talk to a running gitfed-server
// over its admin socket when one is up (live mode), otherwise open the
// store directly (offline mode). See internal/adminrpc for why this
// distinction exists (bbolt's exclusive file lock).
package opsconnect
import (
"fmt"
"git.neuromancer.ovh/bastien-mrq/gitfed/internal/admin"
"git.neuromancer.ovh/bastien-mrq/gitfed/internal/adminrpc"
"git.neuromancer.ovh/bastien-mrq/gitfed/internal/ca"
"git.neuromancer.ovh/bastien-mrq/gitfed/internal/config"
"git.neuromancer.ovh/bastien-mrq/gitfed/internal/federation"
"git.neuromancer.ovh/bastien-mrq/gitfed/internal/store"
)
// Connect returns an admin.Ops backed by whichever mode is available, a
// human-readable description of which one it picked, and a cleanup func
// that must be called when done (closes the store in offline mode, a no-op
// in live mode).
func Connect(cfg config.Config) (ops admin.Ops, mode string, closeFn func(), err error) {
client := adminrpc.NewClient(cfg.AdminSocketPath())
if pingErr := client.Ping(); pingErr == nil {
return client, "live (connected to running gitfed-server)", func() {}, nil
}
st, err := store.Open(cfg.DBPath())
if err != nil {
return nil, "", nil, fmt.Errorf("no running server on %s, and could not open store directly: %w", cfg.AdminSocketPath(), err)
}
resolver := federation.NewResolver(st, cfg.Domain, cfg.InsecureFederation)
localCA, err := ca.LoadOrCreate(cfg.CADir())
if err != nil {
st.Close()
return nil, "", nil, fmt.Errorf("load CA: %w", err)
}
a := admin.New(st, resolver, cfg.Domain, cfg.ReposDir, localCA)
return a, "offline (server not running, editing store directly)", func() { st.Close() }, nil
}