/* Backend Detection - Auto-detect the best available container backend. Uses a registration pattern to avoid import cycles: backend packages register themselves via init() by calling Register(). */ package backend import ( "fmt" "sync" ) var ( mu sync.Mutex registry = map[string]func() ContainerBackend{} // order tracks registration order for priority-based detection order []string ) // Register adds a backend factory to the registry. // Backends should call this from their init() function. func Register(name string, factory func() ContainerBackend) { mu.Lock() defer mu.Unlock() registry[name] = factory order = append(order, name) } // DetectBackend returns the best available backend for the current platform. // Tries backends in registration order, returning the first that is available. func DetectBackend() ContainerBackend { mu.Lock() defer mu.Unlock() for _, name := range order { b := registry[name]() if b.Available() { return b } } // If nothing is available, return the first registered backend anyway // (allows --help and other non-runtime operations to work) if len(order) > 0 { return registry[order[0]]() } return nil } // GetBackend returns a backend by name, or an error if unknown. func GetBackend(name string) (ContainerBackend, error) { mu.Lock() defer mu.Unlock() if factory, ok := registry[name]; ok { return factory(), nil } available := make([]string, 0, len(registry)) for k := range registry { available = append(available, k) } return nil, fmt.Errorf("unknown backend: %q (available: %v)", name, available) }