Merge branch v3.0 into master
This commit is contained in:
commit
1ffbffb26a
326 changed files with 8850 additions and 9322 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"))
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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] ||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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": {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
],
|
||||
"service": "api@internal",
|
||||
"rule": "PathPrefix(`/api`)",
|
||||
"priority": 2147483646
|
||||
"priority": 9223372036854775806
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
|
@ -17,4 +17,4 @@
|
|||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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": {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
],
|
||||
"service": "ping@internal",
|
||||
"rule": "PathPrefix(`/ping`)",
|
||||
"priority": 2147483647
|
||||
"priority": 9223372036854775807
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
|
@ -17,4 +17,4 @@
|
|||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
],
|
||||
"service": "prometheus@internal",
|
||||
"rule": "PathPrefix(`/metrics`)",
|
||||
"priority": 2147483647
|
||||
"priority": 9223372036854775807
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
|
@ -17,4 +17,4 @@
|
|||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
],
|
||||
"service": "rest@internal",
|
||||
"rule": "PathPrefix(`/api/providers`)",
|
||||
"priority": 2147483647
|
||||
"priority": 9223372036854775807
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
|
@ -17,4 +17,4 @@
|
|||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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`)",
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue