mirror of
https://github.com/yusing/godoxy.git
synced 2025-06-15 06:26:47 +02:00
refactor(config): enhance provider conflict error messages, streamline provider loading, and improve validation for config files, rename provider.GetType() to Type()
This commit is contained in:
parent
73a5c57d67
commit
b53dd17b84
4 changed files with 35 additions and 47 deletions
|
@ -51,6 +51,8 @@ You may run "ls-config" to show or dump the current config.`
|
|||
|
||||
var Validate = config.Validate
|
||||
|
||||
var ErrProviderNameConflict = gperr.New("provider name conflict")
|
||||
|
||||
func newConfig() *Config {
|
||||
return &Config{
|
||||
value: config.DefaultConfig(),
|
||||
|
@ -263,56 +265,48 @@ func (cfg *Config) initAutoCert(autocertCfg *autocert.AutocertConfig) (err gperr
|
|||
}
|
||||
|
||||
func (cfg *Config) errIfExists(p *proxy.Provider) gperr.Error {
|
||||
if _, ok := cfg.providers.Load(p.String()); ok {
|
||||
return gperr.Errorf("provider %s already exists", p.String())
|
||||
if conflict, ok := cfg.providers.Load(p.String()); ok {
|
||||
return ErrProviderNameConflict.
|
||||
Subject(p.String()).
|
||||
Withf("one is %q", conflict.Type()).
|
||||
Withf("the other is %q", p.Type())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfg *Config) storeProvider(p *proxy.Provider) {
|
||||
cfg.providers.Store(p.String(), p)
|
||||
}
|
||||
|
||||
func (cfg *Config) loadRouteProviders(providers *config.Providers) gperr.Error {
|
||||
errs := gperr.NewBuilder("route provider errors")
|
||||
results := gperr.NewBuilder("loaded route providers")
|
||||
|
||||
removeAllAgents()
|
||||
|
||||
routeProviders := make([]*proxy.Provider, 0, len(providers.Agents)+len(providers.Docker)+len(providers.Files))
|
||||
|
||||
for _, agent := range providers.Agents {
|
||||
if err := agent.Init(cfg.task.Context()); err != nil {
|
||||
errs.Add(err.Subject(agent.String()))
|
||||
continue
|
||||
}
|
||||
addAgent(agent)
|
||||
p := proxy.NewAgentProvider(agent)
|
||||
if err := cfg.errIfExists(p); err != nil {
|
||||
errs.Add(err.Subject(p.String()))
|
||||
continue
|
||||
}
|
||||
cfg.storeProvider(p)
|
||||
routeProviders = append(routeProviders, proxy.NewAgentProvider(agent))
|
||||
}
|
||||
for _, filename := range providers.Files {
|
||||
p, err := proxy.NewFileProvider(filename)
|
||||
if err == nil {
|
||||
err = cfg.errIfExists(p)
|
||||
}
|
||||
if err != nil {
|
||||
errs.Add(gperr.PrependSubject(filename, err))
|
||||
continue
|
||||
}
|
||||
cfg.storeProvider(p)
|
||||
routeProviders = append(routeProviders, proxy.NewFileProvider(filename))
|
||||
}
|
||||
for name, dockerHost := range providers.Docker {
|
||||
p := proxy.NewDockerProvider(name, dockerHost)
|
||||
routeProviders = append(routeProviders, proxy.NewDockerProvider(name, dockerHost))
|
||||
}
|
||||
if len(routeProviders) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// check if all providers are unique (should not happen but just in case)
|
||||
for _, p := range routeProviders {
|
||||
if err := cfg.errIfExists(p); err != nil {
|
||||
errs.Add(err.Subject(p.String()))
|
||||
errs.Add(err)
|
||||
continue
|
||||
}
|
||||
cfg.storeProvider(p)
|
||||
}
|
||||
if cfg.providers.Size() == 0 {
|
||||
return nil
|
||||
cfg.providers.Store(p.String(), p)
|
||||
}
|
||||
|
||||
lenLongestName := 0
|
||||
|
|
|
@ -2,12 +2,15 @@ package types
|
|||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"sync"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/yusing/go-proxy/agent/pkg/agent"
|
||||
"github.com/yusing/go-proxy/internal/autocert"
|
||||
"github.com/yusing/go-proxy/internal/common"
|
||||
"github.com/yusing/go-proxy/internal/gperr"
|
||||
"github.com/yusing/go-proxy/internal/net/gphttp/accesslog"
|
||||
"github.com/yusing/go-proxy/internal/notif"
|
||||
|
@ -24,10 +27,10 @@ type (
|
|||
TimeoutShutdown int `json:"timeout_shutdown" validate:"gte=0"`
|
||||
}
|
||||
Providers struct {
|
||||
Files []string `json:"include" yaml:"include,omitempty" validate:"dive,filepath"`
|
||||
Docker map[string]string `json:"docker" yaml:"docker,omitempty" validate:"non_empty_docker_keys,dive,unix_addr|url"`
|
||||
Agents []*agent.AgentConfig `json:"agents" yaml:"agents,omitempty"`
|
||||
Notification []notif.NotificationConfig `json:"notification" yaml:"notification,omitempty"`
|
||||
Files []string `json:"include" yaml:"include,omitempty" validate:"unique,dive,config_file_exists"`
|
||||
Docker map[string]string `json:"docker" yaml:"docker,omitempty" validate:"unique,dive,unix_addr|url"`
|
||||
Agents []*agent.AgentConfig `json:"agents" yaml:"agents,omitempty" validate:"unique=Addr"`
|
||||
Notification []notif.NotificationConfig `json:"notification" yaml:"notification,omitempty" validate:"unique=ProviderName"`
|
||||
}
|
||||
Entrypoint struct {
|
||||
Middlewares []map[string]any `json:"middlewares"`
|
||||
|
@ -97,13 +100,9 @@ func init() {
|
|||
}
|
||||
return true
|
||||
})
|
||||
utils.MustRegisterValidation("non_empty_docker_keys", func(fl validator.FieldLevel) bool {
|
||||
m := fl.Field().Interface().(map[string]string)
|
||||
for k := range m {
|
||||
if k == "" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
utils.MustRegisterValidation("config_file_exists", func(fl validator.FieldLevel) bool {
|
||||
filename := fl.Field().Interface().(string)
|
||||
info, err := os.Stat(path.Join(common.ConfigBasePath, filename))
|
||||
return err == nil && !info.IsDir()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ func (handler *EventHandler) matchAny(events []watcher.Event, route *route.Route
|
|||
}
|
||||
|
||||
func (handler *EventHandler) match(event watcher.Event, route *route.Route) bool {
|
||||
switch handler.provider.GetType() {
|
||||
switch handler.provider.Type() {
|
||||
case types.ProviderTypeDocker, types.ProviderTypeAgent:
|
||||
return route.Container.ContainerID == event.ActorID ||
|
||||
route.Container.ContainerName == event.ActorName
|
||||
|
|
|
@ -20,17 +20,12 @@ type FileProvider struct {
|
|||
l zerolog.Logger
|
||||
}
|
||||
|
||||
func FileProviderImpl(filename string) (ProviderImpl, error) {
|
||||
impl := &FileProvider{
|
||||
func FileProviderImpl(filename string) ProviderImpl {
|
||||
return &FileProvider{
|
||||
fileName: filename,
|
||||
path: path.Join(common.ConfigBasePath, filename),
|
||||
l: logging.With().Str("type", "file").Str("name", filename).Logger(),
|
||||
}
|
||||
_, err := os.Stat(impl.path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return impl, nil
|
||||
}
|
||||
|
||||
func validate(data []byte) (routes route.Routes, err gperr.Error) {
|
||||
|
|
Loading…
Add table
Reference in a new issue