7723119d80
Service registration (register) calls ParseService, which captures logger.Default() into each service/handler/listener. Since logger.SetDefault was called after register, all components captured the initial Info-level logger, making -D/-DD ineffective for service logging.
322 lines
9.2 KiB
Go
322 lines
9.2 KiB
Go
// Package loader converts a parsed [config.Config] into running components
|
|
// by parsing each config section and registering the results into the
|
|
// global registries. Components are registered in dependency order so that
|
|
// when a component reads its dependencies from registries during parsing,
|
|
// those dependencies are already available.
|
|
package loader
|
|
|
|
import (
|
|
"github.com/go-gost/core/admission"
|
|
"github.com/go-gost/core/auth"
|
|
"github.com/go-gost/core/bypass"
|
|
"github.com/go-gost/core/chain"
|
|
"github.com/go-gost/core/hop"
|
|
"github.com/go-gost/core/hosts"
|
|
"github.com/go-gost/core/ingress"
|
|
"github.com/go-gost/core/limiter/conn"
|
|
"github.com/go-gost/core/limiter/rate"
|
|
"github.com/go-gost/core/limiter/traffic"
|
|
"github.com/go-gost/core/logger"
|
|
"github.com/go-gost/core/observer"
|
|
"github.com/go-gost/core/recorder"
|
|
reg "github.com/go-gost/core/registry"
|
|
"github.com/go-gost/core/resolver"
|
|
"github.com/go-gost/core/router"
|
|
"github.com/go-gost/core/sd"
|
|
"github.com/go-gost/core/service"
|
|
"github.com/go-gost/x/config"
|
|
"github.com/go-gost/x/config/parsing"
|
|
admission_parser "github.com/go-gost/x/config/parsing/admission"
|
|
auth_parser "github.com/go-gost/x/config/parsing/auth"
|
|
bypass_parser "github.com/go-gost/x/config/parsing/bypass"
|
|
chain_parser "github.com/go-gost/x/config/parsing/chain"
|
|
hop_parser "github.com/go-gost/x/config/parsing/hop"
|
|
hosts_parser "github.com/go-gost/x/config/parsing/hosts"
|
|
ingress_parser "github.com/go-gost/x/config/parsing/ingress"
|
|
limiter_parser "github.com/go-gost/x/config/parsing/limiter"
|
|
logger_parser "github.com/go-gost/x/config/parsing/logger"
|
|
observer_parser "github.com/go-gost/x/config/parsing/observer"
|
|
recorder_parser "github.com/go-gost/x/config/parsing/recorder"
|
|
resolver_parser "github.com/go-gost/x/config/parsing/resolver"
|
|
router_parser "github.com/go-gost/x/config/parsing/router"
|
|
sd_parser "github.com/go-gost/x/config/parsing/sd"
|
|
service_parser "github.com/go-gost/x/config/parsing/service"
|
|
"github.com/go-gost/x/registry"
|
|
)
|
|
|
|
// defaultLoader is a singleton loader used by the top-level Load function.
|
|
var (
|
|
defaultLoader *loader = &loader{}
|
|
)
|
|
|
|
// Load parses all config sections from cfg and registers the resulting
|
|
// components into the global registries, then sets up the default logger
|
|
// and TLS config.
|
|
func Load(cfg *config.Config) error {
|
|
return defaultLoader.Load(cfg)
|
|
}
|
|
|
|
// loader holds no state; its Load method is the entry point for converting
|
|
// a config into running components.
|
|
type loader struct{}
|
|
|
|
// Load builds the default TLS config, registers all named components from
|
|
// cfg into the global registries, and sets the default logger and TLS config.
|
|
func (l *loader) Load(cfg *config.Config) error {
|
|
if cfg == nil {
|
|
return nil
|
|
}
|
|
|
|
tlsCfg, err := parsing.BuildDefaultTLSConfig(cfg.TLS)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
logCfg := cfg.Log
|
|
if logCfg == nil {
|
|
logCfg = &config.LogConfig{}
|
|
}
|
|
logger.SetDefault(logger_parser.ParseLogger(&config.LoggerConfig{Log: logCfg}))
|
|
|
|
if err := register(cfg); err != nil {
|
|
return err
|
|
}
|
|
|
|
parsing.SetDefaultTLSConfig(tlsCfg)
|
|
|
|
return nil
|
|
}
|
|
|
|
// named is a generic name+value pair used to buffer parsed components
|
|
// before registering them.
|
|
type named[T any] struct {
|
|
name string
|
|
v T
|
|
}
|
|
|
|
// registerGroup replaces all entries in r with the given entries.
|
|
// Old entries are unregistered first; if any new entry fails to register,
|
|
// the group is left partially updated (matching the historical reload
|
|
// behavior for intra-group failures).
|
|
func registerGroup[T any](entries []named[T], r reg.Registry[T]) error {
|
|
for name := range r.GetAll() {
|
|
r.Unregister(name)
|
|
}
|
|
for _, e := range entries {
|
|
if err := r.Register(e.name, e.v); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// register parses config sections and registers them into the global
|
|
// registries. Groups are processed in dependency order: leaf components
|
|
// first, then hops, chains, and finally services. This ensures that
|
|
// when a component reads its dependencies from registries during
|
|
// parsing, those dependencies are already registered.
|
|
func register(cfg *config.Config) error {
|
|
if cfg == nil {
|
|
return nil
|
|
}
|
|
|
|
// --- leaf components (no inter-group registry dependencies) ---
|
|
|
|
{
|
|
var entries []named[logger.Logger]
|
|
for _, c := range cfg.Loggers {
|
|
entries = append(entries, named[logger.Logger]{c.Name, logger_parser.ParseLogger(c)})
|
|
}
|
|
if err := registerGroup(entries, registry.LoggerRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
{
|
|
var entries []named[auth.Authenticator]
|
|
for _, c := range cfg.Authers {
|
|
entries = append(entries, named[auth.Authenticator]{c.Name, auth_parser.ParseAuther(c)})
|
|
}
|
|
if err := registerGroup(entries, registry.AutherRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
{
|
|
var entries []named[admission.Admission]
|
|
for _, c := range cfg.Admissions {
|
|
entries = append(entries, named[admission.Admission]{c.Name, admission_parser.ParseAdmission(c)})
|
|
}
|
|
if err := registerGroup(entries, registry.AdmissionRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
{
|
|
var entries []named[bypass.Bypass]
|
|
for _, c := range cfg.Bypasses {
|
|
entries = append(entries, named[bypass.Bypass]{c.Name, bypass_parser.ParseBypass(c)})
|
|
}
|
|
if err := registerGroup(entries, registry.BypassRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
{
|
|
var entries []named[resolver.Resolver]
|
|
for _, c := range cfg.Resolvers {
|
|
r, err := resolver_parser.ParseResolver(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
entries = append(entries, named[resolver.Resolver]{c.Name, r})
|
|
}
|
|
if err := registerGroup(entries, registry.ResolverRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
{
|
|
var entries []named[hosts.HostMapper]
|
|
for _, c := range cfg.Hosts {
|
|
entries = append(entries, named[hosts.HostMapper]{c.Name, hosts_parser.ParseHostMapper(c)})
|
|
}
|
|
if err := registerGroup(entries, registry.HostsRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
{
|
|
var entries []named[ingress.Ingress]
|
|
for _, c := range cfg.Ingresses {
|
|
entries = append(entries, named[ingress.Ingress]{c.Name, ingress_parser.ParseIngress(c)})
|
|
}
|
|
if err := registerGroup(entries, registry.IngressRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
{
|
|
var entries []named[router.Router]
|
|
for _, c := range cfg.Routers {
|
|
entries = append(entries, named[router.Router]{c.Name, router_parser.ParseRouter(c)})
|
|
}
|
|
if err := registerGroup(entries, registry.RouterRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
{
|
|
var entries []named[sd.SD]
|
|
for _, c := range cfg.SDs {
|
|
entries = append(entries, named[sd.SD]{c.Name, sd_parser.ParseSD(c)})
|
|
}
|
|
if err := registerGroup(entries, registry.SDRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
{
|
|
var entries []named[observer.Observer]
|
|
for _, c := range cfg.Observers {
|
|
entries = append(entries, named[observer.Observer]{c.Name, observer_parser.ParseObserver(c)})
|
|
}
|
|
if err := registerGroup(entries, registry.ObserverRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
{
|
|
var entries []named[recorder.Recorder]
|
|
for _, c := range cfg.Recorders {
|
|
entries = append(entries, named[recorder.Recorder]{c.Name, recorder_parser.ParseRecorder(c)})
|
|
}
|
|
if err := registerGroup(entries, registry.RecorderRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
{
|
|
var entries []named[traffic.TrafficLimiter]
|
|
for _, c := range cfg.Limiters {
|
|
entries = append(entries, named[traffic.TrafficLimiter]{c.Name, limiter_parser.ParseTrafficLimiter(c)})
|
|
}
|
|
if err := registerGroup(entries, registry.TrafficLimiterRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
{
|
|
var entries []named[conn.ConnLimiter]
|
|
for _, c := range cfg.CLimiters {
|
|
entries = append(entries, named[conn.ConnLimiter]{c.Name, limiter_parser.ParseConnLimiter(c)})
|
|
}
|
|
if err := registerGroup(entries, registry.ConnLimiterRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
{
|
|
var entries []named[rate.RateLimiter]
|
|
for _, c := range cfg.RLimiters {
|
|
entries = append(entries, named[rate.RateLimiter]{c.Name, limiter_parser.ParseRateLimiter(c)})
|
|
}
|
|
if err := registerGroup(entries, registry.RateLimiterRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// --- hops (references bypasses, resolvers, hosts from registries) ---
|
|
|
|
{
|
|
var entries []named[hop.Hop]
|
|
for _, c := range cfg.Hops {
|
|
h, err := hop_parser.ParseHop(c, logger.Default())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
entries = append(entries, named[hop.Hop]{c.Name, h})
|
|
}
|
|
if err := registerGroup(entries, registry.HopRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// --- chains (references hops from registries) ---
|
|
|
|
{
|
|
var entries []named[chain.Chainer]
|
|
for _, c := range cfg.Chains {
|
|
ch, err := chain_parser.ParseChain(c, logger.Default())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
entries = append(entries, named[chain.Chainer]{c.Name, ch})
|
|
}
|
|
if err := registerGroup(entries, registry.ChainRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// --- services (references chains, resolvers, hosts, recorders,
|
|
// limiters, observers, hops from registries) ---
|
|
|
|
{
|
|
var entries []named[service.Service]
|
|
for _, c := range cfg.Services {
|
|
svc, err := service_parser.ParseService(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if svc != nil {
|
|
entries = append(entries, named[service.Service]{c.Name, svc})
|
|
}
|
|
}
|
|
if err := registerGroup(entries, registry.ServiceRegistry()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|