Fix HTTP challenge router unexpected delayed creation
This commit is contained in:
parent
9a931e4dc9
commit
2065f4c003
4 changed files with 98 additions and 8 deletions
|
@ -1,7 +1,7 @@
|
||||||
whoami:
|
whoami:
|
||||||
image: traefik/whoami
|
image: traefik/whoami
|
||||||
labels:
|
labels:
|
||||||
- traefik.http.routers.route1.rule=PathPrefix(`/`)
|
- traefik.http.routers.route1.rule=PathPrefix(`/foo`)
|
||||||
- traefik.http.routers.route1.middlewares=passtls
|
- traefik.http.routers.route1.middlewares=passtls
|
||||||
- traefik.http.routers.route1.tls=true
|
- traefik.http.routers.route1.tls=true
|
||||||
- traefik.http.middlewares.passtls.passtlsclientcert.pem=true
|
- traefik.http.middlewares.passtls.passtlsclientcert.pem=true
|
||||||
|
|
|
@ -50,10 +50,10 @@ func (s *TLSClientHeadersSuite) TestTLSClientHeaders(c *check.C) {
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
defer s.killCmd(cmd)
|
defer s.killCmd(cmd)
|
||||||
|
|
||||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second, try.BodyContains("PathPrefix(`/foo`)"))
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
request, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:8443", nil)
|
request, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:8443/foo", nil)
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
certificate, err := tls.LoadX509KeyPair(certPemPath, certKeyPath)
|
certificate, err := tls.LoadX509KeyPair(certPemPath, certKeyPath)
|
||||||
|
|
|
@ -8,12 +8,14 @@ import (
|
||||||
"github.com/traefik/traefik/v2/pkg/log"
|
"github.com/traefik/traefik/v2/pkg/log"
|
||||||
"github.com/traefik/traefik/v2/pkg/provider"
|
"github.com/traefik/traefik/v2/pkg/provider"
|
||||||
"github.com/traefik/traefik/v2/pkg/provider/file"
|
"github.com/traefik/traefik/v2/pkg/provider/file"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/provider/traefik"
|
||||||
"github.com/traefik/traefik/v2/pkg/safe"
|
"github.com/traefik/traefik/v2/pkg/safe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProviderAggregator aggregates providers.
|
// ProviderAggregator aggregates providers.
|
||||||
type ProviderAggregator struct {
|
type ProviderAggregator struct {
|
||||||
fileProvider *file.Provider
|
internalProvider provider.Provider
|
||||||
|
fileProvider provider.Provider
|
||||||
providers []provider.Provider
|
providers []provider.Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,11 +100,15 @@ func (p *ProviderAggregator) AddProvider(provider provider.Provider) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if fileProvider, ok := provider.(*file.Provider); ok {
|
switch provider.(type) {
|
||||||
p.fileProvider = fileProvider
|
case *file.Provider:
|
||||||
} else {
|
p.fileProvider = provider
|
||||||
|
case *traefik.Provider:
|
||||||
|
p.internalProvider = provider
|
||||||
|
default:
|
||||||
p.providers = append(p.providers, provider)
|
p.providers = append(p.providers, provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,12 +123,17 @@ func (p ProviderAggregator) Provide(configurationChan chan<- dynamic.Message, po
|
||||||
launchProvider(configurationChan, pool, p.fileProvider)
|
launchProvider(configurationChan, pool, p.fileProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.internalProvider != nil {
|
||||||
|
launchProvider(configurationChan, pool, p.internalProvider)
|
||||||
|
}
|
||||||
|
|
||||||
for _, prd := range p.providers {
|
for _, prd := range p.providers {
|
||||||
prd := prd
|
prd := prd
|
||||||
safe.Go(func() {
|
safe.Go(func() {
|
||||||
launchProvider(configurationChan, pool, prd)
|
launchProvider(configurationChan, pool, prd)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
79
pkg/provider/aggregator/aggregator_test.go
Normal file
79
pkg/provider/aggregator/aggregator_test.go
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
package aggregator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/provider"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/safe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestProviderAggregator_Provide(t *testing.T) {
|
||||||
|
aggregator := ProviderAggregator{
|
||||||
|
internalProvider: &providerMock{"internal"},
|
||||||
|
fileProvider: &providerMock{"file"},
|
||||||
|
providers: []provider.Provider{
|
||||||
|
&providerMock{"salad"},
|
||||||
|
&providerMock{"tomato"},
|
||||||
|
&providerMock{"onion"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cfgCh := make(chan dynamic.Message)
|
||||||
|
errCh := make(chan error)
|
||||||
|
pool := safe.NewPool(context.Background())
|
||||||
|
|
||||||
|
t.Cleanup(pool.Stop)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
errCh <- aggregator.Provide(cfgCh, pool)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Make sure the file provider is always called first, followed by the internal provider.
|
||||||
|
requireReceivedMessageFromProviders(t, cfgCh, []string{"file"})
|
||||||
|
requireReceivedMessageFromProviders(t, cfgCh, []string{"internal"})
|
||||||
|
|
||||||
|
// Check if all providers have been called, the order doesn't matter.
|
||||||
|
requireReceivedMessageFromProviders(t, cfgCh, []string{"salad", "tomato", "onion"})
|
||||||
|
|
||||||
|
require.NoError(t, <-errCh)
|
||||||
|
}
|
||||||
|
|
||||||
|
// requireReceivedMessageFromProviders makes sure the given providers have emitted a message on the given message channel.
|
||||||
|
// Providers order is not enforced.
|
||||||
|
func requireReceivedMessageFromProviders(t *testing.T, cfgCh <-chan dynamic.Message, names []string) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
var msg dynamic.Message
|
||||||
|
var receivedMessagesFrom []string
|
||||||
|
|
||||||
|
for range names {
|
||||||
|
select {
|
||||||
|
case <-time.After(10 * time.Millisecond):
|
||||||
|
case msg = <-cfgCh:
|
||||||
|
receivedMessagesFrom = append(receivedMessagesFrom, msg.ProviderName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
require.ElementsMatch(t, names, receivedMessagesFrom)
|
||||||
|
}
|
||||||
|
|
||||||
|
type providerMock struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *providerMock) Init() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *providerMock) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {
|
||||||
|
configurationChan <- dynamic.Message{
|
||||||
|
ProviderName: p.Name,
|
||||||
|
Configuration: &dynamic.Configuration{},
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in a new issue