diff --git a/pkg/config/runtime/runtime.go b/pkg/config/runtime/runtime.go index c64b22cbe..b59e768b8 100644 --- a/pkg/config/runtime/runtime.go +++ b/pkg/config/runtime/runtime.go @@ -1,10 +1,8 @@ package runtime import ( - "context" "sort" "strings" - "sync" "github.com/containous/traefik/v2/pkg/config/dynamic" "github.com/containous/traefik/v2/pkg/log" @@ -171,255 +169,6 @@ func contains(entryPoints []string, entryPointName string) bool { return false } -// GetRoutersByEntryPoints returns all the http routers by entry points name and routers name -func (c *Configuration) GetRoutersByEntryPoints(ctx context.Context, entryPoints []string, tls bool) map[string]map[string]*RouterInfo { - entryPointsRouters := make(map[string]map[string]*RouterInfo) - - for rtName, rt := range c.Routers { - if (tls && rt.TLS == nil) || (!tls && rt.TLS != nil) { - continue - } - - eps := rt.EntryPoints - if len(eps) == 0 { - eps = entryPoints - } - for _, entryPointName := range eps { - if !contains(entryPoints, entryPointName) { - log.FromContext(log.With(ctx, log.Str(log.EntryPointName, entryPointName))). - Errorf("entryPoint %q doesn't exist", entryPointName) - continue - } - - if _, ok := entryPointsRouters[entryPointName]; !ok { - entryPointsRouters[entryPointName] = make(map[string]*RouterInfo) - } - - entryPointsRouters[entryPointName][rtName] = rt - } - } - - return entryPointsRouters -} - -// GetTCPRoutersByEntryPoints returns all the tcp routers by entry points name and routers name -func (c *Configuration) GetTCPRoutersByEntryPoints(ctx context.Context, entryPoints []string) map[string]map[string]*TCPRouterInfo { - entryPointsRouters := make(map[string]map[string]*TCPRouterInfo) - - for rtName, rt := range c.TCPRouters { - eps := rt.EntryPoints - if len(eps) == 0 { - eps = entryPoints - } - - for _, entryPointName := range eps { - if !contains(entryPoints, entryPointName) { - log.FromContext(log.With(ctx, log.Str(log.EntryPointName, entryPointName))). - Errorf("entryPoint %q doesn't exist", entryPointName) - continue - } - - if _, ok := entryPointsRouters[entryPointName]; !ok { - entryPointsRouters[entryPointName] = make(map[string]*TCPRouterInfo) - } - - entryPointsRouters[entryPointName][rtName] = rt - } - } - - return entryPointsRouters -} - -// RouterInfo holds information about a currently running HTTP router -type RouterInfo struct { - *dynamic.Router // dynamic configuration - // Err contains all the errors that occurred during router's creation. - Err []string `json:"error,omitempty"` - // Status reports whether the router is disabled, in a warning state, or all good (enabled). - // If not in "enabled" state, the reason for it should be in the list of Err. - // It is the caller's responsibility to set the initial status. - Status string `json:"status,omitempty"` -} - -// AddError adds err to r.Err, if it does not already exist. -// If critical is set, r is marked as disabled. -func (r *RouterInfo) AddError(err error, critical bool) { - for _, value := range r.Err { - if value == err.Error() { - return - } - } - - r.Err = append(r.Err, err.Error()) - if critical { - r.Status = StatusDisabled - return - } - - // only set it to "warning" if not already in a worse state - if r.Status != StatusDisabled { - r.Status = StatusWarning - } -} - -// TCPRouterInfo holds information about a currently running TCP router -type TCPRouterInfo struct { - *dynamic.TCPRouter // dynamic configuration - Err []string `json:"error,omitempty"` // initialization error - // Status reports whether the router is disabled, in a warning state, or all good (enabled). - // If not in "enabled" state, the reason for it should be in the list of Err. - // It is the caller's responsibility to set the initial status. - Status string `json:"status,omitempty"` -} - -// AddError adds err to r.Err, if it does not already exist. -// If critical is set, r is marked as disabled. -func (r *TCPRouterInfo) AddError(err error, critical bool) { - for _, value := range r.Err { - if value == err.Error() { - return - } - } - - r.Err = append(r.Err, err.Error()) - if critical { - r.Status = StatusDisabled - return - } - - // only set it to "warning" if not already in a worse state - if r.Status != StatusDisabled { - r.Status = StatusWarning - } -} - -// MiddlewareInfo holds information about a currently running middleware -type MiddlewareInfo struct { - *dynamic.Middleware // dynamic configuration - // Err contains all the errors that occurred during service creation. - Err []string `json:"error,omitempty"` - Status string `json:"status,omitempty"` - UsedBy []string `json:"usedBy,omitempty"` // list of routers and services using that middleware -} - -// AddError adds err to s.Err, if it does not already exist. -// If critical is set, m is marked as disabled. -func (m *MiddlewareInfo) AddError(err error, critical bool) { - for _, value := range m.Err { - if value == err.Error() { - return - } - } - - m.Err = append(m.Err, err.Error()) - if critical { - m.Status = StatusDisabled - return - } - - // only set it to "warning" if not already in a worse state - if m.Status != StatusDisabled { - m.Status = StatusWarning - } -} - -// ServiceInfo holds information about a currently running service -type ServiceInfo struct { - *dynamic.Service // dynamic configuration - // Err contains all the errors that occurred during service creation. - Err []string `json:"error,omitempty"` - // Status reports whether the service is disabled, in a warning state, or all good (enabled). - // If not in "enabled" state, the reason for it should be in the list of Err. - // It is the caller's responsibility to set the initial status. - Status string `json:"status,omitempty"` - UsedBy []string `json:"usedBy,omitempty"` // list of routers using that service - - serverStatusMu sync.RWMutex - serverStatus map[string]string // keyed by server URL -} - -// AddError adds err to s.Err, if it does not already exist. -// If critical is set, s is marked as disabled. -func (s *ServiceInfo) AddError(err error, critical bool) { - for _, value := range s.Err { - if value == err.Error() { - return - } - } - - s.Err = append(s.Err, err.Error()) - if critical { - s.Status = StatusDisabled - return - } - - // only set it to "warning" if not already in a worse state - if s.Status != StatusDisabled { - s.Status = StatusWarning - } -} - -// UpdateServerStatus sets the status of the server in the ServiceInfo. -// It is the responsibility of the caller to check that s is not nil. -func (s *ServiceInfo) UpdateServerStatus(server string, status string) { - s.serverStatusMu.Lock() - defer s.serverStatusMu.Unlock() - - if s.serverStatus == nil { - s.serverStatus = make(map[string]string) - } - s.serverStatus[server] = status -} - -// GetAllStatus returns all the statuses of all the servers in ServiceInfo. -// It is the responsibility of the caller to check that s is not nil -func (s *ServiceInfo) GetAllStatus() map[string]string { - s.serverStatusMu.RLock() - defer s.serverStatusMu.RUnlock() - - if len(s.serverStatus) == 0 { - return nil - } - - allStatus := make(map[string]string, len(s.serverStatus)) - for k, v := range s.serverStatus { - allStatus[k] = v - } - return allStatus -} - -// TCPServiceInfo holds information about a currently running TCP service -type TCPServiceInfo struct { - *dynamic.TCPService // dynamic configuration - Err []string `json:"error,omitempty"` // initialization error - // Status reports whether the service is disabled, in a warning state, or all good (enabled). - // If not in "enabled" state, the reason for it should be in the list of Err. - // It is the caller's responsibility to set the initial status. - Status string `json:"status,omitempty"` - UsedBy []string `json:"usedBy,omitempty"` // list of routers using that service -} - -// AddError adds err to s.Err, if it does not already exist. -// If critical is set, s is marked as disabled. -func (s *TCPServiceInfo) AddError(err error, critical bool) { - for _, value := range s.Err { - if value == err.Error() { - return - } - } - - s.Err = append(s.Err, err.Error()) - if critical { - s.Status = StatusDisabled - return - } - - // only set it to "warning" if not already in a worse state - if s.Status != StatusDisabled { - s.Status = StatusWarning - } -} - func getProviderName(elementName string) string { parts := strings.Split(elementName, "@") if len(parts) > 1 { diff --git a/pkg/config/runtime/runtime_http.go b/pkg/config/runtime/runtime_http.go new file mode 100644 index 000000000..1c6b9e4aa --- /dev/null +++ b/pkg/config/runtime/runtime_http.go @@ -0,0 +1,167 @@ +package runtime + +import ( + "context" + "sync" + + "github.com/containous/traefik/v2/pkg/config/dynamic" + "github.com/containous/traefik/v2/pkg/log" +) + +// GetRoutersByEntryPoints returns all the http routers by entry points name and routers name +func (c *Configuration) GetRoutersByEntryPoints(ctx context.Context, entryPoints []string, tls bool) map[string]map[string]*RouterInfo { + entryPointsRouters := make(map[string]map[string]*RouterInfo) + + for rtName, rt := range c.Routers { + if (tls && rt.TLS == nil) || (!tls && rt.TLS != nil) { + continue + } + + eps := rt.EntryPoints + if len(eps) == 0 { + eps = entryPoints + } + for _, entryPointName := range eps { + if !contains(entryPoints, entryPointName) { + log.FromContext(log.With(ctx, log.Str(log.EntryPointName, entryPointName))). + Errorf("entryPoint %q doesn't exist", entryPointName) + continue + } + + if _, ok := entryPointsRouters[entryPointName]; !ok { + entryPointsRouters[entryPointName] = make(map[string]*RouterInfo) + } + + entryPointsRouters[entryPointName][rtName] = rt + } + } + + return entryPointsRouters +} + +// RouterInfo holds information about a currently running HTTP router +type RouterInfo struct { + *dynamic.Router // dynamic configuration + // Err contains all the errors that occurred during router's creation. + Err []string `json:"error,omitempty"` + // Status reports whether the router is disabled, in a warning state, or all good (enabled). + // If not in "enabled" state, the reason for it should be in the list of Err. + // It is the caller's responsibility to set the initial status. + Status string `json:"status,omitempty"` +} + +// AddError adds err to r.Err, if it does not already exist. +// If critical is set, r is marked as disabled. +func (r *RouterInfo) AddError(err error, critical bool) { + for _, value := range r.Err { + if value == err.Error() { + return + } + } + + r.Err = append(r.Err, err.Error()) + if critical { + r.Status = StatusDisabled + return + } + + // only set it to "warning" if not already in a worse state + if r.Status != StatusDisabled { + r.Status = StatusWarning + } +} + +// MiddlewareInfo holds information about a currently running middleware +type MiddlewareInfo struct { + *dynamic.Middleware // dynamic configuration + // Err contains all the errors that occurred during service creation. + Err []string `json:"error,omitempty"` + Status string `json:"status,omitempty"` + UsedBy []string `json:"usedBy,omitempty"` // list of routers and services using that middleware +} + +// AddError adds err to s.Err, if it does not already exist. +// If critical is set, m is marked as disabled. +func (m *MiddlewareInfo) AddError(err error, critical bool) { + for _, value := range m.Err { + if value == err.Error() { + return + } + } + + m.Err = append(m.Err, err.Error()) + if critical { + m.Status = StatusDisabled + return + } + + // only set it to "warning" if not already in a worse state + if m.Status != StatusDisabled { + m.Status = StatusWarning + } +} + +// ServiceInfo holds information about a currently running service +type ServiceInfo struct { + *dynamic.Service // dynamic configuration + // Err contains all the errors that occurred during service creation. + Err []string `json:"error,omitempty"` + // Status reports whether the service is disabled, in a warning state, or all good (enabled). + // If not in "enabled" state, the reason for it should be in the list of Err. + // It is the caller's responsibility to set the initial status. + Status string `json:"status,omitempty"` + UsedBy []string `json:"usedBy,omitempty"` // list of routers using that service + + serverStatusMu sync.RWMutex + serverStatus map[string]string // keyed by server URL +} + +// AddError adds err to s.Err, if it does not already exist. +// If critical is set, s is marked as disabled. +func (s *ServiceInfo) AddError(err error, critical bool) { + for _, value := range s.Err { + if value == err.Error() { + return + } + } + + s.Err = append(s.Err, err.Error()) + if critical { + s.Status = StatusDisabled + return + } + + // only set it to "warning" if not already in a worse state + if s.Status != StatusDisabled { + s.Status = StatusWarning + } +} + +// UpdateServerStatus sets the status of the server in the ServiceInfo. +// It is the responsibility of the caller to check that s is not nil. +func (s *ServiceInfo) UpdateServerStatus(server string, status string) { + s.serverStatusMu.Lock() + defer s.serverStatusMu.Unlock() + + if s.serverStatus == nil { + s.serverStatus = make(map[string]string) + } + s.serverStatus[server] = status +} + +// GetAllStatus returns all the statuses of all the servers in ServiceInfo. +// It is the responsibility of the caller to check that s is not nil +func (s *ServiceInfo) GetAllStatus() map[string]string { + s.serverStatusMu.RLock() + defer s.serverStatusMu.RUnlock() + + if len(s.serverStatus) == 0 { + return nil + } + + allStatus := make(map[string]string, len(s.serverStatus)) + for k, v := range s.serverStatus { + allStatus[k] = v + } + return allStatus +} diff --git a/pkg/config/runtime/runtime_http_test.go b/pkg/config/runtime/runtime_http_test.go new file mode 100644 index 000000000..38102c61d --- /dev/null +++ b/pkg/config/runtime/runtime_http_test.go @@ -0,0 +1,213 @@ +package runtime + +import ( + "context" + "testing" + + "github.com/containous/traefik/v2/pkg/config/dynamic" + "github.com/stretchr/testify/assert" +) + +func TestGetRoutersByEntryPoints(t *testing.T) { + testCases := []struct { + desc string + conf dynamic.Configuration + entryPoints []string + expected map[string]map[string]*RouterInfo + }{ + { + desc: "Empty Configuration without entrypoint", + conf: dynamic.Configuration{}, + entryPoints: []string{""}, + expected: map[string]map[string]*RouterInfo{}, + }, + { + desc: "Empty Configuration with unknown entrypoints", + conf: dynamic.Configuration{}, + entryPoints: []string{"foo"}, + expected: map[string]map[string]*RouterInfo{}, + }, + { + desc: "Valid configuration with an unknown entrypoint", + conf: dynamic.Configuration{ + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "foo": { + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`bar.foo`)", + }, + }, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "foo": { + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "HostSNI(`bar.foo`)", + }, + }, + }, + }, + entryPoints: []string{"foo"}, + expected: map[string]map[string]*RouterInfo{}, + }, + { + desc: "Valid configuration with a known entrypoint", + conf: dynamic.Configuration{ + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "foo": { + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`bar.foo`)", + }, + "bar": { + EntryPoints: []string{"webs"}, + Service: "bar-service@myprovider", + Rule: "Host(`foo.bar`)", + }, + "foobar": { + EntryPoints: []string{"web", "webs"}, + Service: "foobar-service@myprovider", + Rule: "Host(`bar.foobar`)", + }, + }, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "foo": { + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "HostSNI(`bar.foo`)", + }, + "bar": { + EntryPoints: []string{"webs"}, + Service: "bar-service@myprovider", + Rule: "HostSNI(`foo.bar`)", + }, + "foobar": { + EntryPoints: []string{"web", "webs"}, + Service: "foobar-service@myprovider", + Rule: "HostSNI(`bar.foobar`)", + }, + }, + }, + }, + entryPoints: []string{"web"}, + expected: map[string]map[string]*RouterInfo{ + "web": { + "foo": { + Router: &dynamic.Router{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`bar.foo`)", + }, + Status: "enabled", + }, + "foobar": { + Router: &dynamic.Router{ + EntryPoints: []string{"web", "webs"}, + Service: "foobar-service@myprovider", + Rule: "Host(`bar.foobar`)", + }, + Status: "enabled", + }, + }, + }, + }, + { + desc: "Valid configuration with multiple known entrypoints", + conf: dynamic.Configuration{ + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "foo": { + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`bar.foo`)", + }, + "bar": { + EntryPoints: []string{"webs"}, + Service: "bar-service@myprovider", + Rule: "Host(`foo.bar`)", + }, + "foobar": { + EntryPoints: []string{"web", "webs"}, + Service: "foobar-service@myprovider", + Rule: "Host(`bar.foobar`)", + }, + }, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "foo": { + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "HostSNI(`bar.foo`)", + }, + "bar": { + EntryPoints: []string{"webs"}, + Service: "bar-service@myprovider", + Rule: "HostSNI(`foo.bar`)", + }, + "foobar": { + EntryPoints: []string{"web", "webs"}, + Service: "foobar-service@myprovider", + Rule: "HostSNI(`bar.foobar`)", + }, + }, + }, + }, + entryPoints: []string{"web", "webs"}, + expected: map[string]map[string]*RouterInfo{ + "web": { + "foo": { + Router: &dynamic.Router{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`bar.foo`)", + }, + Status: "enabled", + }, + "foobar": { + Router: &dynamic.Router{ + EntryPoints: []string{"web", "webs"}, + Service: "foobar-service@myprovider", + Rule: "Host(`bar.foobar`)", + }, + Status: "enabled", + }, + }, + "webs": { + "bar": { + Router: &dynamic.Router{ + + EntryPoints: []string{"webs"}, + Service: "bar-service@myprovider", + Rule: "Host(`foo.bar`)", + }, + Status: "enabled", + }, + "foobar": { + Router: &dynamic.Router{ + EntryPoints: []string{"web", "webs"}, + Service: "foobar-service@myprovider", + Rule: "Host(`bar.foobar`)", + }, + Status: "enabled", + }, + }, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + runtimeConfig := NewConfig(test.conf) + actual := runtimeConfig.GetRoutersByEntryPoints(context.Background(), test.entryPoints, false) + assert.Equal(t, test.expected, actual) + }) + } +} diff --git a/pkg/config/runtime/runtime_tcp.go b/pkg/config/runtime/runtime_tcp.go new file mode 100644 index 000000000..a99d519f9 --- /dev/null +++ b/pkg/config/runtime/runtime_tcp.go @@ -0,0 +1,99 @@ +package runtime + +import ( + "context" + + "github.com/containous/traefik/v2/pkg/config/dynamic" + "github.com/containous/traefik/v2/pkg/log" +) + +// GetTCPRoutersByEntryPoints returns all the tcp routers by entry points name and routers name +func (c *Configuration) GetTCPRoutersByEntryPoints(ctx context.Context, entryPoints []string) map[string]map[string]*TCPRouterInfo { + entryPointsRouters := make(map[string]map[string]*TCPRouterInfo) + + for rtName, rt := range c.TCPRouters { + eps := rt.EntryPoints + if len(eps) == 0 { + eps = entryPoints + } + + for _, entryPointName := range eps { + if !contains(entryPoints, entryPointName) { + log.FromContext(log.With(ctx, log.Str(log.EntryPointName, entryPointName))). + Errorf("entryPoint %q doesn't exist", entryPointName) + continue + } + + if _, ok := entryPointsRouters[entryPointName]; !ok { + entryPointsRouters[entryPointName] = make(map[string]*TCPRouterInfo) + } + + entryPointsRouters[entryPointName][rtName] = rt + } + } + + return entryPointsRouters +} + +// TCPRouterInfo holds information about a currently running TCP router +type TCPRouterInfo struct { + *dynamic.TCPRouter // dynamic configuration + Err []string `json:"error,omitempty"` // initialization error + // Status reports whether the router is disabled, in a warning state, or all good (enabled). + // If not in "enabled" state, the reason for it should be in the list of Err. + // It is the caller's responsibility to set the initial status. + Status string `json:"status,omitempty"` +} + +// AddError adds err to r.Err, if it does not already exist. +// If critical is set, r is marked as disabled. +func (r *TCPRouterInfo) AddError(err error, critical bool) { + for _, value := range r.Err { + if value == err.Error() { + return + } + } + + r.Err = append(r.Err, err.Error()) + if critical { + r.Status = StatusDisabled + return + } + + // only set it to "warning" if not already in a worse state + if r.Status != StatusDisabled { + r.Status = StatusWarning + } +} + +// TCPServiceInfo holds information about a currently running TCP service +type TCPServiceInfo struct { + *dynamic.TCPService // dynamic configuration + Err []string `json:"error,omitempty"` // initialization error + // Status reports whether the service is disabled, in a warning state, or all good (enabled). + // If not in "enabled" state, the reason for it should be in the list of Err. + // It is the caller's responsibility to set the initial status. + Status string `json:"status,omitempty"` + UsedBy []string `json:"usedBy,omitempty"` // list of routers using that service +} + +// AddError adds err to s.Err, if it does not already exist. +// If critical is set, s is marked as disabled. +func (s *TCPServiceInfo) AddError(err error, critical bool) { + for _, value := range s.Err { + if value == err.Error() { + return + } + } + + s.Err = append(s.Err, err.Error()) + if critical { + s.Status = StatusDisabled + return + } + + // only set it to "warning" if not already in a worse state + if s.Status != StatusDisabled { + s.Status = StatusWarning + } +} diff --git a/pkg/config/runtime/runtime_tcp_test.go b/pkg/config/runtime/runtime_tcp_test.go new file mode 100644 index 000000000..9fb3f137e --- /dev/null +++ b/pkg/config/runtime/runtime_tcp_test.go @@ -0,0 +1,213 @@ +package runtime + +import ( + "context" + "testing" + + "github.com/containous/traefik/v2/pkg/config/dynamic" + "github.com/stretchr/testify/assert" +) + +func TestGetTCPRoutersByEntryPoints(t *testing.T) { + testCases := []struct { + desc string + conf dynamic.Configuration + entryPoints []string + expected map[string]map[string]*TCPRouterInfo + }{ + { + desc: "Empty Configuration without entrypoint", + conf: dynamic.Configuration{}, + entryPoints: []string{""}, + expected: map[string]map[string]*TCPRouterInfo{}, + }, + { + desc: "Empty Configuration with unknown entrypoints", + conf: dynamic.Configuration{}, + entryPoints: []string{"foo"}, + expected: map[string]map[string]*TCPRouterInfo{}, + }, + { + desc: "Valid configuration with an unknown entrypoint", + conf: dynamic.Configuration{ + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "foo": { + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`bar.foo`)", + }, + }, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "foo": { + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "HostSNI(`bar.foo`)", + }, + }, + }, + }, + entryPoints: []string{"foo"}, + expected: map[string]map[string]*TCPRouterInfo{}, + }, + { + desc: "Valid configuration with a known entrypoint", + conf: dynamic.Configuration{ + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "foo": { + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`bar.foo`)", + }, + "bar": { + EntryPoints: []string{"webs"}, + Service: "bar-service@myprovider", + Rule: "Host(`foo.bar`)", + }, + "foobar": { + EntryPoints: []string{"web", "webs"}, + Service: "foobar-service@myprovider", + Rule: "Host(`bar.foobar`)", + }, + }, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "foo": { + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "HostSNI(`bar.foo`)", + }, + "bar": { + EntryPoints: []string{"webs"}, + Service: "bar-service@myprovider", + Rule: "HostSNI(`foo.bar`)", + }, + "foobar": { + EntryPoints: []string{"web", "webs"}, + Service: "foobar-service@myprovider", + Rule: "HostSNI(`bar.foobar`)", + }, + }, + }, + }, + entryPoints: []string{"web"}, + expected: map[string]map[string]*TCPRouterInfo{ + "web": { + "foo": { + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "HostSNI(`bar.foo`)", + }, + Status: "enabled", + }, + "foobar": { + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web", "webs"}, + Service: "foobar-service@myprovider", + Rule: "HostSNI(`bar.foobar`)", + }, + Status: "enabled", + }, + }, + }, + }, + { + desc: "Valid configuration with multiple known entrypoints", + conf: dynamic.Configuration{ + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "foo": { + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`bar.foo`)", + }, + "bar": { + EntryPoints: []string{"webs"}, + Service: "bar-service@myprovider", + Rule: "Host(`foo.bar`)", + }, + "foobar": { + EntryPoints: []string{"web", "webs"}, + Service: "foobar-service@myprovider", + Rule: "Host(`bar.foobar`)", + }, + }, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "foo": { + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "HostSNI(`bar.foo`)", + }, + "bar": { + EntryPoints: []string{"webs"}, + Service: "bar-service@myprovider", + Rule: "HostSNI(`foo.bar`)", + }, + "foobar": { + EntryPoints: []string{"web", "webs"}, + Service: "foobar-service@myprovider", + Rule: "HostSNI(`bar.foobar`)", + }, + }, + }, + }, + entryPoints: []string{"web", "webs"}, + expected: map[string]map[string]*TCPRouterInfo{ + "web": { + "foo": { + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "HostSNI(`bar.foo`)", + }, + Status: "enabled", + }, + "foobar": { + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web", "webs"}, + Service: "foobar-service@myprovider", + Rule: "HostSNI(`bar.foobar`)", + }, + Status: "enabled", + }, + }, + "webs": { + "bar": { + TCPRouter: &dynamic.TCPRouter{ + + EntryPoints: []string{"webs"}, + Service: "bar-service@myprovider", + Rule: "HostSNI(`foo.bar`)", + }, + Status: "enabled", + }, + "foobar": { + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web", "webs"}, + Service: "foobar-service@myprovider", + Rule: "HostSNI(`bar.foobar`)", + }, + Status: "enabled", + }, + }, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + runtimeConfig := NewConfig(test.conf) + actual := runtimeConfig.GetTCPRoutersByEntryPoints(context.Background(), test.entryPoints) + assert.Equal(t, test.expected, actual) + }) + } +} diff --git a/pkg/config/runtime/runtime_test.go b/pkg/config/runtime/runtime_test.go index 5a20af3d9..d220abe84 100644 --- a/pkg/config/runtime/runtime_test.go +++ b/pkg/config/runtime/runtime_test.go @@ -1,7 +1,6 @@ package runtime_test import ( - "context" "testing" "github.com/containous/traefik/v2/pkg/config/dynamic" @@ -690,411 +689,3 @@ func TestPopulateUsedBy(t *testing.T) { } } - -func TestGetTCPRoutersByEntryPoints(t *testing.T) { - testCases := []struct { - desc string - conf dynamic.Configuration - entryPoints []string - expected map[string]map[string]*runtime.TCPRouterInfo - }{ - { - desc: "Empty Configuration without entrypoint", - conf: dynamic.Configuration{}, - entryPoints: []string{""}, - expected: map[string]map[string]*runtime.TCPRouterInfo{}, - }, - { - desc: "Empty Configuration with unknown entrypoints", - conf: dynamic.Configuration{}, - entryPoints: []string{"foo"}, - expected: map[string]map[string]*runtime.TCPRouterInfo{}, - }, - { - desc: "Valid configuration with an unknown entrypoint", - conf: dynamic.Configuration{ - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "foo": { - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "Host(`bar.foo`)", - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "HostSNI(`bar.foo`)", - }, - }, - }, - }, - entryPoints: []string{"foo"}, - expected: map[string]map[string]*runtime.TCPRouterInfo{}, - }, - { - desc: "Valid configuration with a known entrypoint", - conf: dynamic.Configuration{ - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "foo": { - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "Host(`bar.foo`)", - }, - "bar": { - EntryPoints: []string{"webs"}, - Service: "bar-service@myprovider", - Rule: "Host(`foo.bar`)", - }, - "foobar": { - EntryPoints: []string{"web", "webs"}, - Service: "foobar-service@myprovider", - Rule: "Host(`bar.foobar`)", - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "HostSNI(`bar.foo`)", - }, - "bar": { - EntryPoints: []string{"webs"}, - Service: "bar-service@myprovider", - Rule: "HostSNI(`foo.bar`)", - }, - "foobar": { - EntryPoints: []string{"web", "webs"}, - Service: "foobar-service@myprovider", - Rule: "HostSNI(`bar.foobar`)", - }, - }, - }, - }, - entryPoints: []string{"web"}, - expected: map[string]map[string]*runtime.TCPRouterInfo{ - "web": { - "foo": { - TCPRouter: &dynamic.TCPRouter{ - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "HostSNI(`bar.foo`)", - }, - Status: "enabled", - }, - "foobar": { - TCPRouter: &dynamic.TCPRouter{ - EntryPoints: []string{"web", "webs"}, - Service: "foobar-service@myprovider", - Rule: "HostSNI(`bar.foobar`)", - }, - Status: "enabled", - }, - }, - }, - }, - { - desc: "Valid configuration with multiple known entrypoints", - conf: dynamic.Configuration{ - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "foo": { - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "Host(`bar.foo`)", - }, - "bar": { - EntryPoints: []string{"webs"}, - Service: "bar-service@myprovider", - Rule: "Host(`foo.bar`)", - }, - "foobar": { - EntryPoints: []string{"web", "webs"}, - Service: "foobar-service@myprovider", - Rule: "Host(`bar.foobar`)", - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "HostSNI(`bar.foo`)", - }, - "bar": { - EntryPoints: []string{"webs"}, - Service: "bar-service@myprovider", - Rule: "HostSNI(`foo.bar`)", - }, - "foobar": { - EntryPoints: []string{"web", "webs"}, - Service: "foobar-service@myprovider", - Rule: "HostSNI(`bar.foobar`)", - }, - }, - }, - }, - entryPoints: []string{"web", "webs"}, - expected: map[string]map[string]*runtime.TCPRouterInfo{ - "web": { - "foo": { - TCPRouter: &dynamic.TCPRouter{ - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "HostSNI(`bar.foo`)", - }, - Status: "enabled", - }, - "foobar": { - TCPRouter: &dynamic.TCPRouter{ - EntryPoints: []string{"web", "webs"}, - Service: "foobar-service@myprovider", - Rule: "HostSNI(`bar.foobar`)", - }, - Status: "enabled", - }, - }, - "webs": { - "bar": { - TCPRouter: &dynamic.TCPRouter{ - - EntryPoints: []string{"webs"}, - Service: "bar-service@myprovider", - Rule: "HostSNI(`foo.bar`)", - }, - Status: "enabled", - }, - "foobar": { - TCPRouter: &dynamic.TCPRouter{ - EntryPoints: []string{"web", "webs"}, - Service: "foobar-service@myprovider", - Rule: "HostSNI(`bar.foobar`)", - }, - Status: "enabled", - }, - }, - }, - }, - } - - for _, test := range testCases { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - runtimeConfig := runtime.NewConfig(test.conf) - actual := runtimeConfig.GetTCPRoutersByEntryPoints(context.Background(), test.entryPoints) - assert.Equal(t, test.expected, actual) - }) - } -} - -func TestGetRoutersByEntryPoints(t *testing.T) { - testCases := []struct { - desc string - conf dynamic.Configuration - entryPoints []string - expected map[string]map[string]*runtime.RouterInfo - }{ - { - desc: "Empty Configuration without entrypoint", - conf: dynamic.Configuration{}, - entryPoints: []string{""}, - expected: map[string]map[string]*runtime.RouterInfo{}, - }, - { - desc: "Empty Configuration with unknown entrypoints", - conf: dynamic.Configuration{}, - entryPoints: []string{"foo"}, - expected: map[string]map[string]*runtime.RouterInfo{}, - }, - { - desc: "Valid configuration with an unknown entrypoint", - conf: dynamic.Configuration{ - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "foo": { - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "Host(`bar.foo`)", - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "HostSNI(`bar.foo`)", - }, - }, - }, - }, - entryPoints: []string{"foo"}, - expected: map[string]map[string]*runtime.RouterInfo{}, - }, - { - desc: "Valid configuration with a known entrypoint", - conf: dynamic.Configuration{ - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "foo": { - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "Host(`bar.foo`)", - }, - "bar": { - EntryPoints: []string{"webs"}, - Service: "bar-service@myprovider", - Rule: "Host(`foo.bar`)", - }, - "foobar": { - EntryPoints: []string{"web", "webs"}, - Service: "foobar-service@myprovider", - Rule: "Host(`bar.foobar`)", - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "HostSNI(`bar.foo`)", - }, - "bar": { - EntryPoints: []string{"webs"}, - Service: "bar-service@myprovider", - Rule: "HostSNI(`foo.bar`)", - }, - "foobar": { - EntryPoints: []string{"web", "webs"}, - Service: "foobar-service@myprovider", - Rule: "HostSNI(`bar.foobar`)", - }, - }, - }, - }, - entryPoints: []string{"web"}, - expected: map[string]map[string]*runtime.RouterInfo{ - "web": { - "foo": { - Router: &dynamic.Router{ - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "Host(`bar.foo`)", - }, - Status: "enabled", - }, - "foobar": { - Router: &dynamic.Router{ - EntryPoints: []string{"web", "webs"}, - Service: "foobar-service@myprovider", - Rule: "Host(`bar.foobar`)", - }, - Status: "enabled", - }, - }, - }, - }, - { - desc: "Valid configuration with multiple known entrypoints", - conf: dynamic.Configuration{ - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "foo": { - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "Host(`bar.foo`)", - }, - "bar": { - EntryPoints: []string{"webs"}, - Service: "bar-service@myprovider", - Rule: "Host(`foo.bar`)", - }, - "foobar": { - EntryPoints: []string{"web", "webs"}, - Service: "foobar-service@myprovider", - Rule: "Host(`bar.foobar`)", - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "HostSNI(`bar.foo`)", - }, - "bar": { - EntryPoints: []string{"webs"}, - Service: "bar-service@myprovider", - Rule: "HostSNI(`foo.bar`)", - }, - "foobar": { - EntryPoints: []string{"web", "webs"}, - Service: "foobar-service@myprovider", - Rule: "HostSNI(`bar.foobar`)", - }, - }, - }, - }, - entryPoints: []string{"web", "webs"}, - expected: map[string]map[string]*runtime.RouterInfo{ - "web": { - "foo": { - Router: &dynamic.Router{ - EntryPoints: []string{"web"}, - Service: "foo-service@myprovider", - Rule: "Host(`bar.foo`)", - }, - Status: "enabled", - }, - "foobar": { - Router: &dynamic.Router{ - EntryPoints: []string{"web", "webs"}, - Service: "foobar-service@myprovider", - Rule: "Host(`bar.foobar`)", - }, - Status: "enabled", - }, - }, - "webs": { - "bar": { - Router: &dynamic.Router{ - - EntryPoints: []string{"webs"}, - Service: "bar-service@myprovider", - Rule: "Host(`foo.bar`)", - }, - Status: "enabled", - }, - "foobar": { - Router: &dynamic.Router{ - EntryPoints: []string{"web", "webs"}, - Service: "foobar-service@myprovider", - Rule: "Host(`bar.foobar`)", - }, - Status: "enabled", - }, - }, - }, - }, - } - - for _, test := range testCases { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - runtimeConfig := runtime.NewConfig(test.conf) - actual := runtimeConfig.GetRoutersByEntryPoints(context.Background(), test.entryPoints, false) - assert.Equal(t, test.expected, actual) - }) - } -}