2018-06-11 09:36:03 +00:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
2019-03-14 08:30:04 +00:00
|
|
|
"context"
|
2018-06-11 09:36:03 +00:00
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2019-08-03 01:58:23 +00:00
|
|
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
|
|
|
"github.com/containous/traefik/v2/pkg/config/runtime"
|
|
|
|
"github.com/containous/traefik/v2/pkg/config/static"
|
|
|
|
th "github.com/containous/traefik/v2/pkg/testhelpers"
|
2018-06-11 09:36:03 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
)
|
|
|
|
|
2018-11-14 09:18:03 +00:00
|
|
|
func TestReuseService(t *testing.T) {
|
2018-06-11 09:36:03 +00:00
|
|
|
testServer := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
|
|
|
rw.WriteHeader(http.StatusOK)
|
|
|
|
}))
|
|
|
|
defer testServer.Close()
|
|
|
|
|
2019-03-14 08:30:04 +00:00
|
|
|
entryPoints := TCPEntryPoints{
|
|
|
|
"http": &TCPEntryPoint{},
|
2018-06-11 09:36:03 +00:00
|
|
|
}
|
|
|
|
|
2018-11-27 16:42:04 +00:00
|
|
|
staticConfig := static.Configuration{}
|
2018-11-14 09:18:03 +00:00
|
|
|
|
2019-03-14 08:30:04 +00:00
|
|
|
dynamicConfigs := th.BuildConfiguration(
|
|
|
|
th.WithRouters(
|
|
|
|
th.WithRouter("foo",
|
|
|
|
th.WithServiceName("bar"),
|
|
|
|
th.WithRule("Path(`/ok`)")),
|
|
|
|
th.WithRouter("foo2",
|
|
|
|
th.WithEntryPoints("http"),
|
|
|
|
th.WithRule("Path(`/unauthorized`)"),
|
|
|
|
th.WithServiceName("bar"),
|
|
|
|
th.WithRouterMiddlewares("basicauth")),
|
2018-06-11 09:36:03 +00:00
|
|
|
),
|
2019-03-14 08:30:04 +00:00
|
|
|
th.WithMiddlewares(th.WithMiddleware("basicauth",
|
2019-07-10 07:26:04 +00:00
|
|
|
th.WithBasicAuth(&dynamic.BasicAuth{Users: []string{"foo:bar"}}),
|
2019-03-14 08:30:04 +00:00
|
|
|
)),
|
|
|
|
th.WithLoadBalancerServices(th.WithService("bar",
|
|
|
|
th.WithServers(th.WithServer(testServer.URL))),
|
|
|
|
),
|
|
|
|
)
|
2018-06-11 09:36:03 +00:00
|
|
|
|
2019-03-14 08:30:04 +00:00
|
|
|
srv := NewServer(staticConfig, nil, entryPoints, nil)
|
2018-06-11 09:36:03 +00:00
|
|
|
|
2019-07-15 15:04:04 +00:00
|
|
|
rtConf := runtime.NewConfig(dynamic.Configuration{HTTP: dynamicConfigs})
|
2019-05-16 08:58:06 +00:00
|
|
|
entrypointsHandlers, _ := srv.createHTTPHandlers(context.Background(), rtConf, []string{"http"})
|
2018-06-11 09:36:03 +00:00
|
|
|
|
|
|
|
// Test that the /ok path returns a status 200.
|
|
|
|
responseRecorderOk := &httptest.ResponseRecorder{}
|
|
|
|
requestOk := httptest.NewRequest(http.MethodGet, testServer.URL+"/ok", nil)
|
2018-11-27 16:42:04 +00:00
|
|
|
entrypointsHandlers["http"].ServeHTTP(responseRecorderOk, requestOk)
|
2018-06-11 09:36:03 +00:00
|
|
|
|
|
|
|
assert.Equal(t, http.StatusOK, responseRecorderOk.Result().StatusCode, "status code")
|
|
|
|
|
|
|
|
// Test that the /unauthorized path returns a 401 because of
|
|
|
|
// the basic authentication defined on the frontend.
|
|
|
|
responseRecorderUnauthorized := &httptest.ResponseRecorder{}
|
|
|
|
requestUnauthorized := httptest.NewRequest(http.MethodGet, testServer.URL+"/unauthorized", nil)
|
2018-11-27 16:42:04 +00:00
|
|
|
entrypointsHandlers["http"].ServeHTTP(responseRecorderUnauthorized, requestUnauthorized)
|
2018-06-11 09:36:03 +00:00
|
|
|
|
|
|
|
assert.Equal(t, http.StatusUnauthorized, responseRecorderUnauthorized.Result().StatusCode, "status code")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestThrottleProviderConfigReload(t *testing.T) {
|
|
|
|
throttleDuration := 30 * time.Millisecond
|
2019-07-10 07:26:04 +00:00
|
|
|
publishConfig := make(chan dynamic.Message)
|
|
|
|
providerConfig := make(chan dynamic.Message)
|
2018-06-11 09:36:03 +00:00
|
|
|
stop := make(chan bool)
|
|
|
|
defer func() {
|
|
|
|
stop <- true
|
|
|
|
}()
|
|
|
|
|
2018-11-27 16:42:04 +00:00
|
|
|
staticConfiguration := static.Configuration{}
|
2019-03-14 08:30:04 +00:00
|
|
|
server := NewServer(staticConfiguration, nil, nil, nil)
|
2018-06-11 09:36:03 +00:00
|
|
|
|
|
|
|
go server.throttleProviderConfigReload(throttleDuration, publishConfig, providerConfig, stop)
|
|
|
|
|
|
|
|
publishedConfigCount := 0
|
|
|
|
stopConsumeConfigs := make(chan bool)
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-stop:
|
|
|
|
return
|
|
|
|
case <-stopConsumeConfigs:
|
|
|
|
return
|
|
|
|
case <-publishConfig:
|
|
|
|
publishedConfigCount++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// publish 5 new configs, one new config each 10 milliseconds
|
|
|
|
for i := 0; i < 5; i++ {
|
2019-07-10 07:26:04 +00:00
|
|
|
providerConfig <- dynamic.Message{}
|
2018-06-11 09:36:03 +00:00
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
}
|
|
|
|
|
|
|
|
// after 50 milliseconds 5 new configs were published
|
|
|
|
// with a throttle duration of 30 milliseconds this means, we should have received 2 new configs
|
|
|
|
assert.Equal(t, 2, publishedConfigCount, "times configs were published")
|
|
|
|
|
|
|
|
stopConsumeConfigs <- true
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-publishConfig:
|
|
|
|
// There should be exactly one more message that we receive after ~60 milliseconds since the start of the test.
|
|
|
|
select {
|
|
|
|
case <-publishConfig:
|
|
|
|
t.Error("extra config publication found")
|
|
|
|
case <-time.After(100 * time.Millisecond):
|
|
|
|
return
|
|
|
|
}
|
|
|
|
case <-time.After(100 * time.Millisecond):
|
|
|
|
t.Error("Last config was not published in time")
|
|
|
|
}
|
|
|
|
}
|