mirror of
https://github.com/sot-tech/mochi.git
synced 2026-04-30 17:40:00 -07:00
Add cmd option for quick start w/o config file
This commit is contained in:
@@ -7,12 +7,10 @@ import (
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
fh "github.com/sot-tech/mochi/frontend/http"
|
||||
fu "github.com/sot-tech/mochi/frontend/udp"
|
||||
"github.com/sot-tech/mochi/pkg/conf"
|
||||
|
||||
// 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"
|
||||
@@ -21,12 +19,12 @@ import (
|
||||
|
||||
// Imports to register storage drivers.
|
||||
_ "github.com/sot-tech/mochi/storage/keydb"
|
||||
_ "github.com/sot-tech/mochi/storage/memory"
|
||||
sm "github.com/sot-tech/mochi/storage/memory"
|
||||
_ "github.com/sot-tech/mochi/storage/pg"
|
||||
_ "github.com/sot-tech/mochi/storage/redis"
|
||||
)
|
||||
|
||||
// Config represents the configuration used for executing Conf.
|
||||
// Config represents the configuration used for Server start.
|
||||
type Config struct {
|
||||
// TODO(jzelinskie): Evaluate whether we would like to make
|
||||
// AnnounceInterval and MinAnnounceInterval optional.
|
||||
@@ -42,6 +40,27 @@ type Config struct {
|
||||
PostHooks []conf.NamedMapConfig `yaml:"posthooks"`
|
||||
}
|
||||
|
||||
// QuickConfig is the simple configuration for quick start without config file.
|
||||
// Includes in-memory store, http and udp frontends without any middleware.
|
||||
var QuickConfig = &Config{
|
||||
Frontends: []conf.NamedMapConfig{
|
||||
{
|
||||
Name: fh.Name,
|
||||
Config: conf.MapConfig{},
|
||||
},
|
||||
{
|
||||
Name: fu.Name,
|
||||
Config: conf.MapConfig{},
|
||||
},
|
||||
},
|
||||
Storage: conf.NamedMapConfig{
|
||||
Name: sm.Name,
|
||||
Config: conf.MapConfig{},
|
||||
},
|
||||
PreHooks: []conf.NamedMapConfig{},
|
||||
PostHooks: []conf.NamedMapConfig{},
|
||||
}
|
||||
|
||||
// ParseConfigFile returns a new Config given the path to a YAML
|
||||
// configuration file.
|
||||
//
|
||||
|
||||
@@ -18,23 +18,36 @@ const (
|
||||
logPrettyArg = "logPretty"
|
||||
logColorsArg = "logColored"
|
||||
configArg = "config"
|
||||
quickArg = "quick"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var s Server
|
||||
var err error
|
||||
|
||||
logOut := flag.String(logOutArg, "stderr", "output for logging, might be 'stderr', 'stdout' or file path")
|
||||
logLevel := flag.String(logLevelArg, "warn", "logging level: trace, debug, info, warn, error, fatal, panic")
|
||||
logPretty := flag.Bool(logPrettyArg, false, "enable log pretty print. used only if 'logOut' set to 'stdout' or 'stderr'. if not set, log outputs json")
|
||||
logColored := flag.Bool(logColorsArg, runtime.GOOS == "windows", "enable log coloring. used only if set 'logPretty'")
|
||||
configPath := flag.String(configArg, "/etc/mochi.yaml", "location of configuration file")
|
||||
quickStart := flag.Bool(quickArg, false, "start tracker with default configuration (all frontends, in-memory store, no hooks)")
|
||||
flag.Parse()
|
||||
|
||||
if err := l.ConfigureLogger(*logOut, *logLevel, *logPretty, *logColored); err != nil {
|
||||
if err = l.ConfigureLogger(*logOut, *logLevel, *logPretty, *logColored); err != nil {
|
||||
log.Fatal("unable to configure logger: ", err)
|
||||
}
|
||||
|
||||
if err := s.Run(*configPath); err != nil {
|
||||
var cfg *Config
|
||||
if *quickStart {
|
||||
cfg = QuickConfig
|
||||
} else {
|
||||
cfg, err = ParseConfigFile(*configPath)
|
||||
if err != nil {
|
||||
log.Fatal("unable to read config file: ", err)
|
||||
}
|
||||
}
|
||||
var s Server
|
||||
|
||||
if err = s.Run(cfg); err != nil {
|
||||
log.Fatal("unable to start server: ", err)
|
||||
}
|
||||
defer s.Shutdown()
|
||||
|
||||
@@ -25,12 +25,7 @@ type Server struct {
|
||||
// Run begins an instance of Conf.
|
||||
// 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 {
|
||||
cfg, err := ParseConfigFile(configFilePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read config: %w", err)
|
||||
}
|
||||
|
||||
func (r *Server) Run(cfg *Config) (err error) {
|
||||
if len(cfg.MetricsAddr) > 0 {
|
||||
log.Info().Str("address", cfg.MetricsAddr).Msg("starting metrics server")
|
||||
r.frontends = append(r.frontends, metrics.NewServer(cfg.MetricsAddr))
|
||||
|
||||
@@ -20,14 +20,16 @@ import (
|
||||
"github.com/sot-tech/mochi/pkg/metrics"
|
||||
)
|
||||
|
||||
// Name - registered name of the frontend
|
||||
const Name = "http"
|
||||
|
||||
var (
|
||||
logger = log.NewLogger("frontend/http")
|
||||
errTLSNotProvided = errors.New("tls certificate/key not provided")
|
||||
errRoutesNotProvided = errors.New("routes not provided")
|
||||
logger = log.NewLogger("frontend/http")
|
||||
errTLSNotProvided = errors.New("tls certificate/key not provided")
|
||||
)
|
||||
|
||||
func init() {
|
||||
frontend.RegisterBuilder("http", NewFrontend)
|
||||
frontend.RegisterBuilder(Name, NewFrontend)
|
||||
}
|
||||
|
||||
// Config represents all configurable options for an HTTP BitTorrent Frontend
|
||||
@@ -44,15 +46,17 @@ type Config struct {
|
||||
ParseOptions
|
||||
}
|
||||
|
||||
const defaultIdleTimeout = 30 * time.Second
|
||||
const (
|
||||
defaultIdleTimeout = 30 * time.Second
|
||||
defaultAnnounceRoute = "/announce"
|
||||
defaultScrapeRoute = "/scrape"
|
||||
)
|
||||
|
||||
// Validate sanity checks values set in a config and returns a new config with
|
||||
// default values replacing anything that is invalid.
|
||||
func (cfg Config) Validate() (validCfg Config, err error) {
|
||||
validCfg = cfg
|
||||
if validCfg.ListenOptions, err = cfg.ListenOptions.Validate(); err != nil {
|
||||
return
|
||||
}
|
||||
validCfg.ListenOptions = cfg.ListenOptions.Validate(false)
|
||||
if cfg.UseTLS && (len(cfg.TLSCertPath) == 0 || len(cfg.TLSKeyPath) == 0) {
|
||||
err = errTLSNotProvided
|
||||
return
|
||||
@@ -68,6 +72,22 @@ func (cfg Config) Validate() (validCfg Config, err error) {
|
||||
Msg("falling back to default configuration")
|
||||
}
|
||||
}
|
||||
if len(cfg.AnnounceRoutes) == 0 {
|
||||
validCfg.AnnounceRoutes = []string{defaultAnnounceRoute}
|
||||
logger.Warn().
|
||||
Str("name", "AnnounceRoutes").
|
||||
Strs("provided", cfg.AnnounceRoutes).
|
||||
Strs("default", validCfg.AnnounceRoutes).
|
||||
Msg("falling back to default configuration")
|
||||
}
|
||||
if len(cfg.ScrapeRoutes) == 0 {
|
||||
validCfg.ScrapeRoutes = []string{defaultScrapeRoute}
|
||||
logger.Warn().
|
||||
Str("name", "ScrapeRoutes").
|
||||
Strs("provided", cfg.ScrapeRoutes).
|
||||
Strs("default", validCfg.ScrapeRoutes).
|
||||
Msg("falling back to default configuration")
|
||||
}
|
||||
validCfg.ParseOptions.ParseOptions = cfg.ParseOptions.ParseOptions.Validate()
|
||||
return
|
||||
}
|
||||
@@ -89,9 +109,6 @@ func NewFrontend(c conf.MapConfig, logic *middleware.Logic) (frontend.Frontend,
|
||||
if cfg, err = cfg.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(cfg.AnnounceRoutes) < 1 || len(cfg.ScrapeRoutes) < 1 {
|
||||
return nil, errRoutesNotProvided
|
||||
}
|
||||
|
||||
f := &httpFE{
|
||||
logic: logic,
|
||||
|
||||
@@ -9,15 +9,12 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultReadTimeout = 2 * time.Second
|
||||
defaultWriteTimeout = 2 * time.Second
|
||||
defaultReadTimeout = 2 * time.Second
|
||||
defaultWriteTimeout = 2 * time.Second
|
||||
defaultListenAddress = ":6969"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrAddressNotProvided returned if listen address not provided in configuration
|
||||
ErrAddressNotProvided = errors.New("address not provided")
|
||||
errUnexpectedListenerType = errors.New("unexpected listener type")
|
||||
)
|
||||
var errUnexpectedListenerType = errors.New("unexpected listener type")
|
||||
|
||||
// ListenOptions is the base configuration which may be used in net listeners
|
||||
type ListenOptions struct {
|
||||
@@ -30,11 +27,17 @@ type ListenOptions struct {
|
||||
|
||||
// Validate checks if listen address provided and sets default
|
||||
// timeout options if needed
|
||||
func (lo ListenOptions) Validate() (validOptions ListenOptions, err error) {
|
||||
func (lo ListenOptions) Validate(ignoreTimeouts bool) (validOptions ListenOptions) {
|
||||
validOptions = lo
|
||||
if len(lo.Addr) == 0 {
|
||||
err = ErrAddressNotProvided
|
||||
} else {
|
||||
validOptions.Addr = defaultListenAddress
|
||||
logger.Warn().
|
||||
Str("name", "Addr").
|
||||
Str("provided", lo.Addr).
|
||||
Str("default", validOptions.Addr).
|
||||
Msg("falling back to default configuration")
|
||||
}
|
||||
if !ignoreTimeouts {
|
||||
if lo.ReadTimeout <= 0 {
|
||||
validOptions.ReadTimeout = defaultReadTimeout
|
||||
logger.Warn().
|
||||
|
||||
@@ -23,13 +23,16 @@ import (
|
||||
"github.com/sot-tech/mochi/pkg/timecache"
|
||||
)
|
||||
|
||||
// Name - registered name of the frontend
|
||||
const Name = "udp"
|
||||
|
||||
var (
|
||||
logger = log.NewLogger("frontend/udp")
|
||||
allowedGeneratedPrivateKeyRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
|
||||
)
|
||||
|
||||
func init() {
|
||||
frontend.RegisterBuilder("udp", NewFrontend)
|
||||
frontend.RegisterBuilder(Name, NewFrontend)
|
||||
}
|
||||
|
||||
// Config represents all the configurable options for a UDP BitTorrent
|
||||
@@ -43,13 +46,9 @@ type Config struct {
|
||||
|
||||
// Validate sanity checks values set in a config and returns a new config with
|
||||
// default values replacing anything that is invalid.
|
||||
func (cfg Config) Validate() (validCfg Config, err error) {
|
||||
if len(cfg.Addr) == 0 {
|
||||
err = frontend.ErrAddressNotProvided
|
||||
return
|
||||
}
|
||||
|
||||
func (cfg Config) Validate() (validCfg Config) {
|
||||
validCfg = cfg
|
||||
validCfg.ListenOptions = cfg.ListenOptions.Validate(true)
|
||||
|
||||
// Generate a private key if one isn't provided by the user.
|
||||
if cfg.PrivateKey == "" {
|
||||
@@ -92,9 +91,7 @@ func NewFrontend(c conf.MapConfig, logic *middleware.Logic) (frontend.Frontend,
|
||||
if err = c.Unmarshal(&cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cfg, err = cfg.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg = cfg.Validate()
|
||||
|
||||
f := &udpFE{
|
||||
closing: make(chan any),
|
||||
|
||||
@@ -18,14 +18,18 @@ import (
|
||||
"github.com/sot-tech/mochi/storage"
|
||||
)
|
||||
|
||||
// Default config constants.
|
||||
const defaultShardCount = 1024
|
||||
const (
|
||||
// Name - registered name of the storage
|
||||
Name = "memory"
|
||||
// Default config constants.
|
||||
defaultShardCount = 1024
|
||||
)
|
||||
|
||||
var logger = log.NewLogger("storage/memory")
|
||||
|
||||
func init() {
|
||||
// Register the storage driver.
|
||||
storage.RegisterDriver("memory", builder)
|
||||
storage.RegisterDriver(Name, builder)
|
||||
}
|
||||
|
||||
func builder(icfg conf.MapConfig) (storage.PeerStorage, error) {
|
||||
|
||||
Reference in New Issue
Block a user