1
0
Fork 0

Merge branch v3.0 into master

This commit is contained in:
Fernandez Ludovic 2024-04-03 20:30:13 +02:00
commit 1ffbffb26a
326 changed files with 8850 additions and 9322 deletions

View file

@ -2,6 +2,7 @@ package acme
import (
"fmt"
"slices"
"sync"
"time"
@ -119,7 +120,7 @@ func (c *ChallengeTLSALPN) ListenConfiguration(conf dynamic.Configuration) {
c.muChans.Lock()
for _, certificate := range conf.TLS.Certificates {
if !containsACMETLS1(certificate.Stores) {
if !slices.Contains(certificate.Stores, tlsalpn01.ACMETLS1Protocol) {
continue
}
@ -162,13 +163,3 @@ func createMessage(certs map[string]*Certificate) dynamic.Message {
return conf
}
func containsACMETLS1(stores []string) bool {
for _, store := range stores {
if store == tlsalpn01.ACMETLS1Protocol {
return true
}
}
return false
}

View file

@ -44,7 +44,6 @@ func TestLocalStore_GetAccount(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
s := NewLocalStore(test.filename)

View file

@ -33,9 +33,6 @@ import (
const resolverSuffix = ".acme"
// ocspMustStaple enables OCSP stapling as from https://github.com/go-acme/lego/issues/270.
var ocspMustStaple = false
// Configuration holds ACME configuration provided by users.
type Configuration struct {
Email string `description:"Email address used for registration." json:"email,omitempty" toml:"email,omitempty" yaml:"email,omitempty"`
@ -427,7 +424,7 @@ func (p *Provider) watchNewDomains(ctx context.Context) {
if len(route.TLS.Domains) > 0 {
domains := deleteUnnecessaryDomains(ctxRouter, route.TLS.Domains)
for i := 0; i < len(domains); i++ {
for i := range len(domains) {
domain := domains[i]
safe.Go(func() {
dom, cert, err := p.resolveCertificate(ctx, domain, traefiktls.DefaultTLSStoreName)
@ -464,7 +461,7 @@ func (p *Provider) watchNewDomains(ctx context.Context) {
if len(route.TLS.Domains) > 0 {
domains := deleteUnnecessaryDomains(ctxRouter, route.TLS.Domains)
for i := 0; i < len(domains); i++ {
for i := range len(domains) {
domain := domains[i]
safe.Go(func() {
dom, cert, err := p.resolveCertificate(ctx, domain, traefiktls.DefaultTLSStoreName)
@ -585,7 +582,6 @@ func (p *Provider) resolveDefaultCertificate(ctx context.Context, domains []stri
request := certificate.ObtainRequest{
Domains: domains,
Bundle: true,
MustStaple: ocspMustStaple,
PreferredChain: p.PreferredChain,
}
@ -630,7 +626,6 @@ func (p *Provider) resolveCertificate(ctx context.Context, domain types.Domain,
request := certificate.ObtainRequest{
Domains: domains,
Bundle: true,
MustStaple: ocspMustStaple,
PreferredChain: p.PreferredChain,
}
@ -821,11 +816,18 @@ func (p *Provider) renewCertificates(ctx context.Context, renewPeriod time.Durat
logger.Info().Msgf("Renewing certificate from LE : %+v", cert.Domain)
renewedCert, err := client.Certificate.Renew(certificate.Resource{
res := certificate.Resource{
Domain: cert.Domain.Main,
PrivateKey: cert.Key,
Certificate: cert.Certificate.Certificate,
}, true, ocspMustStaple, p.PreferredChain)
}
opts := &certificate.RenewOptions{
Bundle: true,
PreferredChain: p.PreferredChain,
}
renewedCert, err := client.Certificate.RenewWithOptions(res, opts)
if err != nil {
logger.Error().Err(err).Msgf("Error renewing certificate from LE: %v", cert.Domain)
continue

View file

@ -166,7 +166,6 @@ func TestGetUncheckedCertificates(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -241,7 +240,6 @@ func TestProvider_sanitizeDomains(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -423,7 +421,6 @@ func TestDeleteUnnecessaryDomains(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -497,7 +494,6 @@ func TestIsAccountMatchingCaServer(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -573,7 +569,6 @@ func TestInitAccount(t *testing.T) {
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -632,7 +627,6 @@ func Test_getCertificateRenewDurations(t *testing.T) {
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()

View file

@ -179,7 +179,6 @@ func (p ProviderAggregator) Provide(configurationChan chan<- dynamic.Message, po
}
for _, prd := range p.providers {
prd := prd
safe.Go(func() {
p.launchProvider(configurationChan, pool, prd)
})

View file

@ -13,9 +13,10 @@ import (
"github.com/rs/zerolog/log"
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/logs"
"github.com/traefik/traefik/v3/pkg/tls"
)
// Merge Merges multiple configurations.
// Merge merges multiple configurations.
func Merge(ctx context.Context, configurations map[string]*dynamic.Configuration) *dynamic.Configuration {
logger := log.Ctx(ctx)
@ -36,6 +37,9 @@ func Merge(ctx context.Context, configurations map[string]*dynamic.Configuration
Routers: make(map[string]*dynamic.UDPRouter),
Services: make(map[string]*dynamic.UDPService),
},
TLS: &dynamic.TLSConfiguration{
Stores: make(map[string]tls.Store),
},
}
servicesToDelete := map[string]struct{}{}
@ -68,6 +72,9 @@ func Merge(ctx context.Context, configurations map[string]*dynamic.Configuration
transportsTCPToDelete := map[string]struct{}{}
transportsTCP := map[string][]string{}
storesToDelete := map[string]struct{}{}
stores := map[string][]string{}
var sortedKeys []string
for key := range configurations {
sortedKeys = append(sortedKeys, key)
@ -145,6 +152,13 @@ func Merge(ctx context.Context, configurations map[string]*dynamic.Configuration
middlewaresTCPToDelete[middlewareName] = struct{}{}
}
}
for storeName, store := range conf.TLS.Stores {
stores[storeName] = append(stores[storeName], root)
if !AddStore(configuration.TLS, storeName, store) {
storesToDelete[storeName] = struct{}{}
}
}
}
for serviceName := range servicesToDelete {
@ -217,6 +231,12 @@ func Merge(ctx context.Context, configurations map[string]*dynamic.Configuration
delete(configuration.TCP.Middlewares, middlewareName)
}
for storeName := range storesToDelete {
logger.Error().Str("storeName", storeName).
Msgf("TLS store defined multiple times with different configurations in %v", stores[storeName])
delete(configuration.TLS.Stores, storeName)
}
return configuration
}
@ -365,7 +385,17 @@ func AddMiddleware(configuration *dynamic.HTTPConfiguration, middlewareName stri
return reflect.DeepEqual(configuration.Middlewares[middlewareName], middleware)
}
// MakeDefaultRuleTemplate Creates the default rule template.
// AddStore adds a middleware to a configurations.
func AddStore(configuration *dynamic.TLSConfiguration, storeName string, store tls.Store) bool {
if _, ok := configuration.Stores[storeName]; !ok {
configuration.Stores[storeName] = store
return true
}
return reflect.DeepEqual(configuration.Stores[storeName], store)
}
// MakeDefaultRuleTemplate creates the default rule template.
func MakeDefaultRuleTemplate(defaultRule string, funcMap template.FuncMap) (*template.Template, error) {
defaultFuncMap := sprig.TxtFuncMap()
defaultFuncMap["normalize"] = Normalize
@ -377,7 +407,7 @@ func MakeDefaultRuleTemplate(defaultRule string, funcMap template.FuncMap) (*tem
return template.New("defaultRule").Funcs(defaultFuncMap).Parse(defaultRule)
}
// BuildTCPRouterConfiguration Builds a router configuration.
// BuildTCPRouterConfiguration builds a router configuration.
func BuildTCPRouterConfiguration(ctx context.Context, configuration *dynamic.TCPConfiguration) {
for routerName, router := range configuration.Routers {
loggerRouter := log.Ctx(ctx).With().Str(logs.RouterName, routerName).Logger()
@ -403,7 +433,7 @@ func BuildTCPRouterConfiguration(ctx context.Context, configuration *dynamic.TCP
}
}
// BuildUDPRouterConfiguration Builds a router configuration.
// BuildUDPRouterConfiguration builds a router configuration.
func BuildUDPRouterConfiguration(ctx context.Context, configuration *dynamic.UDPConfiguration) {
for routerName, router := range configuration.Routers {
loggerRouter := log.Ctx(ctx).With().Str(logs.RouterName, routerName).Logger()
@ -426,7 +456,7 @@ func BuildUDPRouterConfiguration(ctx context.Context, configuration *dynamic.UDP
}
}
// BuildRouterConfiguration Builds a router configuration.
// BuildRouterConfiguration builds a router configuration.
func BuildRouterConfiguration(ctx context.Context, configuration *dynamic.HTTPConfiguration, defaultRouterName string, defaultRuleTpl *template.Template, model interface{}) {
if len(configuration.Routers) == 0 {
if len(configuration.Services) > 1 {
@ -474,7 +504,7 @@ func BuildRouterConfiguration(ctx context.Context, configuration *dynamic.HTTPCo
}
}
// Normalize Replace all special chars with `-`.
// Normalize replaces all special chars with `-`.
func Normalize(name string) string {
fargs := func(c rune) bool {
return !unicode.IsLetter(c) && !unicode.IsNumber(c)

View file

@ -161,7 +161,6 @@ func TestMatchLabels(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.expr, func(t *testing.T) {
t.Parallel()

View file

@ -3,6 +3,7 @@ package constraints
import (
"errors"
"regexp"
"slices"
"github.com/vulcand/predicate"
)
@ -47,12 +48,7 @@ func MatchTags(tags []string, expr string) (bool, error) {
func tagFn(name string) constraintTagFunc {
return func(tags []string) bool {
for _, tag := range tags {
if tag == name {
return true
}
}
return false
return slices.Contains(tags, name)
}
}
@ -63,13 +59,9 @@ func tagRegexFn(expr string) constraintTagFunc {
return false
}
for _, tag := range tags {
if exp.MatchString(tag) {
return true
}
}
return false
return slices.ContainsFunc(tags, func(tag string) bool {
return exp.MatchString(tag)
})
}
}

View file

@ -95,7 +95,6 @@ func TestMatchTags(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.expr, func(t *testing.T) {
t.Parallel()

View file

@ -132,8 +132,8 @@ func (p *Provider) keepContainer(ctx context.Context, item itemData) bool {
return false
}
if item.Status != api.HealthPassing && item.Status != api.HealthWarning {
logger.Debug().Msg("Filtering unhealthy or starting item")
if !p.includesHealthStatus(item.Status) {
logger.Debug().Msgf("Status %q is not included in the configured strictChecks of %q", item.Status, strings.Join(p.StrictChecks, ","))
return false
}
@ -324,3 +324,8 @@ func getName(i itemData) string {
hasher.Write([]byte(strings.Join(tags, "")))
return provider.Normalize(fmt.Sprintf("%s-%d", i.Name, hasher.Sum64()))
}
// defaultStrictChecks returns the default healthchecks to allow an upstream to be registered a route for loadbalancers.
func defaultStrictChecks() []string {
return []string{api.HealthPassing, api.HealthWarning}
}

File diff suppressed because it is too large Load diff

View file

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"strconv"
"strings"
"text/template"
"time"
@ -88,6 +89,7 @@ type Configuration struct {
ConnectByDefault bool `description:"Consider every service as Connect capable by default." json:"connectByDefault,omitempty" toml:"connectByDefault,omitempty" yaml:"connectByDefault,omitempty" export:"true"`
ServiceName string `description:"Name of the Traefik service in Consul Catalog (needs to be registered via the orchestrator or manually)." json:"serviceName,omitempty" toml:"serviceName,omitempty" yaml:"serviceName,omitempty" export:"true"`
Watch bool `description:"Watch Consul API events." json:"watch,omitempty" toml:"watch,omitempty" yaml:"watch,omitempty" export:"true"`
StrictChecks []string `description:"A list of service health statuses to allow taking traffic." json:"strictChecks,omitempty" toml:"strictChecks,omitempty" yaml:"strictChecks,omitempty" export:"true"`
}
// SetDefaults sets the default values.
@ -98,6 +100,7 @@ func (c *Configuration) SetDefaults() {
c.ExposedByDefault = true
c.DefaultRule = defaultTemplateRule
c.ServiceName = "traefik"
c.StrictChecks = defaultStrictChecks()
}
// Provider is the Consul Catalog provider implementation.
@ -578,6 +581,21 @@ func (p *Provider) watchConnectTLS(ctx context.Context) error {
}
}
// includesHealthStatus returns true if the status passed in exists in the configured StrictChecks configuration. Statuses are case insensitive.
func (p *Provider) includesHealthStatus(status string) bool {
for _, s := range p.StrictChecks {
// If the "any" status is included, assume all health checks are included
if strings.EqualFold(s, api.HealthAny) {
return true
}
if strings.EqualFold(s, status) {
return true
}
}
return false
}
func createClient(namespace string, endpoint *EndpointConfig) (*api.Client, error) {
config := api.Config{
Address: endpoint.Address,

View file

@ -52,7 +52,6 @@ func Test_tagsToNeutralLabels(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()

View file

@ -13,6 +13,8 @@ import (
"github.com/stretchr/testify/require"
ptypes "github.com/traefik/paerser/types"
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/tls"
"github.com/traefik/traefik/v3/pkg/types"
)
func TestDynConfBuilder_DefaultRule(t *testing.T) {
@ -80,6 +82,9 @@ func TestDynConfBuilder_DefaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -140,6 +145,9 @@ func TestDynConfBuilder_DefaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -202,6 +210,9 @@ func TestDynConfBuilder_DefaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -256,6 +267,9 @@ func TestDynConfBuilder_DefaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -310,6 +324,9 @@ func TestDynConfBuilder_DefaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -370,12 +387,14 @@ func TestDynConfBuilder_DefaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -389,7 +408,7 @@ func TestDynConfBuilder_DefaultRule(t *testing.T) {
err := p.Init()
require.NoError(t, err)
for i := 0; i < len(test.containers); i++ {
for i := range len(test.containers) {
var err error
test.containers[i].ExtraConf, err = p.extractLabels(test.containers[i])
require.NoError(t, err)
@ -452,6 +471,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -493,6 +515,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -534,6 +559,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -593,6 +621,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -686,6 +717,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -766,6 +800,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -827,6 +864,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -889,6 +929,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -949,6 +992,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1010,6 +1056,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1080,6 +1129,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1141,6 +1193,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1208,6 +1263,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1294,6 +1352,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1378,6 +1439,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1445,6 +1509,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1535,6 +1602,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1619,6 +1689,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1725,6 +1798,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1803,6 +1879,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1903,6 +1982,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1986,6 +2068,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2072,6 +2157,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2133,6 +2221,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2195,6 +2286,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2264,6 +2358,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2301,6 +2398,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2340,6 +2440,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2381,6 +2484,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2409,6 +2515,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2453,6 +2562,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2484,6 +2596,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2525,6 +2640,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2556,6 +2674,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2596,6 +2717,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2638,6 +2762,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2700,6 +2827,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2772,6 +2902,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2837,6 +2970,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2895,6 +3031,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2951,6 +3090,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -3002,6 +3144,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -3063,6 +3208,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -3120,6 +3268,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -3225,6 +3376,9 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -3276,6 +3430,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -3328,6 +3485,9 @@ func TestDynConfBuilder_build(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -3397,13 +3557,97 @@ func TestDynConfBuilder_build(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
desc: "one container with default generated certificate labels",
containers: []dockerData{
{
ServiceName: "Test",
Name: "Test",
Labels: map[string]string{
"traefik.tls.stores.default.defaultgeneratedcert.resolver": "foobar",
"traefik.tls.stores.default.defaultgeneratedcert.domain.main": "foobar",
"traefik.tls.stores.default.defaultgeneratedcert.domain.sans": "foobar, fiibar",
},
NetworkSettings: networkSettings{
Ports: nat.PortMap{
nat.Port("79/tcp"): []nat.PortBinding{{
HostIP: "192.168.0.1",
HostPort: "8080",
}},
nat.Port("80/tcp"): []nat.PortBinding{{
HostIP: "192.168.0.1",
HostPort: "8081",
}},
},
Networks: map[string]*networkData{
"bridge": {
Name: "bridge",
Addr: "127.0.0.1",
},
},
},
},
},
expected: &dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"Test": {
Service: "Test",
Rule: "Host(`Test.traefik.wtf`)",
DefaultRule: true,
},
},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{
"Test": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://127.0.0.1:79",
},
},
PassHostHeader: Bool(true),
ResponseForwarding: &dynamic.ResponseForwarding{
FlushInterval: ptypes.Duration(100 * time.Millisecond),
},
},
},
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
ServersTransports: map[string]*dynamic.TCPServersTransport{},
},
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{
"default": {
DefaultGeneratedCert: &tls.GeneratedCert{
Resolver: "foobar",
Domain: &types.Domain{
Main: "foobar",
SANs: []string{"foobar", "fiibar"},
},
},
},
},
},
},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -3420,7 +3664,7 @@ func TestDynConfBuilder_build(t *testing.T) {
err := p.Init()
require.NoError(t, err)
for i := 0; i < len(test.containers); i++ {
for i := range len(test.containers) {
var err error
test.containers[i].ExtraConf, err = p.extractLabels(test.containers[i])
require.NoError(t, err)
@ -3590,7 +3834,6 @@ func TestDynConfBuilder_getIPPort_docker(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -3703,7 +3946,6 @@ func TestDynConfBuilder_getIPAddress_docker(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -3773,7 +4015,6 @@ func TestDynConfBuilder_getIPAddress_swarm(t *testing.T) {
}
for serviceID, test := range testCases {
test := test
t.Run(strconv.Itoa(serviceID), func(t *testing.T) {
t.Parallel()

View file

@ -25,7 +25,7 @@ type networkSettings struct {
Networks map[string]*networkData
}
// Network holds the network data to the provider.
// networkData holds the network data to the provider.
type networkData struct {
Name string
Addr string

View file

@ -187,8 +187,7 @@ func (p *SwarmProvider) listServices(ctx context.Context, dockerClient client.AP
networkMap := make(map[string]*dockertypes.NetworkResource)
for _, network := range networkList {
networkToAdd := network
networkMap[network.ID] = &networkToAdd
networkMap[network.ID] = &network
}
var dockerDataList []dockerData

View file

@ -63,7 +63,6 @@ func TestListTasks(t *testing.T) {
}
for caseID, test := range testCases {
test := test
t.Run(strconv.Itoa(caseID), func(t *testing.T) {
t.Parallel()
@ -230,7 +229,6 @@ func TestSwarmProvider_listServices(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -351,7 +349,6 @@ func TestSwarmProvider_parseService_task(t *testing.T) {
}
for caseID, test := range testCases {
test := test
t.Run(strconv.Itoa(caseID), func(t *testing.T) {
t.Parallel()

View file

@ -66,7 +66,6 @@ func Test_getPort_docker(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -96,7 +95,6 @@ func Test_getPort_swarm(t *testing.T) {
}
for serviceID, test := range testCases {
test := test
t.Run(strconv.Itoa(serviceID), func(t *testing.T) {
t.Parallel()

View file

@ -10,6 +10,8 @@ import (
"github.com/stretchr/testify/require"
ptypes "github.com/traefik/paerser/types"
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/tls"
"github.com/traefik/traefik/v3/pkg/types"
)
func Int(v int) *int { return &v }
@ -76,6 +78,9 @@ func TestDefaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -131,6 +136,9 @@ func TestDefaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -188,6 +196,9 @@ func TestDefaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -237,6 +248,9 @@ func TestDefaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -286,6 +300,9 @@ func TestDefaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -341,12 +358,14 @@ func TestDefaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -359,7 +378,7 @@ func TestDefaultRule(t *testing.T) {
err := p.Init()
require.NoError(t, err)
for i := 0; i < len(test.instances); i++ {
for i := range len(test.instances) {
var err error
test.instances[i].ExtraConf, err = p.getConfiguration(test.instances[i])
require.NoError(t, err)
@ -413,6 +432,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -449,6 +471,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -485,6 +510,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -539,6 +567,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -622,6 +653,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -692,6 +726,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -748,6 +785,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -805,6 +845,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -860,6 +903,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -916,6 +962,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -981,6 +1030,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1037,6 +1089,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1094,6 +1149,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1165,6 +1223,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1239,6 +1300,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1301,6 +1365,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1381,6 +1448,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1455,6 +1525,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1546,6 +1619,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1614,6 +1690,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1699,6 +1778,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1773,6 +1855,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1849,6 +1934,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1905,6 +1993,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1962,6 +2053,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2019,6 +2113,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2097,6 +2194,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2161,6 +2261,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2193,6 +2296,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2227,6 +2333,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2263,6 +2372,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2300,6 +2412,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2336,6 +2451,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2373,6 +2491,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2430,6 +2551,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2497,6 +2621,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2557,6 +2684,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2610,6 +2740,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2661,6 +2794,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2707,6 +2843,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2763,6 +2902,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2815,6 +2957,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2910,6 +3055,9 @@ func Test_buildConfiguration(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2956,6 +3104,9 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -3003,13 +3154,85 @@ func Test_buildConfiguration(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
desc: "one container with default generated certificate",
containers: []ecsInstance{
instance(
name("Test"),
labels(map[string]string{
"traefik.tls.stores.default.defaultgeneratedcert.resolver": "foobar",
"traefik.tls.stores.default.defaultgeneratedcert.domain.main": "foobar",
"traefik.tls.stores.default.defaultgeneratedcert.domain.sans": "foobar, fiibar",
}),
iMachine(
mState(ec2.InstanceStateNameRunning),
mPrivateIP("127.0.0.1"),
mPorts(
mPort(0, 80, "tcp"),
),
),
),
},
expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
ServersTransports: map[string]*dynamic.TCPServersTransport{},
},
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"Test": {
Service: "Test",
Rule: "Host(`Test.traefik.wtf`)",
DefaultRule: true,
},
},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{
"Test": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://127.0.0.1:80",
},
},
PassHostHeader: Bool(true),
ResponseForwarding: &dynamic.ResponseForwarding{
FlushInterval: ptypes.Duration(100 * time.Millisecond),
},
},
},
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{
"default": {
DefaultGeneratedCert: &tls.GeneratedCert{
Resolver: "foobar",
Domain: &types.Domain{
Main: "foobar",
SANs: []string{"foobar", "fiibar"},
},
},
},
},
},
},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -3022,7 +3245,7 @@ func Test_buildConfiguration(t *testing.T) {
err := p.Init()
require.NoError(t, err)
for i := 0; i < len(test.containers); i++ {
for i := range len(test.containers) {
var err error
test.containers[i].ExtraConf, err = p.getConfiguration(test.containers[i])
require.NoError(t, err)

View file

@ -402,7 +402,7 @@ func (p *Provider) listInstances(ctx context.Context, client *awsClient) ([]ecsI
}
func (p *Provider) lookupMiInstances(ctx context.Context, client *awsClient, clusterName *string, ecsDatas map[string]*ecs.Task) (map[string]*ssm.InstanceInformation, error) {
instanceIds := make(map[string]string)
instanceIDs := make(map[string]string)
miInstances := make(map[string]*ssm.InstanceInformation)
var containerInstancesArns []*string
@ -424,7 +424,7 @@ func (p *Provider) lookupMiInstances(ctx context.Context, client *awsClient, clu
}
for _, container := range resp.ContainerInstances {
instanceIds[aws.StringValue(container.Ec2InstanceId)] = aws.StringValue(container.ContainerInstanceArn)
instanceIDs[aws.StringValue(container.Ec2InstanceId)] = aws.StringValue(container.ContainerInstanceArn)
// Disallow EC2 Instance IDs
// This prevents considering EC2 instances in ECS
@ -452,7 +452,7 @@ func (p *Provider) lookupMiInstances(ctx context.Context, client *awsClient, clu
if len(page.InstanceInformationList) > 0 {
for _, i := range page.InstanceInformationList {
if i.InstanceId != nil {
miInstances[instanceIds[aws.StringValue(i.InstanceId)]] = i
miInstances[instanceIDs[aws.StringValue(i.InstanceId)]] = i
}
}
}
@ -468,7 +468,7 @@ func (p *Provider) lookupMiInstances(ctx context.Context, client *awsClient, clu
}
func (p *Provider) lookupEc2Instances(ctx context.Context, client *awsClient, clusterName *string, ecsDatas map[string]*ecs.Task) (map[string]*ec2.Instance, error) {
instanceIds := make(map[string]string)
instanceIDs := make(map[string]string)
ec2Instances := make(map[string]*ec2.Instance)
var containerInstancesArns []*string
@ -490,7 +490,7 @@ func (p *Provider) lookupEc2Instances(ctx context.Context, client *awsClient, cl
}
for _, container := range resp.ContainerInstances {
instanceIds[aws.StringValue(container.Ec2InstanceId)] = aws.StringValue(container.ContainerInstanceArn)
instanceIDs[aws.StringValue(container.Ec2InstanceId)] = aws.StringValue(container.ContainerInstanceArn)
// Disallow Instance IDs of the form mi-*
// This prevents considering external instances in ECS Anywhere setups
// and getting InvalidInstanceID.Malformed error when calling the describe-instances endpoint.
@ -513,7 +513,7 @@ func (p *Provider) lookupEc2Instances(ctx context.Context, client *awsClient, cl
for _, r := range page.Reservations {
for _, i := range r.Instances {
if i.InstanceId != nil {
ec2Instances[instanceIds[aws.StringValue(i.InstanceId)]] = i
ec2Instances[instanceIDs[aws.StringValue(i.InstanceId)]] = i
}
}
}

View file

@ -68,12 +68,11 @@ func TestChunkIDs(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
var IDs []*string
for v := 0; v < test.count; v++ {
for range test.count {
IDs = append(IDs, aws.String("a"))
}

View file

@ -6,6 +6,7 @@ import (
"os"
"path/filepath"
"runtime"
"slices"
"time"
"github.com/rs/zerolog/log"
@ -490,12 +491,8 @@ func (c *clientWrapper) isWatchedNamespace(ns string) bool {
if c.isNamespaceAll {
return true
}
for _, watchedNamespace := range c.watchedNamespaces {
if watchedNamespace == ns {
return true
}
}
return false
return slices.Contains(c.watchedNamespaces, ns)
}
// translateNotFoundError will translate a "not found" error to a boolean return

View file

@ -12,6 +12,7 @@ import (
"fmt"
"net"
"os"
"slices"
"sort"
"strconv"
"strings"
@ -26,6 +27,7 @@ import (
"github.com/traefik/traefik/v3/pkg/logs"
"github.com/traefik/traefik/v3/pkg/provider"
traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/gateway"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s"
"github.com/traefik/traefik/v3/pkg/safe"
"github.com/traefik/traefik/v3/pkg/tls"
@ -73,7 +75,7 @@ func (p *Provider) applyRouterTransform(ctx context.Context, rt *dynamic.Router,
return
}
err := p.routerTransform.Apply(ctx, rt, ingress.Annotations)
err := p.routerTransform.Apply(ctx, rt, ingress)
if err != nil {
log.Ctx(ctx).Error().Err(err).Msg("Apply router transform")
}
@ -712,6 +714,24 @@ func (p *Provider) createErrorPageMiddleware(client Client, namespace string, er
return errorPageMiddleware, balancerServerHTTP, nil
}
func (p *Provider) FillExtensionBuilderRegistry(registry gateway.ExtensionBuilderRegistry) {
registry.RegisterFilterFuncs(traefikv1alpha1.GroupName, "Middleware", func(name, namespace string) (string, *dynamic.Middleware, error) {
if len(p.Namespaces) > 0 && !slices.Contains(p.Namespaces, namespace) {
return "", nil, fmt.Errorf("namespace %q is not allowed", namespace)
}
return makeID(namespace, name) + providerNamespaceSeparator + providerName, nil, nil
})
registry.RegisterBackendFuncs(traefikv1alpha1.GroupName, "TraefikService", func(name, namespace string) (string, *dynamic.Service, error) {
if len(p.Namespaces) > 0 && !slices.Contains(p.Namespaces, namespace) {
return "", nil, fmt.Errorf("namespace %q is not allowed", namespace)
}
return makeID(namespace, name) + providerNamespaceSeparator + providerName, nil, nil
})
}
func createForwardAuthMiddleware(k8sClient Client, namespace string, auth *traefikv1alpha1.ForwardAuth) (*dynamic.ForwardAuth, error) {
if auth == nil {
return nil, nil

View file

@ -16,6 +16,7 @@ import (
"github.com/traefik/traefik/v3/pkg/provider"
traefikcrdfake "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake"
traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/gateway"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s"
"github.com/traefik/traefik/v3/pkg/tls"
"github.com/traefik/traefik/v3/pkg/types"
@ -1569,8 +1570,6 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -4587,7 +4586,6 @@ func TestLoadIngressRoutes(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -5097,8 +5095,6 @@ func TestLoadIngressRouteUDPs(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -5190,8 +5186,6 @@ func TestParseServiceProtocol(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -5422,7 +5416,6 @@ func TestGetServicePort(t *testing.T) {
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -6536,8 +6529,6 @@ func TestCrossNamespace(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -6807,8 +6798,6 @@ func TestExternalNameService(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -6990,8 +6979,6 @@ func TestNativeLB(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -7173,8 +7160,6 @@ func TestNodePortLB(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -7265,6 +7250,62 @@ func TestCreateBasicAuthCredentials(t *testing.T) {
assert.True(t, auth.CheckSecret("test2", hashedPassword))
}
func TestFillExtensionBuilderRegistry(t *testing.T) {
testCases := []struct {
desc string
namespaces []string
wantErr require.ErrorAssertionFunc
}{
{
desc: "no filter on namespaces",
wantErr: require.NoError,
},
{
desc: "filter on default namespace",
namespaces: []string{"default"},
wantErr: require.NoError,
},
{
desc: "filter on not-default namespace",
namespaces: []string{"not-default"},
wantErr: require.Error,
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
r := &extensionBuilderRegistryMock{}
p := Provider{Namespaces: test.namespaces}
p.FillExtensionBuilderRegistry(r)
filterFunc, ok := r.groupKindFilterFuncs[traefikv1alpha1.SchemeGroupVersion.Group]["Middleware"]
require.True(t, ok)
name, conf, err := filterFunc("my-middleware", "default")
test.wantErr(t, err)
if err == nil {
assert.Nil(t, conf)
assert.Equal(t, "default-my-middleware@kubernetescrd", name)
}
backendFunc, ok := r.groupKindBackendFuncs[traefikv1alpha1.SchemeGroupVersion.Group]["TraefikService"]
require.True(t, ok)
name, svc, err := backendFunc("my-service", "default")
test.wantErr(t, err)
if err == nil {
assert.Nil(t, svc)
assert.Equal(t, "default-my-service@kubernetescrd", name)
}
})
}
}
func readResources(t *testing.T, paths []string) ([]runtime.Object, []runtime.Object) {
t.Helper()
@ -7289,3 +7330,34 @@ func readResources(t *testing.T, paths []string) ([]runtime.Object, []runtime.Ob
return k8sObjects, crdObjects
}
type extensionBuilderRegistryMock struct {
groupKindFilterFuncs map[string]map[string]gateway.BuildFilterFunc
groupKindBackendFuncs map[string]map[string]gateway.BuildBackendFunc
}
// RegisterFilterFuncs registers an allowed Group, Kind, and builder for the Filter ExtensionRef objects.
func (p *extensionBuilderRegistryMock) RegisterFilterFuncs(group, kind string, builderFunc gateway.BuildFilterFunc) {
if p.groupKindFilterFuncs == nil {
p.groupKindFilterFuncs = map[string]map[string]gateway.BuildFilterFunc{}
}
if p.groupKindFilterFuncs[group] == nil {
p.groupKindFilterFuncs[group] = map[string]gateway.BuildFilterFunc{}
}
p.groupKindFilterFuncs[group][kind] = builderFunc
}
// RegisterBackendFuncs registers an allowed Group, Kind, and builder for the Backend ExtensionRef objects.
func (p *extensionBuilderRegistryMock) RegisterBackendFuncs(group, kind string, builderFunc gateway.BuildBackendFunc) {
if p.groupKindBackendFuncs == nil {
p.groupKindBackendFuncs = map[string]map[string]gateway.BuildBackendFunc{}
}
if p.groupKindBackendFuncs[group] == nil {
p.groupKindBackendFuncs[group] = map[string]gateway.BuildBackendFunc{}
}
p.groupKindBackendFuncs[group][kind] = builderFunc
}

View file

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"os"
"slices"
"time"
"github.com/rs/zerolog/log"
@ -74,7 +75,8 @@ type clientWrapper struct {
isNamespaceAll bool
watchedNamespaces []string
labelSelector string
labelSelector string
experimentalChannel bool
}
func createClientFromConfig(c *rest.Config) (*clientWrapper, error) {
@ -195,19 +197,22 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
if err != nil {
return nil, err
}
_, err = factoryGateway.Gateway().V1alpha2().TCPRoutes().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
_, err = factoryGateway.Gateway().V1alpha2().TLSRoutes().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
_, err = factoryGateway.Gateway().V1beta1().ReferenceGrants().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
if c.experimentalChannel {
_, err = factoryGateway.Gateway().V1alpha2().TCPRoutes().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
_, err = factoryGateway.Gateway().V1alpha2().TLSRoutes().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
}
factoryKube := kinformers.NewSharedInformerFactoryWithOptions(c.csKube, resyncPeriod, kinformers.WithNamespace(ns))
_, err = factoryKube.Core().V1().Services().Informer().AddEventHandler(eventHandler)
if err != nil {
@ -567,10 +572,6 @@ func (c *clientWrapper) isWatchedNamespace(ns string) bool {
if c.isNamespaceAll {
return true
}
for _, watchedNamespace := range c.watchedNamespaces {
if watchedNamespace == ns {
return true
}
}
return false
return slices.Contains(c.watchedNamespaces, ns)
}

View file

@ -233,8 +233,6 @@ func TestStatusEquals(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()

View file

@ -0,0 +1,57 @@
---
kind: GatewayClass
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: my-gateway-class
spec:
controllerName: traefik.io/gateway-controller
---
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: my-gateway
namespace: default
spec:
gatewayClassName: my-gateway-class
listeners: # Use GatewayClass defaults for listener definition.
- name: http
protocol: HTTP
port: 80
allowedRoutes:
kinds:
- kind: HTTPRoute
group: gateway.networking.k8s.io
namespaces:
from: Same
---
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: http-app-1
namespace: default
spec:
parentRefs:
- name: my-gateway
kind: Gateway
group: gateway.networking.k8s.io
hostnames:
- "foo.com"
rules:
- matches:
- path:
type: Exact
value: /bar
backendRefs:
- name: whoami
port: 80
weight: 1
kind: Service
group: ""
filters:
- type: ExtensionRef
extensionRef:
group: traefik.io
kind: Middleware
name: my-middleware

View file

@ -0,0 +1,51 @@
---
kind: GatewayClass
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: my-gateway-class
spec:
controllerName: traefik.io/gateway-controller
---
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: my-gateway
namespace: default
spec:
gatewayClassName: my-gateway-class
listeners: # Use GatewayClass defaults for listener definition.
- name: http
protocol: HTTP
port: 80
allowedRoutes:
kinds:
- kind: HTTPRoute
group: gateway.networking.k8s.io
namespaces:
from: Same
---
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: http-app-1
namespace: default
spec:
parentRefs:
- name: my-gateway
kind: Gateway
group: gateway.networking.k8s.io
hostnames:
- "foo.com"
rules:
- matches:
- path:
type: Exact
value: /bar
backendRefs:
- name: whoami
port: 80
weight: 1
kind: TraefikService
group: "traefik.io"

View file

@ -51,19 +51,63 @@ const (
// Provider holds configurations of the provider.
type Provider struct {
Endpoint string `description:"Kubernetes server endpoint (required for external cluster client)." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"`
Token types.FileOrContent `description:"Kubernetes bearer token (not needed for in-cluster client). It accepts either a token value or a file path to the token." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"`
CertAuthFilePath string `description:"Kubernetes certificate authority file path (not needed for in-cluster client)." json:"certAuthFilePath,omitempty" toml:"certAuthFilePath,omitempty" yaml:"certAuthFilePath,omitempty"`
Namespaces []string `description:"Kubernetes namespaces." json:"namespaces,omitempty" toml:"namespaces,omitempty" yaml:"namespaces,omitempty" export:"true"`
LabelSelector string `description:"Kubernetes label selector to select specific GatewayClasses." json:"labelSelector,omitempty" toml:"labelSelector,omitempty" yaml:"labelSelector,omitempty" export:"true"`
ThrottleDuration ptypes.Duration `description:"Kubernetes refresh throttle duration" json:"throttleDuration,omitempty" toml:"throttleDuration,omitempty" yaml:"throttleDuration,omitempty" export:"true"`
EntryPoints map[string]Entrypoint `json:"-" toml:"-" yaml:"-" label:"-" file:"-"`
Endpoint string `description:"Kubernetes server endpoint (required for external cluster client)." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"`
Token types.FileOrContent `description:"Kubernetes bearer token (not needed for in-cluster client). It accepts either a token value or a file path to the token." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"`
CertAuthFilePath string `description:"Kubernetes certificate authority file path (not needed for in-cluster client)." json:"certAuthFilePath,omitempty" toml:"certAuthFilePath,omitempty" yaml:"certAuthFilePath,omitempty"`
Namespaces []string `description:"Kubernetes namespaces." json:"namespaces,omitempty" toml:"namespaces,omitempty" yaml:"namespaces,omitempty" export:"true"`
LabelSelector string `description:"Kubernetes label selector to select specific GatewayClasses." json:"labelSelector,omitempty" toml:"labelSelector,omitempty" yaml:"labelSelector,omitempty" export:"true"`
ThrottleDuration ptypes.Duration `description:"Kubernetes refresh throttle duration" json:"throttleDuration,omitempty" toml:"throttleDuration,omitempty" yaml:"throttleDuration,omitempty" export:"true"`
ExperimentalChannel bool `description:"Toggles Experimental Channel resources support (TCPRoute, TLSRoute...)." json:"experimentalChannel,omitempty" toml:"experimentalChannel,omitempty" yaml:"experimentalChannel,omitempty" export:"true"`
EntryPoints map[string]Entrypoint `json:"-" toml:"-" yaml:"-" label:"-" file:"-"`
// groupKindFilterFuncs is the list of allowed Group and Kinds for the Filter ExtensionRef objects.
groupKindFilterFuncs map[string]map[string]BuildFilterFunc
// groupKindBackendFuncs is the list of allowed Group and Kinds for the Backend ExtensionRef objects.
groupKindBackendFuncs map[string]map[string]BuildBackendFunc
lastConfiguration safe.Safe
routerTransform k8s.RouterTransform
}
// BuildFilterFunc returns the name of the filter and the related dynamic.Middleware if needed.
type BuildFilterFunc func(name, namespace string) (string, *dynamic.Middleware, error)
// BuildBackendFunc returns the name of the backend and the related dynamic.Service if needed.
type BuildBackendFunc func(name, namespace string) (string, *dynamic.Service, error)
type ExtensionBuilderRegistry interface {
RegisterFilterFuncs(group, kind string, builderFunc BuildFilterFunc)
RegisterBackendFuncs(group, kind string, builderFunc BuildBackendFunc)
}
// RegisterFilterFuncs registers an allowed Group, Kind, and builder for the Filter ExtensionRef objects.
func (p *Provider) RegisterFilterFuncs(group, kind string, builderFunc BuildFilterFunc) {
if p.groupKindFilterFuncs == nil {
p.groupKindFilterFuncs = map[string]map[string]BuildFilterFunc{}
}
if p.groupKindFilterFuncs[group] == nil {
p.groupKindFilterFuncs[group] = map[string]BuildFilterFunc{}
}
p.groupKindFilterFuncs[group][kind] = builderFunc
}
// RegisterBackendFuncs registers an allowed Group, Kind, and builder for the Backend ExtensionRef objects.
func (p *Provider) RegisterBackendFuncs(group, kind string, builderFunc BuildBackendFunc) {
if p.groupKindBackendFuncs == nil {
p.groupKindBackendFuncs = map[string]map[string]BuildBackendFunc{}
}
if p.groupKindBackendFuncs[group] == nil {
p.groupKindBackendFuncs[group] = map[string]BuildBackendFunc{}
}
p.groupKindBackendFuncs[group][kind] = builderFunc
}
func (p *Provider) SetRouterTransform(routerTransform k8s.RouterTransform) {
p.routerTransform = routerTransform
}
@ -73,7 +117,7 @@ func (p *Provider) applyRouterTransform(ctx context.Context, rt *dynamic.Router,
return
}
err := p.routerTransform.Apply(ctx, rt, route.Annotations)
err := p.routerTransform.Apply(ctx, rt, route)
if err != nil {
log.Ctx(ctx).Error().Err(err).Msg("Apply router transform")
}
@ -113,6 +157,7 @@ func (p *Provider) newK8sClient(ctx context.Context) (*clientWrapper, error) {
}
client.labelSelector = p.LabelSelector
client.experimentalChannel = p.ExperimentalChannel
return client, nil
}
@ -354,7 +399,7 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *
// AttachedRoutes: 0 TODO Set to number of Routes associated with a Listener regardless of Gateway or Route status
}
supportedKinds, conditions := supportedRouteKinds(listener.Protocol)
supportedKinds, conditions := supportedRouteKinds(listener.Protocol, p.ExperimentalChannel)
if len(conditions) > 0 {
listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, conditions...)
continue
@ -674,21 +719,41 @@ func (p *Provider) entryPointName(port gatev1.PortNumber, protocol gatev1.Protoc
return "", fmt.Errorf("no matching entryPoint for port %d and protocol %q", port, protocol)
}
func supportedRouteKinds(protocol gatev1.ProtocolType) ([]gatev1.RouteGroupKind, []metav1.Condition) {
func supportedRouteKinds(protocol gatev1.ProtocolType, experimentalChannel bool) ([]gatev1.RouteGroupKind, []metav1.Condition) {
group := gatev1.Group(gatev1.GroupName)
switch protocol {
case gatev1.TCPProtocolType:
return []gatev1.RouteGroupKind{{Kind: kindTCPRoute, Group: &group}}, nil
if experimentalChannel {
return []gatev1.RouteGroupKind{{Kind: kindTCPRoute, Group: &group}}, nil
}
return nil, []metav1.Condition{{
Type: string(gatev1.ListenerConditionConflicted),
Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(),
Reason: string(gatev1.ListenerReasonInvalidRouteKinds),
Message: fmt.Sprintf("Protocol %q requires the experimental channel support to be enabled, please use the `experimentalChannel` option", protocol),
}}
case gatev1.HTTPProtocolType, gatev1.HTTPSProtocolType:
return []gatev1.RouteGroupKind{{Kind: kindHTTPRoute, Group: &group}}, nil
case gatev1.TLSProtocolType:
return []gatev1.RouteGroupKind{
{Kind: kindTCPRoute, Group: &group},
{Kind: kindTLSRoute, Group: &group},
}, nil
if experimentalChannel {
return []gatev1.RouteGroupKind{
{Kind: kindTCPRoute, Group: &group},
{Kind: kindTLSRoute, Group: &group},
}, nil
}
return nil, []metav1.Condition{{
Type: string(gatev1.ListenerConditionConflicted),
Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(),
Reason: string(gatev1.ListenerReasonInvalidRouteKinds),
Message: fmt.Sprintf("Protocol %q requires the experimental channel support to be enabled, please use the `experimentalChannel` option", protocol),
}}
}
return nil, []metav1.Condition{{
@ -847,7 +912,7 @@ func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, li
continue
}
middlewares, err := loadMiddlewares(listener, routerKey, routeRule.Filters)
middlewares, err := p.loadMiddlewares(listener, route.Namespace, routerKey, routeRule.Filters)
if err != nil {
// update "ResolvedRefs" status true with "InvalidFilters" reason
conditions = append(conditions, metav1.Condition{
@ -864,7 +929,11 @@ func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, li
}
for middlewareName, middleware := range middlewares {
conf.HTTP.Middlewares[middlewareName] = middleware
// If the middleware is not defined in the return of the loadMiddlewares function, it means we just need a reference to that middleware.
if middleware != nil {
conf.HTTP.Middlewares[middlewareName] = middleware
}
router.Middlewares = append(router.Middlewares, middlewareName)
}
@ -876,7 +945,7 @@ func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, li
if len(routeRule.BackendRefs) == 1 && isInternalService(routeRule.BackendRefs[0].BackendRef) {
router.Service = string(routeRule.BackendRefs[0].Name)
} else {
wrrService, subServices, err := loadServices(client, route.Namespace, routeRule.BackendRefs)
wrrService, subServices, err := p.loadServices(client, route.Namespace, routeRule.BackendRefs)
if err != nil {
// update "ResolvedRefs" status true with "DroppedRoutes" reason
conditions = append(conditions, metav1.Condition{
@ -893,7 +962,9 @@ func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, li
}
for svcName, svc := range subServices {
conf.HTTP.Services[svcName] = svc
if svc != nil {
conf.HTTP.Services[svcName] = svc
}
}
serviceName := provider.Normalize(routerKey + "-wrr")
@ -1550,7 +1621,7 @@ func getCertificateBlocks(secret *corev1.Secret, namespace, secretName string) (
}
// loadServices is generating a WRR service, even when there is only one target.
func loadServices(client Client, namespace string, backendRefs []gatev1.HTTPBackendRef) (*dynamic.Service, map[string]*dynamic.Service, error) {
func (p *Provider) loadServices(client Client, namespace string, backendRefs []gatev1.HTTPBackendRef) (*dynamic.Service, map[string]*dynamic.Service, error) {
services := map[string]*dynamic.Service{}
wrrSvc := &dynamic.Service{
@ -1571,13 +1642,20 @@ func loadServices(client Client, namespace string, backendRefs []gatev1.HTTPBack
weight := int(ptr.Deref(backendRef.Weight, 1))
if isTraefikService(backendRef.BackendRef) {
wrrSvc.Weighted.Services = append(wrrSvc.Weighted.Services, dynamic.WRRService{Name: string(backendRef.Name), Weight: &weight})
continue
}
if *backendRef.Group != "" && *backendRef.Group != groupCore && *backendRef.Kind != "Service" {
return nil, nil, fmt.Errorf("unsupported HTTPBackendRef %s/%s/%s", *backendRef.Group, *backendRef.Kind, backendRef.Name)
if backendRef.Namespace != nil && string(*backendRef.Namespace) != namespace {
// TODO: support backend reference grant.
return nil, nil, fmt.Errorf("unsupported HTTPBackendRef %s/%s/%s", *backendRef.Group, *backendRef.Kind, backendRef.Name)
}
name, service, err := p.loadHTTPBackendRef(namespace, backendRef)
if err != nil {
return nil, nil, fmt.Errorf("unable to load HTTPBackendRef %s/%s/%s: %w", *backendRef.Group, *backendRef.Kind, backendRef.Name, err)
}
services[name] = service
wrrSvc.Weighted.Services = append(wrrSvc.Weighted.Services, dynamic.WRRService{Name: name, Weight: &weight})
continue
}
lb := &dynamic.ServersLoadBalancer{}
@ -1672,6 +1750,24 @@ func loadServices(client Client, namespace string, backendRefs []gatev1.HTTPBack
return wrrSvc, services, nil
}
func (p *Provider) loadHTTPBackendRef(namespace string, backendRef gatev1.HTTPBackendRef) (string, *dynamic.Service, error) {
// Support for cross-provider references (e.g: api@internal).
// This provides the same behavior as for IngressRoutes.
if *backendRef.Kind == "TraefikService" && strings.Contains(string(backendRef.Name), "@") {
return string(backendRef.Name), nil, nil
}
backendFunc, ok := p.groupKindBackendFuncs[string(*backendRef.Group)][string(*backendRef.Kind)]
if !ok {
return "", nil, fmt.Errorf("unsupported HTTPBackendRef %s/%s/%s", *backendRef.Group, *backendRef.Kind, backendRef.Name)
}
if backendFunc == nil {
return "", nil, fmt.Errorf("undefined backendFunc for HTTPBackendRef %s/%s/%s", *backendRef.Group, *backendRef.Kind, backendRef.Name)
}
return backendFunc(string(backendRef.Name), namespace)
}
// loadTCPServices is generating a WRR service, even when there is only one target.
func loadTCPServices(client Client, namespace string, backendRefs []gatev1.BackendRef) (*dynamic.TCPService, map[string]*dynamic.TCPService, error) {
services := map[string]*dynamic.TCPService{}
@ -1791,7 +1887,7 @@ func loadTCPServices(client Client, namespace string, backendRefs []gatev1.Backe
return wrrSvc, services, nil
}
func loadMiddlewares(listener gatev1.Listener, prefix string, filters []gatev1.HTTPRouteFilter) (map[string]*dynamic.Middleware, error) {
func (p *Provider) loadMiddlewares(listener gatev1.Listener, namespace string, prefix string, filters []gatev1.HTTPRouteFilter) (map[string]*dynamic.Middleware, error) {
middlewares := make(map[string]*dynamic.Middleware)
// The spec allows for an empty string in which case we should use the
@ -1815,6 +1911,16 @@ func loadMiddlewares(listener gatev1.Listener, prefix string, filters []gatev1.H
if err != nil {
return nil, fmt.Errorf("creating RedirectRegex middleware: %w", err)
}
middlewareName := provider.Normalize(fmt.Sprintf("%s-%s-%d", prefix, strings.ToLower(string(filter.Type)), i))
middlewares[middlewareName] = middleware
case gatev1.HTTPRouteFilterExtensionRef:
name, middleware, err := p.loadHTTPRouteFilterExtensionRef(namespace, filter.ExtensionRef)
if err != nil {
return nil, fmt.Errorf("unsupported filter %s: %w", filter.Type, err)
}
middlewares[name] = middleware
default:
// As per the spec:
// https://gateway-api.sigs.k8s.io/api-types/httproute/#filters-optional
@ -1823,14 +1929,27 @@ func loadMiddlewares(listener gatev1.Listener, prefix string, filters []gatev1.H
// status.
return nil, fmt.Errorf("unsupported filter %s", filter.Type)
}
middlewareName := provider.Normalize(fmt.Sprintf("%s-%s-%d", prefix, strings.ToLower(string(filter.Type)), i))
middlewares[middlewareName] = middleware
}
return middlewares, nil
}
func (p *Provider) loadHTTPRouteFilterExtensionRef(namespace string, extensionRef *gatev1.LocalObjectReference) (string, *dynamic.Middleware, error) {
if extensionRef == nil {
return "", nil, errors.New("filter extension ref undefined")
}
filterFunc, ok := p.groupKindFilterFuncs[string(extensionRef.Group)][string(extensionRef.Kind)]
if !ok {
return "", nil, fmt.Errorf("unsupported filter extension ref %s/%s/%s", extensionRef.Group, extensionRef.Kind, extensionRef.Name)
}
if filterFunc == nil {
return "", nil, fmt.Errorf("undefined filterFunc for filter extension ref %s/%s/%s", extensionRef.Group, extensionRef.Kind, extensionRef.Name)
}
return filterFunc(string(extensionRef.Name), namespace)
}
func createRedirectRegexMiddleware(scheme string, filter *gatev1.HTTPRequestRedirectFilter) (*dynamic.Middleware, error) {
// Use the HTTPRequestRedirectFilter scheme if defined.
filterScheme := scheme

View file

@ -2,6 +2,7 @@ package gateway
import (
"context"
"errors"
"testing"
"time"
@ -10,6 +11,7 @@ import (
ptypes "github.com/traefik/paerser/types"
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/provider"
traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
"github.com/traefik/traefik/v3/pkg/tls"
"github.com/traefik/traefik/v3/pkg/types"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -22,11 +24,12 @@ var _ provider.Provider = (*Provider)(nil)
func TestLoadHTTPRoutes(t *testing.T) {
testCases := []struct {
desc string
ingressClass string
paths []string
expected *dynamic.Configuration
entryPoints map[string]Entrypoint
desc string
ingressClass string
paths []string
expected *dynamic.Configuration
entryPoints map[string]Entrypoint
experimentalChannel bool
}{
{
desc: "Empty",
@ -473,6 +476,7 @@ func TestLoadHTTPRoutes(t *testing.T) {
entryPoints: map[string]Entrypoint{"TCP": {
Address: ":8080",
}},
experimentalChannel: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
@ -621,70 +625,6 @@ func TestLoadHTTPRoutes(t *testing.T) {
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "Simple HTTPRoute, with myservice@file service",
paths: []string{"services.yml", "httproute/simple_cross_provider.yml"},
entryPoints: map[string]Entrypoint{"web": {
Address: ":80",
}},
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
ServersTransports: map[string]*dynamic.TCPServersTransport{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06": {
EntryPoints: []string{"web"},
Service: "default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06-wrr",
Rule: "Host(`foo.com`) && Path(`/bar`)",
RuleSyntax: "v3",
},
},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{
"default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06-wrr": {
Weighted: &dynamic.WeightedRoundRobin{
Services: []dynamic.WRRService{
{
Name: "service@file",
Weight: func(i int) *int { return &i }(1),
},
{
Name: "default-whoami-80",
Weight: func(i int) *int { return &i }(1),
},
},
},
},
"default-whoami-80": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://10.10.0.1:80",
},
{
URL: "http://10.10.0.2:80",
},
},
PassHostHeader: ptr.To(true),
ResponseForwarding: &dynamic.ResponseForwarding{
FlushInterval: ptypes.Duration(100 * time.Millisecond),
},
},
},
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "Simple HTTPRoute with protocol HTTPS",
paths: []string{"services.yml", "httproute/with_protocol_https.yml"},
@ -1717,7 +1657,264 @@ func TestLoadHTTPRoutes(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
if test.expected == nil {
return
}
p := Provider{EntryPoints: test.entryPoints, ExperimentalChannel: test.experimentalChannel}
conf := p.loadConfigurationFromGateway(context.Background(), newClientMock(test.paths...))
assert.Equal(t, test.expected, conf)
})
}
}
func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) {
testCases := []struct {
desc string
paths []string
groupKindBackendFuncs map[string]map[string]BuildBackendFunc
expected *dynamic.Configuration
entryPoints map[string]Entrypoint
}{
{
desc: "Simple HTTPRoute with TraefikService",
paths: []string{"services.yml", "httproute/simple_with_TraefikService.yml"},
groupKindBackendFuncs: map[string]map[string]BuildBackendFunc{
traefikv1alpha1.GroupName: {"TraefikService": func(name, namespace string) (string, *dynamic.Service, error) {
return name, nil, nil
}},
},
entryPoints: map[string]Entrypoint{"web": {
Address: ":80",
}},
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
ServersTransports: map[string]*dynamic.TCPServersTransport{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06": {
EntryPoints: []string{"web"},
Service: "default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06-wrr",
Rule: "Host(`foo.com`) && Path(`/bar`)",
RuleSyntax: "v3",
},
},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{
"default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06-wrr": {
Weighted: &dynamic.WeightedRoundRobin{
Services: []dynamic.WRRService{
{
Name: "whoami",
Weight: func(i int) *int { return &i }(1),
},
},
},
},
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "Simple HTTPRoute with TraefikService with service configuration",
paths: []string{"services.yml", "httproute/simple_with_TraefikService.yml"},
groupKindBackendFuncs: map[string]map[string]BuildBackendFunc{
traefikv1alpha1.GroupName: {"TraefikService": func(name, namespace string) (string, *dynamic.Service, error) {
return name, &dynamic.Service{LoadBalancer: &dynamic.ServersLoadBalancer{Servers: []dynamic.Server{{URL: "foobar"}}}}, nil
}},
},
entryPoints: map[string]Entrypoint{"web": {
Address: ":80",
}},
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
ServersTransports: map[string]*dynamic.TCPServersTransport{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06": {
EntryPoints: []string{"web"},
Service: "default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06-wrr",
Rule: "Host(`foo.com`) && Path(`/bar`)",
RuleSyntax: "v3",
},
},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{
"default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06-wrr": {
Weighted: &dynamic.WeightedRoundRobin{
Services: []dynamic.WRRService{
{
Name: "whoami",
Weight: func(i int) *int { return &i }(1),
},
},
},
},
"whoami": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{URL: "foobar"},
},
},
},
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "Simple HTTPRoute with invalid TraefikService kind",
paths: []string{"services.yml", "httproute/simple_with_TraefikService.yml"},
entryPoints: map[string]Entrypoint{"web": {
Address: ":80",
}},
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
ServersTransports: map[string]*dynamic.TCPServersTransport{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "Simple HTTPRoute with backendFunc error",
paths: []string{"services.yml", "httproute/simple_with_TraefikService.yml"},
groupKindBackendFuncs: map[string]map[string]BuildBackendFunc{
traefikv1alpha1.GroupName: {"TraefikService": func(name, namespace string) (string, *dynamic.Service, error) {
return "", nil, errors.New("BOOM")
}},
},
entryPoints: map[string]Entrypoint{"web": {
Address: ":80",
}},
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
ServersTransports: map[string]*dynamic.TCPServersTransport{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "Simple HTTPRoute, with myservice@file service",
paths: []string{"services.yml", "httproute/simple_cross_provider.yml"},
groupKindBackendFuncs: map[string]map[string]BuildBackendFunc{
traefikv1alpha1.GroupName: {"TraefikService": func(name, namespace string) (string, *dynamic.Service, error) {
// func should never be executed in case of cross-provider reference.
return "", nil, errors.New("BOOM")
}},
},
entryPoints: map[string]Entrypoint{"web": {
Address: ":80",
}},
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
ServersTransports: map[string]*dynamic.TCPServersTransport{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06": {
EntryPoints: []string{"web"},
Service: "default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06-wrr",
Rule: "Host(`foo.com`) && Path(`/bar`)",
RuleSyntax: "v3",
},
},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{
"default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06-wrr": {
Weighted: &dynamic.WeightedRoundRobin{
Services: []dynamic.WRRService{
{
Name: "service@file",
Weight: func(i int) *int { return &i }(1),
},
{
Name: "default-whoami-80",
Weight: func(i int) *int { return &i }(1),
},
},
},
},
"default-whoami-80": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://10.10.0.1:80",
},
{
URL: "http://10.10.0.2:80",
},
},
PassHostHeader: ptr.To(true),
ResponseForwarding: &dynamic.ResponseForwarding{
FlushInterval: ptypes.Duration(100 * time.Millisecond),
},
},
},
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -1726,12 +1923,233 @@ func TestLoadHTTPRoutes(t *testing.T) {
}
p := Provider{EntryPoints: test.entryPoints}
for group, kindFuncs := range test.groupKindBackendFuncs {
for kind, backendFunc := range kindFuncs {
p.RegisterBackendFuncs(group, kind, backendFunc)
}
}
conf := p.loadConfigurationFromGateway(context.Background(), newClientMock(test.paths...))
assert.Equal(t, test.expected, conf)
})
}
}
func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) {
testCases := []struct {
desc string
groupKindFilterFuncs map[string]map[string]BuildFilterFunc
expected *dynamic.Configuration
entryPoints map[string]Entrypoint
}{
{
desc: "HTTPRoute with ExtensionRef filter",
groupKindFilterFuncs: map[string]map[string]BuildFilterFunc{
traefikv1alpha1.GroupName: {"Middleware": func(name, namespace string) (string, *dynamic.Middleware, error) {
return namespace + "-" + name, nil, nil
}},
},
entryPoints: map[string]Entrypoint{"web": {
Address: ":80",
}},
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
ServersTransports: map[string]*dynamic.TCPServersTransport{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06": {
EntryPoints: []string{"web"},
Service: "default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06-wrr",
Rule: "Host(`foo.com`) && Path(`/bar`)",
RuleSyntax: "v3",
Middlewares: []string{"default-my-middleware"},
},
},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{
"default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06-wrr": {
Weighted: &dynamic.WeightedRoundRobin{
Services: []dynamic.WRRService{
{
Name: "default-whoami-80",
Weight: func(i int) *int { return &i }(1),
},
},
},
},
"default-whoami-80": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://10.10.0.1:80",
},
{
URL: "http://10.10.0.2:80",
},
},
PassHostHeader: ptr.To(true),
ResponseForwarding: &dynamic.ResponseForwarding{
FlushInterval: ptypes.Duration(100 * time.Millisecond),
},
},
},
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "HTTPRoute with ExtensionRef filter and create middleware",
groupKindFilterFuncs: map[string]map[string]BuildFilterFunc{
traefikv1alpha1.GroupName: {"Middleware": func(name, namespace string) (string, *dynamic.Middleware, error) {
return namespace + "-" + name, &dynamic.Middleware{Headers: &dynamic.Headers{CustomRequestHeaders: map[string]string{"Test-Header": "Test"}}}, nil
}},
},
entryPoints: map[string]Entrypoint{"web": {
Address: ":80",
}},
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
ServersTransports: map[string]*dynamic.TCPServersTransport{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06": {
EntryPoints: []string{"web"},
Service: "default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06-wrr",
Rule: "Host(`foo.com`) && Path(`/bar`)",
RuleSyntax: "v3",
Middlewares: []string{"default-my-middleware"},
},
},
Middlewares: map[string]*dynamic.Middleware{
"default-my-middleware": {Headers: &dynamic.Headers{CustomRequestHeaders: map[string]string{"Test-Header": "Test"}}},
},
Services: map[string]*dynamic.Service{
"default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06-wrr": {
Weighted: &dynamic.WeightedRoundRobin{
Services: []dynamic.WRRService{
{
Name: "default-whoami-80",
Weight: func(i int) *int { return &i }(1),
},
},
},
},
"default-whoami-80": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://10.10.0.1:80",
},
{
URL: "http://10.10.0.2:80",
},
},
PassHostHeader: ptr.To(true),
ResponseForwarding: &dynamic.ResponseForwarding{
FlushInterval: ptypes.Duration(100 * time.Millisecond),
},
},
},
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "ExtensionRef filter: Unknown",
entryPoints: map[string]Entrypoint{"web": {
Address: ":80",
}},
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
ServersTransports: map[string]*dynamic.TCPServersTransport{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "ExtensionRef filter with filterFunc error",
groupKindFilterFuncs: map[string]map[string]BuildFilterFunc{
traefikv1alpha1.GroupName: {"Middleware": func(name, namespace string) (string, *dynamic.Middleware, error) {
return "", nil, errors.New("BOOM")
}},
},
entryPoints: map[string]Entrypoint{"web": {
Address: ":80",
}},
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
ServersTransports: map[string]*dynamic.TCPServersTransport{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
if test.expected == nil {
return
}
p := Provider{EntryPoints: test.entryPoints}
for group, kindFuncs := range test.groupKindFilterFuncs {
for kind, filterFunc := range kindFuncs {
p.RegisterFilterFuncs(group, kind, filterFunc)
}
}
conf := p.loadConfigurationFromGateway(context.Background(), newClientMock([]string{"services.yml", "httproute/filter_extension_ref.yml"}...))
assert.Equal(t, test.expected, conf)
})
}
}
func TestLoadTCPRoutes(t *testing.T) {
testCases := []struct {
desc string
@ -2477,7 +2895,6 @@ func TestLoadTCPRoutes(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -2485,7 +2902,7 @@ func TestLoadTCPRoutes(t *testing.T) {
return
}
p := Provider{EntryPoints: test.entryPoints}
p := Provider{EntryPoints: test.entryPoints, ExperimentalChannel: true}
conf := p.loadConfigurationFromGateway(context.Background(), newClientMock(test.paths...))
assert.Equal(t, test.expected, conf)
})
@ -3606,7 +4023,6 @@ func TestLoadTLSRoutes(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -3614,7 +4030,7 @@ func TestLoadTLSRoutes(t *testing.T) {
return
}
p := Provider{EntryPoints: test.entryPoints}
p := Provider{EntryPoints: test.entryPoints, ExperimentalChannel: true}
conf := p.loadConfigurationFromGateway(context.Background(), newClientMock(test.paths...))
assert.Equal(t, test.expected, conf)
})
@ -3623,11 +4039,12 @@ func TestLoadTLSRoutes(t *testing.T) {
func TestLoadMixedRoutes(t *testing.T) {
testCases := []struct {
desc string
ingressClass string
paths []string
expected *dynamic.Configuration
entryPoints map[string]Entrypoint
desc string
ingressClass string
paths []string
expected *dynamic.Configuration
entryPoints map[string]Entrypoint
experimentalChannel bool
}{
{
desc: "Empty",
@ -3739,6 +4156,7 @@ func TestLoadMixedRoutes(t *testing.T) {
"tls-1": {Address: ":10000"},
"tls-2": {Address: ":11000"},
},
experimentalChannel: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
@ -3923,6 +4341,7 @@ func TestLoadMixedRoutes(t *testing.T) {
"tls-1": {Address: ":10000"},
"tls-2": {Address: ":11000"},
},
experimentalChannel: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
@ -4079,6 +4498,7 @@ func TestLoadMixedRoutes(t *testing.T) {
"tls-1": {Address: ":10000"},
"tls-2": {Address: ":11000"},
},
experimentalChannel: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
@ -4329,6 +4749,7 @@ func TestLoadMixedRoutes(t *testing.T) {
"tls-1": {Address: ":10000"},
"tls-2": {Address: ":11000"},
},
experimentalChannel: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
@ -4484,6 +4905,7 @@ func TestLoadMixedRoutes(t *testing.T) {
"tcp": {Address: ":9000"},
"tls": {Address: ":10000"},
},
experimentalChannel: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
@ -4614,7 +5036,6 @@ func TestLoadMixedRoutes(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -4622,7 +5043,7 @@ func TestLoadMixedRoutes(t *testing.T) {
return
}
p := Provider{EntryPoints: test.entryPoints}
p := Provider{EntryPoints: test.entryPoints, ExperimentalChannel: test.experimentalChannel}
conf := p.loadConfigurationFromGateway(context.Background(), newClientMock(test.paths...))
assert.Equal(t, test.expected, conf)
})
@ -4631,11 +5052,12 @@ func TestLoadMixedRoutes(t *testing.T) {
func TestLoadRoutesWithReferenceGrants(t *testing.T) {
testCases := []struct {
desc string
ingressClass string
paths []string
expected *dynamic.Configuration
entryPoints map[string]Entrypoint
desc string
ingressClass string
paths []string
expected *dynamic.Configuration
entryPoints map[string]Entrypoint
experimentalChannel bool
}{
{
desc: "Empty",
@ -4743,6 +5165,7 @@ func TestLoadRoutesWithReferenceGrants(t *testing.T) {
entryPoints: map[string]Entrypoint{
"tls": {Address: ":9000"},
},
experimentalChannel: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
@ -4804,7 +5227,6 @@ func TestLoadRoutesWithReferenceGrants(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -4812,7 +5234,7 @@ func TestLoadRoutesWithReferenceGrants(t *testing.T) {
return
}
p := Provider{EntryPoints: test.entryPoints}
p := Provider{EntryPoints: test.entryPoints, ExperimentalChannel: test.experimentalChannel}
conf := p.loadConfigurationFromGateway(context.Background(), newClientMock(test.paths...))
assert.Equal(t, test.expected, conf)
})
@ -4914,7 +5336,6 @@ func Test_hostRule(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
rule, err := hostRule(test.hostnames)
@ -5145,7 +5566,6 @@ func Test_extractRule(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -5220,7 +5640,6 @@ func Test_hostSNIRule(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -5541,7 +5960,6 @@ func Test_shouldAttach(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -5645,7 +6063,6 @@ func Test_matchingHostnames(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -5757,7 +6174,6 @@ func Test_getAllowedRoutes(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -5803,7 +6219,6 @@ func Test_makeListenerKey(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -5938,7 +6353,6 @@ func Test_referenceGrantMatchesFrom(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -6067,7 +6481,6 @@ func Test_referenceGrantMatchesTo(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()

View file

@ -80,7 +80,6 @@ func Test_parseRouterConfig(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -155,7 +154,6 @@ func Test_parseServiceConfig(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -239,7 +237,6 @@ func Test_convertAnnotations(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()

View file

@ -7,6 +7,7 @@ import (
"os"
"path/filepath"
"runtime"
"slices"
"time"
"github.com/hashicorp/go-version"
@ -415,12 +416,8 @@ func (c *clientWrapper) isWatchedNamespace(ns string) bool {
if c.isNamespaceAll {
return true
}
for _, watchedNamespace := range c.watchedNamespaces {
if watchedNamespace == ns {
return true
}
}
return false
return slices.Contains(c.watchedNamespaces, ns)
}
// filterIngressClassByName return a slice containing ingressclasses with the correct name.

View file

@ -46,7 +46,6 @@ func TestTranslateNotFoundError(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -124,7 +123,6 @@ func TestIsLoadBalancerIngressEquals(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()

View file

@ -9,6 +9,7 @@ import (
"net"
"os"
"regexp"
"slices"
"sort"
"strconv"
"strings"
@ -66,7 +67,7 @@ func (p *Provider) applyRouterTransform(ctx context.Context, rt *dynamic.Router,
return
}
err := p.routerTransform.Apply(ctx, rt, ingress.Annotations)
err := p.routerTransform.Apply(ctx, rt, ingress)
if err != nil {
log.Ctx(ctx).Error().Err(err).Msg("Apply router transform")
}
@ -418,13 +419,9 @@ func (p *Provider) updateIngressStatus(ing *netv1.Ingress, k8sClient Client) err
func (p *Provider) shouldProcessIngress(ingress *netv1.Ingress, ingressClasses []*netv1.IngressClass) bool {
// configuration through the new kubernetes ingressClass
if ingress.Spec.IngressClassName != nil {
for _, ic := range ingressClasses {
if *ingress.Spec.IngressClassName == ic.ObjectMeta.Name {
return true
}
}
return false
return slices.ContainsFunc(ingressClasses, func(ic *netv1.IngressClass) bool {
return *ingress.Spec.IngressClassName == ic.ObjectMeta.Name
})
}
return p.IngressClass == ingress.Annotations[annotationKubernetesIngressClass] ||

View file

@ -1495,8 +1495,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -1626,8 +1624,6 @@ func TestLoadConfigurationFromIngressesWithExternalNameServices(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -1679,8 +1675,6 @@ func TestLoadConfigurationFromIngressesWithNativeLB(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -1731,8 +1725,6 @@ func TestLoadConfigurationFromIngressesWithNodePortLB(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -1907,7 +1899,6 @@ func TestGetCertificates(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()

View file

@ -507,7 +507,6 @@ func Test_detectChanges(t *testing.T) {
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()

View file

@ -4,8 +4,9 @@ import (
"context"
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"k8s.io/apimachinery/pkg/runtime"
)
type RouterTransform interface {
Apply(ctx context.Context, rt *dynamic.Router, annotations map[string]string) error
Apply(ctx context.Context, rt *dynamic.Router, object runtime.Object) error
}

View file

@ -29,8 +29,6 @@ func TestNamespaces(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()

View file

@ -9,6 +9,8 @@ import (
"github.com/stretchr/testify/require"
ptypes "github.com/traefik/paerser/types"
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/tls"
"github.com/traefik/traefik/v3/pkg/types"
)
func Test_defaultRule(t *testing.T) {
@ -68,6 +70,9 @@ func Test_defaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -123,6 +128,9 @@ func Test_defaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -169,6 +177,9 @@ func Test_defaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -221,6 +232,9 @@ func Test_defaultRule(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
}
@ -296,6 +310,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -373,6 +390,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -437,6 +457,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -498,6 +521,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -562,6 +588,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -615,6 +644,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -669,6 +701,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -721,6 +756,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -774,6 +812,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -836,6 +877,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -885,6 +929,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -944,6 +991,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1010,6 +1060,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1069,6 +1122,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1141,6 +1197,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1207,6 +1266,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1267,6 +1329,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1332,6 +1397,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1385,6 +1453,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1439,6 +1510,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1500,6 +1574,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1531,6 +1608,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1563,6 +1643,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1596,6 +1679,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1630,6 +1716,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1684,6 +1773,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1748,6 +1840,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1805,6 +1900,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1855,6 +1953,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1903,6 +2004,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1946,6 +2050,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -1999,6 +2106,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2048,6 +2158,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2139,6 +2252,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2227,6 +2343,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2270,6 +2389,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2313,6 +2435,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2357,6 +2482,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2445,6 +2573,9 @@ func Test_buildConfig(t *testing.T) {
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2522,6 +2653,9 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
@ -2599,6 +2733,78 @@ func Test_buildConfig(t *testing.T) {
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{},
},
},
},
{
desc: "one service with default generated certificate tags",
items: []item{
{
ID: "id",
Node: "Node1",
Name: "dev/Test",
Address: "127.0.0.1",
Port: 9999,
ExtraConf: configuration{Enable: true},
Tags: []string{
"traefik.tls.stores.default.defaultgeneratedcert.resolver = foobar",
"traefik.tls.stores.default.defaultgeneratedcert.domain.main = foobar",
"traefik.tls.stores.default.defaultgeneratedcert.domain.sans = foobar, fiibar",
},
},
},
expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
ServersTransports: map[string]*dynamic.TCPServersTransport{},
},
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"dev-Test": {
Service: "dev-Test",
Rule: "Host(`dev-Test.traefik.test`)",
DefaultRule: true,
},
},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{
"dev-Test": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://127.0.0.1:9999",
},
},
PassHostHeader: Bool(true),
ResponseForwarding: &dynamic.ResponseForwarding{
FlushInterval: ptypes.Duration(100 * time.Millisecond),
},
},
},
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Stores: map[string]tls.Store{
"default": {
DefaultGeneratedCert: &tls.GeneratedCert{
Resolver: "foobar",
Domain: &types.Domain{
Main: "foobar",
SANs: []string{"foobar", "fiibar"},
},
},
},
},
},
},
},
}
@ -2691,8 +2897,6 @@ func TestNamespaces(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()

View file

@ -118,7 +118,6 @@ func TestProvider_SetDefaults_Endpoint(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
for k, v := range test.envs {
t.Setenv(k, v)

View file

@ -97,7 +97,6 @@ func Test_tagsToLabels(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()

View file

@ -120,7 +120,6 @@ func TestProvider_findDomains(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -189,7 +188,6 @@ func TestProvider_sendDynamicConfig(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -229,7 +227,6 @@ func Test_sanitizeDomains(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
@ -268,7 +265,6 @@ func Test_isTailscaleDomain(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()

View file

@ -7,7 +7,7 @@
],
"service": "api@internal",
"rule": "PathPrefix(`/api`)",
"priority": 2147483646
"priority": 9223372036854775806
},
"dashboard": {
"entryPoints": [
@ -19,7 +19,7 @@
],
"service": "dashboard@internal",
"rule": "PathPrefix(`/`)",
"priority": 2147483645
"priority": 9223372036854775805
}
},
"services": {
@ -47,4 +47,4 @@
},
"tcp": {},
"tls": {}
}
}

View file

@ -7,7 +7,7 @@
],
"service": "api@internal",
"rule": "PathPrefix(`/api`)",
"priority": 2147483646
"priority": 9223372036854775806
}
},
"services": {
@ -17,4 +17,4 @@
},
"tcp": {},
"tls": {}
}
}

View file

@ -7,7 +7,7 @@
],
"service": "api@internal",
"rule": "PathPrefix(`/api`)",
"priority": 2147483646
"priority": 9223372036854775806
},
"dashboard": {
"entryPoints": [
@ -19,7 +19,7 @@
],
"service": "dashboard@internal",
"rule": "PathPrefix(`/`)",
"priority": 2147483645
"priority": 9223372036854775805
},
"debug": {
"entryPoints": [
@ -27,7 +27,7 @@
],
"service": "api@internal",
"rule": "PathPrefix(`/debug`)",
"priority": 2147483646
"priority": 9223372036854775806
},
"ping": {
"entryPoints": [
@ -35,7 +35,7 @@
],
"service": "ping@internal",
"rule": "PathPrefix(`/ping`)",
"priority": 2147483647
"priority": 9223372036854775807
},
"prometheus": {
"entryPoints": [
@ -43,7 +43,7 @@
],
"service": "prometheus@internal",
"rule": "PathPrefix(`/metrics`)",
"priority": 2147483647
"priority": 9223372036854775807
},
"rest": {
"entryPoints": [
@ -51,7 +51,7 @@
],
"service": "rest@internal",
"rule": "PathPrefix(`/api/providers`)",
"priority": 2147483647
"priority": 9223372036854775807
}
},
"services": {
@ -82,4 +82,4 @@
},
"tcp": {},
"tls": {}
}
}

View file

@ -7,7 +7,7 @@
],
"service": "ping@internal",
"rule": "PathPrefix(`/ping`)",
"priority": 2147483647
"priority": 9223372036854775807
}
},
"services": {
@ -17,4 +17,4 @@
},
"tcp": {},
"tls": {}
}
}

View file

@ -7,7 +7,7 @@
],
"service": "prometheus@internal",
"rule": "PathPrefix(`/metrics`)",
"priority": 2147483647
"priority": 9223372036854775807
}
},
"services": {
@ -17,4 +17,4 @@
},
"tcp": {},
"tls": {}
}
}

View file

@ -7,7 +7,7 @@
],
"service": "rest@internal",
"rule": "PathPrefix(`/api/providers`)",
"priority": 2147483647
"priority": 9223372036854775807
}
},
"services": {
@ -17,4 +17,4 @@
},
"tcp": {},
"tls": {}
}
}

View file

@ -108,7 +108,7 @@ func (i *Provider) acme(cfg *dynamic.Configuration) {
Rule: "PathPrefix(`/.well-known/acme-challenge/`)",
EntryPoints: eps,
Service: "acme-http@internal",
Priority: math.MaxInt32,
Priority: math.MaxInt,
}
cfg.HTTP.Routers["acme-http"] = rt
@ -239,7 +239,7 @@ func (i *Provider) apiConfiguration(cfg *dynamic.Configuration) {
cfg.HTTP.Routers["api"] = &dynamic.Router{
EntryPoints: []string{defaultInternalEntryPointName},
Service: "api@internal",
Priority: math.MaxInt32 - 1,
Priority: math.MaxInt - 1,
Rule: "PathPrefix(`/api`)",
}
@ -247,7 +247,7 @@ func (i *Provider) apiConfiguration(cfg *dynamic.Configuration) {
cfg.HTTP.Routers["dashboard"] = &dynamic.Router{
EntryPoints: []string{defaultInternalEntryPointName},
Service: "dashboard@internal",
Priority: math.MaxInt32 - 2,
Priority: math.MaxInt - 2,
Rule: "PathPrefix(`/`)",
Middlewares: []string{"dashboard_redirect@internal", "dashboard_stripprefix@internal"},
}
@ -268,7 +268,7 @@ func (i *Provider) apiConfiguration(cfg *dynamic.Configuration) {
cfg.HTTP.Routers["debug"] = &dynamic.Router{
EntryPoints: []string{defaultInternalEntryPointName},
Service: "api@internal",
Priority: math.MaxInt32 - 1,
Priority: math.MaxInt - 1,
Rule: "PathPrefix(`/debug`)",
}
}
@ -290,7 +290,7 @@ func (i *Provider) pingConfiguration(cfg *dynamic.Configuration) {
cfg.HTTP.Routers["ping"] = &dynamic.Router{
EntryPoints: []string{i.staticCfg.Ping.EntryPoint},
Service: "ping@internal",
Priority: math.MaxInt32,
Priority: math.MaxInt,
Rule: "PathPrefix(`/ping`)",
}
}
@ -307,7 +307,7 @@ func (i *Provider) restConfiguration(cfg *dynamic.Configuration) {
cfg.HTTP.Routers["rest"] = &dynamic.Router{
EntryPoints: []string{defaultInternalEntryPointName},
Service: "rest@internal",
Priority: math.MaxInt32,
Priority: math.MaxInt,
Rule: "PathPrefix(`/api/providers`)",
}
}
@ -324,7 +324,7 @@ func (i *Provider) prometheusConfiguration(cfg *dynamic.Configuration) {
cfg.HTTP.Routers["prometheus"] = &dynamic.Router{
EntryPoints: []string{i.staticCfg.Metrics.Prometheus.EntryPoint},
Service: "prometheus@internal",
Priority: math.MaxInt32,
Priority: math.MaxInt,
Rule: "PathPrefix(`/metrics`)",
}
}

View file

@ -257,7 +257,6 @@ func Test_createConfiguration(t *testing.T) {
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()