56 lines
1.7 KiB
Go
56 lines
1.7 KiB
Go
package traefik
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
// ErrConflict meldet zwei unterschiedliche Definitionen unter demselben Namen.
|
|
var ErrConflict = errors.New("Namenskonflikt")
|
|
|
|
// Merge führt die Konfigurationen mehrerer Knoten zu einer zusammen.
|
|
// nil-Einträge werden übersprungen. Identische Definitionen unter demselben
|
|
// Namen sind erlaubt, unterschiedliche ergeben ErrConflict; das Vergeben
|
|
// eindeutiger Namen (z. B. pro Mandant/Knoten) ist Aufgabe des Aufrufers.
|
|
// Die Eingaben werden nicht verändert, das Ergebnis teilt sich aber die
|
|
// Router-, Service- und Middleware-Objekte mit ihnen.
|
|
func Merge(configs ...*Configuration) (*Configuration, error) {
|
|
out := &HTTPConfiguration{
|
|
Routers: map[string]*Router{},
|
|
Services: map[string]*Service{},
|
|
Middlewares: map[string]Middleware{},
|
|
}
|
|
var errs []error
|
|
for _, c := range configs {
|
|
if c == nil || c.HTTP == nil {
|
|
continue
|
|
}
|
|
errs = append(errs, mergeInto(out.Routers, c.HTTP.Routers, "router")...)
|
|
errs = append(errs, mergeInto(out.Services, c.HTTP.Services, "service")...)
|
|
errs = append(errs, mergeInto(out.Middlewares, c.HTTP.Middlewares, "middleware")...)
|
|
}
|
|
if len(errs) > 0 {
|
|
return nil, errors.Join(errs...)
|
|
}
|
|
if len(out.Routers) == 0 && len(out.Services) == 0 && len(out.Middlewares) == 0 {
|
|
return &Configuration{}, nil
|
|
}
|
|
return &Configuration{HTTP: out}, nil
|
|
}
|
|
|
|
func mergeInto[V any](dst, src map[string]V, kind string) []error {
|
|
var errs []error
|
|
for name, v := range src {
|
|
existing, ok := dst[name]
|
|
if !ok {
|
|
dst[name] = v
|
|
continue
|
|
}
|
|
if !reflect.DeepEqual(existing, v) {
|
|
errs = append(errs, fmt.Errorf("%s %q: %w", kind, name, ErrConflict))
|
|
}
|
|
}
|
|
return errs
|
|
}
|