// Package registry assembles a set of named providers from a // provider.Config by dispatching each entry's Type through a // caller-supplied map of constructors. // // This package deliberately never imports internal/provider/mock or // internal/provider/gcp. If it did, and internal/provider ever needed to // import this package (e.g. to expose a default registry), that would be an // import cycle: internal/provider/mock already imports internal/provider // for the Provider interface. Keeping the type→constructor map external — // supplied by the composition root in cmd/main.go — avoids the cycle // entirely and keeps this package trivially testable with fake // constructors. package registry import ( "context" "fmt" "gitea.home.hrajfrisbee.cz/kacerr/egress-proxies-operator/internal/provider" ) // Constructor builds a provider.Provider from its config block. type Constructor func(ctx context.Context, cfg provider.ProviderConfig) (provider.Provider, error) // Build constructs every provider listed in cfg, dispatching on // ProviderConfig.Type through builtins. Fails fast: an unknown type or a // constructor error aborts the whole build rather than returning a // partially-usable provider set that would misbehave once a caller reaches // for the missing entry. func Build(ctx context.Context, cfg *provider.Config, builtins map[string]Constructor) (map[string]provider.Provider, error) { providers := make(map[string]provider.Provider, len(cfg.Providers)) for _, pc := range cfg.Providers { ctor, ok := builtins[pc.Type] if !ok { return nil, fmt.Errorf("provider %q: unknown type %q", pc.Name, pc.Type) } p, err := ctor(ctx, pc) if err != nil { return nil, fmt.Errorf("provider %q: %w", pc.Name, err) } providers[pc.Name] = p } return providers, nil }