Gitfed
bastien-mrq/gitfed / internal / opsconnect / connect.go
// 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
}