(wip) rework configuration to support multiple frontends

This commit is contained in:
Lawrence, Rendall
2022-10-21 17:53:03 +03:00
parent 3d48b882c5
commit dff0ba6da8
23 changed files with 545 additions and 558 deletions
+15 -20
View File
@@ -9,7 +9,11 @@ import (
"github.com/sot-tech/mochi/pkg/conf"
// Imports to register middleware drivers.
// Imports to register frontends
_ "github.com/sot-tech/mochi/frontend/http"
_ "github.com/sot-tech/mochi/frontend/udp"
// Imports to register middleware hooks.
_ "github.com/sot-tech/mochi/middleware/clientapproval"
_ "github.com/sot-tech/mochi/middleware/jwt"
_ "github.com/sot-tech/mochi/middleware/torrentapproval"
@@ -29,29 +33,20 @@ type Config struct {
// We can make Conf extensible enough that you can program a new response
// generator at the cost of making it possible for users to create config that
// won't compose a functional tracker.
AnnounceInterval time.Duration `yaml:"announce_interval"`
MinAnnounceInterval time.Duration `yaml:"min_announce_interval"`
MetricsAddr string `yaml:"metrics_addr"`
HTTPConfig conf.MapConfig `yaml:"http"`
UDPConfig conf.MapConfig `yaml:"udp"`
Storage struct {
Name string `yaml:"name"`
Config conf.MapConfig `yaml:"config"`
} `yaml:"storage"`
PreHooks []conf.MapConfig `yaml:"prehooks"`
PostHooks []conf.MapConfig `yaml:"posthooks"`
AnnounceInterval time.Duration `yaml:"announce_interval"`
MinAnnounceInterval time.Duration `yaml:"min_announce_interval"`
MetricsAddr string `yaml:"metrics_addr"`
Frontends []conf.NamedMapConfig `yaml:"frontends"`
Storage conf.NamedMapConfig `yaml:"storage"`
PreHooks []conf.NamedMapConfig `yaml:"prehooks"`
PostHooks []conf.NamedMapConfig `yaml:"posthooks"`
}
// ConfigFile represents a namespaced YAML configation file.
type ConfigFile struct {
Conf Config `yaml:"mochi"`
}
// ParseConfigFile returns a new ConfigFile given the path to a YAML
// ParseConfigFile returns a new Config given the path to a YAML
// configuration file.
//
// It supports relative and absolute paths and environment variables.
func ParseConfigFile(path string) (*ConfigFile, error) {
func ParseConfigFile(path string) (*Config, error) {
if path == "" {
return nil, errors.New("no config path specified")
}
@@ -59,7 +54,7 @@ func ParseConfigFile(path string) (*ConfigFile, error) {
f, err := os.Open(os.ExpandEnv(path))
if err == nil {
defer f.Close()
cfgFile := new(ConfigFile)
cfgFile := new(Config)
err = yaml.NewDecoder(f).Decode(cfgFile)
return cfgFile, err
}
+16 -34
View File
@@ -4,8 +4,7 @@ import (
"errors"
"fmt"
"github.com/sot-tech/mochi/frontend/http"
"github.com/sot-tech/mochi/frontend/udp"
"github.com/sot-tech/mochi/frontend"
"github.com/sot-tech/mochi/middleware"
"github.com/sot-tech/mochi/pkg/log"
"github.com/sot-tech/mochi/pkg/metrics"
@@ -24,11 +23,10 @@ type Server struct {
// It is optional to provide an instance of the peer store to avoid the
// creation of a new one.
func (r *Server) Run(configFilePath string) error {
configFile, err := ParseConfigFile(configFilePath)
cfg, err := ParseConfigFile(configFilePath)
if err != nil {
return fmt.Errorf("failed to read config: %w", err)
}
cfg := configFile.Conf
r.sg = stop.NewGroup()
@@ -39,51 +37,35 @@ func (r *Server) Run(configFilePath string) error {
log.Info().Msg("metrics disabled because of empty address")
}
log.Debug().Str("name", cfg.Storage.Name).Object("config", cfg.Storage.Config).Msg("starting storage")
r.storage, err = storage.NewStorage(cfg.Storage.Name, cfg.Storage.Config)
r.storage, err = storage.NewStorage(cfg.Storage)
if err != nil {
return fmt.Errorf("failed to create storage: %w", err)
}
log.Info().Str("name", cfg.Storage.Name).Msg("started storage")
preHooks, err := middleware.NewHooks(cfg.PreHooks, r.storage)
if err != nil {
return fmt.Errorf("failed to validate hook config: %w", err)
return fmt.Errorf("failed to configure pre-hooks: %w", err)
}
postHooks, err := middleware.NewHooks(cfg.PostHooks, r.storage)
if err != nil {
return fmt.Errorf("failed to validate hook config: %w", err)
return fmt.Errorf("failed to configure post-hooks: %w", err)
}
r.logic = middleware.NewLogic(cfg.AnnounceInterval, cfg.MinAnnounceInterval, r.storage, preHooks, postHooks)
var started bool
if len(cfg.HTTPConfig) > 0 {
log.Info().Object("config", cfg.HTTPConfig).Msg("starting HTTP frontend")
httpFE, err := http.NewFrontend(r.logic, cfg.HTTPConfig)
if err == nil {
r.sg.Add(httpFE)
started = true
if len(cfg.Frontends) > 0 {
var fs []frontend.Frontend
r.logic = middleware.NewLogic(cfg.AnnounceInterval, cfg.MinAnnounceInterval, r.storage, preHooks, postHooks)
if fs, err = frontend.NewFrontends(cfg.Frontends, r.logic); err == nil {
for _, f := range fs {
r.sg.Add(f)
}
} else {
return err
err = fmt.Errorf("failed to configure frontends: %w", err)
}
} else {
err = errors.New("no frontends configured")
}
if len(cfg.UDPConfig) > 0 {
log.Info().Object("config", cfg.UDPConfig).Msg("starting UDP frontend")
udpFE, err := udp.NewFrontend(r.logic, cfg.UDPConfig)
if err == nil {
r.sg.Add(udpFE)
started = true
} else {
return err
}
}
if !started {
return errors.New("no frontends configured")
}
return nil
return err
}
// Dispose shuts down an instance of Server.