Improve integration tests
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
This commit is contained in:
parent
cd8d5b8f10
commit
e522446909
85 changed files with 3482 additions and 4609 deletions
|
@ -11,13 +11,15 @@ import (
|
|||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
"github.com/traefik/traefik/v2/pkg/middlewares/accesslog"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -28,6 +30,10 @@ const (
|
|||
// AccessLogSuite tests suite.
|
||||
type AccessLogSuite struct{ BaseSuite }
|
||||
|
||||
func TestAccessLogSuite(t *testing.T) {
|
||||
suite.Run(t, new(AccessLogSuite))
|
||||
}
|
||||
|
||||
type accessLogValue struct {
|
||||
formatOnly bool
|
||||
code string
|
||||
|
@ -36,67 +42,67 @@ type accessLogValue struct {
|
|||
serviceURL string
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "access_log")
|
||||
s.composeUp(c)
|
||||
func (s *AccessLogSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
s.createComposeProject("access_log")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TearDownTest(c *check.C) {
|
||||
displayTraefikLogFile(c, traefikTestLogFile)
|
||||
func (s *AccessLogSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TearDownTest() {
|
||||
s.displayTraefikLogFile(traefikTestLogFile)
|
||||
_ = os.Remove(traefikTestAccessLogFile)
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLog(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLog() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
defer func() {
|
||||
traefikLog, err := os.ReadFile(traefikTestLogFile)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
log.WithoutContext().Info(string(traefikLog))
|
||||
}()
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.waitForTraefik("server1")
|
||||
|
||||
waitForTraefik(c, "server1")
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Make some requests
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "frontend1.docker.local"
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "frontend2.docker.local"
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogOutput(c)
|
||||
count := s.checkAccessLogOutput()
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, 3)
|
||||
assert.Equal(s.T(), 3, count)
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogAuthFrontend(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogAuthFrontend() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -124,48 +130,43 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontend(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "authFrontend")
|
||||
s.waitForTraefik("authFrontend")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test auth entrypoint
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8006/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "frontend.auth.docker.local"
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req.SetBasicAuth("test", "")
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req.SetBasicAuth("test", "test")
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogDigestAuthMiddleware(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogDigestAuthMiddleware() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -193,27 +194,22 @@ func (s *AccessLogSuite) TestAccessLogDigestAuthMiddleware(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "digestAuthMiddleware")
|
||||
s.waitForTraefik("digestAuthMiddleware")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test auth entrypoint
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8008/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "entrypoint.digest.auth.docker.local"
|
||||
|
||||
resp, err := try.ResponseUntilStatusCode(req, 500*time.Millisecond, http.StatusUnauthorized)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
digest := digestParts(resp)
|
||||
digest["uri"] = "/"
|
||||
|
@ -225,22 +221,22 @@ func (s *AccessLogSuite) TestAccessLogDigestAuthMiddleware(c *check.C) {
|
|||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
digest["password"] = "test"
|
||||
|
||||
req.Header.Set("Authorization", getDigestAuthorization(digest))
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
// Thanks to mvndaai for digest authentication
|
||||
|
@ -291,7 +287,7 @@ func getDigestAuthorization(digestParts map[string]string) string {
|
|||
return authorization
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogFrontendRedirect(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogFrontendRedirect() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -308,38 +304,33 @@ func (s *AccessLogSuite) TestAccessLogFrontendRedirect(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "frontendRedirect")
|
||||
s.waitForTraefik("frontendRedirect")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test frontend redirect
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8005/test", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = ""
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogJSONFrontendRedirect(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogJSONFrontendRedirect() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
type logLine struct {
|
||||
|
@ -365,30 +356,25 @@ func (s *AccessLogSuite) TestAccessLogJSONFrontendRedirect(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_json_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_json_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "frontendRedirect")
|
||||
s.waitForTraefik("frontendRedirect")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test frontend redirect
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8005/test", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = ""
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
lines := extractLines(c)
|
||||
c.Assert(len(lines), checker.GreaterOrEqualThan, len(expected))
|
||||
lines := s.extractLines()
|
||||
assert.GreaterOrEqual(s.T(), len(lines), len(expected))
|
||||
|
||||
for i, line := range lines {
|
||||
if line == "" {
|
||||
|
@ -396,15 +382,15 @@ func (s *AccessLogSuite) TestAccessLogJSONFrontendRedirect(c *check.C) {
|
|||
}
|
||||
var logline logLine
|
||||
err := json.Unmarshal([]byte(line), &logline)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(logline.DownstreamStatus, checker.Equals, expected[i].DownstreamStatus)
|
||||
c.Assert(logline.OriginStatus, checker.Equals, expected[i].OriginStatus)
|
||||
c.Assert(logline.RouterName, checker.Equals, expected[i].RouterName)
|
||||
c.Assert(logline.ServiceName, checker.Equals, expected[i].ServiceName)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), expected[i].DownstreamStatus, logline.DownstreamStatus)
|
||||
assert.Equal(s.T(), expected[i].OriginStatus, logline.OriginStatus)
|
||||
assert.Equal(s.T(), expected[i].RouterName, logline.RouterName)
|
||||
assert.Equal(s.T(), expected[i].ServiceName, logline.ServiceName)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogRateLimit(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogRateLimit() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -424,42 +410,37 @@ func (s *AccessLogSuite) TestAccessLogRateLimit(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "rateLimit")
|
||||
s.waitForTraefik("rateLimit")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test rate limit
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8007/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "ratelimit.docker.local"
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogBackendNotFound(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogBackendNotFound() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -473,38 +454,33 @@ func (s *AccessLogSuite) TestAccessLogBackendNotFound(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.waitForTraefik("server1")
|
||||
|
||||
waitForTraefik(c, "server1")
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test rate limit
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "backendnotfound.docker.local"
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogFrontendWhitelist(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogFrontendWhitelist() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -518,38 +494,33 @@ func (s *AccessLogSuite) TestAccessLogFrontendWhitelist(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "frontendWhitelist")
|
||||
s.waitForTraefik("frontendWhitelist")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test rate limit
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "frontend.whitelist.docker.local"
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusForbidden), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogAuthFrontendSuccess(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogAuthFrontendSuccess() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -563,39 +534,34 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontendSuccess(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "authFrontend")
|
||||
s.waitForTraefik("authFrontend")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test auth entrypoint
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8006/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "frontend.auth.docker.local"
|
||||
req.SetBasicAuth("test", "test")
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogPreflightHeadersMiddleware(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogPreflightHeadersMiddleware() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -609,79 +575,74 @@ func (s *AccessLogSuite) TestAccessLogPreflightHeadersMiddleware(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "preflightCORS")
|
||||
s.waitForTraefik("preflightCORS")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test preflight response
|
||||
req, err := http.NewRequest(http.MethodOptions, "http://127.0.0.1:8009/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "preflight.docker.local"
|
||||
req.Header.Set("Origin", "whatever")
|
||||
req.Header.Set("Access-Control-Request-Method", "GET")
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func checkNoOtherTraefikProblems(c *check.C) {
|
||||
func (s *AccessLogSuite) checkNoOtherTraefikProblems() {
|
||||
traefikLog, err := os.ReadFile(traefikTestLogFile)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
if len(traefikLog) > 0 {
|
||||
fmt.Printf("%s\n", string(traefikLog))
|
||||
}
|
||||
}
|
||||
|
||||
func checkAccessLogOutput(c *check.C) int {
|
||||
lines := extractLines(c)
|
||||
func (s *AccessLogSuite) checkAccessLogOutput() int {
|
||||
lines := s.extractLines()
|
||||
count := 0
|
||||
for i, line := range lines {
|
||||
if len(line) > 0 {
|
||||
count++
|
||||
CheckAccessLogFormat(c, line, i)
|
||||
s.CheckAccessLogFormat(line, i)
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func checkAccessLogExactValuesOutput(c *check.C, values []accessLogValue) int {
|
||||
lines := extractLines(c)
|
||||
func (s *AccessLogSuite) checkAccessLogExactValuesOutput(values []accessLogValue) int {
|
||||
lines := s.extractLines()
|
||||
count := 0
|
||||
for i, line := range lines {
|
||||
fmt.Println(line)
|
||||
if len(line) > 0 {
|
||||
count++
|
||||
if values[i].formatOnly {
|
||||
CheckAccessLogFormat(c, line, i)
|
||||
s.CheckAccessLogFormat(line, i)
|
||||
} else {
|
||||
checkAccessLogExactValues(c, line, i, values[i])
|
||||
s.checkAccessLogExactValues(line, i, values[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func extractLines(c *check.C) []string {
|
||||
func (s *AccessLogSuite) extractLines() []string {
|
||||
accessLog, err := os.ReadFile(traefikTestAccessLogFile)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
lines := strings.Split(string(accessLog), "\n")
|
||||
|
||||
|
@ -694,14 +655,14 @@ func extractLines(c *check.C) []string {
|
|||
return clean
|
||||
}
|
||||
|
||||
func checkStatsForLogFile(c *check.C) {
|
||||
func (s *AccessLogSuite) checkStatsForLogFile() {
|
||||
err := try.Do(1*time.Second, func() error {
|
||||
if _, errStat := os.Stat(traefikTestLogFile); errStat != nil {
|
||||
return fmt.Errorf("could not get stats for log file: %w", errStat)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func ensureWorkingDirectoryIsClean() {
|
||||
|
@ -709,69 +670,38 @@ func ensureWorkingDirectoryIsClean() {
|
|||
os.Remove(traefikTestLogFile)
|
||||
}
|
||||
|
||||
func checkTraefikStarted(c *check.C) []byte {
|
||||
func (s *AccessLogSuite) checkTraefikStarted() []byte {
|
||||
traefikLog, err := os.ReadFile(traefikTestLogFile)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
if len(traefikLog) > 0 {
|
||||
fmt.Printf("%s\n", string(traefikLog))
|
||||
}
|
||||
return traefikLog
|
||||
}
|
||||
|
||||
func CheckAccessLogFormat(c *check.C, line string, i int) {
|
||||
func (s *BaseSuite) CheckAccessLogFormat(line string, i int) {
|
||||
results, err := accesslog.ParseAccessLog(line)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(results, checker.HasLen, 14)
|
||||
c.Assert(results[accesslog.OriginStatus], checker.Matches, `^(-|\d{3})$`)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Len(s.T(), results, 14)
|
||||
assert.Regexp(s.T(), `^(-|\d{3})$`, results[accesslog.OriginStatus])
|
||||
count, _ := strconv.Atoi(results[accesslog.RequestCount])
|
||||
c.Assert(count, checker.GreaterOrEqualThan, i+1)
|
||||
c.Assert(results[accesslog.RouterName], checker.Matches, `"(rt-.+@docker|api@internal)"`)
|
||||
c.Assert(results[accesslog.ServiceURL], checker.HasPrefix, `"http://`)
|
||||
c.Assert(results[accesslog.Duration], checker.Matches, `^\d+ms$`)
|
||||
assert.GreaterOrEqual(s.T(), count, i+1)
|
||||
assert.Regexp(s.T(), `"(rt-.+@docker|api@internal)"`, results[accesslog.RouterName])
|
||||
assert.True(s.T(), strings.HasPrefix(results[accesslog.ServiceURL], `"http://`))
|
||||
assert.Regexp(s.T(), `^\d+ms$`, results[accesslog.Duration])
|
||||
}
|
||||
|
||||
func checkAccessLogExactValues(c *check.C, line string, i int, v accessLogValue) {
|
||||
func (s *AccessLogSuite) checkAccessLogExactValues(line string, i int, v accessLogValue) {
|
||||
results, err := accesslog.ParseAccessLog(line)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(results, checker.HasLen, 14)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Len(s.T(), results, 14)
|
||||
if len(v.user) > 0 {
|
||||
c.Assert(results[accesslog.ClientUsername], checker.Equals, v.user)
|
||||
assert.Equal(s.T(), v.user, results[accesslog.ClientUsername])
|
||||
}
|
||||
c.Assert(results[accesslog.OriginStatus], checker.Equals, v.code)
|
||||
assert.Equal(s.T(), v.code, results[accesslog.OriginStatus])
|
||||
count, _ := strconv.Atoi(results[accesslog.RequestCount])
|
||||
c.Assert(count, checker.GreaterOrEqualThan, i+1)
|
||||
c.Assert(results[accesslog.RouterName], checker.Matches, `^"?`+v.routerName+`.*(@docker)?$`)
|
||||
c.Assert(results[accesslog.ServiceURL], checker.Matches, `^"?`+v.serviceURL+`.*$`)
|
||||
c.Assert(results[accesslog.Duration], checker.Matches, `^\d+ms$`)
|
||||
}
|
||||
|
||||
func waitForTraefik(c *check.C, containerName string) {
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// Wait for Traefik to turn ready.
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/api/rawdata", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains(containerName))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func displayTraefikLogFile(c *check.C, path string) {
|
||||
if c.Failed() {
|
||||
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
||||
content, errRead := os.ReadFile(path)
|
||||
fmt.Printf("%s: Traefik logs: \n", c.TestName())
|
||||
if errRead == nil {
|
||||
fmt.Println(content)
|
||||
} else {
|
||||
fmt.Println(errRead)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("%s: No Traefik logs.\n", c.TestName())
|
||||
}
|
||||
errRemove := os.Remove(path)
|
||||
if errRemove != nil {
|
||||
fmt.Println(errRemove)
|
||||
}
|
||||
}
|
||||
assert.GreaterOrEqual(s.T(), count, i+1)
|
||||
assert.Regexp(s.T(), `^"?`+v.routerName+`.*(@docker)?$`, results[accesslog.RouterName])
|
||||
assert.Regexp(s.T(), `^"?`+v.serviceURL+`.*$`, results[accesslog.ServiceURL])
|
||||
assert.Regexp(s.T(), `^\d+ms$`, results[accesslog.Duration])
|
||||
}
|
||||
|
|
|
@ -8,16 +8,19 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/miekg/dns"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/config/static"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
"github.com/traefik/traefik/v2/pkg/provider/acme"
|
||||
"github.com/traefik/traefik/v2/pkg/testhelpers"
|
||||
"github.com/traefik/traefik/v2/pkg/types"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// ACME test suites.
|
||||
|
@ -27,6 +30,10 @@ type AcmeSuite struct {
|
|||
fakeDNSServer *dns.Server
|
||||
}
|
||||
|
||||
func TestAcmeSuite(t *testing.T) {
|
||||
suite.Run(t, new(AcmeSuite))
|
||||
}
|
||||
|
||||
type subCases struct {
|
||||
host string
|
||||
expectedCommonName string
|
||||
|
@ -87,17 +94,18 @@ func setupPebbleRootCA() (*http.Transport, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "pebble")
|
||||
s.composeUp(c)
|
||||
func (s *AcmeSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.fakeDNSServer = startFakeDNSServer(s.getContainerIP(c, "traefik"))
|
||||
s.pebbleIP = s.getComposeServiceIP(c, "pebble")
|
||||
s.createComposeProject("pebble")
|
||||
s.composeUp()
|
||||
|
||||
// Retrieving the Docker host ip.
|
||||
s.fakeDNSServer = startFakeDNSServer(s.hostIP)
|
||||
s.pebbleIP = s.getComposeServiceIP("pebble")
|
||||
|
||||
pebbleTransport, err := setupPebbleRootCA()
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// wait for pebble
|
||||
req := testhelpers.MustNewRequest(http.MethodGet, s.getAcmeURL(), nil)
|
||||
|
@ -113,21 +121,24 @@ func (s *AcmeSuite) SetUpSuite(c *check.C) {
|
|||
}
|
||||
return try.StatusCodeIs(http.StatusOK)(resp)
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TearDownSuite(c *check.C) {
|
||||
func (s *AcmeSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
|
||||
if s.fakeDNSServer != nil {
|
||||
err := s.fakeDNSServer.Shutdown()
|
||||
if err != nil {
|
||||
c.Log(err)
|
||||
log.WithoutContext().Info(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
s.composeDown(c)
|
||||
s.composeDown()
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01Domains(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01Domains() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_domains.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -147,10 +158,10 @@ func (s *AcmeSuite) TestHTTP01Domains(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01StoreDomains(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01StoreDomains() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_store_domains.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -170,10 +181,10 @@ func (s *AcmeSuite) TestHTTP01StoreDomains(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01DomainsInSAN(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01DomainsInSAN() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_domains.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -194,10 +205,10 @@ func (s *AcmeSuite) TestHTTP01DomainsInSAN(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRule(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRule() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_base.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -214,10 +225,10 @@ func (s *AcmeSuite) TestHTTP01OnHostRule(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestMultipleResolver(c *check.C) {
|
||||
func (s *AcmeSuite) TestMultipleResolver() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_multiple_resolvers.toml",
|
||||
subCases: []subCases{
|
||||
|
@ -245,10 +256,10 @@ func (s *AcmeSuite) TestMultipleResolver(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleECDSA(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleECDSA() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_base.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -266,10 +277,10 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleECDSA(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleInvalidAlgo(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleInvalidAlgo() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_base.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -287,10 +298,10 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleInvalidAlgo(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleDefaultDynamicCertificatesWithWildcard(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleDefaultDynamicCertificatesWithWildcard() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_tls.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -307,10 +318,10 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleDefaultDynamicCertificatesWithWildcard(c
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleDynamicCertificatesWithWildcard(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleDynamicCertificatesWithWildcard() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_tls_dynamic.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -327,10 +338,10 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleDynamicCertificatesWithWildcard(c *check
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestTLSALPN01OnHostRuleTCP(c *check.C) {
|
||||
func (s *AcmeSuite) TestTLSALPN01OnHostRuleTCP() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_tcp.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -347,10 +358,10 @@ func (s *AcmeSuite) TestTLSALPN01OnHostRuleTCP(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestTLSALPN01OnHostRule(c *check.C) {
|
||||
func (s *AcmeSuite) TestTLSALPN01OnHostRule() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_base.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -367,10 +378,10 @@ func (s *AcmeSuite) TestTLSALPN01OnHostRule(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestTLSALPN01Domains(c *check.C) {
|
||||
func (s *AcmeSuite) TestTLSALPN01Domains() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_domains.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -390,10 +401,10 @@ func (s *AcmeSuite) TestTLSALPN01Domains(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestTLSALPN01DomainsInSAN(c *check.C) {
|
||||
func (s *AcmeSuite) TestTLSALPN01DomainsInSAN() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_domains.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -414,12 +425,12 @@ func (s *AcmeSuite) TestTLSALPN01DomainsInSAN(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
// Test Let's encrypt down.
|
||||
func (s *AcmeSuite) TestNoValidLetsEncryptServer(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/acme/acme_base.toml", templateModel{
|
||||
func (s *AcmeSuite) TestNoValidLetsEncryptServer() {
|
||||
file := s.adaptFile("fixtures/acme/acme_base.toml", templateModel{
|
||||
Acme: map[string]static.CertificateResolver{
|
||||
"default": {ACME: &acme.Configuration{
|
||||
CAServer: "http://wrongurl:4001/directory",
|
||||
|
@ -427,21 +438,16 @@ func (s *AcmeSuite) TestNoValidLetsEncryptServer(c *check.C) {
|
|||
}},
|
||||
},
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Expected traefik works
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
// Doing an HTTPS request and test the response certificate.
|
||||
func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase acmeTestCase) {
|
||||
func (s *AcmeSuite) retrieveAcmeCertificate(testCase acmeTestCase) {
|
||||
if len(testCase.template.PortHTTP) == 0 {
|
||||
testCase.template.PortHTTP = ":5002"
|
||||
}
|
||||
|
@ -456,14 +462,10 @@ func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase acmeTestCase) {
|
|||
}
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, testCase.traefikConfFilePath, testCase.template)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile(testCase.traefikConfFilePath, testCase.template)
|
||||
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
// A real file is needed to have the right mode on acme.json file
|
||||
defer os.Remove("/tmp/acme.json")
|
||||
|
||||
|
@ -477,11 +479,11 @@ func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase acmeTestCase) {
|
|||
}
|
||||
|
||||
// wait for traefik (generating acme account take some seconds)
|
||||
err = try.Do(60*time.Second, func() error {
|
||||
err := try.Do(60*time.Second, func() error {
|
||||
_, errGet := client.Get("https://127.0.0.1:5001")
|
||||
return errGet
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
for _, sub := range testCase.subCases {
|
||||
client = &http.Client{
|
||||
|
@ -503,7 +505,7 @@ func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase acmeTestCase) {
|
|||
var resp *http.Response
|
||||
|
||||
// Retry to send a Request which uses the LE generated certificate
|
||||
err = try.Do(60*time.Second, func() error {
|
||||
err := try.Do(60*time.Second, func() error {
|
||||
resp, err = client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -517,10 +519,10 @@ func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase acmeTestCase) {
|
|||
return nil
|
||||
})
|
||||
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusOK, resp.StatusCode)
|
||||
// Check Domain into response certificate
|
||||
c.Assert(resp.TLS.PeerCertificates[0].Subject.CommonName, checker.Equals, sub.expectedCommonName)
|
||||
c.Assert(resp.TLS.PeerCertificates[0].PublicKeyAlgorithm, checker.Equals, sub.expectedAlgorithm)
|
||||
assert.Equal(s.T(), sub.expectedCommonName, resp.TLS.PeerCertificates[0].Subject.CommonName)
|
||||
assert.Equal(s.T(), sub.expectedAlgorithm, resp.TLS.PeerCertificates[0].PublicKeyAlgorithm)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,36 +8,38 @@ import (
|
|||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type ThrottlingSuite struct{ BaseSuite }
|
||||
|
||||
func (s *ThrottlingSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "rest")
|
||||
s.composeUp(c)
|
||||
func TestThrottlingSuite(t *testing.T) {
|
||||
suite.Run(t, new(ThrottlingSuite))
|
||||
}
|
||||
|
||||
func (s *ThrottlingSuite) TestThrottleConfReload(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/throttling/simple.toml"))
|
||||
func (s *ThrottlingSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
s.createComposeProject("rest")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
func (s *ThrottlingSuite) TestThrottleConfReload() {
|
||||
s.traefikCmd(withConfigFile("fixtures/throttling/simple.toml"))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1000*time.Millisecond, try.BodyContains("rest@internal"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1000*time.Millisecond, try.BodyContains("rest@internal"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Expected a 404 as we did not configure anything.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
config := &dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
|
@ -47,7 +49,7 @@ func (s *ThrottlingSuite) TestThrottleConfReload(c *check.C) {
|
|||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "http://" + s.getComposeServiceIP(c, "whoami1") + ":80",
|
||||
URL: "http://" + s.getComposeServiceIP("whoami1") + ":80",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -68,28 +70,28 @@ func (s *ThrottlingSuite) TestThrottleConfReload(c *check.C) {
|
|||
for i := 0; i < confChanges; i++ {
|
||||
config.HTTP.Routers[fmt.Sprintf("routerHTTP%d", i)] = router
|
||||
data, err := json.Marshal(config)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
request, err := http.NewRequest(http.MethodPut, "http://127.0.0.1:8080/api/providers/rest", bytes.NewReader(data))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
response, err := http.DefaultClient.Do(request)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusOK, response.StatusCode)
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
|
||||
reloadsRegexp := regexp.MustCompile(`traefik_config_reloads_total (\d*)\n`)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/metrics")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
fields := reloadsRegexp.FindStringSubmatch(string(body))
|
||||
c.Assert(len(fields), checker.Equals, 2)
|
||||
assert.Len(s.T(), fields, 2)
|
||||
|
||||
reloads, err := strconv.Atoi(fields[1])
|
||||
if err != nil {
|
||||
|
@ -101,5 +103,5 @@ func (s *ThrottlingSuite) TestThrottleConfReload(c *check.C) {
|
|||
// Therefore the throttling (set at 400ms for this test) should only let
|
||||
// (2s / 400 ms =) 5 config reloads happen in theory.
|
||||
// In addition, we have to take into account the extra config reload from the internal provider (5 + 1).
|
||||
c.Assert(reloads, checker.LessOrEqualThan, 6)
|
||||
assert.LessOrEqual(s.T(), reloads, 6)
|
||||
}
|
||||
|
|
|
@ -4,13 +4,14 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type ConsulCatalogSuite struct {
|
||||
|
@ -20,26 +21,36 @@ type ConsulCatalogSuite struct {
|
|||
consulURL string
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "consul_catalog")
|
||||
s.composeUp(c)
|
||||
func TestConsulCatalogSuite(t *testing.T) {
|
||||
suite.Run(t, new(ConsulCatalogSuite))
|
||||
}
|
||||
|
||||
s.consulURL = "http://" + net.JoinHostPort(s.getComposeServiceIP(c, "consul"), "8500")
|
||||
func (s *ConsulCatalogSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("consul_catalog")
|
||||
s.composeUp()
|
||||
|
||||
s.consulURL = "http://" + net.JoinHostPort(s.getComposeServiceIP("consul"), "8500")
|
||||
|
||||
var err error
|
||||
s.consulClient, err = api.NewClient(&api.Config{
|
||||
Address: s.consulURL,
|
||||
})
|
||||
c.Check(err, check.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Wait for consul to elect itself leader
|
||||
err = s.waitToElectConsulLeader()
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
s.consulAgentClient, err = api.NewClient(&api.Config{
|
||||
Address: "http://" + net.JoinHostPort(s.getComposeServiceIP(c, "consul-agent"), "8500"),
|
||||
Address: "http://" + net.JoinHostPort(s.getComposeServiceIP("consul-agent"), "8500"),
|
||||
})
|
||||
c.Check(err, check.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) waitToElectConsulLeader() error {
|
||||
|
@ -83,36 +94,36 @@ func (s *ConsulCatalogSuite) deregisterService(id string, onAgent bool) error {
|
|||
return client.Agent().ServiceDeregister(id)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings() {
|
||||
reg1 := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami",
|
||||
Tags: []string{"traefik.enable=true"},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
Address: s.getComposeServiceIP("whoami1"),
|
||||
}
|
||||
err := s.registerService(reg1, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
reg2 := &api.AgentServiceRegistration{
|
||||
ID: "whoami2",
|
||||
Name: "whoami",
|
||||
Tags: []string{"traefik.enable=true"},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami2"),
|
||||
Address: s.getComposeServiceIP("whoami2"),
|
||||
}
|
||||
err = s.registerService(reg2, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
reg3 := &api.AgentServiceRegistration{
|
||||
ID: "whoami3",
|
||||
Name: "whoami",
|
||||
Tags: []string{"traefik.enable=true"},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami3"),
|
||||
Address: s.getComposeServiceIP("whoami3"),
|
||||
}
|
||||
err = s.registerService(reg3, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
|
@ -120,23 +131,18 @@ func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *c
|
|||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "whoami"
|
||||
|
||||
err = try.Request(req, 2*time.Second,
|
||||
try.StatusCodeIs(200),
|
||||
try.BodyContainsOr("Hostname: whoami1", "Hostname: whoami2", "Hostname: whoami3"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
try.StatusCodeIs(200),
|
||||
|
@ -145,18 +151,18 @@ func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *c
|
|||
fmt.Sprintf(`"http://%s:80":"UP"`, reg2.Address),
|
||||
fmt.Sprintf(`"http://%s:80":"UP"`, reg3.Address),
|
||||
))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = s.deregisterService("whoami2", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = s.deregisterService("whoami3", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestByLabels(c *check.C) {
|
||||
containerIP := s.getComposeServiceIP(c, "whoami1")
|
||||
func (s *ConsulCatalogSuite) TestByLabels() {
|
||||
containerIP := s.getComposeServiceIP("whoami1")
|
||||
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
|
@ -171,7 +177,7 @@ func (s *ConsulCatalogSuite) TestByLabels(c *check.C) {
|
|||
Address: containerIP,
|
||||
}
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
|
@ -179,23 +185,18 @@ func (s *ConsulCatalogSuite) TestByLabels(c *check.C) {
|
|||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/whoami", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContainsOr("Hostname: whoami1", "Hostname: whoami2", "Hostname: whoami3"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestSimpleConfiguration(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestSimpleConfiguration() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -204,37 +205,32 @@ func (s *ConsulCatalogSuite) TestSimpleConfiguration(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami",
|
||||
Tags: []string{"traefik.enable=true"},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
Address: s.getComposeServiceIP("whoami1"),
|
||||
}
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "whoami.consul.localhost"
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200), try.BodyContainsOr("Hostname: whoami1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestSimpleConfigurationWithWatch(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestSimpleConfigurationWithWatch() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -243,39 +239,34 @@ func (s *ConsulCatalogSuite) TestSimpleConfigurationWithWatch(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple_watch.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple_watch.toml", tempObjects)
|
||||
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami",
|
||||
Tags: []string{"traefik.enable=true"},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
Address: s.getComposeServiceIP("whoami1"),
|
||||
}
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "whoami.consul.localhost"
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContainsOr("Hostname: whoami1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
whoamiIP := s.getComposeServiceIP(c, "whoami1")
|
||||
whoamiIP := s.getComposeServiceIP("whoami1")
|
||||
reg.Check = &api.AgentServiceCheck{
|
||||
CheckID: "some-ok-check",
|
||||
TCP: whoamiIP + ":80",
|
||||
|
@ -285,10 +276,10 @@ func (s *ConsulCatalogSuite) TestSimpleConfigurationWithWatch(c *check.C) {
|
|||
}
|
||||
|
||||
err = s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContainsOr("Hostname: whoami1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.Request(req, 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContainsOr("Hostname: whoami1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
reg.Check = &api.AgentServiceCheck{
|
||||
CheckID: "some-failing-check",
|
||||
|
@ -299,16 +290,16 @@ func (s *ConsulCatalogSuite) TestSimpleConfigurationWithWatch(c *check.C) {
|
|||
}
|
||||
|
||||
err = s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.Request(req, 5*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestRegisterServiceWithoutIP(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestRegisterServiceWithoutIP() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -317,8 +308,7 @@ func (s *ConsulCatalogSuite) TestRegisterServiceWithoutIP(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
|
@ -328,25 +318,21 @@ func (s *ConsulCatalogSuite) TestRegisterServiceWithoutIP(c *check.C) {
|
|||
Address: "",
|
||||
}
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/api/http/services", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200), try.BodyContainsOr("whoami@consulcatalog", "\"http://127.0.0.1:80\": \"UP\""))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestDefaultConsulService(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestDefaultConsulService() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -355,37 +341,32 @@ func (s *ConsulCatalogSuite) TestDefaultConsulService(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami",
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
Address: s.getComposeServiceIP("whoami1"),
|
||||
}
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "whoami.consul.localhost"
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200), try.BodyContainsOr("Hostname: whoami1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithTCPLabels(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithTCPLabels() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -394,8 +375,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithTCPLabels(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
|
||||
// Start a container with some tags
|
||||
reg := &api.AgentServiceRegistration{
|
||||
|
@ -407,32 +387,28 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithTCPLabels(c *check.C) {
|
|||
"traefik.tcp.Services.Super.Loadbalancer.server.port=8080",
|
||||
},
|
||||
Port: 8080,
|
||||
Address: s.getComposeServiceIP(c, "whoamitcp"),
|
||||
Address: s.getComposeServiceIP("whoamitcp"),
|
||||
}
|
||||
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`my.super.host`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
who, err := guessWho("127.0.0.1:8000", "my.super.host", true)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
c.Assert(who, checker.Contains, "whoamitcp")
|
||||
assert.Contains(s.T(), who, "whoamitcp")
|
||||
|
||||
err = s.deregisterService("whoamitcp", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithLabels(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithLabels() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -441,8 +417,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithLabels(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
|
||||
// Start a container with some tags
|
||||
reg1 := &api.AgentServiceRegistration{
|
||||
|
@ -452,11 +427,11 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithLabels(c *check.C) {
|
|||
"traefik.http.Routers.Super.Rule=Host(`my.super.host`)",
|
||||
},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
Address: s.getComposeServiceIP("whoami1"),
|
||||
}
|
||||
|
||||
err := s.registerService(reg1, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Start another container by replacing a '.' by a '-'
|
||||
reg2 := &api.AgentServiceRegistration{
|
||||
|
@ -466,40 +441,36 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithLabels(c *check.C) {
|
|||
"traefik.http.Routers.SuperHost.Rule=Host(`my-super.host`)",
|
||||
},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami2"),
|
||||
Address: s.getComposeServiceIP("whoami2"),
|
||||
}
|
||||
err = s.registerService(reg2, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my-super.host"
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200), try.BodyContainsOr("Hostname: whoami1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my.super.host"
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200), try.BodyContainsOr("Hostname: whoami2"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami2", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -508,8 +479,7 @@ func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent(c *check.C)
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
|
||||
|
||||
// Start a container with some tags
|
||||
tags := []string{
|
||||
|
@ -523,50 +493,46 @@ func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent(c *check.C)
|
|||
Name: "whoami",
|
||||
Tags: tags,
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
Address: s.getComposeServiceIP("whoami1"),
|
||||
}
|
||||
err := s.registerService(reg1, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
reg2 := &api.AgentServiceRegistration{
|
||||
ID: "whoami",
|
||||
Name: "whoami",
|
||||
Tags: tags,
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami2"),
|
||||
Address: s.getComposeServiceIP("whoami2"),
|
||||
}
|
||||
err = s.registerService(reg2, true)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my.super.host"
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200), try.BodyContainsOr("Hostname: whoami1", "Hostname: whoami2"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/api/rawdata", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200),
|
||||
try.BodyContainsOr(s.getComposeServiceIP(c, "whoami1"), s.getComposeServiceIP(c, "whoami2")))
|
||||
c.Assert(err, checker.IsNil)
|
||||
try.BodyContainsOr(s.getComposeServiceIP("whoami1"), s.getComposeServiceIP("whoami2")))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami", true)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithOneMissingLabels(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithOneMissingLabels() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -575,8 +541,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithOneMissingLabels(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
|
||||
// Start a container with some tags
|
||||
reg := &api.AgentServiceRegistration{
|
||||
|
@ -586,32 +551,28 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithOneMissingLabels(c *check.C) {
|
|||
"traefik.random.value=my.super.host",
|
||||
},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
Address: s.getComposeServiceIP("whoami1"),
|
||||
}
|
||||
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my.super.host"
|
||||
|
||||
// TODO Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
|
||||
// TODO validate : run on 80
|
||||
// Expected a 404 as we did not configure anything
|
||||
err = try.Request(req, 1500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
|
||||
whoamiIP := s.getComposeServiceIP(c, "whoami1")
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck() {
|
||||
whoamiIP := s.getComposeServiceIP("whoami1")
|
||||
tags := []string{
|
||||
"traefik.enable=true",
|
||||
"traefik.http.routers.router1.rule=Path(`/whoami`)",
|
||||
|
@ -635,7 +596,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
|
|||
}
|
||||
|
||||
err := s.registerService(reg1, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
|
@ -643,22 +604,17 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
|
|||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/whoami", 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
whoami2IP := s.getComposeServiceIP(c, "whoami2")
|
||||
whoami2IP := s.getComposeServiceIP("whoami2")
|
||||
reg2 := &api.AgentServiceRegistration{
|
||||
ID: "whoami2",
|
||||
Name: "whoami",
|
||||
|
@ -675,26 +631,26 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
|
|||
}
|
||||
|
||||
err = s.registerService(reg2, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/whoami", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "whoami"
|
||||
|
||||
// TODO Need to wait for up to 10 seconds (for consul discovery or traefik to boot up ?)
|
||||
err = try.Request(req, 10*time.Second, try.StatusCodeIs(200), try.BodyContainsOr("Hostname: whoami2"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami2", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestConsulConnect(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestConsulConnect() {
|
||||
// Wait for consul to fully initialize connect CA
|
||||
err := s.waitForConnectCA()
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
connectIP := s.getComposeServiceIP(c, "connect")
|
||||
connectIP := s.getComposeServiceIP("connect")
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "uuid-api1",
|
||||
Name: "uuid-api",
|
||||
|
@ -712,9 +668,9 @@ func (s *ConsulCatalogSuite) TestConsulConnect(c *check.C) {
|
|||
Address: connectIP,
|
||||
}
|
||||
err = s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
whoamiIP := s.getComposeServiceIP(c, "whoami1")
|
||||
whoamiIP := s.getComposeServiceIP("whoami1")
|
||||
regWhoami := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami",
|
||||
|
@ -727,40 +683,35 @@ func (s *ConsulCatalogSuite) TestConsulConnect(c *check.C) {
|
|||
Address: whoamiIP,
|
||||
}
|
||||
err = s.registerService(regWhoami, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
}{
|
||||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/connect.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/connect.toml", tempObjects)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 10*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/whoami", 10*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("uuid-api1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault() {
|
||||
// Wait for consul to fully initialize connect CA
|
||||
err := s.waitForConnectCA()
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
connectIP := s.getComposeServiceIP(c, "connect")
|
||||
connectIP := s.getComposeServiceIP("connect")
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "uuid-api1",
|
||||
Name: "uuid-api",
|
||||
|
@ -777,9 +728,9 @@ func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
|
|||
Address: connectIP,
|
||||
}
|
||||
err = s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
whoamiIP := s.getComposeServiceIP(c, "whoami1")
|
||||
whoamiIP := s.getComposeServiceIP("whoami1")
|
||||
regWhoami := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami1",
|
||||
|
@ -792,9 +743,9 @@ func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
|
|||
Address: whoamiIP,
|
||||
}
|
||||
err = s.registerService(regWhoami, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
whoami2IP := s.getComposeServiceIP(c, "whoami2")
|
||||
whoami2IP := s.getComposeServiceIP("whoami2")
|
||||
regWhoami2 := &api.AgentServiceRegistration{
|
||||
ID: "whoami2",
|
||||
Name: "whoami2",
|
||||
|
@ -808,45 +759,40 @@ func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
|
|||
Address: whoami2IP,
|
||||
}
|
||||
err = s.registerService(regWhoami2, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
}{
|
||||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/connect_by_default.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/connect_by_default.toml", tempObjects)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 10*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/whoami", 10*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/whoami2", 10*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("uuid-api1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = s.deregisterService("whoami2", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestConsulConnect_NotAware(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestConsulConnect_NotAware() {
|
||||
// Wait for consul to fully initialize connect CA
|
||||
err := s.waitForConnectCA()
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
connectIP := s.getComposeServiceIP(c, "connect")
|
||||
connectIP := s.getComposeServiceIP("connect")
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "uuid-api1",
|
||||
Name: "uuid-api",
|
||||
|
@ -864,9 +810,9 @@ func (s *ConsulCatalogSuite) TestConsulConnect_NotAware(c *check.C) {
|
|||
Address: connectIP,
|
||||
}
|
||||
err = s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
whoamiIP := s.getComposeServiceIP(c, "whoami1")
|
||||
whoamiIP := s.getComposeServiceIP("whoami1")
|
||||
regWhoami := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami",
|
||||
|
@ -879,30 +825,25 @@ func (s *ConsulCatalogSuite) TestConsulConnect_NotAware(c *check.C) {
|
|||
Address: whoamiIP,
|
||||
}
|
||||
err = s.registerService(regWhoami, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
}{
|
||||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/connect_not_aware.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/connect_not_aware.toml", tempObjects)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 10*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/whoami", 10*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("uuid-api1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -10,16 +10,17 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/kvtools/consul"
|
||||
"github.com/kvtools/valkeyrie"
|
||||
"github.com/kvtools/valkeyrie/store"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/api"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Consul test suites.
|
||||
|
@ -29,18 +30,16 @@ type ConsulSuite struct {
|
|||
consulURL string
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) resetStore(c *check.C) {
|
||||
err := s.kvClient.DeleteTree(context.Background(), "traefik")
|
||||
if err != nil && !errors.Is(err, store.ErrKeyNotFound) {
|
||||
c.Fatal(err)
|
||||
}
|
||||
func TestConsulSuite(t *testing.T) {
|
||||
suite.Run(t, new(ConsulSuite))
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) setupStore(c *check.C) {
|
||||
s.createComposeProject(c, "consul")
|
||||
s.composeUp(c)
|
||||
func (s *ConsulSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
s.createComposeProject("consul")
|
||||
s.composeUp()
|
||||
|
||||
consulAddr := net.JoinHostPort(s.getComposeServiceIP(c, "consul"), "8500")
|
||||
consulAddr := net.JoinHostPort(s.getComposeServiceIP("consul"), "8500")
|
||||
s.consulURL = fmt.Sprintf("http://%s", consulAddr)
|
||||
|
||||
kv, err := valkeyrie.NewStore(
|
||||
|
@ -51,21 +50,27 @@ func (s *ConsulSuite) setupStore(c *check.C) {
|
|||
ConnectionTimeout: 10 * time.Second,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
c.Fatal("Cannot create store consul")
|
||||
}
|
||||
require.NoError(s.T(), err, "Cannot create store consul")
|
||||
s.kvClient = kv
|
||||
|
||||
// wait for consul
|
||||
err = try.Do(60*time.Second, try.KVExists(kv, "test"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) TestSimpleConfiguration(c *check.C) {
|
||||
s.setupStore(c)
|
||||
func (s *ConsulSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul/simple.toml", struct{ ConsulAddress string }{s.consulURL})
|
||||
defer os.Remove(file)
|
||||
func (s *ConsulSuite) TearDownTest() {
|
||||
err := s.kvClient.DeleteTree(context.Background(), "traefik")
|
||||
if err != nil && !errors.Is(err, store.ErrKeyNotFound) {
|
||||
require.ErrorIs(s.T(), err, store.ErrKeyNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/consul/simple.toml", struct{ ConsulAddress string }{s.consulURL})
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
|
@ -115,39 +120,35 @@ func (s *ConsulSuite) TestSimpleConfiguration(c *check.C) {
|
|||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(context.Background(), k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
try.BodyContains(`"striper@consul":`, `"compressor@consul":`, `"srvcA@consul":`, `"srvcB@consul":`),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-consul.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = os.WriteFile(expectedJSON, got, 0o666)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
expected, err := os.ReadFile(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
|
@ -159,33 +160,27 @@ func (s *ConsulSuite) TestSimpleConfiguration(c *check.C) {
|
|||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Error(text)
|
||||
require.NoError(s.T(), err, text)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) assertWhoami(c *check.C, host string, expectedStatusCode int) {
|
||||
func (s *ConsulSuite) assertWhoami(host string, expectedStatusCode int) {
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = host
|
||||
|
||||
resp, err := try.ResponseUntilStatusCode(req, 15*time.Second, expectedStatusCode)
|
||||
require.NoError(s.T(), err)
|
||||
resp.Body.Close()
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) TestDeleteRootKey(c *check.C) {
|
||||
func (s *ConsulSuite) TestDeleteRootKey() {
|
||||
// This test case reproduce the issue: https://github.com/traefik/traefik/issues/8092
|
||||
s.setupStore(c)
|
||||
s.resetStore(c)
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul/simple.toml", struct{ ConsulAddress string }{s.consulURL})
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul/simple.toml", struct{ ConsulAddress string }{s.consulURL})
|
||||
|
||||
ctx := context.Background()
|
||||
svcaddr := net.JoinHostPort(s.getComposeServiceIP(c, "whoami"), "80")
|
||||
svcaddr := net.JoinHostPort(s.getComposeServiceIP("whoami"), "80")
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
|
@ -202,32 +197,28 @@ func (s *ConsulSuite) TestDeleteRootKey(c *check.C) {
|
|||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(ctx, k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
try.BodyContains(`"Router0@consul":`, `"Router1@consul":`, `"simplesvc0@consul":`, `"simplesvc1@consul":`),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
s.assertWhoami(c, "kv1.localhost", http.StatusOK)
|
||||
s.assertWhoami(c, "kv2.localhost", http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
s.assertWhoami("kv1.localhost", http.StatusOK)
|
||||
s.assertWhoami("kv2.localhost", http.StatusOK)
|
||||
|
||||
// delete router1
|
||||
err = s.kvClient.DeleteTree(ctx, "traefik/http/routers/Router1")
|
||||
c.Assert(err, checker.IsNil)
|
||||
s.assertWhoami(c, "kv1.localhost", http.StatusOK)
|
||||
s.assertWhoami(c, "kv2.localhost", http.StatusNotFound)
|
||||
require.NoError(s.T(), err)
|
||||
s.assertWhoami("kv1.localhost", http.StatusOK)
|
||||
s.assertWhoami("kv2.localhost", http.StatusNotFound)
|
||||
|
||||
// delete simple services and router0
|
||||
err = s.kvClient.DeleteTree(ctx, "traefik")
|
||||
c.Assert(err, checker.IsNil)
|
||||
s.assertWhoami(c, "kv1.localhost", http.StatusNotFound)
|
||||
s.assertWhoami(c, "kv2.localhost", http.StatusNotFound)
|
||||
require.NoError(s.T(), err)
|
||||
s.assertWhoami("kv1.localhost", http.StatusNotFound)
|
||||
s.assertWhoami("kv2.localhost", http.StatusNotFound)
|
||||
}
|
||||
|
|
|
@ -3,15 +3,16 @@ package integration
|
|||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/api"
|
||||
"github.com/traefik/traefik/v2/pkg/testhelpers"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Docker tests suite.
|
||||
|
@ -19,12 +20,21 @@ type DockerComposeSuite struct {
|
|||
BaseSuite
|
||||
}
|
||||
|
||||
func (s *DockerComposeSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "minimal")
|
||||
s.composeUp(c)
|
||||
func TestDockerComposeSuite(t *testing.T) {
|
||||
suite.Run(t, new(DockerComposeSuite))
|
||||
}
|
||||
|
||||
func (s *DockerComposeSuite) TestComposeScale(c *check.C) {
|
||||
func (s *DockerComposeSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
s.createComposeProject("minimal")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *DockerComposeSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *DockerComposeSuite) TestComposeScale() {
|
||||
tempObjects := struct {
|
||||
DockerHost string
|
||||
DefaultRule string
|
||||
|
@ -32,45 +42,36 @@ func (s *DockerComposeSuite) TestComposeScale(c *check.C) {
|
|||
DockerHost: s.getDockerHost(),
|
||||
DefaultRule: "Host(`{{ normalize .Name }}.docker.localhost`)",
|
||||
}
|
||||
file := s.adaptFile(c, "fixtures/docker/minimal.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/docker/minimal.toml", tempObjects)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req := testhelpers.MustNewRequest(http.MethodGet, "http://127.0.0.1:8000/whoami", nil)
|
||||
req.Host = "my.super.host"
|
||||
|
||||
_, err = try.ResponseUntilStatusCode(req, 1500*time.Millisecond, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
_, err := try.ResponseUntilStatusCode(req, 5*time.Second, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
var rtconf api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&rtconf)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// check that we have only three routers (the one from this test + 2 unrelated internal ones)
|
||||
c.Assert(rtconf.Routers, checker.HasLen, 3)
|
||||
assert.Len(s.T(), rtconf.Routers, 3)
|
||||
|
||||
// check that we have only one service (not counting the internal ones) with n servers
|
||||
services := rtconf.Services
|
||||
c.Assert(services, checker.HasLen, 4)
|
||||
assert.Len(s.T(), services, 4)
|
||||
for name, service := range services {
|
||||
if strings.HasSuffix(name, "@internal") {
|
||||
continue
|
||||
}
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
c.Assert(name, checker.Equals, "whoami1-"+composeProject.Name+"@docker")
|
||||
c.Assert(service.LoadBalancer.Servers, checker.HasLen, 2)
|
||||
assert.Equal(s.T(), "service-mini@docker", name)
|
||||
assert.Len(s.T(), service.LoadBalancer.Servers, 2)
|
||||
// We could break here, but we don't just to keep us honest.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,15 @@ package integration
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Docker tests suite.
|
||||
|
@ -18,15 +18,24 @@ type DockerSuite struct {
|
|||
BaseSuite
|
||||
}
|
||||
|
||||
func (s *DockerSuite) SetUpTest(c *check.C) {
|
||||
s.createComposeProject(c, "docker")
|
||||
func TestDockerSuite(t *testing.T) {
|
||||
suite.Run(t, new(DockerSuite))
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TearDownTest(c *check.C) {
|
||||
s.composeDown(c)
|
||||
func (s *DockerSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
s.createComposeProject("docker")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestSimpleConfiguration(c *check.C) {
|
||||
func (s *DockerSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TearDownTest() {
|
||||
s.composeStop("simple", "withtcplabels", "withlabels1", "withlabels2", "withonelabelmissing", "powpow")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestSimpleConfiguration() {
|
||||
tempObjects := struct {
|
||||
DockerHost string
|
||||
DefaultRule string
|
||||
|
@ -35,24 +44,18 @@ func (s *DockerSuite) TestSimpleConfiguration(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.docker.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/docker/simple.toml", tempObjects)
|
||||
|
||||
s.composeUp(c)
|
||||
s.composeUp()
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Expected a 404 as we did not configure anything
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestDefaultDockerContainers(c *check.C) {
|
||||
func (s *DockerSuite) TestDefaultDockerContainers() {
|
||||
tempObjects := struct {
|
||||
DockerHost string
|
||||
DefaultRule string
|
||||
|
@ -61,41 +64,30 @@ func (s *DockerSuite) TestDefaultDockerContainers(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.docker.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/docker/simple.toml", tempObjects)
|
||||
|
||||
s.composeUp(c, "simple")
|
||||
s.composeUp("simple")
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "simple.docker.localhost"
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
req.Host = fmt.Sprintf("simple-%s.docker.localhost", composeProject.Name)
|
||||
|
||||
// TODO Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
|
||||
resp, err := try.ResponseUntilStatusCode(req, 1500*time.Millisecond, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
resp, err := try.ResponseUntilStatusCode(req, 3*time.Second, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var version map[string]interface{}
|
||||
|
||||
c.Assert(json.Unmarshal(body, &version), checker.IsNil)
|
||||
c.Assert(version["Version"], checker.Equals, "swarm/1.0.0")
|
||||
assert.NoError(s.T(), json.Unmarshal(body, &version))
|
||||
assert.Equal(s.T(), "swarm/1.0.0", version["Version"])
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestDockerContainersWithTCPLabels(c *check.C) {
|
||||
func (s *DockerSuite) TestDockerContainersWithTCPLabels() {
|
||||
tempObjects := struct {
|
||||
DockerHost string
|
||||
DefaultRule string
|
||||
|
@ -104,29 +96,23 @@ func (s *DockerSuite) TestDockerContainersWithTCPLabels(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.docker.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/docker/simple.toml", tempObjects)
|
||||
|
||||
s.composeUp(c, "withtcplabels")
|
||||
s.composeUp("withtcplabels")
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`my.super.host`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`my.super.host`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
who, err := guessWho("127.0.0.1:8000", "my.super.host", true)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
c.Assert(who, checker.Contains, "my.super.host")
|
||||
assert.Contains(s.T(), who, "my.super.host")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestDockerContainersWithLabels(c *check.C) {
|
||||
func (s *DockerSuite) TestDockerContainersWithLabels() {
|
||||
tempObjects := struct {
|
||||
DockerHost string
|
||||
DefaultRule string
|
||||
|
@ -135,44 +121,37 @@ func (s *DockerSuite) TestDockerContainersWithLabels(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.docker.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/docker/simple.toml", tempObjects)
|
||||
|
||||
s.composeUp(c, "withlabels1", "withlabels2")
|
||||
s.composeUp("withlabels1", "withlabels2")
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my-super.host"
|
||||
|
||||
// TODO Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
|
||||
_, err = try.ResponseUntilStatusCode(req, 1500*time.Millisecond, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
_, err = try.ResponseUntilStatusCode(req, 3*time.Second, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my.super.host"
|
||||
|
||||
// TODO Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
|
||||
resp, err := try.ResponseUntilStatusCode(req, 1500*time.Millisecond, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
resp, err := try.ResponseUntilStatusCode(req, 3*time.Second, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var version map[string]interface{}
|
||||
|
||||
c.Assert(json.Unmarshal(body, &version), checker.IsNil)
|
||||
c.Assert(version["Version"], checker.Equals, "swarm/1.0.0")
|
||||
assert.NoError(s.T(), json.Unmarshal(body, &version))
|
||||
assert.Equal(s.T(), "swarm/1.0.0", version["Version"])
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestDockerContainersWithOneMissingLabels(c *check.C) {
|
||||
func (s *DockerSuite) TestDockerContainersWithOneMissingLabels() {
|
||||
tempObjects := struct {
|
||||
DockerHost string
|
||||
DefaultRule string
|
||||
|
@ -181,31 +160,23 @@ func (s *DockerSuite) TestDockerContainersWithOneMissingLabels(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.docker.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/docker/simple.toml", tempObjects)
|
||||
|
||||
s.composeUp(c, "withonelabelmissing")
|
||||
s.composeUp("withonelabelmissing")
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my.super.host"
|
||||
|
||||
// TODO Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
|
||||
// TODO validate : run on 80
|
||||
// Expected a 404 as we did not configure anything
|
||||
err = try.Request(req, 1500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.Request(req, 3*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRestartDockerContainers(c *check.C) {
|
||||
func (s *DockerSuite) TestRestartDockerContainers() {
|
||||
tempObjects := struct {
|
||||
DockerHost string
|
||||
DefaultRule string
|
||||
|
@ -214,46 +185,40 @@ func (s *DockerSuite) TestRestartDockerContainers(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.docker.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/docker/simple.toml", tempObjects)
|
||||
|
||||
s.composeUp(c, "powpow")
|
||||
s.composeUp("powpow")
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my.super.host"
|
||||
|
||||
// TODO Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
|
||||
resp, err := try.ResponseUntilStatusCode(req, 1500*time.Millisecond, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var version map[string]interface{}
|
||||
|
||||
c.Assert(json.Unmarshal(body, &version), checker.IsNil)
|
||||
c.Assert(version["Version"], checker.Equals, "swarm/1.0.0")
|
||||
assert.NoError(s.T(), json.Unmarshal(body, &version))
|
||||
assert.Equal(s.T(), "swarm/1.0.0", version["Version"])
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("powpow"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
s.composeStop(c, "powpow")
|
||||
s.composeStop("powpow")
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("powpow"))
|
||||
c.Assert(err, checker.NotNil)
|
||||
assert.Error(s.T(), err)
|
||||
|
||||
s.composeUp(c, "powpow")
|
||||
s.composeUp("powpow")
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("powpow"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@ package integration
|
|||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// ErrorPagesSuite test suites.
|
||||
|
@ -18,83 +18,78 @@ type ErrorPagesSuite struct {
|
|||
BackendIP string
|
||||
}
|
||||
|
||||
func (s *ErrorPagesSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "error_pages")
|
||||
s.composeUp(c)
|
||||
|
||||
s.ErrorPageIP = s.getComposeServiceIP(c, "nginx2")
|
||||
s.BackendIP = s.getComposeServiceIP(c, "nginx1")
|
||||
func TestErrorPagesSuite(t *testing.T) {
|
||||
suite.Run(t, new(ErrorPagesSuite))
|
||||
}
|
||||
|
||||
func (s *ErrorPagesSuite) TestSimpleConfiguration(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/error_pages/simple.toml", struct {
|
||||
func (s *ErrorPagesSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("error_pages")
|
||||
s.composeUp()
|
||||
|
||||
s.ErrorPageIP = s.getComposeServiceIP("nginx2")
|
||||
s.BackendIP = s.getComposeServiceIP("nginx1")
|
||||
}
|
||||
|
||||
func (s *ErrorPagesSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *ErrorPagesSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/error_pages/simple.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
}{"http://" + s.BackendIP + ":80", s.ErrorPageIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
frontendReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendReq.Host = "test.local"
|
||||
|
||||
err = try.Request(frontendReq, 2*time.Second, try.BodyContains("nginx"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ErrorPagesSuite) TestErrorPage(c *check.C) {
|
||||
func (s *ErrorPagesSuite) TestErrorPage() {
|
||||
// error.toml contains a mis-configuration of the backend host
|
||||
file := s.adaptFile(c, "fixtures/error_pages/error.toml", struct {
|
||||
file := s.adaptFile("fixtures/error_pages/error.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
}{s.BackendIP, s.ErrorPageIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
frontendReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendReq.Host = "test.local"
|
||||
|
||||
err = try.Request(frontendReq, 2*time.Second, try.BodyContains("An error occurred."))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ErrorPagesSuite) TestErrorPageFlush(c *check.C) {
|
||||
func (s *ErrorPagesSuite) TestErrorPageFlush() {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.Header().Add("Transfer-Encoding", "chunked")
|
||||
rw.WriteHeader(http.StatusInternalServerError)
|
||||
_, _ = rw.Write([]byte("KO"))
|
||||
}))
|
||||
|
||||
file := s.adaptFile(c, "fixtures/error_pages/simple.toml", struct {
|
||||
file := s.adaptFile("fixtures/error_pages/simple.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
}{srv.URL, s.ErrorPageIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
frontendReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendReq.Host = "test.local"
|
||||
|
||||
err = try.Request(frontendReq, 2*time.Second,
|
||||
try.BodyContains("An error occurred."),
|
||||
try.HasHeaderValue("Content-Type", "text/html", true),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -8,16 +8,17 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/kvtools/etcdv3"
|
||||
"github.com/kvtools/valkeyrie"
|
||||
"github.com/kvtools/valkeyrie/store"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/api"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// etcd test suites.
|
||||
|
@ -27,12 +28,18 @@ type EtcdSuite struct {
|
|||
etcdAddr string
|
||||
}
|
||||
|
||||
func (s *EtcdSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "etcd")
|
||||
s.composeUp(c)
|
||||
func TestEtcdSuite(t *testing.T) {
|
||||
suite.Run(t, new(EtcdSuite))
|
||||
}
|
||||
|
||||
func (s *EtcdSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("etcd")
|
||||
s.composeUp()
|
||||
|
||||
var err error
|
||||
s.etcdAddr = net.JoinHostPort(s.getComposeServiceIP(c, "etcd"), "2379")
|
||||
s.etcdAddr = net.JoinHostPort(s.getComposeServiceIP("etcd"), "2379")
|
||||
s.kvClient, err = valkeyrie.NewStore(
|
||||
context.Background(),
|
||||
etcdv3.StoreName,
|
||||
|
@ -41,18 +48,19 @@ func (s *EtcdSuite) SetUpSuite(c *check.C) {
|
|||
ConnectionTimeout: 10 * time.Second,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
c.Fatal("Cannot create store etcd")
|
||||
}
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// wait for etcd
|
||||
err = try.Do(60*time.Second, try.KVExists(s.kvClient, "test"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *EtcdSuite) TestSimpleConfiguration(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/etcd/simple.toml", struct{ EtcdAddress string }{s.etcdAddr})
|
||||
defer os.Remove(file)
|
||||
func (s *EtcdSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *EtcdSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/etcd/simple.toml", struct{ EtcdAddress string }{s.etcdAddr})
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
|
@ -102,39 +110,35 @@ func (s *EtcdSuite) TestSimpleConfiguration(c *check.C) {
|
|||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(context.Background(), k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
try.BodyContains(`"striper@etcd":`, `"compressor@etcd":`, `"srvcA@etcd":`, `"srvcB@etcd":`),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-etcd.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = os.WriteFile(expectedJSON, got, 0o666)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
expected, err := os.ReadFile(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
|
@ -146,7 +150,6 @@ func (s *EtcdSuite) TestSimpleConfiguration(c *check.C) {
|
|||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Error(text)
|
||||
require.NoError(s.T(), err, text)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,61 +2,58 @@ package integration
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// File tests suite.
|
||||
type FileSuite struct{ BaseSuite }
|
||||
|
||||
func (s *FileSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "file")
|
||||
s.composeUp(c)
|
||||
func TestFileSuite(t *testing.T) {
|
||||
suite.Run(t, new(FileSuite))
|
||||
}
|
||||
|
||||
func (s *FileSuite) TestSimpleConfiguration(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/file/simple.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
func (s *FileSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("file")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *FileSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *FileSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/file/simple.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Expected a 404 as we did not configure anything
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
// #56 regression test, make sure it does not fail?
|
||||
func (s *FileSuite) TestSimpleConfigurationNoPanic(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/file/56-simple-panic.toml"))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
func (s *FileSuite) TestSimpleConfigurationNoPanic() {
|
||||
s.traefikCmd(withConfigFile("fixtures/file/56-simple-panic.toml"))
|
||||
|
||||
// Expected a 404 as we did not configure anything
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *FileSuite) TestDirectoryConfiguration(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/file/directory.toml"))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
func (s *FileSuite) TestDirectoryConfiguration() {
|
||||
s.traefikCmd(withConfigFile("fixtures/file/directory.toml"))
|
||||
|
||||
// Expected a 404 as we did not configure anything at /test
|
||||
err = try.GetRequest("http://127.0.0.1:8000/test", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/test", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Expected a 502 as there is no backend server
|
||||
err = try.GetRequest("http://127.0.0.1:8000/test2", 1000*time.Millisecond, try.StatusCodeIs(http.StatusBadGateway))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -6,10 +6,14 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
[entryPoints.trust]
|
||||
address = ":8000"
|
||||
[entryPoints.web.proxyProtocol]
|
||||
trustedIPs = ["{{.HaproxyIP}}"]
|
||||
[entryPoints.trust.proxyProtocol]
|
||||
trustedIPs = ["127.0.0.1"]
|
||||
[entryPoints.nottrust]
|
||||
address = ":9000"
|
||||
[entryPoints.nottrust.proxyProtocol]
|
||||
trustedIPs = ["1.2.3.4"]
|
||||
|
||||
[api]
|
||||
insecure = true
|
|
@ -1,32 +0,0 @@
|
|||
[global]
|
||||
checkNewVersion = false
|
||||
sendAnonymousUsage = false
|
||||
|
||||
[log]
|
||||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
address = ":8000"
|
||||
[entryPoints.web.proxyProtocol]
|
||||
trustedIPs = ["1.2.3.4"]
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
||||
## dynamic configuration ##
|
||||
|
||||
[http.routers]
|
||||
[http.routers.router1]
|
||||
service = "service1"
|
||||
rule = "Path(`/whoami`)"
|
||||
|
||||
[http.services]
|
||||
[http.services.service1]
|
||||
[http.services.service1.loadBalancer]
|
||||
|
||||
[[http.services.service1.loadBalancer.servers]]
|
||||
url = "http://{{.WhoamiIP}}"
|
|
@ -8,9 +8,11 @@ import (
|
|||
"math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/helloworld"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
|
@ -29,16 +31,20 @@ const randCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567
|
|||
// GRPCSuite tests suite.
|
||||
type GRPCSuite struct{ BaseSuite }
|
||||
|
||||
func TestGRPCSuite(t *testing.T) {
|
||||
suite.Run(t, new(GRPCSuite))
|
||||
}
|
||||
|
||||
type myserver struct {
|
||||
stopStreamExample chan bool
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) SetUpSuite(c *check.C) {
|
||||
func (s *GRPCSuite) SetupSuite() {
|
||||
var err error
|
||||
LocalhostCert, err = os.ReadFile("./resources/tls/local.cert")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
LocalhostKey, err = os.ReadFile("./resources/tls/local.key")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *myserver) SayHello(ctx context.Context, in *helloworld.HelloRequest) (*helloworld.HelloReply, error) {
|
||||
|
@ -137,19 +143,18 @@ func callStreamExampleClientGRPC() (helloworld.Greeter_StreamExampleClient, func
|
|||
return t, closer, nil
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) TestGRPC(c *check.C) {
|
||||
func (s *GRPCSuite) TestGRPC() {
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
_, port, err := net.SplitHostPort(lis.Addr().String())
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
go func() {
|
||||
err := startGRPCServer(lis, &myserver{})
|
||||
c.Log(err)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/grpc/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/grpc/config.toml", struct {
|
||||
CertContent string
|
||||
KeyContent string
|
||||
GRPCServerPort string
|
||||
|
@ -159,79 +164,65 @@ func (s *GRPCSuite) TestGRPC(c *check.C) {
|
|||
GRPCServerPort: port,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err = cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`127.0.0.1`)"))
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
var response string
|
||||
err = try.Do(1*time.Second, func() error {
|
||||
response, err = callHelloClientGRPC("World", true)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(response, check.Equals, "Hello World")
|
||||
assert.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "Hello World", response)
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) TestGRPCh2c(c *check.C) {
|
||||
func (s *GRPCSuite) TestGRPCh2c() {
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
_, port, err := net.SplitHostPort(lis.Addr().String())
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
go func() {
|
||||
err := starth2cGRPCServer(lis, &myserver{})
|
||||
c.Log(err)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/grpc/config_h2c.toml", struct {
|
||||
file := s.adaptFile("fixtures/grpc/config_h2c.toml", struct {
|
||||
GRPCServerPort string
|
||||
}{
|
||||
GRPCServerPort: port,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err = cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`127.0.0.1`)"))
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
var response string
|
||||
err = try.Do(1*time.Second, func() error {
|
||||
response, err = callHelloClientGRPC("World", false)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(response, check.Equals, "Hello World")
|
||||
assert.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "Hello World", response)
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) TestGRPCh2cTermination(c *check.C) {
|
||||
func (s *GRPCSuite) TestGRPCh2cTermination() {
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
_, port, err := net.SplitHostPort(lis.Addr().String())
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
go func() {
|
||||
err := starth2cGRPCServer(lis, &myserver{})
|
||||
c.Log(err)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/grpc/config_h2c_termination.toml", struct {
|
||||
file := s.adaptFile("fixtures/grpc/config_h2c_termination.toml", struct {
|
||||
CertContent string
|
||||
KeyContent string
|
||||
GRPCServerPort string
|
||||
|
@ -241,40 +232,33 @@ func (s *GRPCSuite) TestGRPCh2cTermination(c *check.C) {
|
|||
GRPCServerPort: port,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err = cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`127.0.0.1`)"))
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
var response string
|
||||
err = try.Do(1*time.Second, func() error {
|
||||
response, err = callHelloClientGRPC("World", true)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(response, check.Equals, "Hello World")
|
||||
assert.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "Hello World", response)
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) TestGRPCInsecure(c *check.C) {
|
||||
func (s *GRPCSuite) TestGRPCInsecure() {
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
_, port, err := net.SplitHostPort(lis.Addr().String())
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
go func() {
|
||||
err := startGRPCServer(lis, &myserver{})
|
||||
c.Log(err)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/grpc/config_insecure.toml", struct {
|
||||
file := s.adaptFile("fixtures/grpc/config_insecure.toml", struct {
|
||||
CertContent string
|
||||
KeyContent string
|
||||
GRPCServerPort string
|
||||
|
@ -284,44 +268,37 @@ func (s *GRPCSuite) TestGRPCInsecure(c *check.C) {
|
|||
GRPCServerPort: port,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err = cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`127.0.0.1`)"))
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
var response string
|
||||
err = try.Do(1*time.Second, func() error {
|
||||
response, err = callHelloClientGRPC("World", true)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(response, check.Equals, "Hello World")
|
||||
assert.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "Hello World", response)
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) TestGRPCBuffer(c *check.C) {
|
||||
func (s *GRPCSuite) TestGRPCBuffer() {
|
||||
stopStreamExample := make(chan bool)
|
||||
defer func() { stopStreamExample <- true }()
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
_, port, err := net.SplitHostPort(lis.Addr().String())
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
go func() {
|
||||
err := startGRPCServer(lis, &myserver{
|
||||
stopStreamExample: stopStreamExample,
|
||||
})
|
||||
c.Log(err)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/grpc/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/grpc/config.toml", struct {
|
||||
CertContent string
|
||||
KeyContent string
|
||||
GRPCServerPort string
|
||||
|
@ -331,27 +308,21 @@ func (s *GRPCSuite) TestGRPCBuffer(c *check.C) {
|
|||
GRPCServerPort: port,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err = cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`127.0.0.1`)"))
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
var client helloworld.Greeter_StreamExampleClient
|
||||
client, closer, err := callStreamExampleClientGRPC()
|
||||
defer func() { _ = closer() }()
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
received := make(chan bool)
|
||||
go func() {
|
||||
tr, err := client.Recv()
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(len(tr.GetData()), check.Equals, 512)
|
||||
assert.NoError(s.T(), err)
|
||||
assert.Len(s.T(), tr.GetData(), 512)
|
||||
received <- true
|
||||
}()
|
||||
|
||||
|
@ -363,25 +334,24 @@ func (s *GRPCSuite) TestGRPCBuffer(c *check.C) {
|
|||
return errors.New("failed to receive stream data")
|
||||
}
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) TestGRPCBufferWithFlushInterval(c *check.C) {
|
||||
func (s *GRPCSuite) TestGRPCBufferWithFlushInterval() {
|
||||
stopStreamExample := make(chan bool)
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
_, port, err := net.SplitHostPort(lis.Addr().String())
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
go func() {
|
||||
err := startGRPCServer(lis, &myserver{
|
||||
stopStreamExample: stopStreamExample,
|
||||
})
|
||||
c.Log(err)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/grpc/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/grpc/config.toml", struct {
|
||||
CertContent string
|
||||
KeyContent string
|
||||
GRPCServerPort string
|
||||
|
@ -390,17 +360,11 @@ func (s *GRPCSuite) TestGRPCBufferWithFlushInterval(c *check.C) {
|
|||
KeyContent: string(LocalhostKey),
|
||||
GRPCServerPort: port,
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`127.0.0.1`)"))
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
var client helloworld.Greeter_StreamExampleClient
|
||||
client, closer, err := callStreamExampleClientGRPC()
|
||||
|
@ -408,13 +372,13 @@ func (s *GRPCSuite) TestGRPCBufferWithFlushInterval(c *check.C) {
|
|||
_ = closer()
|
||||
stopStreamExample <- true
|
||||
}()
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
received := make(chan bool)
|
||||
go func() {
|
||||
tr, err := client.Recv()
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(len(tr.GetData()), check.Equals, 512)
|
||||
assert.NoError(s.T(), err)
|
||||
assert.Len(s.T(), tr.GetData(), 512)
|
||||
received <- true
|
||||
}()
|
||||
|
||||
|
@ -426,22 +390,21 @@ func (s *GRPCSuite) TestGRPCBufferWithFlushInterval(c *check.C) {
|
|||
return errors.New("failed to receive stream data")
|
||||
}
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) TestGRPCWithRetry(c *check.C) {
|
||||
func (s *GRPCSuite) TestGRPCWithRetry() {
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
_, port, err := net.SplitHostPort(lis.Addr().String())
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
go func() {
|
||||
err := startGRPCServer(lis, &myserver{})
|
||||
c.Log(err)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/grpc/config_retry.toml", struct {
|
||||
file := s.adaptFile("fixtures/grpc/config_retry.toml", struct {
|
||||
CertContent string
|
||||
KeyContent string
|
||||
GRPCServerPort string
|
||||
|
@ -451,23 +414,17 @@ func (s *GRPCSuite) TestGRPCWithRetry(c *check.C) {
|
|||
GRPCServerPort: port,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err = cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`127.0.0.1`)"))
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
var response string
|
||||
err = try.Do(1*time.Second, func() error {
|
||||
response, err = callHelloClientGRPC("World", true)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(response, check.Equals, "Hello World")
|
||||
assert.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "Hello World", response)
|
||||
}
|
||||
|
|
|
@ -4,50 +4,45 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Headers tests suite.
|
||||
type HeadersSuite struct{ BaseSuite }
|
||||
|
||||
func (s *HeadersSuite) TestSimpleConfiguration(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/headers/basic.toml"))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
// Expected a 404 as we did not configure anything
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
func TestHeadersSuite(t *testing.T) {
|
||||
suite.Run(t, new(HeadersSuite))
|
||||
}
|
||||
|
||||
func (s *HeadersSuite) TestReverseProxyHeaderRemoved(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/headers/remove_reverseproxy_headers.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
func (s *HeadersSuite) TestSimpleConfiguration() {
|
||||
s.traefikCmd(withConfigFile("fixtures/headers/basic.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
// Expected a 404 as we did not configure anything
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *HeadersSuite) TestReverseProxyHeaderRemoved() {
|
||||
file := s.adaptFile("fixtures/headers/remove_reverseproxy_headers.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, found := r.Header["X-Forwarded-Host"]
|
||||
c.Assert(found, checker.True)
|
||||
assert.True(s.T(), found)
|
||||
_, found = r.Header["Foo"]
|
||||
c.Assert(found, checker.False)
|
||||
assert.False(s.T(), found)
|
||||
_, found = r.Header["X-Forwarded-For"]
|
||||
c.Assert(found, checker.False)
|
||||
assert.False(s.T(), found)
|
||||
})
|
||||
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:9000")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
ts := &httptest.Server{
|
||||
Listener: listener,
|
||||
|
@ -57,31 +52,25 @@ func (s *HeadersSuite) TestReverseProxyHeaderRemoved(c *check.C) {
|
|||
defer ts.Close()
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "test.localhost"
|
||||
req.Header = http.Header{
|
||||
"Foo": {"bar"},
|
||||
}
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *HeadersSuite) TestCorsResponses(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/headers/cors.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
func (s *HeadersSuite) TestCorsResponses() {
|
||||
file := s.adaptFile("fixtures/headers/cors.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
backend := startTestServer("9000", http.StatusOK, "")
|
||||
defer backend.Close()
|
||||
|
||||
err = try.GetRequest(backend.URL, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest(backend.URL, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
testCase := []struct {
|
||||
desc string
|
||||
|
@ -147,30 +136,24 @@ func (s *HeadersSuite) TestCorsResponses(c *check.C) {
|
|||
|
||||
for _, test := range testCase {
|
||||
req, err := http.NewRequest(test.method, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = test.reqHost
|
||||
req.Header = test.requestHeaders
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.HasHeaderStruct(test.expected))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HeadersSuite) TestSecureHeadersResponses(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/headers/secure.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
func (s *HeadersSuite) TestSecureHeadersResponses() {
|
||||
file := s.adaptFile("fixtures/headers/secure.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
backend := startTestServer("9000", http.StatusOK, "")
|
||||
defer backend.Close()
|
||||
|
||||
err = try.GetRequest(backend.URL, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest(backend.URL, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
testCase := []struct {
|
||||
desc string
|
||||
|
@ -190,36 +173,30 @@ func (s *HeadersSuite) TestSecureHeadersResponses(c *check.C) {
|
|||
|
||||
for _, test := range testCase {
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = test.reqHost
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasHeaderStruct(test.expected))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/api/rawdata", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = test.internalReqHost
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasHeaderStruct(test.expected))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HeadersSuite) TestMultipleSecureHeadersResponses(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/headers/secure_multiple.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
func (s *HeadersSuite) TestMultipleSecureHeadersResponses() {
|
||||
file := s.adaptFile("fixtures/headers/secure_multiple.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
backend := startTestServer("9000", http.StatusOK, "")
|
||||
defer backend.Close()
|
||||
|
||||
err = try.GetRequest(backend.URL, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest(backend.URL, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
testCase := []struct {
|
||||
desc string
|
||||
|
@ -238,10 +215,10 @@ func (s *HeadersSuite) TestMultipleSecureHeadersResponses(c *check.C) {
|
|||
|
||||
for _, test := range testCase {
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = test.reqHost
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.HasHeaderStruct(test.expected))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,13 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// HealthCheck test suites.
|
||||
|
@ -23,287 +25,272 @@ type HealthCheckSuite struct {
|
|||
whoami4IP string
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "healthcheck")
|
||||
s.composeUp(c)
|
||||
|
||||
s.whoami1IP = s.getComposeServiceIP(c, "whoami1")
|
||||
s.whoami2IP = s.getComposeServiceIP(c, "whoami2")
|
||||
s.whoami3IP = s.getComposeServiceIP(c, "whoami3")
|
||||
s.whoami4IP = s.getComposeServiceIP(c, "whoami4")
|
||||
func TestHealthCheckSuite(t *testing.T) {
|
||||
suite.Run(t, new(HealthCheckSuite))
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestSimpleConfiguration(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/healthcheck/simple.toml", struct {
|
||||
func (s *HealthCheckSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("healthcheck")
|
||||
s.composeUp()
|
||||
|
||||
s.whoami1IP = s.getComposeServiceIP("whoami1")
|
||||
s.whoami2IP = s.getComposeServiceIP("whoami2")
|
||||
s.whoami3IP = s.getComposeServiceIP("whoami3")
|
||||
s.whoami4IP = s.getComposeServiceIP("whoami4")
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/healthcheck/simple.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
}{s.whoami1IP, s.whoami2IP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`test.localhost`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`test.localhost`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
frontendHealthReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/health", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendHealthReq.Host = "test.localhost"
|
||||
|
||||
err = try.Request(frontendHealthReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Fix all whoami health to 500
|
||||
client := &http.Client{}
|
||||
whoamiHosts := []string{s.whoami1IP, s.whoami2IP}
|
||||
for _, whoami := range whoamiHosts {
|
||||
statusInternalServerErrorReq, err := http.NewRequest(http.MethodPost, "http://"+whoami+"/health", bytes.NewBufferString("500"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerErrorReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
// Verify no backend service is available due to failing health checks
|
||||
err = try.Request(frontendHealthReq, 3*time.Second, try.StatusCodeIs(http.StatusServiceUnavailable))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Change one whoami health to 200
|
||||
statusOKReq1, err := http.NewRequest(http.MethodPost, "http://"+s.whoami1IP+"/health", bytes.NewBufferString("200"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusOKReq1)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify frontend health : after
|
||||
err = try.Request(frontendHealthReq, 3*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
frontendReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendReq.Host = "test.localhost"
|
||||
|
||||
// Check if whoami1 responds
|
||||
err = try.Request(frontendReq, 500*time.Millisecond, try.BodyContains(s.whoami1IP))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Check if the service with bad health check (whoami2) never respond.
|
||||
err = try.Request(frontendReq, 2*time.Second, try.BodyContains(s.whoami2IP))
|
||||
c.Assert(err, checker.NotNil)
|
||||
assert.Error(s.T(), err)
|
||||
|
||||
// TODO validate : run on 80
|
||||
resp, err := http.Get("http://127.0.0.1:8000/")
|
||||
|
||||
// Expected a 404 as we did not configure anything
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusNotFound, resp.StatusCode)
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestMultipleEntrypoints(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/healthcheck/multiple-entrypoints.toml", struct {
|
||||
func (s *HealthCheckSuite) TestMultipleEntrypoints() {
|
||||
file := s.adaptFile("fixtures/healthcheck/multiple-entrypoints.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
}{s.whoami1IP, s.whoami2IP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Wait for traefik
|
||||
err = try.GetRequest("http://localhost:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`test.localhost`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`test.localhost`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Check entrypoint http1
|
||||
frontendHealthReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/health", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendHealthReq.Host = "test.localhost"
|
||||
|
||||
err = try.Request(frontendHealthReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.Request(frontendHealthReq, 5*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Check entrypoint http2
|
||||
frontendHealthReq, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:9000/health", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendHealthReq.Host = "test.localhost"
|
||||
|
||||
err = try.Request(frontendHealthReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.Request(frontendHealthReq, 5*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Set the both whoami health to 500
|
||||
client := &http.Client{}
|
||||
whoamiHosts := []string{s.whoami1IP, s.whoami2IP}
|
||||
for _, whoami := range whoamiHosts {
|
||||
statusInternalServerErrorReq, err := http.NewRequest(http.MethodPost, "http://"+whoami+"/health", bytes.NewBufferString("500"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerErrorReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
// Verify no backend service is available due to failing health checks
|
||||
err = try.Request(frontendHealthReq, 5*time.Second, try.StatusCodeIs(http.StatusServiceUnavailable))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// reactivate the whoami2
|
||||
statusInternalServerOkReq, err := http.NewRequest(http.MethodPost, "http://"+s.whoami2IP+"/health", bytes.NewBufferString("200"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerOkReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
frontend1Req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontend1Req.Host = "test.localhost"
|
||||
|
||||
frontend2Req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:9000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontend2Req.Host = "test.localhost"
|
||||
|
||||
// Check if whoami1 never responds
|
||||
err = try.Request(frontend2Req, 2*time.Second, try.BodyContains(s.whoami1IP))
|
||||
c.Assert(err, checker.NotNil)
|
||||
assert.Error(s.T(), err)
|
||||
|
||||
// Check if whoami1 never responds
|
||||
err = try.Request(frontend1Req, 2*time.Second, try.BodyContains(s.whoami1IP))
|
||||
c.Assert(err, checker.NotNil)
|
||||
assert.Error(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestPortOverload(c *check.C) {
|
||||
func (s *HealthCheckSuite) TestPortOverload() {
|
||||
// Set one whoami health to 200
|
||||
client := &http.Client{}
|
||||
statusInternalServerErrorReq, err := http.NewRequest(http.MethodPost, "http://"+s.whoami1IP+"/health", bytes.NewBufferString("200"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerErrorReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
file := s.adaptFile(c, "fixtures/healthcheck/port_overload.toml", struct {
|
||||
file := s.adaptFile("fixtures/healthcheck/port_overload.toml", struct {
|
||||
Server1 string
|
||||
}{s.whoami1IP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("Host(`test.localhost`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
frontendHealthReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/health", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendHealthReq.Host = "test.localhost"
|
||||
|
||||
// We test bad gateway because we use an invalid port for the backend
|
||||
err = try.Request(frontendHealthReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusBadGateway))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Set one whoami health to 500
|
||||
statusInternalServerErrorReq, err = http.NewRequest(http.MethodPost, "http://"+s.whoami1IP+"/health", bytes.NewBufferString("500"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerErrorReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify no backend service is available due to failing health checks
|
||||
err = try.Request(frontendHealthReq, 3*time.Second, try.StatusCodeIs(http.StatusServiceUnavailable))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
// Checks if all the loadbalancers created will correctly update the server status.
|
||||
func (s *HealthCheckSuite) TestMultipleRoutersOnSameService(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/healthcheck/multiple-routers-one-same-service.toml", struct {
|
||||
func (s *HealthCheckSuite) TestMultipleRoutersOnSameService() {
|
||||
file := s.adaptFile("fixtures/healthcheck/multiple-routers-one-same-service.toml", struct {
|
||||
Server1 string
|
||||
}{s.whoami1IP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`test.localhost`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`test.localhost`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Set whoami health to 200 to be sure to start with the wanted status
|
||||
client := &http.Client{}
|
||||
statusOkReq, err := http.NewRequest(http.MethodPost, "http://"+s.whoami1IP+"/health", bytes.NewBufferString("200"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusOkReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// check healthcheck on web1 entrypoint
|
||||
healthReqWeb1, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/health", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
healthReqWeb1.Host = "test.localhost"
|
||||
err = try.Request(healthReqWeb1, 1*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// check healthcheck on web2 entrypoint
|
||||
healthReqWeb2, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:9000/health", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
healthReqWeb2.Host = "test.localhost"
|
||||
|
||||
err = try.Request(healthReqWeb2, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Set whoami health to 500
|
||||
statusInternalServerErrorReq, err := http.NewRequest(http.MethodPost, "http://"+s.whoami1IP+"/health", bytes.NewBufferString("500"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerErrorReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify no backend service is available due to failing health checks
|
||||
err = try.Request(healthReqWeb1, 3*time.Second, try.StatusCodeIs(http.StatusServiceUnavailable))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(healthReqWeb2, 3*time.Second, try.StatusCodeIs(http.StatusServiceUnavailable))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Change one whoami health to 200
|
||||
statusOKReq1, err := http.NewRequest(http.MethodPost, "http://"+s.whoami1IP+"/health", bytes.NewBufferString("200"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusOKReq1)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify health check
|
||||
err = try.Request(healthReqWeb1, 3*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(healthReqWeb2, 3*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/healthcheck/propagate.toml", struct {
|
||||
func (s *HealthCheckSuite) TestPropagate() {
|
||||
file := s.adaptFile("fixtures/healthcheck/propagate.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
Server3 string
|
||||
Server4 string
|
||||
}{s.whoami1IP, s.whoami2IP, s.whoami3IP, s.whoami4IP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`root.localhost`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`root.localhost`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
rootReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
rootReq.Host = "root.localhost"
|
||||
|
||||
err = try.Request(rootReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Bring whoami1 and whoami3 down
|
||||
client := http.Client{
|
||||
|
@ -313,9 +300,9 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
whoamiHosts := []string{s.whoami1IP, s.whoami3IP}
|
||||
for _, whoami := range whoamiHosts {
|
||||
statusInternalServerErrorReq, err := http.NewRequest(http.MethodPost, "http://"+whoami+"/health", bytes.NewBufferString("500"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerErrorReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
try.Sleep(time.Second)
|
||||
|
@ -327,19 +314,19 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
reachedServers := make(map[string]int)
|
||||
for i := 0; i < 4; i++ {
|
||||
resp, err := client.Do(rootReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if reachedServers[s.whoami4IP] > reachedServers[s.whoami2IP] {
|
||||
c.Assert(string(body), checker.Contains, want2)
|
||||
assert.Contains(s.T(), string(body), want2)
|
||||
reachedServers[s.whoami2IP]++
|
||||
continue
|
||||
}
|
||||
|
||||
if reachedServers[s.whoami2IP] > reachedServers[s.whoami4IP] {
|
||||
c.Assert(string(body), checker.Contains, want4)
|
||||
assert.Contains(s.T(), string(body), want4)
|
||||
reachedServers[s.whoami4IP]++
|
||||
continue
|
||||
}
|
||||
|
@ -356,48 +343,48 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
c.Assert(reachedServers[s.whoami2IP], checker.Equals, 2)
|
||||
c.Assert(reachedServers[s.whoami4IP], checker.Equals, 2)
|
||||
assert.Equal(s.T(), 2, reachedServers[s.whoami2IP])
|
||||
assert.Equal(s.T(), 2, reachedServers[s.whoami4IP])
|
||||
|
||||
fooReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
fooReq.Host = "foo.localhost"
|
||||
|
||||
// Verify load-balancing on foo still works, and that we're getting wsp2, wsp2, wsp2, wsp2, etc.
|
||||
want := `IP: ` + s.whoami2IP
|
||||
for i := 0; i < 4; i++ {
|
||||
resp, err := client.Do(fooReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
c.Assert(string(body), checker.Contains, want)
|
||||
assert.Contains(s.T(), string(body), want)
|
||||
}
|
||||
|
||||
barReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
barReq.Host = "bar.localhost"
|
||||
|
||||
// Verify load-balancing on bar still works, and that we're getting wsp2, wsp2, wsp2, wsp2, etc.
|
||||
want = `IP: ` + s.whoami2IP
|
||||
for i := 0; i < 4; i++ {
|
||||
resp, err := client.Do(barReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
c.Assert(string(body), checker.Contains, want)
|
||||
assert.Contains(s.T(), string(body), want)
|
||||
}
|
||||
|
||||
// Bring whoami2 and whoami4 down
|
||||
whoamiHosts = []string{s.whoami2IP, s.whoami4IP}
|
||||
for _, whoami := range whoamiHosts {
|
||||
statusInternalServerErrorReq, err := http.NewRequest(http.MethodPost, "http://"+whoami+"/health", bytes.NewBufferString("500"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerErrorReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
try.Sleep(time.Second)
|
||||
|
@ -405,25 +392,25 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
// Verify that everything is down, and that we get 503s everywhere.
|
||||
for i := 0; i < 2; i++ {
|
||||
resp, err := client.Do(rootReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusServiceUnavailable)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusServiceUnavailable, resp.StatusCode)
|
||||
|
||||
resp, err = client.Do(fooReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusServiceUnavailable)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusServiceUnavailable, resp.StatusCode)
|
||||
|
||||
resp, err = client.Do(barReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusServiceUnavailable)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusServiceUnavailable, resp.StatusCode)
|
||||
}
|
||||
|
||||
// Bring everything back up.
|
||||
whoamiHosts = []string{s.whoami1IP, s.whoami2IP, s.whoami3IP, s.whoami4IP}
|
||||
for _, whoami := range whoamiHosts {
|
||||
statusOKReq, err := http.NewRequest(http.MethodPost, "http://"+whoami+"/health", bytes.NewBufferString("200"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusOKReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
try.Sleep(time.Second)
|
||||
|
@ -432,10 +419,10 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
reachedServers = make(map[string]int)
|
||||
for i := 0; i < 4; i++ {
|
||||
resp, err := client.Do(rootReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if strings.Contains(string(body), `IP: `+s.whoami1IP) {
|
||||
reachedServers[s.whoami1IP]++
|
||||
|
@ -458,19 +445,19 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
c.Assert(reachedServers[s.whoami1IP], checker.Equals, 1)
|
||||
c.Assert(reachedServers[s.whoami2IP], checker.Equals, 1)
|
||||
c.Assert(reachedServers[s.whoami3IP], checker.Equals, 1)
|
||||
c.Assert(reachedServers[s.whoami4IP], checker.Equals, 1)
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami1IP])
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami2IP])
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami3IP])
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami4IP])
|
||||
|
||||
// Verify everything is up on foo router.
|
||||
reachedServers = make(map[string]int)
|
||||
for i := 0; i < 4; i++ {
|
||||
resp, err := client.Do(fooReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if strings.Contains(string(body), `IP: `+s.whoami1IP) {
|
||||
reachedServers[s.whoami1IP]++
|
||||
|
@ -493,19 +480,19 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
c.Assert(reachedServers[s.whoami1IP], checker.Equals, 2)
|
||||
c.Assert(reachedServers[s.whoami2IP], checker.Equals, 1)
|
||||
c.Assert(reachedServers[s.whoami3IP], checker.Equals, 1)
|
||||
c.Assert(reachedServers[s.whoami4IP], checker.Equals, 0)
|
||||
assert.Equal(s.T(), 2, reachedServers[s.whoami1IP])
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami2IP])
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami3IP])
|
||||
assert.Equal(s.T(), 0, reachedServers[s.whoami4IP])
|
||||
|
||||
// Verify everything is up on bar router.
|
||||
reachedServers = make(map[string]int)
|
||||
for i := 0; i < 4; i++ {
|
||||
resp, err := client.Do(barReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if strings.Contains(string(body), `IP: `+s.whoami1IP) {
|
||||
reachedServers[s.whoami1IP]++
|
||||
|
@ -528,102 +515,87 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
c.Assert(reachedServers[s.whoami1IP], checker.Equals, 2)
|
||||
c.Assert(reachedServers[s.whoami2IP], checker.Equals, 1)
|
||||
c.Assert(reachedServers[s.whoami3IP], checker.Equals, 1)
|
||||
c.Assert(reachedServers[s.whoami4IP], checker.Equals, 0)
|
||||
assert.Equal(s.T(), 2, reachedServers[s.whoami1IP])
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami2IP])
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami3IP])
|
||||
assert.Equal(s.T(), 0, reachedServers[s.whoami4IP])
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestPropagateNoHealthCheck(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/healthcheck/propagate_no_healthcheck.toml", struct {
|
||||
func (s *HealthCheckSuite) TestPropagateNoHealthCheck() {
|
||||
file := s.adaptFile("fixtures/healthcheck/propagate_no_healthcheck.toml", struct {
|
||||
Server1 string
|
||||
}{s.whoami1IP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`noop.localhost`)"), try.BodyNotContains("Host(`root.localhost`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`noop.localhost`)"), try.BodyNotContains("Host(`root.localhost`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
rootReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
rootReq.Host = "root.localhost"
|
||||
|
||||
err = try.Request(rootReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestPropagateReload(c *check.C) {
|
||||
func (s *HealthCheckSuite) TestPropagateReload() {
|
||||
// Setup a WSP service without the healthcheck enabled (wsp-service1)
|
||||
withoutHealthCheck := s.adaptFile(c, "fixtures/healthcheck/reload_without_healthcheck.toml", struct {
|
||||
withoutHealthCheck := s.adaptFile("fixtures/healthcheck/reload_without_healthcheck.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
}{s.whoami1IP, s.whoami2IP})
|
||||
defer os.Remove(withoutHealthCheck)
|
||||
withHealthCheck := s.adaptFile(c, "fixtures/healthcheck/reload_with_healthcheck.toml", struct {
|
||||
withHealthCheck := s.adaptFile("fixtures/healthcheck/reload_with_healthcheck.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
}{s.whoami1IP, s.whoami2IP})
|
||||
defer os.Remove(withHealthCheck)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(withoutHealthCheck))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(withoutHealthCheck))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`root.localhost`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`root.localhost`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Allow one of the underlying services on it to fail all servers HC (whoami2)
|
||||
client := http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
statusOKReq, err := http.NewRequest(http.MethodPost, "http://"+s.whoami2IP+"/health", bytes.NewBufferString("500"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusOKReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
rootReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
rootReq.Host = "root.localhost"
|
||||
|
||||
// Check the failed service (whoami2) is getting requests, but answer 500
|
||||
err = try.Request(rootReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusServiceUnavailable))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Enable the healthcheck on the root WSP (wsp-service1) and let Traefik reload the config
|
||||
fr1, err := os.OpenFile(withoutHealthCheck, os.O_APPEND|os.O_WRONLY, 0o644)
|
||||
c.Assert(fr1, checker.NotNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
assert.NotNil(s.T(), fr1)
|
||||
require.NoError(s.T(), err)
|
||||
err = fr1.Truncate(0)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
fr2, err := os.ReadFile(withHealthCheck)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = fmt.Fprint(fr1, string(fr2))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = fr1.Close()
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
try.Sleep(1 * time.Second)
|
||||
// Waiting for the reflected change.
|
||||
err = try.Request(rootReq, 5*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Check the failed service (whoami2) is not getting requests
|
||||
wantIPs := []string{s.whoami1IP, s.whoami1IP, s.whoami1IP, s.whoami1IP}
|
||||
for _, ip := range wantIPs {
|
||||
want := "IP: " + ip
|
||||
resp, err := client.Do(rootReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
c.Assert(string(body), checker.Contains, want)
|
||||
err = try.Request(rootReq, 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("IP: "+ip))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,27 +2,33 @@ package integration
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type HostResolverSuite struct{ BaseSuite }
|
||||
|
||||
func (s *HostResolverSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "hostresolver")
|
||||
s.composeUp(c)
|
||||
func TestHostResolverSuite(t *testing.T) {
|
||||
suite.Run(t, new(HostResolverSuite))
|
||||
}
|
||||
|
||||
func (s *HostResolverSuite) TestSimpleConfig(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/simple_hostresolver.toml"))
|
||||
defer display(c)
|
||||
func (s *HostResolverSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.createComposeProject("hostresolver")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *HostResolverSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *HostResolverSuite) TestSimpleConfig() {
|
||||
s.traefikCmd(withConfigFile("fixtures/simple_hostresolver.toml"))
|
||||
|
||||
testCase := []struct {
|
||||
desc string
|
||||
|
@ -43,10 +49,10 @@ func (s *HostResolverSuite) TestSimpleConfig(c *check.C) {
|
|||
|
||||
for _, test := range testCase {
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = test.host
|
||||
|
||||
err = try.Request(req, 1*time.Second, try.StatusCodeIs(test.status), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.Request(req, 5*time.Second, try.StatusCodeIs(test.status), try.HasBody())
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,28 +5,27 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type HTTPSuite struct{ BaseSuite }
|
||||
|
||||
func (s *HTTPSuite) TestSimpleConfiguration(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/http/simple.toml"))
|
||||
defer display(c)
|
||||
func TestHTTPSuite(t *testing.T) {
|
||||
suite.Run(t, new(HTTPSuite))
|
||||
}
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
defer s.killCmd(cmd)
|
||||
func (s *HTTPSuite) TestSimpleConfiguration() {
|
||||
s.traefikCmd(withConfigFile("fixtures/http/simple.toml"))
|
||||
|
||||
// Expect a 404 as we configured nothing.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Provide a configuration, fetched by Traefik provider.
|
||||
configuration := &dynamic.Configuration{
|
||||
|
@ -55,14 +54,14 @@ func (s *HTTPSuite) TestSimpleConfiguration(c *check.C) {
|
|||
}
|
||||
|
||||
configData, err := json.Marshal(configuration)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
server := startTestServerWithResponse(configData)
|
||||
defer server.Close()
|
||||
|
||||
// Expect configuration to be applied.
|
||||
err = try.GetRequest("http://127.0.0.1:9090/api/rawdata", 3*time.Second, try.BodyContains("routerHTTP@http", "serviceHTTP@http", "http://bacon:80"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func startTestServerWithResponse(response []byte) (ts *httptest.Server) {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,210 +9,325 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
stdlog "log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/cli/context/docker"
|
||||
"github.com/docker/cli/cli/context/store"
|
||||
manifeststore "github.com/docker/cli/cli/manifest/store"
|
||||
registryclient "github.com/docker/cli/cli/registry/client"
|
||||
"github.com/docker/cli/cli/streams"
|
||||
"github.com/docker/cli/cli/trust"
|
||||
cmdcompose "github.com/docker/compose/v2/cmd/compose"
|
||||
"github.com/docker/compose/v2/cmd/formatter"
|
||||
composeapi "github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/compose"
|
||||
dockertypes "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
dockernetwork "github.com/docker/docker/api/types/network"
|
||||
"github.com/fatih/structs"
|
||||
"github.com/go-check/check"
|
||||
notaryclient "github.com/theupdateframework/notary/client"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/testcontainers/testcontainers-go"
|
||||
"github.com/testcontainers/testcontainers-go/network"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var (
|
||||
integration = flag.Bool("integration", false, "run integration tests")
|
||||
showLog = flag.Bool("tlog", false, "always show Traefik logs")
|
||||
)
|
||||
var showLog = flag.Bool("tlog", false, "always show Traefik logs")
|
||||
|
||||
func Test(t *testing.T) {
|
||||
if !*integration {
|
||||
log.WithoutContext().Info("Integration tests disabled.")
|
||||
return
|
||||
}
|
||||
type composeConfig struct {
|
||||
Services map[string]composeService `yaml:"services"`
|
||||
}
|
||||
|
||||
// TODO(mpl): very niche optimization: do not start tailscale if none of the
|
||||
// wanted tests actually need it (e.g. KeepAliveSuite does not).
|
||||
var (
|
||||
vpn *tailscaleNotSuite
|
||||
useVPN bool
|
||||
)
|
||||
if os.Getenv("IN_DOCKER") != "true" {
|
||||
if vpn = setupVPN(nil, "tailscale.secret"); vpn != nil {
|
||||
defer vpn.TearDownSuite(nil)
|
||||
useVPN = true
|
||||
}
|
||||
}
|
||||
type composeService struct {
|
||||
Image string `yaml:"image"`
|
||||
Labels map[string]string `yaml:"labels"`
|
||||
Hostname string `yaml:"hostname"`
|
||||
Volumes []string `yaml:"volumes"`
|
||||
CapAdd []string `yaml:"cap_add"`
|
||||
Command []string `yaml:"command"`
|
||||
Environment map[string]string `yaml:"environment"`
|
||||
Privileged bool `yaml:"privileged"`
|
||||
Deploy composeDeploy `yaml:"deploy"`
|
||||
}
|
||||
|
||||
check.Suite(&AccessLogSuite{})
|
||||
if !useVPN {
|
||||
check.Suite(&AcmeSuite{})
|
||||
}
|
||||
check.Suite(&ConsulCatalogSuite{})
|
||||
check.Suite(&ConsulSuite{})
|
||||
check.Suite(&DockerComposeSuite{})
|
||||
check.Suite(&DockerSuite{})
|
||||
check.Suite(&ErrorPagesSuite{})
|
||||
check.Suite(&EtcdSuite{})
|
||||
check.Suite(&FileSuite{})
|
||||
check.Suite(&GRPCSuite{})
|
||||
check.Suite(&HeadersSuite{})
|
||||
check.Suite(&HealthCheckSuite{})
|
||||
check.Suite(&HostResolverSuite{})
|
||||
check.Suite(&HTTPSSuite{})
|
||||
check.Suite(&HTTPSuite{})
|
||||
if !useVPN {
|
||||
check.Suite(&K8sSuite{})
|
||||
}
|
||||
check.Suite(&KeepAliveSuite{})
|
||||
check.Suite(&LogRotationSuite{})
|
||||
check.Suite(&MarathonSuite{})
|
||||
check.Suite(&MarathonSuite15{})
|
||||
if !useVPN {
|
||||
check.Suite(&ProxyProtocolSuite{})
|
||||
}
|
||||
check.Suite(&RateLimitSuite{})
|
||||
check.Suite(&RedisSuite{})
|
||||
check.Suite(&RestSuite{})
|
||||
check.Suite(&RetrySuite{})
|
||||
check.Suite(&SimpleSuite{})
|
||||
check.Suite(&TCPSuite{})
|
||||
check.Suite(&TimeoutSuite{})
|
||||
check.Suite(&ThrottlingSuite{})
|
||||
check.Suite(&TLSClientHeadersSuite{})
|
||||
check.Suite(&TracingSuite{})
|
||||
check.Suite(&UDPSuite{})
|
||||
check.Suite(&WebsocketSuite{})
|
||||
check.Suite(&ZookeeperSuite{})
|
||||
|
||||
check.TestingT(t)
|
||||
type composeDeploy struct {
|
||||
Replicas int `yaml:"replicas"`
|
||||
}
|
||||
|
||||
var traefikBinary = "../dist/traefik"
|
||||
|
||||
type BaseSuite struct {
|
||||
composeProjectOptions *cmdcompose.ProjectOptions
|
||||
dockerComposeService composeapi.Service
|
||||
dockerClient *client.Client
|
||||
suite.Suite
|
||||
containers map[string]testcontainers.Container
|
||||
network *testcontainers.DockerNetwork
|
||||
hostIP string
|
||||
}
|
||||
|
||||
func (s *BaseSuite) TearDownSuite(c *check.C) {
|
||||
if s.composeProjectOptions != nil && s.dockerComposeService != nil {
|
||||
s.composeDown(c)
|
||||
func (s *BaseSuite) waitForTraefik(containerName string) {
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// Wait for Traefik to turn ready.
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/api/rawdata", nil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains(containerName))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *BaseSuite) displayTraefikLogFile(path string) {
|
||||
if s.T().Failed() {
|
||||
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
||||
content, errRead := os.ReadFile(path)
|
||||
// TODO TestName
|
||||
// fmt.Printf("%s: Traefik logs: \n", c.TestName())
|
||||
fmt.Print("Traefik logs: \n")
|
||||
if errRead == nil {
|
||||
fmt.Println(content)
|
||||
} else {
|
||||
fmt.Println(errRead)
|
||||
}
|
||||
} else {
|
||||
// fmt.Printf("%s: No Traefik logs.\n", c.TestName())
|
||||
fmt.Print("No Traefik logs.\n")
|
||||
}
|
||||
errRemove := os.Remove(path)
|
||||
if errRemove != nil {
|
||||
fmt.Println(errRemove)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *BaseSuite) SetupSuite() {
|
||||
// configure default standard log.
|
||||
stdlog.SetFlags(stdlog.Lshortfile | stdlog.LstdFlags)
|
||||
// TODO
|
||||
// stdlog.SetOutput(log.Logger)
|
||||
|
||||
ctx := context.Background()
|
||||
// Create docker network
|
||||
// docker network create traefik-test-network --driver bridge --subnet 172.31.42.0/24
|
||||
var opts []network.NetworkCustomizer
|
||||
opts = append(opts, network.WithDriver("bridge"))
|
||||
opts = append(opts, network.WithIPAM(&dockernetwork.IPAM{
|
||||
Driver: "default",
|
||||
Config: []dockernetwork.IPAMConfig{
|
||||
{
|
||||
Subnet: "172.31.42.0/24",
|
||||
},
|
||||
},
|
||||
}))
|
||||
dockerNetwork, err := network.New(ctx, opts...)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
s.network = dockerNetwork
|
||||
s.hostIP = "172.31.42.1"
|
||||
if isDockerDesktop(ctx, s.T()) {
|
||||
s.hostIP = getDockerDesktopHostIP(ctx, s.T())
|
||||
s.setupVPN("tailscale.secret")
|
||||
}
|
||||
}
|
||||
|
||||
func getDockerDesktopHostIP(ctx context.Context, t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
req := testcontainers.ContainerRequest{
|
||||
Image: "alpine",
|
||||
HostConfigModifier: func(config *container.HostConfig) {
|
||||
config.AutoRemove = true
|
||||
},
|
||||
Cmd: []string{"getent", "hosts", "host.docker.internal"},
|
||||
}
|
||||
|
||||
con, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
|
||||
ContainerRequest: req,
|
||||
Started: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
closer, err := con.Logs(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
all, err := io.ReadAll(closer)
|
||||
require.NoError(t, err)
|
||||
|
||||
ipRegex := regexp.MustCompile(`\b(?:\d{1,3}\.){3}\d{1,3}\b`)
|
||||
matches := ipRegex.FindAllString(string(all), -1)
|
||||
require.Len(t, matches, 1)
|
||||
|
||||
return matches[0]
|
||||
}
|
||||
|
||||
func isDockerDesktop(ctx context.Context, t *testing.T) bool {
|
||||
t.Helper()
|
||||
|
||||
cli, err := testcontainers.NewDockerClientWithOpts(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create docker client: %s", err)
|
||||
}
|
||||
|
||||
info, err := cli.Info(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get docker info: %s", err)
|
||||
}
|
||||
|
||||
return info.OperatingSystem == "Docker Desktop"
|
||||
}
|
||||
|
||||
func (s *BaseSuite) TearDownSuite() {
|
||||
s.composeDown()
|
||||
|
||||
err := try.Do(5*time.Second, func() error {
|
||||
if s.network != nil {
|
||||
err := s.network.Remove(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
// createComposeProject creates the docker compose project stored as a field in the BaseSuite.
|
||||
// This method should be called before starting and/or stopping compose services.
|
||||
func (s *BaseSuite) createComposeProject(c *check.C, name string) {
|
||||
projectName := fmt.Sprintf("traefik-integration-test-%s", name)
|
||||
func (s *BaseSuite) createComposeProject(name string) {
|
||||
composeFile := fmt.Sprintf("resources/compose/%s.yml", name)
|
||||
|
||||
var err error
|
||||
s.dockerClient, err = client.NewClientWithOpts()
|
||||
c.Assert(err, checker.IsNil)
|
||||
file, err := os.ReadFile(composeFile)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
fakeCLI := &FakeDockerCLI{client: s.dockerClient}
|
||||
s.dockerComposeService = compose.NewComposeService(fakeCLI)
|
||||
var composeConfigData composeConfig
|
||||
err = yaml.Unmarshal(file, &composeConfigData)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
s.composeProjectOptions = &cmdcompose.ProjectOptions{
|
||||
ProjectDir: ".",
|
||||
ProjectName: projectName,
|
||||
ConfigPaths: []string{composeFile},
|
||||
if s.containers == nil {
|
||||
s.containers = map[string]testcontainers.Container{}
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
for id, containerConfig := range composeConfigData.Services {
|
||||
var mounts []mount.Mount
|
||||
for _, volume := range containerConfig.Volumes {
|
||||
split := strings.Split(volume, ":")
|
||||
if len(split) != 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(split[0], "./") {
|
||||
path, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.WithoutContext().Errorf("can't determine current directory: %v", err)
|
||||
continue
|
||||
}
|
||||
split[0] = strings.Replace(split[0], "./", path+"/", 1)
|
||||
}
|
||||
|
||||
abs, err := filepath.Abs(split[0])
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
mounts = append(mounts, mount.Mount{Source: abs, Target: split[1], Type: mount.TypeBind})
|
||||
}
|
||||
|
||||
if containerConfig.Deploy.Replicas > 0 {
|
||||
for i := 0; i < containerConfig.Deploy.Replicas; i++ {
|
||||
id = fmt.Sprintf("%s-%d", id, i+1)
|
||||
con, err := s.createContainer(ctx, containerConfig, id, mounts)
|
||||
require.NoError(s.T(), err)
|
||||
s.containers[id] = con
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
con, err := s.createContainer(ctx, containerConfig, id, mounts)
|
||||
require.NoError(s.T(), err)
|
||||
s.containers[id] = con
|
||||
}
|
||||
}
|
||||
|
||||
func (s *BaseSuite) createContainer(ctx context.Context, containerConfig composeService, id string, mounts []mount.Mount) (testcontainers.Container, error) {
|
||||
req := testcontainers.ContainerRequest{
|
||||
Image: containerConfig.Image,
|
||||
Env: containerConfig.Environment,
|
||||
Cmd: containerConfig.Command,
|
||||
Labels: containerConfig.Labels,
|
||||
Name: id,
|
||||
Hostname: containerConfig.Hostname,
|
||||
Privileged: containerConfig.Privileged,
|
||||
Networks: []string{s.network.Name},
|
||||
HostConfigModifier: func(config *container.HostConfig) {
|
||||
if containerConfig.CapAdd != nil {
|
||||
config.CapAdd = containerConfig.CapAdd
|
||||
}
|
||||
if !isDockerDesktop(ctx, s.T()) {
|
||||
config.ExtraHosts = append(config.ExtraHosts, "host.docker.internal:"+s.hostIP)
|
||||
}
|
||||
config.Mounts = mounts
|
||||
},
|
||||
}
|
||||
con, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
|
||||
ContainerRequest: req,
|
||||
Started: false,
|
||||
})
|
||||
|
||||
return con, err
|
||||
}
|
||||
|
||||
// composeUp starts the given services of the current docker compose project, if they are not already started.
|
||||
// Already running services are not affected (i.e. not stopped).
|
||||
func (s *BaseSuite) composeUp(c *check.C, services ...string) {
|
||||
c.Assert(s.composeProjectOptions, check.NotNil)
|
||||
c.Assert(s.dockerComposeService, check.NotNil)
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// We use Create and Restart instead of Up, because the only option that actually works to control which containers
|
||||
// are started is within the RestartOptions.
|
||||
err = s.dockerComposeService.Create(context.Background(), composeProject, composeapi.CreateOptions{})
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = s.dockerComposeService.Restart(context.Background(), composeProject.Name, composeapi.RestartOptions{Services: services})
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
// composeExec runs the command in the given args in the given compose service container.
|
||||
// Already running services are not affected (i.e. not stopped).
|
||||
func (s *BaseSuite) composeExec(c *check.C, service string, args ...string) {
|
||||
c.Assert(s.composeProjectOptions, check.NotNil)
|
||||
c.Assert(s.dockerComposeService, check.NotNil)
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
_, err = s.dockerComposeService.Exec(context.Background(), composeProject.Name, composeapi.RunOptions{
|
||||
Service: service,
|
||||
Command: args,
|
||||
Tty: false,
|
||||
Index: 1,
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
func (s *BaseSuite) composeUp(services ...string) {
|
||||
for name, con := range s.containers {
|
||||
if len(services) == 0 || slices.Contains(services, name) {
|
||||
err := con.Start(context.Background())
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// composeStop stops the given services of the current docker compose project and removes the corresponding containers.
|
||||
func (s *BaseSuite) composeStop(c *check.C, services ...string) {
|
||||
c.Assert(s.composeProjectOptions, check.NotNil)
|
||||
c.Assert(s.dockerComposeService, check.NotNil)
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = s.dockerComposeService.Stop(context.Background(), composeProject.Name, composeapi.StopOptions{Services: services})
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = s.dockerComposeService.Remove(context.Background(), composeProject.Name, composeapi.RemoveOptions{})
|
||||
c.Assert(err, checker.IsNil)
|
||||
func (s *BaseSuite) composeStop(services ...string) {
|
||||
for name, con := range s.containers {
|
||||
if len(services) == 0 || slices.Contains(services, name) {
|
||||
timeout := 10 * time.Second
|
||||
err := con.Stop(context.Background(), &timeout)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// composeDown stops all compose project services and removes the corresponding containers.
|
||||
func (s *BaseSuite) composeDown(c *check.C) {
|
||||
c.Assert(s.composeProjectOptions, check.NotNil)
|
||||
c.Assert(s.dockerComposeService, check.NotNil)
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = s.dockerComposeService.Down(context.Background(), composeProject.Name, composeapi.DownOptions{})
|
||||
c.Assert(err, checker.IsNil)
|
||||
func (s *BaseSuite) composeDown() {
|
||||
for _, c := range s.containers {
|
||||
err := c.Terminate(context.Background())
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
s.containers = map[string]testcontainers.Container{}
|
||||
}
|
||||
|
||||
func (s *BaseSuite) cmdTraefik(args ...string) (*exec.Cmd, *bytes.Buffer) {
|
||||
cmd := exec.Command(traefikBinary, args...)
|
||||
|
||||
s.T().Cleanup(func() {
|
||||
s.killCmd(cmd)
|
||||
})
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &out
|
||||
|
||||
err := cmd.Start()
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
return cmd, &out
|
||||
}
|
||||
|
||||
func (s *BaseSuite) killCmd(cmd *exec.Cmd) {
|
||||
if cmd.Process == nil {
|
||||
log.WithoutContext().Error("No process to kill")
|
||||
return
|
||||
}
|
||||
err := cmd.Process.Kill()
|
||||
if err != nil {
|
||||
log.WithoutContext().Errorf("Kill: %v", err)
|
||||
|
@ -221,15 +336,18 @@ func (s *BaseSuite) killCmd(cmd *exec.Cmd) {
|
|||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
func (s *BaseSuite) traefikCmd(args ...string) (*exec.Cmd, func(*check.C)) {
|
||||
func (s *BaseSuite) traefikCmd(args ...string) *exec.Cmd {
|
||||
cmd, out := s.cmdTraefik(args...)
|
||||
return cmd, func(c *check.C) {
|
||||
if c.Failed() || *showLog {
|
||||
|
||||
s.T().Cleanup(func() {
|
||||
if s.T().Failed() || *showLog {
|
||||
s.displayLogK3S()
|
||||
s.displayLogCompose(c)
|
||||
s.displayTraefikLog(c, out)
|
||||
s.displayLogCompose()
|
||||
s.displayTraefikLog(out)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (s *BaseSuite) displayLogK3S() {
|
||||
|
@ -246,34 +364,33 @@ func (s *BaseSuite) displayLogK3S() {
|
|||
log.WithoutContext().Println()
|
||||
}
|
||||
|
||||
func (s *BaseSuite) displayLogCompose(c *check.C) {
|
||||
if s.dockerComposeService == nil || s.composeProjectOptions == nil {
|
||||
log.WithoutContext().Infof("%s: No docker compose logs.", c.TestName())
|
||||
return
|
||||
func (s *BaseSuite) displayLogCompose() {
|
||||
for name, ctn := range s.containers {
|
||||
readCloser, err := ctn.Logs(context.Background())
|
||||
require.NoError(s.T(), err)
|
||||
for {
|
||||
b := make([]byte, 1024)
|
||||
_, err := readCloser.Read(b)
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
trimLogs := bytes.Trim(bytes.TrimSpace(b), string([]byte{0}))
|
||||
if len(trimLogs) > 0 {
|
||||
log.WithoutContext().WithField("container", name).Info(string(trimLogs))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.WithoutContext().Infof("%s: docker compose logs: ", c.TestName())
|
||||
|
||||
logWriter := log.WithoutContext().WriterLevel(log.GetLevel())
|
||||
logConsumer := formatter.NewLogConsumer(context.Background(), logWriter, logWriter, false, true, true)
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = s.dockerComposeService.Logs(context.Background(), composeProject.Name, logConsumer, composeapi.LogOptions{})
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
log.WithoutContext().Println()
|
||||
log.WithoutContext().Println("################################")
|
||||
log.WithoutContext().Println()
|
||||
}
|
||||
|
||||
func (s *BaseSuite) displayTraefikLog(c *check.C, output *bytes.Buffer) {
|
||||
func (s *BaseSuite) displayTraefikLog(output *bytes.Buffer) {
|
||||
if output == nil || output.Len() == 0 {
|
||||
log.WithoutContext().Infof("%s: No Traefik logs.", c.TestName())
|
||||
log.WithoutContext().Info("No Traefik logs.")
|
||||
} else {
|
||||
log.WithoutContext().Infof("%s: Traefik logs: ", c.TestName())
|
||||
log.WithoutContext().Infof(output.String())
|
||||
for _, line := range strings.Split(output.String(), "\n") {
|
||||
log.WithoutContext().Info(line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,73 +404,47 @@ func (s *BaseSuite) getDockerHost() string {
|
|||
return dockerHost
|
||||
}
|
||||
|
||||
func (s *BaseSuite) adaptFile(c *check.C, path string, tempObjects interface{}) string {
|
||||
func (s *BaseSuite) adaptFile(path string, tempObjects interface{}) string {
|
||||
// Load file
|
||||
tmpl, err := template.ParseFiles(path)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
folder, prefix := filepath.Split(path)
|
||||
tmpFile, err := os.CreateTemp(folder, strings.TrimSuffix(prefix, filepath.Ext(prefix))+"_*"+filepath.Ext(prefix))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
defer tmpFile.Close()
|
||||
|
||||
model := structs.Map(tempObjects)
|
||||
model["SelfFilename"] = tmpFile.Name()
|
||||
|
||||
err = tmpl.ExecuteTemplate(tmpFile, prefix, model)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = tmpFile.Sync()
|
||||
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
s.T().Cleanup(func() {
|
||||
os.Remove(tmpFile.Name())
|
||||
})
|
||||
return tmpFile.Name()
|
||||
}
|
||||
|
||||
func (s *BaseSuite) getComposeServiceIP(c *check.C, name string) string {
|
||||
c.Assert(s.composeProjectOptions, check.NotNil)
|
||||
c.Assert(s.dockerComposeService, check.NotNil)
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
filter := filters.NewArgs(
|
||||
filters.Arg("label", fmt.Sprintf("%s=%s", composeapi.ProjectLabel, composeProject.Name)),
|
||||
filters.Arg("label", fmt.Sprintf("%s=%s", composeapi.ServiceLabel, name)),
|
||||
)
|
||||
|
||||
containers, err := s.dockerClient.ContainerList(context.Background(), dockertypes.ContainerListOptions{Filters: filter})
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(containers, checker.HasLen, 1)
|
||||
|
||||
networkNames := composeProject.NetworkNames()
|
||||
c.Assert(networkNames, checker.HasLen, 1)
|
||||
|
||||
network := composeProject.Networks[networkNames[0]]
|
||||
return containers[0].NetworkSettings.Networks[network.Name].IPAddress
|
||||
}
|
||||
|
||||
func (s *BaseSuite) getContainerIP(c *check.C, name string) string {
|
||||
container, err := s.dockerClient.ContainerInspect(context.Background(), name)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(container.NetworkSettings.Networks, check.NotNil)
|
||||
|
||||
for _, network := range container.NetworkSettings.Networks {
|
||||
return network.IPAddress
|
||||
func (s *BaseSuite) getComposeServiceIP(name string) string {
|
||||
container, ok := s.containers[name]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Should never happen.
|
||||
c.Error("No network found")
|
||||
return ""
|
||||
ip, err := container.ContainerIP(context.Background())
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return ip
|
||||
}
|
||||
|
||||
func withConfigFile(file string) string {
|
||||
return "--configFile=" + file
|
||||
}
|
||||
|
||||
// tailscaleNotSuite includes a BaseSuite out of convenience, so we can benefit
|
||||
// from composeUp et co., but it is not meant to function as a TestSuite per se.
|
||||
type tailscaleNotSuite struct{ BaseSuite }
|
||||
|
||||
// setupVPN starts Tailscale on the corresponding container, and makes it a subnet
|
||||
// router, for all the other containers (whoamis, etc) subsequently started for the
|
||||
// integration tests.
|
||||
|
@ -369,101 +460,35 @@ type tailscaleNotSuite struct{ BaseSuite }
|
|||
// "172.0.0.0/8": ["your_tailscale_identity"],
|
||||
// },
|
||||
// },
|
||||
//
|
||||
// TODO(mpl): we could maybe even move this setup to the Makefile, to start it
|
||||
// and let it run (forever, or until voluntarily stopped).
|
||||
func setupVPN(c *check.C, keyFile string) *tailscaleNotSuite {
|
||||
func (s *BaseSuite) setupVPN(keyFile string) {
|
||||
data, err := os.ReadFile(keyFile)
|
||||
if err != nil {
|
||||
if !errors.Is(err, fs.ErrNotExist) {
|
||||
log.Fatal(err)
|
||||
log.WithoutContext().Error(err)
|
||||
}
|
||||
return nil
|
||||
|
||||
return
|
||||
}
|
||||
authKey := strings.TrimSpace(string(data))
|
||||
// TODO: copy and create versions that don't need a check.C?
|
||||
vpn := &tailscaleNotSuite{}
|
||||
vpn.createComposeProject(c, "tailscale")
|
||||
vpn.composeUp(c)
|
||||
// // TODO: copy and create versions that don't need a check.C?
|
||||
s.createComposeProject("tailscale")
|
||||
s.composeUp()
|
||||
time.Sleep(5 * time.Second)
|
||||
// If we ever change the docker subnet in the Makefile,
|
||||
// we need to change this one below correspondingly.
|
||||
vpn.composeExec(c, "tailscaled", "tailscale", "up", "--authkey="+authKey, "--advertise-routes=172.31.42.0/24")
|
||||
return vpn
|
||||
s.composeExec("tailscaled", "tailscale", "up", "--authkey="+authKey, "--advertise-routes=172.31.42.0/24")
|
||||
}
|
||||
|
||||
type FakeDockerCLI struct {
|
||||
client client.APIClient
|
||||
}
|
||||
// composeExec runs the command in the given args in the given compose service container.
|
||||
// Already running services are not affected (i.e. not stopped).
|
||||
func (s *BaseSuite) composeExec(service string, args ...string) string {
|
||||
require.Contains(s.T(), s.containers, service)
|
||||
|
||||
func (f FakeDockerCLI) Client() client.APIClient {
|
||||
return f.client
|
||||
}
|
||||
_, reader, err := s.containers[service].Exec(context.Background(), args)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
func (f FakeDockerCLI) In() *streams.In {
|
||||
return streams.NewIn(os.Stdin)
|
||||
}
|
||||
content, err := io.ReadAll(reader)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
func (f FakeDockerCLI) Out() *streams.Out {
|
||||
return streams.NewOut(os.Stdout)
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) Err() io.Writer {
|
||||
return streams.NewOut(os.Stderr)
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) SetIn(in *streams.In) {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) Apply(ops ...command.DockerCliOption) error {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) ConfigFile() *configfile.ConfigFile {
|
||||
return &configfile.ConfigFile{}
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) ServerInfo() command.ServerInfo {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) NotaryClient(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error) {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) DefaultVersion() string {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) CurrentVersion() string {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) ManifestStore() manifeststore.Store {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) RegistryClient(b bool) registryclient.RegistryClient {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) ContentTrustEnabled() bool {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) BuildKitEnabled() (bool, error) {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) ContextStore() store.Store {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) CurrentContext() string {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) DockerEndpoint() docker.Endpoint {
|
||||
panic("implement me if you need me")
|
||||
return string(content)
|
||||
}
|
||||
|
|
|
@ -7,18 +7,21 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/api"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
var updateExpected = flag.Bool("update_expected", false, "Update expected files in testdata")
|
||||
|
@ -26,25 +29,39 @@ var updateExpected = flag.Bool("update_expected", false, "Update expected files
|
|||
// K8sSuite tests suite.
|
||||
type K8sSuite struct{ BaseSuite }
|
||||
|
||||
func (s *K8sSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "k8s")
|
||||
s.composeUp(c)
|
||||
func TestK8sSuite(t *testing.T) {
|
||||
suite.Run(t, new(K8sSuite))
|
||||
}
|
||||
|
||||
func (s *K8sSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("k8s")
|
||||
s.composeUp()
|
||||
|
||||
abs, err := filepath.Abs("./fixtures/k8s/config.skip/kubeconfig.yaml")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Do(60*time.Second, func() error {
|
||||
_, err := os.Stat(abs)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
data, err := os.ReadFile(abs)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
content := strings.ReplaceAll(string(data), "https://server:6443", fmt.Sprintf("https://%s", net.JoinHostPort(s.getComposeServiceIP("server"), "6443")))
|
||||
|
||||
err = os.WriteFile(abs, []byte(content), 0o644)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = os.Setenv("KUBECONFIG", abs)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *K8sSuite) TearDownSuite(c *check.C) {
|
||||
s.composeDown(c)
|
||||
func (s *K8sSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
|
||||
generatedFiles := []string{
|
||||
"./fixtures/k8s/config.skip/kubeconfig.yaml",
|
||||
|
@ -62,109 +79,78 @@ func (s *K8sSuite) TearDownSuite(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *K8sSuite) TestIngressConfiguration(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/k8s_default.toml"))
|
||||
defer display(c)
|
||||
func (s *K8sSuite) TestIngressConfiguration() {
|
||||
s.traefikCmd(withConfigFile("fixtures/k8s_default.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
testConfiguration(c, "testdata/rawdata-ingress.json", "8080")
|
||||
s.testConfiguration("testdata/rawdata-ingress.json", "8080")
|
||||
}
|
||||
|
||||
func (s *K8sSuite) TestIngressLabelSelector(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/k8s_ingress_label_selector.toml"))
|
||||
defer display(c)
|
||||
func (s *K8sSuite) TestIngressLabelSelector() {
|
||||
s.traefikCmd(withConfigFile("fixtures/k8s_ingress_label_selector.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
testConfiguration(c, "testdata/rawdata-ingress-label-selector.json", "8080")
|
||||
s.testConfiguration("testdata/rawdata-ingress-label-selector.json", "8080")
|
||||
}
|
||||
|
||||
func (s *K8sSuite) TestCRDConfiguration(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/k8s_crd.toml"))
|
||||
defer display(c)
|
||||
func (s *K8sSuite) TestCRDConfiguration() {
|
||||
s.traefikCmd(withConfigFile("fixtures/k8s_crd.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
testConfiguration(c, "testdata/rawdata-crd.json", "8000")
|
||||
s.testConfiguration("testdata/rawdata-crd.json", "8000")
|
||||
}
|
||||
|
||||
func (s *K8sSuite) TestCRDLabelSelector(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/k8s_crd_label_selector.toml"))
|
||||
defer display(c)
|
||||
func (s *K8sSuite) TestCRDLabelSelector() {
|
||||
s.traefikCmd(withConfigFile("fixtures/k8s_crd_label_selector.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
testConfiguration(c, "testdata/rawdata-crd-label-selector.json", "8000")
|
||||
s.testConfiguration("testdata/rawdata-crd-label-selector.json", "8000")
|
||||
}
|
||||
|
||||
func (s *K8sSuite) TestGatewayConfiguration(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/k8s_gateway.toml"))
|
||||
defer display(c)
|
||||
func (s *K8sSuite) TestGatewayConfiguration() {
|
||||
s.traefikCmd(withConfigFile("fixtures/k8s_gateway.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
testConfiguration(c, "testdata/rawdata-gateway.json", "8080")
|
||||
s.testConfiguration("testdata/rawdata-gateway.json", "8080")
|
||||
}
|
||||
|
||||
func (s *K8sSuite) TestIngressclass(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/k8s_ingressclass.toml"))
|
||||
defer display(c)
|
||||
func (s *K8sSuite) TestIngressclass() {
|
||||
s.traefikCmd(withConfigFile("fixtures/k8s_ingressclass.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
testConfiguration(c, "testdata/rawdata-ingressclass.json", "8080")
|
||||
s.testConfiguration("testdata/rawdata-ingressclass.json", "8080")
|
||||
}
|
||||
|
||||
func testConfiguration(c *check.C, path, apiPort string) {
|
||||
func (s *K8sSuite) testConfiguration(path, apiPort string) {
|
||||
err := try.GetRequest("http://127.0.0.1:"+apiPort+"/api/entrypoints", 20*time.Second, try.BodyContains(`"name":"web"`))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
expectedJSON := filepath.FromSlash(path)
|
||||
|
||||
if *updateExpected {
|
||||
fi, err := os.Create(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = fi.Close()
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
err = try.GetRequest("http://127.0.0.1:"+apiPort+"/api/rawdata", 1*time.Minute, try.StatusCodeIs(http.StatusOK), matchesConfig(expectedJSON, &buf))
|
||||
|
||||
if !*updateExpected {
|
||||
if err != nil {
|
||||
c.Error(err)
|
||||
}
|
||||
require.NoError(s.T(), err)
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.Logf("In file update mode, got expected error: %v", err)
|
||||
log.WithoutContext().Infof("In file update mode, got expected error: %v", err)
|
||||
}
|
||||
|
||||
var rtRepr api.RunTimeRepresentation
|
||||
err = json.Unmarshal(buf.Bytes(), &rtRepr)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
newJSON, err := json.MarshalIndent(rtRepr, "", "\t")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = os.WriteFile(expectedJSON, newJSON, 0o644)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Errorf("We do not want a passing test in file update mode")
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
s.T().Fatal("We do not want a passing test in file update mode")
|
||||
}
|
||||
|
||||
func matchesConfig(wantConfig string, buf *bytes.Buffer) try.ResponseCondition {
|
||||
|
|
|
@ -5,18 +5,23 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
)
|
||||
|
||||
type KeepAliveSuite struct {
|
||||
BaseSuite
|
||||
}
|
||||
|
||||
func TestKeepAliveSuite(t *testing.T) {
|
||||
suite.Run(t, new(KeepAliveSuite))
|
||||
}
|
||||
|
||||
type KeepAliveConfig struct {
|
||||
KeepAliveServer string
|
||||
IdleConnTimeout string
|
||||
|
@ -27,7 +32,7 @@ type connStateChangeEvent struct {
|
|||
state http.ConnState
|
||||
}
|
||||
|
||||
func (s *KeepAliveSuite) TestShouldRespectConfiguredBackendHttpKeepAliveTime(c *check.C) {
|
||||
func (s *KeepAliveSuite) TestShouldRespectConfiguredBackendHttpKeepAliveTime() {
|
||||
idleTimeout := time.Duration(75) * time.Millisecond
|
||||
|
||||
connStateChanges := make(chan connStateChangeEvent)
|
||||
|
@ -59,18 +64,18 @@ func (s *KeepAliveSuite) TestShouldRespectConfiguredBackendHttpKeepAliveTime(c *
|
|||
case <-noMoreRequests:
|
||||
moreRequestsExpected = false
|
||||
case <-maxWaitTimeExceeded:
|
||||
c.Logf("timeout waiting for all connections to close, waited for %v, configured idle timeout was %v", maxWaitDuration, idleTimeout)
|
||||
c.Fail()
|
||||
log.WithoutContext().Infof("timeout waiting for all connections to close, waited for %v, configured idle timeout was %v", maxWaitDuration, idleTimeout)
|
||||
s.T().Fail()
|
||||
close(completed)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.Check(connCount, checker.Equals, 1)
|
||||
require.Equal(s.T(), 1, connCount)
|
||||
|
||||
for _, idlePeriod := range idlePeriodLengthMap {
|
||||
// Our method of measuring the actual idle period is not precise, so allow some sub-ms deviation
|
||||
c.Check(math.Round(idlePeriod.Seconds()), checker.LessOrEqualThan, idleTimeout.Seconds())
|
||||
require.LessOrEqual(s.T(), math.Round(idlePeriod.Seconds()), idleTimeout.Seconds())
|
||||
}
|
||||
|
||||
close(completed)
|
||||
|
@ -87,22 +92,16 @@ func (s *KeepAliveSuite) TestShouldRespectConfiguredBackendHttpKeepAliveTime(c *
|
|||
defer server.Close()
|
||||
|
||||
config := KeepAliveConfig{KeepAliveServer: server.URL, IdleConnTimeout: idleTimeout.String()}
|
||||
file := s.adaptFile(c, "fixtures/timeout/keepalive.toml", config)
|
||||
file := s.adaptFile("fixtures/timeout/keepalive.toml", config)
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Check(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Duration(1)*time.Second, try.StatusCodeIs(200), try.BodyContains("PathPrefix(`/keepalive`)"))
|
||||
c.Check(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Duration(1)*time.Second, try.StatusCodeIs(200), try.BodyContains("PathPrefix(`/keepalive`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/keepalive", time.Duration(1)*time.Second, try.StatusCodeIs(200))
|
||||
c.Check(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
close(noMoreRequests)
|
||||
<-completed
|
||||
|
|
|
@ -9,12 +9,14 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -25,13 +27,23 @@ const (
|
|||
// Log rotation integration test suite.
|
||||
type LogRotationSuite struct{ BaseSuite }
|
||||
|
||||
func (s *LogRotationSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "access_log")
|
||||
s.composeUp(c)
|
||||
func TestLogRorationSuite(t *testing.T) {
|
||||
suite.Run(t, new(LogRotationSuite))
|
||||
}
|
||||
|
||||
func (s *LogRotationSuite) TearDownSuite(c *check.C) {
|
||||
s.composeDown(c)
|
||||
func (s *LogRotationSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
os.Remove(traefikTestAccessLogFile)
|
||||
os.Remove(traefikTestLogFile)
|
||||
os.Remove(traefikTestAccessLogFileRotated)
|
||||
|
||||
s.createComposeProject("access_log")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *LogRotationSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
|
||||
generatedFiles := []string{
|
||||
traefikTestLogFile,
|
||||
|
@ -47,126 +59,116 @@ func (s *LogRotationSuite) TearDownSuite(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *LogRotationSuite) TestAccessLogRotation(c *check.C) {
|
||||
func (s *LogRotationSuite) TestAccessLogRotation() {
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
defer displayTraefikLogFile(c, traefikTestLogFile)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
cmd, _ := s.cmdTraefik(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer s.displayTraefikLogFile(traefikTestLogFile)
|
||||
|
||||
// Verify Traefik started ok
|
||||
verifyEmptyErrorLog(c, "traefik.log")
|
||||
s.verifyEmptyErrorLog("traefik.log")
|
||||
|
||||
waitForTraefik(c, "server1")
|
||||
s.waitForTraefik("server1")
|
||||
|
||||
// Make some requests
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "frontend1.docker.local"
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Rename access log
|
||||
err = os.Rename(traefikTestAccessLogFile, traefikTestAccessLogFileRotated)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// in the midst of the requests, issue SIGUSR1 signal to server process
|
||||
err = cmd.Process.Signal(syscall.SIGUSR1)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// continue issuing requests
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log.rotated output as expected
|
||||
logAccessLogFile(c, traefikTestAccessLogFileRotated)
|
||||
lineCount := verifyLogLines(c, traefikTestAccessLogFileRotated, 0, true)
|
||||
c.Assert(lineCount, checker.GreaterOrEqualThan, 1)
|
||||
s.logAccessLogFile(traefikTestAccessLogFileRotated)
|
||||
lineCount := s.verifyLogLines(traefikTestAccessLogFileRotated, 0, true)
|
||||
assert.GreaterOrEqual(s.T(), lineCount, 1)
|
||||
|
||||
// make sure that the access log file is at least created before we do assertions on it
|
||||
err = try.Do(1*time.Second, func() error {
|
||||
_, err := os.Stat(traefikTestAccessLogFile)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, checker.IsNil, check.Commentf("access log file was not created in time"))
|
||||
assert.NoError(s.T(), err, "access log file was not created in time")
|
||||
|
||||
// Verify access.log output as expected
|
||||
logAccessLogFile(c, traefikTestAccessLogFile)
|
||||
lineCount = verifyLogLines(c, traefikTestAccessLogFile, lineCount, true)
|
||||
c.Assert(lineCount, checker.Equals, 3)
|
||||
s.logAccessLogFile(traefikTestAccessLogFile)
|
||||
lineCount = s.verifyLogLines(traefikTestAccessLogFile, lineCount, true)
|
||||
assert.Equal(s.T(), 3, lineCount)
|
||||
|
||||
verifyEmptyErrorLog(c, traefikTestLogFile)
|
||||
s.verifyEmptyErrorLog(traefikTestLogFile)
|
||||
}
|
||||
|
||||
func (s *LogRotationSuite) TestTraefikLogRotation(c *check.C) {
|
||||
func (s *LogRotationSuite) TestTraefikLogRotation() {
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/traefik_log_config.toml"))
|
||||
defer display(c)
|
||||
defer displayTraefikLogFile(c, traefikTestLogFile)
|
||||
cmd := s.traefikCmd(withConfigFile("fixtures/traefik_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
waitForTraefik(c, "server1")
|
||||
s.waitForTraefik("server1")
|
||||
|
||||
// Rename traefik log
|
||||
err = os.Rename(traefikTestLogFile, traefikTestLogFileRotated)
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := os.Rename(traefikTestLogFile, traefikTestLogFileRotated)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// issue SIGUSR1 signal to server process
|
||||
err = cmd.Process.Signal(syscall.SIGUSR1)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = cmd.Process.Signal(syscall.SIGTERM)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Allow time for switch to be processed
|
||||
err = try.Do(3*time.Second, func() error {
|
||||
_, err = os.Stat(traefikTestLogFile)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// we have at least 6 lines in traefik.log.rotated
|
||||
lineCount := verifyLogLines(c, traefikTestLogFileRotated, 0, false)
|
||||
lineCount := s.verifyLogLines(traefikTestLogFileRotated, 0, false)
|
||||
|
||||
// GreaterOrEqualThan used to ensure test doesn't break
|
||||
// If more log entries are output on startup
|
||||
c.Assert(lineCount, checker.GreaterOrEqualThan, 5)
|
||||
assert.GreaterOrEqual(s.T(), lineCount, 5)
|
||||
|
||||
// Verify traefik.log output as expected
|
||||
lineCount = verifyLogLines(c, traefikTestLogFile, lineCount, false)
|
||||
c.Assert(lineCount, checker.GreaterOrEqualThan, 7)
|
||||
lineCount = s.verifyLogLines(traefikTestLogFile, lineCount, false)
|
||||
assert.GreaterOrEqual(s.T(), lineCount, 7)
|
||||
}
|
||||
|
||||
func logAccessLogFile(c *check.C, fileName string) {
|
||||
func (s *LogRotationSuite) logAccessLogFile(fileName string) {
|
||||
output, err := os.ReadFile(fileName)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Logf("Contents of file %s\n%s", fileName, string(output))
|
||||
require.NoError(s.T(), err)
|
||||
log.WithoutContext().Infof("Contents of file %s\n%s", fileName, string(output))
|
||||
}
|
||||
|
||||
func verifyEmptyErrorLog(c *check.C, name string) {
|
||||
func (s *LogRotationSuite) verifyEmptyErrorLog(name string) {
|
||||
err := try.Do(5*time.Second, func() error {
|
||||
traefikLog, e2 := os.ReadFile(name)
|
||||
if e2 != nil {
|
||||
return e2
|
||||
}
|
||||
c.Assert(string(traefikLog), checker.HasLen, 0)
|
||||
assert.Empty(s.T(), string(traefikLog))
|
||||
|
||||
return nil
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func verifyLogLines(c *check.C, fileName string, countInit int, accessLog bool) int {
|
||||
func (s *LogRotationSuite) verifyLogLines(fileName string, countInit int, accessLog bool) int {
|
||||
rotated, err := os.Open(fileName)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
rotatedLog := bufio.NewScanner(rotated)
|
||||
count := countInit
|
||||
for rotatedLog.Scan() {
|
||||
|
@ -174,7 +176,7 @@ func verifyLogLines(c *check.C, fileName string, countInit int, accessLog bool)
|
|||
if accessLog {
|
||||
if len(line) > 0 {
|
||||
if !strings.Contains(line, "/api/rawdata") {
|
||||
CheckAccessLogFormat(c, line, count)
|
||||
s.CheckAccessLogFormat(line, count)
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@ package integration
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gambol99/go-marathon"
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Marathon test suites.
|
||||
|
@ -17,42 +17,46 @@ type MarathonSuite15 struct {
|
|||
marathonURL string
|
||||
}
|
||||
|
||||
func (s *MarathonSuite15) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "marathon15")
|
||||
s.composeUp(c)
|
||||
func TestMarathonSuite15(t *testing.T) {
|
||||
suite.Run(t, new(MarathonSuite))
|
||||
}
|
||||
|
||||
s.marathonURL = "http://" + s.getComposeServiceIP(c, containerNameMarathon) + ":8080"
|
||||
func (s *MarathonSuite15) SetUpSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
s.createComposeProject("marathon15")
|
||||
s.composeUp()
|
||||
|
||||
s.marathonURL = "http://" + s.getComposeServiceIP(containerNameMarathon) + ":8080"
|
||||
|
||||
// Wait for Marathon readiness prior to creating the client so that we
|
||||
// don't run into the "all cluster members down" state right from the
|
||||
// start.
|
||||
err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *MarathonSuite15) TestConfigurationUpdate(c *check.C) {
|
||||
c.Skip("doesn't work")
|
||||
func (s *MarathonSuite15) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *MarathonSuite15) TestConfigurationUpdate() {
|
||||
s.T().Skip("doesn't work")
|
||||
|
||||
// Start Traefik.
|
||||
file := s.adaptFile(c, "fixtures/marathon/simple.toml", struct {
|
||||
file := s.adaptFile("fixtures/marathon/simple.toml", struct {
|
||||
MarathonURL string
|
||||
}{s.marathonURL})
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Wait for Traefik to turn ready.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Prepare Marathon client.
|
||||
config := marathon.NewDefaultConfig()
|
||||
config.URL = s.marathonURL
|
||||
client, err := marathon.NewClient(config)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Create test application to be deployed.
|
||||
app := marathon.NewDockerApplication().
|
||||
|
@ -68,11 +72,11 @@ func (s *MarathonSuite15) TestConfigurationUpdate(c *check.C) {
|
|||
*app.Networks = append(*app.Networks, *marathon.NewBridgePodNetwork())
|
||||
|
||||
// Deploy the test application.
|
||||
deployApplication(c, client, app)
|
||||
s.deployApplication(client, app)
|
||||
|
||||
// Query application via Traefik.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/service", 30*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Create test application with services to be deployed.
|
||||
app = marathon.NewDockerApplication().
|
||||
|
@ -88,9 +92,9 @@ func (s *MarathonSuite15) TestConfigurationUpdate(c *check.C) {
|
|||
*app.Networks = append(*app.Networks, *marathon.NewBridgePodNetwork())
|
||||
|
||||
// Deploy the test application.
|
||||
deployApplication(c, client, app)
|
||||
s.deployApplication(client, app)
|
||||
|
||||
// Query application via Traefik.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/app", 30*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@ package integration
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gambol99/go-marathon"
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
const containerNameMarathon = "marathon"
|
||||
|
@ -19,50 +19,55 @@ type MarathonSuite struct {
|
|||
marathonURL string
|
||||
}
|
||||
|
||||
func (s *MarathonSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "marathon")
|
||||
s.composeUp(c)
|
||||
func TestMarathonSuite(t *testing.T) {
|
||||
suite.Run(t, new(MarathonSuite))
|
||||
}
|
||||
|
||||
s.marathonURL = "http://" + s.getComposeServiceIP(c, containerNameMarathon) + ":8080"
|
||||
func (s *MarathonSuite) SetUpSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
s.createComposeProject("marathon")
|
||||
s.composeUp()
|
||||
|
||||
s.marathonURL = "http://" + s.getComposeServiceIP(containerNameMarathon) + ":8080"
|
||||
|
||||
// Wait for Marathon readiness prior to creating the client so that we
|
||||
// don't run into the "all cluster members down" state right from the
|
||||
// start.
|
||||
err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func deployApplication(c *check.C, client marathon.Marathon, application *marathon.Application) {
|
||||
func (s *MarathonSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *BaseSuite) deployApplication(client marathon.Marathon, application *marathon.Application) {
|
||||
deploy, err := client.UpdateApplication(application, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
// Wait for deployment to complete.
|
||||
c.Assert(client.WaitOnDeployment(deploy.DeploymentID, 1*time.Minute), checker.IsNil)
|
||||
err = client.WaitOnDeployment(deploy.DeploymentID, 1*time.Minute)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *MarathonSuite) TestConfigurationUpdate(c *check.C) {
|
||||
c.Skip("doesn't work")
|
||||
func (s *MarathonSuite) TestConfigurationUpdate() {
|
||||
s.T().Skip("doesn't work")
|
||||
|
||||
// Start Traefik.
|
||||
file := s.adaptFile(c, "fixtures/marathon/simple.toml", struct {
|
||||
file := s.adaptFile("fixtures/marathon/simple.toml", struct {
|
||||
MarathonURL string
|
||||
}{s.marathonURL})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Wait for Traefik to turn ready.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Prepare Marathon client.
|
||||
config := marathon.NewDefaultConfig()
|
||||
config.URL = s.marathonURL
|
||||
client, err := marathon.NewClient(config)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Create test application to be deployed.
|
||||
app := marathon.NewDockerApplication().
|
||||
|
@ -75,11 +80,11 @@ func (s *MarathonSuite) TestConfigurationUpdate(c *check.C) {
|
|||
Container("traefik/whoami")
|
||||
|
||||
// Deploy the test application.
|
||||
deployApplication(c, client, app)
|
||||
s.deployApplication(client, app)
|
||||
|
||||
// Query application via Traefik.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/service", 30*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Create test application with services to be deployed.
|
||||
app = marathon.NewDockerApplication().
|
||||
|
@ -92,9 +97,9 @@ func (s *MarathonSuite) TestConfigurationUpdate(c *check.C) {
|
|||
Container("traefik/whoami")
|
||||
|
||||
// Deploy the test application.
|
||||
deployApplication(c, client, app)
|
||||
s.deployApplication(client, app)
|
||||
|
||||
// Query application via Traefik.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/app", 30*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -1,103 +1,138 @@
|
|||
package integration
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"bufio"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/pires/go-proxyproto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type ProxyProtocolSuite struct {
|
||||
BaseSuite
|
||||
gatewayIP string
|
||||
haproxyIP string
|
||||
whoamiIP string
|
||||
whoamiIP string
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "proxy-protocol")
|
||||
s.composeUp(c)
|
||||
|
||||
s.gatewayIP = s.getContainerIP(c, "traefik")
|
||||
s.haproxyIP = s.getComposeServiceIP(c, "haproxy")
|
||||
s.whoamiIP = s.getComposeServiceIP(c, "whoami")
|
||||
func TestProxyProtocolSuite(t *testing.T) {
|
||||
suite.Run(t, new(ProxyProtocolSuite))
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolTrusted(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/proxy-protocol/with.toml", struct {
|
||||
func (s *ProxyProtocolSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("proxy-protocol")
|
||||
s.composeUp()
|
||||
|
||||
s.whoamiIP = s.getComposeServiceIP("whoami")
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolTrusted() {
|
||||
file := s.adaptFile("fixtures/proxy-protocol/proxy-protocol.toml", struct {
|
||||
HaproxyIP string
|
||||
WhoamiIP string
|
||||
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
}{WhoamiIP: s.whoamiIP})
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://"+s.haproxyIP+"/whoami", 1*time.Second,
|
||||
try.StatusCodeIs(http.StatusOK),
|
||||
try.BodyContains("X-Forwarded-For: "+s.gatewayIP))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/whoami", 10*time.Second)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
content, err := proxyProtoRequest("127.0.0.1:8000", 1)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), content, "X-Forwarded-For: 1.2.3.4")
|
||||
|
||||
content, err = proxyProtoRequest("127.0.0.1:8000", 2)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), content, "X-Forwarded-For: 1.2.3.4")
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolV2Trusted(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/proxy-protocol/with.toml", struct {
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolNotTrusted() {
|
||||
file := s.adaptFile("fixtures/proxy-protocol/proxy-protocol.toml", struct {
|
||||
HaproxyIP string
|
||||
WhoamiIP string
|
||||
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
}{WhoamiIP: s.whoamiIP})
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://"+s.haproxyIP+":81/whoami", 1*time.Second,
|
||||
try.StatusCodeIs(http.StatusOK),
|
||||
try.BodyContains("X-Forwarded-For: "+s.gatewayIP))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:9000/whoami", 10*time.Second)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
content, err := proxyProtoRequest("127.0.0.1:9000", 1)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), content, "X-Forwarded-For: 127.0.0.1")
|
||||
|
||||
content, err = proxyProtoRequest("127.0.0.1:9000", 2)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), content, "X-Forwarded-For: 127.0.0.1")
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolNotTrusted(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/proxy-protocol/without.toml", struct {
|
||||
HaproxyIP string
|
||||
WhoamiIP string
|
||||
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
func proxyProtoRequest(address string, version byte) (string, error) {
|
||||
// Open a TCP connection to the server
|
||||
conn, err := net.Dial("tcp", address)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
// Create a Proxy Protocol header with v1
|
||||
proxyHeader := &proxyproto.Header{
|
||||
Version: version,
|
||||
Command: proxyproto.PROXY,
|
||||
TransportProtocol: proxyproto.TCPv4,
|
||||
DestinationAddr: &net.TCPAddr{
|
||||
IP: net.ParseIP("127.0.0.1"),
|
||||
Port: 8000,
|
||||
},
|
||||
SourceAddr: &net.TCPAddr{
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
Port: 62541,
|
||||
},
|
||||
}
|
||||
|
||||
err = try.GetRequest("http://"+s.haproxyIP+"/whoami", 1*time.Second,
|
||||
try.StatusCodeIs(http.StatusOK),
|
||||
try.BodyContains("X-Forwarded-For: "+s.haproxyIP))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolV2NotTrusted(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/proxy-protocol/without.toml", struct {
|
||||
HaproxyIP string
|
||||
WhoamiIP string
|
||||
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://"+s.haproxyIP+":81/whoami", 1*time.Second,
|
||||
try.StatusCodeIs(http.StatusOK),
|
||||
try.BodyContains("X-Forwarded-For: "+s.haproxyIP))
|
||||
c.Assert(err, checker.IsNil)
|
||||
// After the connection was created write the proxy headers first
|
||||
_, err = proxyHeader.WriteTo(conn)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Create an HTTP request
|
||||
request := "GET /whoami HTTP/1.1\r\n" +
|
||||
"Host: 127.0.0.1\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n"
|
||||
|
||||
// Write the HTTP request to the TCP connection
|
||||
writer := bufio.NewWriter(conn)
|
||||
_, err = writer.WriteString(request)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Flush the buffer to ensure the request is sent
|
||||
err = writer.Flush()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Read the response from the server
|
||||
var content string
|
||||
scanner := bufio.NewScanner(conn)
|
||||
for scanner.Scan() {
|
||||
content += scanner.Text() + "\n"
|
||||
}
|
||||
|
||||
if scanner.Err() != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return content, nil
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@ package integration
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type RateLimitSuite struct {
|
||||
|
@ -15,33 +15,38 @@ type RateLimitSuite struct {
|
|||
ServerIP string
|
||||
}
|
||||
|
||||
func (s *RateLimitSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "ratelimit")
|
||||
s.composeUp(c)
|
||||
|
||||
s.ServerIP = s.getComposeServiceIP(c, "whoami1")
|
||||
func TestRateLimitSuite(t *testing.T) {
|
||||
suite.Run(t, new(RateLimitSuite))
|
||||
}
|
||||
|
||||
func (s *RateLimitSuite) TestSimpleConfiguration(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/ratelimit/simple.toml", struct {
|
||||
func (s *RateLimitSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("ratelimit")
|
||||
s.composeUp()
|
||||
|
||||
s.ServerIP = s.getComposeServiceIP("whoami1")
|
||||
}
|
||||
|
||||
func (s *RateLimitSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *RateLimitSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/ratelimit/simple.toml", struct {
|
||||
Server1 string
|
||||
}{s.ServerIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("ratelimit"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("ratelimit"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
start := time.Now()
|
||||
count := 0
|
||||
for {
|
||||
err = try.GetRequest("http://127.0.0.1:8081/", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
count++
|
||||
if count > 100 {
|
||||
break
|
||||
|
@ -50,6 +55,6 @@ func (s *RateLimitSuite) TestSimpleConfiguration(c *check.C) {
|
|||
stop := time.Now()
|
||||
elapsed := stop.Sub(start)
|
||||
if elapsed < time.Second*99/100 {
|
||||
c.Fatalf("requests throughput was too fast wrt to rate limiting: 100 requests in %v", elapsed)
|
||||
s.T().Fatalf("requests throughput was too fast wrt to rate limiting: 100 requests in %v", elapsed)
|
||||
}
|
||||
}
|
||||
|
|
201
integration/redis_sentinel_test.go
Normal file
201
integration/redis_sentinel_test.go
Normal file
|
@ -0,0 +1,201 @@
|
|||
package integration
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/structs"
|
||||
"github.com/kvtools/redis"
|
||||
"github.com/kvtools/valkeyrie"
|
||||
"github.com/kvtools/valkeyrie/store"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/api"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
)
|
||||
|
||||
// Redis test suites.
|
||||
type RedisSentinelSuite struct {
|
||||
BaseSuite
|
||||
kvClient store.Store
|
||||
redisEndpoints []string
|
||||
}
|
||||
|
||||
func TestRedisSentinelSuite(t *testing.T) {
|
||||
suite.Run(t, new(RedisSentinelSuite))
|
||||
}
|
||||
|
||||
func (s *RedisSentinelSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.setupSentinelConfiguration([]string{"26379", "26379", "26379"})
|
||||
|
||||
s.createComposeProject("redis_sentinel")
|
||||
s.composeUp()
|
||||
|
||||
s.redisEndpoints = []string{
|
||||
net.JoinHostPort(s.getComposeServiceIP("sentinel1"), "26379"),
|
||||
net.JoinHostPort(s.getComposeServiceIP("sentinel2"), "26379"),
|
||||
net.JoinHostPort(s.getComposeServiceIP("sentinel3"), "26379"),
|
||||
}
|
||||
kv, err := valkeyrie.NewStore(
|
||||
context.Background(),
|
||||
redis.StoreName,
|
||||
s.redisEndpoints,
|
||||
&redis.Config{
|
||||
Sentinel: &redis.Sentinel{
|
||||
MasterName: "mymaster",
|
||||
},
|
||||
},
|
||||
)
|
||||
require.NoError(s.T(), err, "Cannot create store redis")
|
||||
s.kvClient = kv
|
||||
|
||||
// wait for redis
|
||||
err = try.Do(60*time.Second, try.KVExists(kv, "test"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *RedisSentinelSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
|
||||
for _, filename := range []string{"sentinel1.conf", "sentinel2.conf", "sentinel3.conf"} {
|
||||
_ = os.Remove(filepath.Join(".", "resources", "compose", "config", filename))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RedisSentinelSuite) setupSentinelConfiguration(ports []string) {
|
||||
for i, port := range ports {
|
||||
templateValue := struct{ SentinelPort string }{SentinelPort: port}
|
||||
|
||||
// Load file
|
||||
templateFile := "resources/compose/config/sentinel_template.conf"
|
||||
tmpl, err := template.ParseFiles(templateFile)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
folder, prefix := filepath.Split(templateFile)
|
||||
|
||||
fileName := fmt.Sprintf("%s/sentinel%d.conf", folder, i+1)
|
||||
tmpFile, err := os.Create(fileName)
|
||||
require.NoError(s.T(), err)
|
||||
defer tmpFile.Close()
|
||||
|
||||
model := structs.Map(templateValue)
|
||||
model["SelfFilename"] = tmpFile.Name()
|
||||
|
||||
err = tmpl.ExecuteTemplate(tmpFile, prefix, model)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = tmpFile.Sync()
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RedisSentinelSuite) TestSentinelConfiguration() {
|
||||
file := s.adaptFile("fixtures/redis/sentinel.toml", struct{ RedisAddress string }{
|
||||
RedisAddress: strings.Join(s.redisEndpoints, `","`),
|
||||
})
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router0/middlewares/0": "compressor",
|
||||
"traefik/http/routers/Router0/middlewares/1": "striper",
|
||||
"traefik/http/routers/Router0/service": "simplesvc",
|
||||
"traefik/http/routers/Router0/rule": "Host(`kv1.localhost`)",
|
||||
"traefik/http/routers/Router0/priority": "42",
|
||||
"traefik/http/routers/Router0/tls": "true",
|
||||
|
||||
"traefik/http/routers/Router1/rule": "Host(`kv2.localhost`)",
|
||||
"traefik/http/routers/Router1/priority": "42",
|
||||
"traefik/http/routers/Router1/tls/domains/0/main": "aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/0": "aaa.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/1": "bbb.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/main": "bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/0": "aaa.bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/1": "bbb.bbb.localhost",
|
||||
"traefik/http/routers/Router1/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router1/service": "simplesvc",
|
||||
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/0/url": "http://10.0.1.1:8888",
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/1/url": "http://10.0.1.1:8889",
|
||||
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/0/url": "http://10.0.1.2:8888",
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/1/url": "http://10.0.1.2:8889",
|
||||
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/0/url": "http://10.0.1.3:8888",
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/1/url": "http://10.0.1.3:8889",
|
||||
|
||||
"traefik/http/services/mirror/mirroring/service": "simplesvc",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/name": "srvcA",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/percent": "42",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/name": "srvcB",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/percent": "42",
|
||||
|
||||
"traefik/http/services/Service03/weighted/services/0/name": "srvcA",
|
||||
"traefik/http/services/Service03/weighted/services/0/weight": "42",
|
||||
"traefik/http/services/Service03/weighted/services/1/name": "srvcB",
|
||||
"traefik/http/services/Service03/weighted/services/1/weight": "42",
|
||||
|
||||
"traefik/http/middlewares/compressor/compress": "true",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/0": "foo",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/1": "bar",
|
||||
}
|
||||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(context.Background(), k, []byte(v), nil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
try.BodyContains(`"striper@redis":`, `"compressor@redis":`, `"srvcA@redis":`, `"srvcB@redis":`),
|
||||
)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
require.NoError(s.T(), err)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-redis.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = os.WriteFile(expectedJSON, got, 0o666)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
expected, err := os.ReadFile(expectedJSON)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
FromFile: "Expected",
|
||||
A: difflib.SplitLines(string(expected)),
|
||||
ToFile: "Got",
|
||||
B: difflib.SplitLines(string(got)),
|
||||
Context: 3,
|
||||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
require.NoError(s.T(), err)
|
||||
log.WithoutContext().Info(text)
|
||||
}
|
||||
}
|
|
@ -4,26 +4,22 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/structs"
|
||||
"github.com/go-check/check"
|
||||
"github.com/kvtools/redis"
|
||||
"github.com/kvtools/valkeyrie"
|
||||
"github.com/kvtools/valkeyrie/store"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/api"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Redis test suites.
|
||||
|
@ -33,23 +29,18 @@ type RedisSuite struct {
|
|||
redisEndpoints []string
|
||||
}
|
||||
|
||||
func (s *RedisSuite) TearDownSuite(c *check.C) {
|
||||
s.composeDown(c)
|
||||
|
||||
for _, filename := range []string{"sentinel1.conf", "sentinel2.conf", "sentinel3.conf"} {
|
||||
err := os.Remove(filepath.Join(".", "resources", "compose", "config", filename))
|
||||
if err != nil && !errors.Is(err, fs.ErrNotExist) {
|
||||
c.Fatal("unable to clean configuration file for sentinel: ", err)
|
||||
}
|
||||
}
|
||||
func TestRedisSuite(t *testing.T) {
|
||||
suite.Run(t, new(RedisSuite))
|
||||
}
|
||||
|
||||
func (s *RedisSuite) setupStore(c *check.C) {
|
||||
s.createComposeProject(c, "redis")
|
||||
s.composeUp(c)
|
||||
func (s *RedisSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("redis")
|
||||
s.composeUp()
|
||||
|
||||
s.redisEndpoints = []string{}
|
||||
s.redisEndpoints = append(s.redisEndpoints, net.JoinHostPort(s.getComposeServiceIP(c, "redis"), "6379"))
|
||||
s.redisEndpoints = append(s.redisEndpoints, net.JoinHostPort(s.getComposeServiceIP("redis"), "6379"))
|
||||
|
||||
kv, err := valkeyrie.NewStore(
|
||||
context.Background(),
|
||||
|
@ -57,23 +48,23 @@ func (s *RedisSuite) setupStore(c *check.C) {
|
|||
s.redisEndpoints,
|
||||
&redis.Config{},
|
||||
)
|
||||
if err != nil {
|
||||
c.Fatal("Cannot create store redis: ", err)
|
||||
}
|
||||
require.NoError(s.T(), err, "Cannot create store redis")
|
||||
|
||||
s.kvClient = kv
|
||||
|
||||
// wait for redis
|
||||
err = try.Do(60*time.Second, try.KVExists(kv, "test"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *RedisSuite) TestSimpleConfiguration(c *check.C) {
|
||||
s.setupStore(c)
|
||||
func (s *RedisSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/redis/simple.toml", struct{ RedisAddress string }{
|
||||
func (s *RedisSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/redis/simple.toml", struct{ RedisAddress string }{
|
||||
RedisAddress: strings.Join(s.redisEndpoints, ","),
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
|
@ -123,39 +114,35 @@ func (s *RedisSuite) TestSimpleConfiguration(c *check.C) {
|
|||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(context.Background(), k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
try.BodyContains(`"striper@redis":`, `"compressor@redis":`, `"srvcA@redis":`, `"srvcB@redis":`),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-redis.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = os.WriteFile(expectedJSON, got, 0o666)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
expected, err := os.ReadFile(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
|
@ -167,171 +154,6 @@ func (s *RedisSuite) TestSimpleConfiguration(c *check.C) {
|
|||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Error(text)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RedisSuite) setupSentinelStore(c *check.C) {
|
||||
s.setupSentinelConfiguration(c, []string{"26379", "36379", "46379"})
|
||||
|
||||
s.createComposeProject(c, "redis_sentinel")
|
||||
s.composeUp(c)
|
||||
|
||||
s.redisEndpoints = []string{
|
||||
net.JoinHostPort(s.getComposeServiceIP(c, "sentinel1"), "26379"),
|
||||
net.JoinHostPort(s.getComposeServiceIP(c, "sentinel2"), "36379"),
|
||||
net.JoinHostPort(s.getComposeServiceIP(c, "sentinel3"), "46379"),
|
||||
}
|
||||
|
||||
kv, err := valkeyrie.NewStore(
|
||||
context.Background(),
|
||||
redis.StoreName,
|
||||
s.redisEndpoints,
|
||||
&redis.Config{
|
||||
Sentinel: &redis.Sentinel{
|
||||
MasterName: "mymaster",
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
c.Fatal("Cannot create store redis sentinel")
|
||||
}
|
||||
s.kvClient = kv
|
||||
|
||||
// wait for redis
|
||||
err = try.Do(60*time.Second, try.KVExists(kv, "test"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *RedisSuite) setupSentinelConfiguration(c *check.C, ports []string) {
|
||||
for i, port := range ports {
|
||||
templateValue := struct{ SentinelPort string }{SentinelPort: port}
|
||||
|
||||
// Load file
|
||||
templateFile := "resources/compose/config/sentinel_template.conf"
|
||||
tmpl, err := template.ParseFiles(templateFile)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
folder, prefix := filepath.Split(templateFile)
|
||||
|
||||
fileName := fmt.Sprintf("%s/sentinel%d.conf", folder, i+1)
|
||||
tmpFile, err := os.Create(fileName)
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer tmpFile.Close()
|
||||
|
||||
model := structs.Map(templateValue)
|
||||
model["SelfFilename"] = tmpFile.Name()
|
||||
|
||||
err = tmpl.ExecuteTemplate(tmpFile, prefix, model)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = tmpFile.Sync()
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RedisSuite) TestSentinelConfiguration(c *check.C) {
|
||||
s.setupSentinelStore(c)
|
||||
|
||||
file := s.adaptFile(c, "fixtures/redis/sentinel.toml", struct{ RedisAddress string }{
|
||||
RedisAddress: strings.Join(s.redisEndpoints, `","`),
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router0/middlewares/0": "compressor",
|
||||
"traefik/http/routers/Router0/middlewares/1": "striper",
|
||||
"traefik/http/routers/Router0/service": "simplesvc",
|
||||
"traefik/http/routers/Router0/rule": "Host(`kv1.localhost`)",
|
||||
"traefik/http/routers/Router0/priority": "42",
|
||||
"traefik/http/routers/Router0/tls": "true",
|
||||
|
||||
"traefik/http/routers/Router1/rule": "Host(`kv2.localhost`)",
|
||||
"traefik/http/routers/Router1/priority": "42",
|
||||
"traefik/http/routers/Router1/tls/domains/0/main": "aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/0": "aaa.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/1": "bbb.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/main": "bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/0": "aaa.bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/1": "bbb.bbb.localhost",
|
||||
"traefik/http/routers/Router1/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router1/service": "simplesvc",
|
||||
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/0/url": "http://10.0.1.1:8888",
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/1/url": "http://10.0.1.1:8889",
|
||||
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/0/url": "http://10.0.1.2:8888",
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/1/url": "http://10.0.1.2:8889",
|
||||
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/0/url": "http://10.0.1.3:8888",
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/1/url": "http://10.0.1.3:8889",
|
||||
|
||||
"traefik/http/services/mirror/mirroring/service": "simplesvc",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/name": "srvcA",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/percent": "42",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/name": "srvcB",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/percent": "42",
|
||||
|
||||
"traefik/http/services/Service03/weighted/services/0/name": "srvcA",
|
||||
"traefik/http/services/Service03/weighted/services/0/weight": "42",
|
||||
"traefik/http/services/Service03/weighted/services/1/name": "srvcB",
|
||||
"traefik/http/services/Service03/weighted/services/1/weight": "42",
|
||||
|
||||
"traefik/http/middlewares/compressor/compress": "true",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/0": "foo",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/1": "bar",
|
||||
"traefik/http/middlewares/striper/stripPrefix/forceSlash": "true",
|
||||
}
|
||||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(context.Background(), k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
try.BodyContains(`"striper@redis":`, `"compressor@redis":`, `"srvcA@redis":`, `"srvcB@redis":`),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
c.Assert(err, checker.IsNil)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-redis.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = os.WriteFile(expectedJSON, got, 0o666)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
expected, err := os.ReadFile(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
FromFile: "Expected",
|
||||
A: difflib.SplitLines(string(expected)),
|
||||
ToFile: "Got",
|
||||
B: difflib.SplitLines(string(got)),
|
||||
Context: 3,
|
||||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Error(text)
|
||||
require.NoError(s.T(), err, text)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ services:
|
|||
traefik.http.routers.rt-authFrontend.entryPoints: httpFrontendAuth
|
||||
traefik.http.routers.rt-authFrontend.rule: Host(`frontend.auth.docker.local`)
|
||||
traefik.http.routers.rt-authFrontend.middlewares: basicauth
|
||||
traefik.http.middlewares.basicauth.basicauth.users: test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/
|
||||
traefik.http.middlewares.basicauth.basicauth.users: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"
|
||||
traefik.http.services.service3.loadbalancer.server.port: 80
|
||||
|
||||
digestAuthMiddleware:
|
||||
|
@ -94,8 +94,3 @@ services:
|
|||
traefik.http.routers.rt-preflightCORS.middlewares: preflightCORS
|
||||
traefik.http.middlewares.preflightCORS.headers.accessControlAllowMethods: OPTIONS, GET
|
||||
traefik.http.services.preflightCORS.loadbalancer.server.port: 80
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -34,8 +34,3 @@ services:
|
|||
traefik.http.routers.rt4.middlewares: wl4
|
||||
traefik.http.middlewares.wl4.ipallowlist.sourceRange: 8.8.8.8
|
||||
traefik.http.middlewares.wl4.ipallowlist.ipStrategy.excludedIPs: 10.0.0.1,10.0.0.2
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -11,8 +11,3 @@ services:
|
|||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: false
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -4,8 +4,3 @@ services:
|
|||
image: consul:1.6
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,11 +2,24 @@ version: "3.8"
|
|||
services:
|
||||
consul:
|
||||
image: consul:1.6.2
|
||||
command: agent -server -bootstrap -ui -client 0.0.0.0 -hcl 'connect { enabled = true }'
|
||||
command:
|
||||
- agent
|
||||
- -server
|
||||
- -bootstrap
|
||||
- -ui
|
||||
- -client
|
||||
- 0.0.0.0
|
||||
- -hcl
|
||||
- 'connect { enabled = true }'
|
||||
|
||||
consul-agent:
|
||||
image: consul:1.6.2
|
||||
command: agent -retry-join consul -client 0.0.0.0
|
||||
command:
|
||||
- agent
|
||||
- -retry-join
|
||||
- consul
|
||||
- -client
|
||||
- 0.0.0.0
|
||||
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
|
@ -30,8 +43,3 @@ services:
|
|||
PORT: 443
|
||||
BIND: 0.0.0.0
|
||||
CONSUL_HTTP_ADDR: http://consul:8500
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -36,8 +36,3 @@ services:
|
|||
labels:
|
||||
traefik.http.Routers.Super.Rule: Host(`my.super.host`)
|
||||
traefik.http.Services.powpow.LoadBalancer.server.Port: 2375
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
version: "3.8"
|
||||
services:
|
||||
nginx1:
|
||||
image: nginx:1.13.8-alpine
|
||||
image: nginx:1.25.3-alpine3.18
|
||||
|
||||
nginx2:
|
||||
image: nginx:1.13.8-alpine
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
image: nginx:1.25.3-alpine3.18
|
||||
|
|
|
@ -2,9 +2,9 @@ version: "3.8"
|
|||
services:
|
||||
etcd:
|
||||
image: quay.io/coreos/etcd:v3.3.18
|
||||
command: etcd --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://0.0.0.0:2380
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
command:
|
||||
- etcd
|
||||
- --listen-client-urls
|
||||
- http://0.0.0.0:2379
|
||||
- --advertise-client-urls
|
||||
- http://0.0.0.0:2380
|
||||
|
|
|
@ -14,8 +14,3 @@ services:
|
|||
|
||||
whoami5:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -11,8 +11,3 @@ services:
|
|||
|
||||
whoami4:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -6,8 +6,3 @@ services:
|
|||
traefik.enable: true
|
||||
traefik.http.services.service1.loadbalancer.server.port: 80
|
||||
traefik.http.routers.router1.rule: Host(`github.com`)
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,9 +2,23 @@ version: "3.8"
|
|||
services:
|
||||
server:
|
||||
image: rancher/k3s:v1.20.15-k3s1
|
||||
command: server --disable-agent --no-deploy coredns --no-deploy servicelb --no-deploy traefik --no-deploy local-storage --no-deploy metrics-server --log /output/k3s.log --bind-address=server --tls-san=server
|
||||
privileged: true
|
||||
command:
|
||||
- server
|
||||
- --disable-agent
|
||||
- --disable=coredns
|
||||
- --disable=servicelb
|
||||
- --disable=traefik
|
||||
- --disable=local-storage
|
||||
- --disable=metrics-server
|
||||
- --log=/output/k3s.log
|
||||
- --bind-address=server
|
||||
- --tls-san=server
|
||||
- --tls-san=172.31.42.3
|
||||
- --tls-san=172.31.42.4
|
||||
environment:
|
||||
K3S_CLUSTER_SECRET: somethingtotallyrandom
|
||||
K3S_TOKEN: somethingtotallyrandom
|
||||
K3S_KUBECONFIG_OUTPUT: /output/kubeconfig.yaml
|
||||
K3S_KUBECONFIG_MODE: 666
|
||||
volumes:
|
||||
|
@ -15,10 +29,6 @@ services:
|
|||
image: rancher/k3s:v1.20.15-k3s1
|
||||
privileged: true
|
||||
environment:
|
||||
K3S_TOKEN: somethingtotallyrandom
|
||||
K3S_URL: https://server:6443
|
||||
K3S_CLUSTER_SECRET: somethingtotallyrandom
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -3,12 +3,9 @@ services:
|
|||
whoami1:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.http.Routers.RouterMini.Rule: PathPrefix(`/whoami`)
|
||||
traefik.http.routers.router-mini.Rule: PathPrefix(`/whoami`)
|
||||
traefik.http.routers.router-mini.service: service-mini
|
||||
traefik.http.services.service-mini.loadbalancer.server.port: 80
|
||||
traefik.enable: true
|
||||
deploy:
|
||||
replicas: 2
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,14 +2,12 @@ version: "3.8"
|
|||
services:
|
||||
pebble:
|
||||
image: letsencrypt/pebble:v2.3.1
|
||||
command: pebble --dnsserver traefik:5053
|
||||
command:
|
||||
- pebble
|
||||
- --dnsserver
|
||||
- host.docker.internal:5053
|
||||
environment:
|
||||
# https://github.com/letsencrypt/pebble#testing-at-full-speed
|
||||
PEBBLE_VA_NOSLEEP: 1
|
||||
# https://github.com/letsencrypt/pebble#invalid-anti-replay-nonce-errors
|
||||
PEBBLE_WFE_NONCEREJECT: 0
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -1,14 +1,4 @@
|
|||
version: "3.8"
|
||||
services:
|
||||
haproxy:
|
||||
image: haproxy:2.2
|
||||
volumes:
|
||||
- ./resources/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
|
||||
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,8 +2,3 @@ version: "3.8"
|
|||
services:
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,8 +2,3 @@ version: "3.8"
|
|||
services:
|
||||
redis:
|
||||
image: redis:5.0
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -3,59 +3,51 @@ services:
|
|||
master:
|
||||
image: redis
|
||||
container_name: redis-master
|
||||
command: redis-server --port 6380
|
||||
ports:
|
||||
- 6380:6380
|
||||
healthcheck:
|
||||
test: redis-cli -p 6380 ping
|
||||
command:
|
||||
- redis-server
|
||||
- --port
|
||||
- 6380
|
||||
node1:
|
||||
image: redis
|
||||
container_name: redis-node-1
|
||||
ports:
|
||||
- 6381:6381
|
||||
command: redis-server --port 6381 --slaveof redis-master 6380
|
||||
healthcheck:
|
||||
test: redis-cli -p 6381 ping
|
||||
command:
|
||||
- redis-server
|
||||
- --port
|
||||
- 6381
|
||||
- --slaveof
|
||||
- redis-master
|
||||
- 6380
|
||||
node2:
|
||||
image: redis
|
||||
container_name: redis-node-2
|
||||
ports:
|
||||
- 6382:6382
|
||||
command: redis-server --port 6382 --slaveof redis-master 6380
|
||||
healthcheck:
|
||||
test: redis-cli -p 6382 ping
|
||||
command:
|
||||
- redis-server
|
||||
- --port
|
||||
- 6382
|
||||
- --slaveof
|
||||
- redis-master
|
||||
- 6380
|
||||
sentinel1:
|
||||
image: redis
|
||||
container_name: redis-sentinel-1
|
||||
ports:
|
||||
- 26379:26379
|
||||
command: redis-sentinel /usr/local/etc/redis/conf/sentinel1.conf
|
||||
healthcheck:
|
||||
test: redis-cli -p 26379 ping
|
||||
command:
|
||||
- redis-sentinel
|
||||
- /usr/local/etc/redis/conf/sentinel1.conf
|
||||
volumes:
|
||||
- ./resources/compose/config:/usr/local/etc/redis/conf
|
||||
sentinel2:
|
||||
image: redis
|
||||
container_name: redis-sentinel-2
|
||||
ports:
|
||||
- 36379:26379
|
||||
command: redis-sentinel /usr/local/etc/redis/conf/sentinel2.conf
|
||||
healthcheck:
|
||||
test: redis-cli -p 36379 ping
|
||||
command:
|
||||
- redis-sentinel
|
||||
- /usr/local/etc/redis/conf/sentinel2.conf
|
||||
volumes:
|
||||
- ./resources/compose/config:/usr/local/etc/redis/conf
|
||||
sentinel3:
|
||||
image: redis
|
||||
container_name: redis-sentinel-3
|
||||
ports:
|
||||
- 46379:26379
|
||||
command: redis-sentinel /usr/local/etc/redis/conf/sentinel3.conf
|
||||
healthcheck:
|
||||
test: redis-cli -p 46379 ping
|
||||
command:
|
||||
- redis-sentinel
|
||||
- /usr/local/etc/redis/conf/sentinel3.conf
|
||||
volumes:
|
||||
- ./resources/compose/config:/usr/local/etc/redis/conf
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,8 +2,3 @@ version: "3.8"
|
|||
services:
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,8 +2,3 @@ version: "3.8"
|
|||
services:
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,8 +2,3 @@ version: "3.8"
|
|||
services:
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -5,8 +5,3 @@ services:
|
|||
|
||||
whoami2:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -9,9 +9,5 @@ services:
|
|||
cap_add: # Required for tailscale to work
|
||||
- net_admin
|
||||
- sys_module
|
||||
command: tailscaled
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
command:
|
||||
- tailscaled
|
||||
|
|
|
@ -2,38 +2,58 @@ version: "3.8"
|
|||
services:
|
||||
whoami-a:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-a -certFile /certs/whoami-a.crt -keyFile /certs/whoami-a.key
|
||||
command:
|
||||
- -name
|
||||
- whoami-a
|
||||
- -certFile
|
||||
- /certs/whoami-a.crt
|
||||
- -keyFile
|
||||
- /certs/whoami-a.key
|
||||
volumes:
|
||||
- ./fixtures/tcp:/certs
|
||||
|
||||
whoami-b:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-b -certFile /certs/whoami-b.crt -keyFile /certs/whoami-b.key
|
||||
command:
|
||||
- -name
|
||||
- whoami-b
|
||||
- -certFile
|
||||
- /certs/whoami-b.crt
|
||||
- -keyFile
|
||||
- /certs/whoami-b.key
|
||||
volumes:
|
||||
- ./fixtures/tcp:/certs
|
||||
|
||||
whoami-ab:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-ab -certFile /certs/whoami-b.crt -keyFile /certs/whoami-b.key
|
||||
command:
|
||||
- -name
|
||||
- whoami-ab
|
||||
- -certFile
|
||||
- /certs/whoami-b.crt
|
||||
- -keyFile
|
||||
- /certs/whoami-b.key
|
||||
volumes:
|
||||
- ./fixtures/tcp:/certs
|
||||
|
||||
whoami-no-cert:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-no-cert
|
||||
command:
|
||||
- -name
|
||||
- whoami-no-cert
|
||||
|
||||
whoami-no-tls:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-no-tls
|
||||
command:
|
||||
- -name
|
||||
- whoami-no-tls
|
||||
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
whoami-banner:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-banner --banner
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
command:
|
||||
- -name
|
||||
- whoami-banner
|
||||
- --banner
|
||||
|
|
|
@ -5,8 +5,3 @@ services:
|
|||
environment:
|
||||
PROTO: http
|
||||
PORT: 9000
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -7,8 +7,3 @@ services:
|
|||
traefik.http.routers.route1.middlewares: passtls
|
||||
traefik.http.routers.route1.tls: true
|
||||
traefik.http.middlewares.passtls.passtlsclientcert.pem: true
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -13,8 +13,3 @@ services:
|
|||
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,20 +2,21 @@ version: "3.8"
|
|||
services:
|
||||
whoami-a:
|
||||
image: traefik/whoamiudp:latest
|
||||
command: -name whoami-a
|
||||
command:
|
||||
- -name
|
||||
- whoami-a
|
||||
|
||||
whoami-b:
|
||||
image: traefik/whoamiudp:latest
|
||||
command: -name whoami-b
|
||||
command:
|
||||
- -name
|
||||
- whoami-b
|
||||
|
||||
whoami-c:
|
||||
image: traefik/whoamiudp:latest
|
||||
command: -name whoami-c
|
||||
command:
|
||||
- -name
|
||||
- whoami-c
|
||||
|
||||
whoami-d:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,8 +2,3 @@ version: "3.8"
|
|||
services:
|
||||
zookeeper:
|
||||
image: zookeeper:3.5
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
global
|
||||
maxconn 4096
|
||||
|
||||
defaults
|
||||
log global
|
||||
mode http
|
||||
retries 3
|
||||
option redispatch
|
||||
maxconn 2000
|
||||
timeout connect 5000
|
||||
timeout client 50000
|
||||
timeout server 50000
|
||||
|
||||
frontend TestServerTest
|
||||
bind 0.0.0.0:80
|
||||
mode tcp
|
||||
default_backend TestServerNodes
|
||||
|
||||
frontend TestServerTestV2
|
||||
bind 0.0.0.0:81
|
||||
mode tcp
|
||||
default_backend TestServerNodesV2
|
||||
|
||||
backend TestServerNodes
|
||||
mode tcp
|
||||
server TestServer01 traefik:8000 send-proxy
|
||||
|
||||
backend TestServerNodesV2
|
||||
mode tcp
|
||||
server TestServer01 traefik:8000 send-proxy-v2
|
|
@ -5,14 +5,15 @@ import (
|
|||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type RestSuite struct {
|
||||
|
@ -20,28 +21,33 @@ type RestSuite struct {
|
|||
whoamiAddr string
|
||||
}
|
||||
|
||||
func (s *RestSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "rest")
|
||||
s.composeUp(c)
|
||||
|
||||
s.whoamiAddr = net.JoinHostPort(s.getComposeServiceIP(c, "whoami1"), "80")
|
||||
func TestRestSuite(t *testing.T) {
|
||||
suite.Run(t, new(RestSuite))
|
||||
}
|
||||
|
||||
func (s *RestSuite) TestSimpleConfigurationInsecure(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/rest/simple.toml"))
|
||||
func (s *RestSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.createComposeProject("rest")
|
||||
s.composeUp()
|
||||
|
||||
s.whoamiAddr = net.JoinHostPort(s.getComposeServiceIP("whoami1"), "80")
|
||||
}
|
||||
|
||||
func (s *RestSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *RestSuite) TestSimpleConfigurationInsecure() {
|
||||
s.traefikCmd(withConfigFile("fixtures/rest/simple.toml"))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1000*time.Millisecond, try.BodyContains("rest@internal"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1000*time.Millisecond, try.BodyContains("rest@internal"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Expected a 404 as we did not configure anything.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
testCase := []struct {
|
||||
desc string
|
||||
|
@ -105,47 +111,41 @@ func (s *RestSuite) TestSimpleConfigurationInsecure(c *check.C) {
|
|||
|
||||
for _, test := range testCase {
|
||||
data, err := json.Marshal(test.config)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
request, err := http.NewRequest(http.MethodPut, "http://127.0.0.1:8080/api/providers/rest", bytes.NewReader(data))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
response, err := http.DefaultClient.Do(request)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusOK, response.StatusCode)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 3*time.Second, try.BodyContains(test.ruleMatch))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/rest/simple_secure.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
func (s *RestSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/rest/simple_secure.toml", struct{}{})
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Expected a 404 as we did not configure anything.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2000*time.Millisecond, try.BodyContains("PathPrefix(`/secure`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
request, err := http.NewRequest(http.MethodPut, "http://127.0.0.1:8080/api/providers/rest", strings.NewReader("{}"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
response, err := http.DefaultClient.Do(request)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusNotFound)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusNotFound, response.StatusCode)
|
||||
|
||||
testCase := []struct {
|
||||
desc string
|
||||
|
@ -209,19 +209,19 @@ func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
|
|||
|
||||
for _, test := range testCase {
|
||||
data, err := json.Marshal(test.config)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
request, err := http.NewRequest(http.MethodPut, "http://127.0.0.1:8000/secure/api/providers/rest", bytes.NewReader(data))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
response, err := http.DefaultClient.Do(request)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusOK, response.StatusCode)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains(test.ruleMatch))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,14 @@ package integration
|
|||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type RetrySuite struct {
|
||||
|
@ -17,96 +18,86 @@ type RetrySuite struct {
|
|||
whoamiIP string
|
||||
}
|
||||
|
||||
func (s *RetrySuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "retry")
|
||||
s.composeUp(c)
|
||||
|
||||
s.whoamiIP = s.getComposeServiceIP(c, "whoami")
|
||||
func TestRetrySuite(t *testing.T) {
|
||||
suite.Run(t, new(RetrySuite))
|
||||
}
|
||||
|
||||
func (s *RetrySuite) TestRetry(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/retry/simple.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
func (s *RetrySuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.createComposeProject("retry")
|
||||
s.composeUp()
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
s.whoamiIP = s.getComposeServiceIP("whoami")
|
||||
}
|
||||
|
||||
func (s *RetrySuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *RetrySuite) TestRetry() {
|
||||
file := s.adaptFile("fixtures/retry/simple.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
response, err := http.Get("http://127.0.0.1:8000/")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// The test only verifies that the retry middleware makes sure that the working service is eventually reached.
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
|
||||
assert.Equal(s.T(), http.StatusOK, response.StatusCode)
|
||||
}
|
||||
|
||||
func (s *RetrySuite) TestRetryBackoff(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/retry/backoff.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
func (s *RetrySuite) TestRetryBackoff() {
|
||||
file := s.adaptFile("fixtures/retry/backoff.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
response, err := http.Get("http://127.0.0.1:8000/")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// The test only verifies that the retry middleware allows finally to reach the working service.
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
|
||||
assert.Equal(s.T(), http.StatusOK, response.StatusCode)
|
||||
}
|
||||
|
||||
func (s *RetrySuite) TestRetryWebsocket(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/retry/simple.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
func (s *RetrySuite) TestRetryWebsocket() {
|
||||
file := s.adaptFile("fixtures/retry/simple.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// The test only verifies that the retry middleware makes sure that the working service is eventually reached.
|
||||
_, response, err := websocket.DefaultDialer.Dial("ws://127.0.0.1:8000/echo", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusSwitchingProtocols)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusSwitchingProtocols, response.StatusCode)
|
||||
|
||||
// The test verifies a second time that the working service is eventually reached.
|
||||
_, response, err = websocket.DefaultDialer.Dial("ws://127.0.0.1:8000/echo", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusSwitchingProtocols)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusSwitchingProtocols, response.StatusCode)
|
||||
}
|
||||
|
||||
func (s *RetrySuite) TestRetryWithStripPrefix(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/retry/strip_prefix.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
func (s *RetrySuite) TestRetryWithStripPrefix() {
|
||||
file := s.adaptFile("fixtures/retry/strip_prefix.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
response, err := http.Get("http://127.0.0.1:8000/test")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(response.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
c.Assert(string(body), checker.Contains, "GET / HTTP/1.1")
|
||||
c.Assert(string(body), checker.Contains, "X-Forwarded-Prefix: /test")
|
||||
assert.Contains(s.T(), string(body), "GET / HTTP/1.1")
|
||||
assert.Contains(s.T(), string(body), "X-Forwarded-Prefix: /test")
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,63 +5,69 @@ import (
|
|||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type TCPSuite struct{ BaseSuite }
|
||||
|
||||
func (s *TCPSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "tcp")
|
||||
s.composeUp(c)
|
||||
func TestTCPSuite(t *testing.T) {
|
||||
suite.Run(t, new(TCPSuite))
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestMixed(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/mixed.toml", struct {
|
||||
func (s *TCPSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("tcp")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestMixed() {
|
||||
file := s.adaptFile("fixtures/tcp/mixed.toml", struct {
|
||||
Whoami string
|
||||
WhoamiA string
|
||||
WhoamiB string
|
||||
WhoamiNoCert string
|
||||
}{
|
||||
Whoami: "http://" + s.getComposeServiceIP(c, "whoami") + ":80",
|
||||
WhoamiA: s.getComposeServiceIP(c, "whoami-a") + ":8080",
|
||||
WhoamiB: s.getComposeServiceIP(c, "whoami-b") + ":8080",
|
||||
WhoamiNoCert: s.getComposeServiceIP(c, "whoami-no-cert") + ":8080",
|
||||
Whoami: "http://" + s.getComposeServiceIP("whoami") + ":80",
|
||||
WhoamiA: s.getComposeServiceIP("whoami-a") + ":8080",
|
||||
WhoamiB: s.getComposeServiceIP("whoami-b") + ":8080",
|
||||
WhoamiNoCert: s.getComposeServiceIP("whoami-no-cert") + ":8080",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("Path(`/test`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("Path(`/test`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Traefik passes through, termination handled by whoami-a
|
||||
out, err := guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-a.test")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-a")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-a")
|
||||
|
||||
// Traefik passes through, termination handled by whoami-b
|
||||
out, err = guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-b.test")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-b")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-b")
|
||||
|
||||
// Termination handled by traefik
|
||||
out, err = guessWho("127.0.0.1:8093", "whoami-c.test", true)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-no-cert")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-no-cert")
|
||||
|
||||
tr1 := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
|
@ -69,174 +75,143 @@ func (s *TCPSuite) TestMixed(c *check.C) {
|
|||
},
|
||||
}
|
||||
req, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:8093/whoami/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.RequestWithTransport(req, 10*time.Second, tr1, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err = http.NewRequest(http.MethodGet, "https://127.0.0.1:8093/not-found/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.RequestWithTransport(req, 10*time.Second, tr1, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8093/test", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.GetRequest("http://127.0.0.1:8093/not-found", 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestTLSOptions(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/multi-tls-options.toml", struct {
|
||||
func (s *TCPSuite) TestTLSOptions() {
|
||||
file := s.adaptFile("fixtures/tcp/multi-tls-options.toml", struct {
|
||||
WhoamiNoCert string
|
||||
}{
|
||||
WhoamiNoCert: s.getComposeServiceIP(c, "whoami-no-cert") + ":8080",
|
||||
WhoamiNoCert: s.getComposeServiceIP("whoami-no-cert") + ":8080",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`whoami-c.test`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`whoami-c.test`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Check that we can use a client tls version <= 1.2 with hostSNI 'whoami-c.test'
|
||||
out, err := guessWhoTLSMaxVersion("127.0.0.1:8093", "whoami-c.test", true, tls.VersionTLS12)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-no-cert")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-no-cert")
|
||||
|
||||
// Check that we can use a client tls version <= 1.3 with hostSNI 'whoami-d.test'
|
||||
out, err = guessWhoTLSMaxVersion("127.0.0.1:8093", "whoami-d.test", true, tls.VersionTLS13)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-no-cert")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-no-cert")
|
||||
|
||||
// Check that we cannot use a client tls version <= 1.2 with hostSNI 'whoami-d.test'
|
||||
_, err = guessWhoTLSMaxVersion("127.0.0.1:8093", "whoami-d.test", true, tls.VersionTLS12)
|
||||
c.Assert(err, checker.NotNil)
|
||||
c.Assert(err.Error(), checker.Contains, "protocol version not supported")
|
||||
assert.ErrorContains(s.T(), err, "protocol version not supported")
|
||||
|
||||
// Check that we can't reach a route with an invalid mTLS configuration.
|
||||
conn, err := tls.Dial("tcp", "127.0.0.1:8093", &tls.Config{
|
||||
ServerName: "whoami-i.test",
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
c.Assert(conn, checker.IsNil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
assert.Nil(s.T(), conn)
|
||||
assert.Error(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestNonTLSFallback(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/non-tls-fallback.toml", struct {
|
||||
func (s *TCPSuite) TestNonTLSFallback() {
|
||||
file := s.adaptFile("fixtures/tcp/non-tls-fallback.toml", struct {
|
||||
WhoamiA string
|
||||
WhoamiB string
|
||||
WhoamiNoCert string
|
||||
WhoamiNoTLS string
|
||||
}{
|
||||
WhoamiA: s.getComposeServiceIP(c, "whoami-a") + ":8080",
|
||||
WhoamiB: s.getComposeServiceIP(c, "whoami-b") + ":8080",
|
||||
WhoamiNoCert: s.getComposeServiceIP(c, "whoami-no-cert") + ":8080",
|
||||
WhoamiNoTLS: s.getComposeServiceIP(c, "whoami-no-tls") + ":8080",
|
||||
WhoamiA: s.getComposeServiceIP("whoami-a") + ":8080",
|
||||
WhoamiB: s.getComposeServiceIP("whoami-b") + ":8080",
|
||||
WhoamiNoCert: s.getComposeServiceIP("whoami-no-cert") + ":8080",
|
||||
WhoamiNoTLS: s.getComposeServiceIP("whoami-no-tls") + ":8080",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Traefik passes through, termination handled by whoami-a
|
||||
out, err := guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-a.test")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-a")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-a")
|
||||
|
||||
// Traefik passes through, termination handled by whoami-b
|
||||
out, err = guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-b.test")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-b")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-b")
|
||||
|
||||
// Termination handled by traefik
|
||||
out, err = guessWho("127.0.0.1:8093", "whoami-c.test", true)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-no-cert")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-no-cert")
|
||||
|
||||
out, err = guessWho("127.0.0.1:8093", "", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-no-tls")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-no-tls")
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestNonTlsTcp(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/non-tls.toml", struct {
|
||||
func (s *TCPSuite) TestNonTlsTcp() {
|
||||
file := s.adaptFile("fixtures/tcp/non-tls.toml", struct {
|
||||
WhoamiNoTLS string
|
||||
}{
|
||||
WhoamiNoTLS: s.getComposeServiceIP(c, "whoami-no-tls") + ":8080",
|
||||
WhoamiNoTLS: s.getComposeServiceIP("whoami-no-tls") + ":8080",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Traefik will forward every requests on the given port to whoami-no-tls
|
||||
out, err := guessWho("127.0.0.1:8093", "", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-no-tls")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-no-tls")
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestCatchAllNoTLS(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/catch-all-no-tls.toml", struct {
|
||||
func (s *TCPSuite) TestCatchAllNoTLS() {
|
||||
file := s.adaptFile("fixtures/tcp/catch-all-no-tls.toml", struct {
|
||||
WhoamiBannerAddress string
|
||||
}{
|
||||
WhoamiBannerAddress: s.getComposeServiceIP(c, "whoami-banner") + ":8080",
|
||||
WhoamiBannerAddress: s.getComposeServiceIP("whoami-banner") + ":8080",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Traefik will forward every requests on the given port to whoami-no-tls
|
||||
out, err := welcome("127.0.0.1:8093")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "Welcome")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "Welcome")
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestCatchAllNoTLSWithHTTPS(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/catch-all-no-tls-with-https.toml", struct {
|
||||
func (s *TCPSuite) TestCatchAllNoTLSWithHTTPS() {
|
||||
file := s.adaptFile("fixtures/tcp/catch-all-no-tls-with-https.toml", struct {
|
||||
WhoamiNoTLSAddress string
|
||||
WhoamiURL string
|
||||
}{
|
||||
WhoamiNoTLSAddress: s.getComposeServiceIP(c, "whoami-no-tls") + ":8080",
|
||||
WhoamiURL: "http://" + s.getComposeServiceIP(c, "whoami") + ":80",
|
||||
WhoamiNoTLSAddress: s.getComposeServiceIP("whoami-no-tls") + ":8080",
|
||||
WhoamiURL: "http://" + s.getComposeServiceIP("whoami") + ":80",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "https://127.0.0.1:8093/test", nil)
|
||||
req.RequestURI = ""
|
||||
|
@ -246,64 +221,52 @@ func (s *TCPSuite) TestCatchAllNoTLSWithHTTPS(c *check.C) {
|
|||
InsecureSkipVerify: true,
|
||||
},
|
||||
}, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestMiddlewareAllowList(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/ip-allowlist.toml", struct {
|
||||
func (s *TCPSuite) TestMiddlewareAllowList() {
|
||||
file := s.adaptFile("fixtures/tcp/ip-allowlist.toml", struct {
|
||||
WhoamiA string
|
||||
WhoamiB string
|
||||
}{
|
||||
WhoamiA: s.getComposeServiceIP(c, "whoami-a") + ":8080",
|
||||
WhoamiB: s.getComposeServiceIP(c, "whoami-b") + ":8080",
|
||||
WhoamiA: s.getComposeServiceIP("whoami-a") + ":8080",
|
||||
WhoamiB: s.getComposeServiceIP("whoami-b") + ":8080",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`whoami-a.test`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`whoami-a.test`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Traefik not passes through, ipWhitelist closes connection
|
||||
_, err = guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-a.test")
|
||||
c.Assert(err, checker.ErrorMatches, "EOF")
|
||||
assert.ErrorIs(s.T(), err, io.EOF)
|
||||
|
||||
// Traefik passes through, termination handled by whoami-b
|
||||
out, err := guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-b.test")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-b")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-b")
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestWRR(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/wrr.toml", struct {
|
||||
func (s *TCPSuite) TestWRR() {
|
||||
file := s.adaptFile("fixtures/tcp/wrr.toml", struct {
|
||||
WhoamiB string
|
||||
WhoamiAB string
|
||||
}{
|
||||
WhoamiB: s.getComposeServiceIP(c, "whoami-b") + ":8080",
|
||||
WhoamiAB: s.getComposeServiceIP(c, "whoami-ab") + ":8080",
|
||||
WhoamiB: s.getComposeServiceIP("whoami-b") + ":8080",
|
||||
WhoamiAB: s.getComposeServiceIP("whoami-ab") + ":8080",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`whoami-b.test`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`whoami-b.test`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
call := map[string]int{}
|
||||
for i := 0; i < 4; i++ {
|
||||
// Traefik passes through, termination handled by whoami-b or whoami-bb
|
||||
out, err := guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-b.test")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
switch {
|
||||
case strings.Contains(out, "whoami-b"):
|
||||
call["whoami-b"]++
|
||||
|
@ -315,7 +278,7 @@ func (s *TCPSuite) TestWRR(c *check.C) {
|
|||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
c.Assert(call, checker.DeepEquals, map[string]int{"whoami-b": 3, "whoami-ab": 1})
|
||||
assert.EqualValues(s.T(), call, map[string]int{"whoami-b": 3, "whoami-ab": 1})
|
||||
}
|
||||
|
||||
func welcome(addr string) (string, error) {
|
||||
|
|
|
@ -4,47 +4,53 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type TimeoutSuite struct{ BaseSuite }
|
||||
|
||||
func (s *TimeoutSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "timeout")
|
||||
s.composeUp(c)
|
||||
func TestTimeoutSuite(t *testing.T) {
|
||||
suite.Run(t, new(TimeoutSuite))
|
||||
}
|
||||
|
||||
func (s *TimeoutSuite) TestForwardingTimeouts(c *check.C) {
|
||||
timeoutEndpointIP := s.getComposeServiceIP(c, "timeoutEndpoint")
|
||||
file := s.adaptFile(c, "fixtures/timeout/forwarding_timeouts.toml", struct{ TimeoutEndpoint string }{timeoutEndpointIP})
|
||||
defer os.Remove(file)
|
||||
func (s *TimeoutSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.createComposeProject("timeout")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Path(`/dialTimeout`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
func (s *TimeoutSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *TimeoutSuite) TestForwardingTimeouts() {
|
||||
timeoutEndpointIP := s.getComposeServiceIP("timeoutEndpoint")
|
||||
file := s.adaptFile("fixtures/timeout/forwarding_timeouts.toml", struct{ TimeoutEndpoint string }{timeoutEndpointIP})
|
||||
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Path(`/dialTimeout`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// This simulates a DialTimeout when connecting to the backend server.
|
||||
response, err := http.Get("http://127.0.0.1:8000/dialTimeout")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusGatewayTimeout)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusGatewayTimeout, response.StatusCode)
|
||||
|
||||
// Check that timeout service is available
|
||||
statusURL := fmt.Sprintf("http://%s/statusTest?status=200",
|
||||
net.JoinHostPort(timeoutEndpointIP, "9000"))
|
||||
c.Assert(try.GetRequest(statusURL, 60*time.Second, try.StatusCodeIs(http.StatusOK)), checker.IsNil)
|
||||
assert.NoError(s.T(), try.GetRequest(statusURL, 60*time.Second, try.StatusCodeIs(http.StatusOK)))
|
||||
|
||||
// This simulates a ResponseHeaderTimeout.
|
||||
response, err = http.Get("http://127.0.0.1:8000/responseHeaderTimeout?sleep=1000")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusGatewayTimeout)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusGatewayTimeout, response.StatusCode)
|
||||
}
|
||||
|
|
|
@ -4,11 +4,13 @@ import (
|
|||
"crypto/tls"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -19,20 +21,30 @@ const (
|
|||
|
||||
type TLSClientHeadersSuite struct{ BaseSuite }
|
||||
|
||||
func (s *TLSClientHeadersSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "tlsclientheaders")
|
||||
s.composeUp(c)
|
||||
func TestTLSClientHeadersSuite(t *testing.T) {
|
||||
suite.Run(t, new(TLSClientHeadersSuite))
|
||||
}
|
||||
|
||||
func (s *TLSClientHeadersSuite) TestTLSClientHeaders(c *check.C) {
|
||||
rootCertContent, err := os.ReadFile(rootCertPath)
|
||||
c.Assert(err, check.IsNil)
|
||||
serverCertContent, err := os.ReadFile(certPemPath)
|
||||
c.Assert(err, check.IsNil)
|
||||
ServerKeyContent, err := os.ReadFile(certKeyPath)
|
||||
c.Assert(err, check.IsNil)
|
||||
func (s *TLSClientHeadersSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tlsclientheaders/simple.toml", struct {
|
||||
s.createComposeProject("tlsclientheaders")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *TLSClientHeadersSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *TLSClientHeadersSuite) TestTLSClientHeaders() {
|
||||
rootCertContent, err := os.ReadFile(rootCertPath)
|
||||
assert.NoError(s.T(), err)
|
||||
serverCertContent, err := os.ReadFile(certPemPath)
|
||||
assert.NoError(s.T(), err)
|
||||
ServerKeyContent, err := os.ReadFile(certKeyPath)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
file := s.adaptFile("fixtures/tlsclientheaders/simple.toml", struct {
|
||||
RootCertContent string
|
||||
ServerCertContent string
|
||||
ServerKeyContent string
|
||||
|
@ -41,22 +53,17 @@ func (s *TLSClientHeadersSuite) TestTLSClientHeaders(c *check.C) {
|
|||
ServerCertContent: string(serverCertContent),
|
||||
ServerKeyContent: string(ServerKeyContent),
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second, try.BodyContains("PathPrefix(`/foo`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
request, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:8443/foo", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
certificate, err := tls.LoadX509KeyPair(certPemPath, certKeyPath)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
|
@ -66,5 +73,5 @@ func (s *TLSClientHeadersSuite) TestTLSClientHeaders(c *check.C) {
|
|||
}
|
||||
|
||||
err = try.RequestWithTransport(request, 2*time.Second, tr, try.BodyContains("Forwarded-Tls-Client-Cert: MIIDNTCCAh0CFD0QQcHXUJuKwMBYDA+bBExVSP26MA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZGcmFuY2UxFTATBgNVBAoMDFRyYWVmaWsgTGFiczEQMA4GA1UECwwHdHJhZWZpazENMAsGA1UEAwwEcm9vdDAeFw0yMTAxMDgxNzQ0MjRaFw0zMTAxMDYxNzQ0MjRaMFgxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZGcmFuY2UxFTATBgNVBAoMDFRyYWVmaWsgTGFiczEQMA4GA1UECwwHdHJhZWZpazEPMA0GA1UEAwwGc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvYK2z8gLPOfFLgXNWP2460aeJ9vrH47x/lhKLlv4amSDHDx8Cmz/6blOUM8XOfMRW1xx++AgChWN9dx/kf7G2xlA5grZxRvUQ6xj7AvFG9TQUA3muNh2hvm9c3IjaZBNKH27bRKuDIBvZBvXdX4NL/aaFy7w7v7IKxk8j4WkfB23sgyH43g4b7NqKHJugZiedFu5GALmtLbShVOFbjWcre7Wvatdw8dIBmiFJqZQT3UjIuGAgqczIShtLxo4V+XyVkIPmzfPrRV+4zoMFIFOIaj3syyxb4krPBtxhe7nz2cWvvq0wePB2y4YbAAoVY8NYpd5JsMFwZtG6Uk59ygv4QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQDaPg69wNeFNFisfBJTrscqVCTW+B80gMhpLdxXD+KO0/Wgc5xpB/wLSirNtRQyxAa3+EEcIwJv/wdh8EyjlDLSpFm/8ghntrKhkOfIOPDFE41M5HNfx/Fuh5btKEenOL/XdapqtNUt2ZE4RrsfbL79sPYepa9kDUVi2mCbeH5ollZ0MDU68HpB2YwHbCEuQNk5W3pjYK2NaDkVnxTkfEDM1k+3QydO1lqB5JJmcrs59BEveTqaJ3eeh/0I4OOab6OkTTZ0JNjJp1573oxO+fce/bfGud8xHY5gSN9huU7U6RsgvO7Dhmal/sDNl8XC8oU90hVDVXZdA7ewh4jjaoIv"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -2,19 +2,24 @@ package integration
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type TracingSuite struct {
|
||||
BaseSuite
|
||||
whoamiIP string
|
||||
whoamiPort int
|
||||
tracerIP string
|
||||
whoamiIP string
|
||||
whoamiPort int
|
||||
tracerZipkinIP string
|
||||
tracerJaegerIP string
|
||||
}
|
||||
|
||||
func TestTracingSuite(t *testing.T) {
|
||||
suite.Run(t, new(TracingSuite))
|
||||
}
|
||||
|
||||
type TracingTemplate struct {
|
||||
|
@ -24,302 +29,264 @@ type TracingTemplate struct {
|
|||
TraceContextHeaderName string
|
||||
}
|
||||
|
||||
func (s *TracingSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "tracing")
|
||||
s.composeUp(c)
|
||||
func (s *TracingSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.whoamiIP = s.getComposeServiceIP(c, "whoami")
|
||||
s.createComposeProject("tracing")
|
||||
s.composeUp()
|
||||
|
||||
s.whoamiIP = s.getComposeServiceIP("whoami")
|
||||
s.whoamiPort = 80
|
||||
}
|
||||
|
||||
func (s *TracingSuite) startZipkin(c *check.C) {
|
||||
s.composeUp(c, "zipkin")
|
||||
s.tracerIP = s.getComposeServiceIP(c, "zipkin")
|
||||
func (s *TracingSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *TracingSuite) startZipkin() {
|
||||
s.composeUp("zipkin")
|
||||
s.tracerZipkinIP = s.getComposeServiceIP("zipkin")
|
||||
|
||||
// Wait for Zipkin to turn ready.
|
||||
err := try.GetRequest("http://"+s.tracerIP+":9411/api/v2/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://"+s.tracerZipkinIP+":9411/api/v2/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestZipkinRateLimit(c *check.C) {
|
||||
s.startZipkin(c)
|
||||
// defer s.composeStop(c, "zipkin")
|
||||
func (s *TracingSuite) TestZipkinRateLimit() {
|
||||
s.startZipkin()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-zipkin.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: s.whoamiPort,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerZipkinIP,
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// sleep for 4 seconds to be certain the configured time period has elapsed
|
||||
// then test another request and verify a 200 status code
|
||||
time.Sleep(4 * time.Second)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// continue requests at 3 second intervals to test the other rate limit time period
|
||||
time.Sleep(3 * time.Second)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
time.Sleep(3 * time.Second)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
time.Sleep(3 * time.Second)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit-1@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerZipkinIP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit-1@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestZipkinRetry(c *check.C) {
|
||||
s.startZipkin(c)
|
||||
defer s.composeStop(c, "zipkin")
|
||||
func (s *TracingSuite) TestZipkinRetry() {
|
||||
s.startZipkin()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-zipkin.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: 81,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerZipkinIP,
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/retry", 500*time.Millisecond, try.StatusCodeIs(http.StatusBadGateway))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("forward service2/router2@file", "retry@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerZipkinIP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("forward service2/router2@file", "retry@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestZipkinAuth(c *check.C) {
|
||||
s.startZipkin(c)
|
||||
defer s.composeStop(c, "zipkin")
|
||||
func (s *TracingSuite) TestZipkinAuth() {
|
||||
s.startZipkin()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-zipkin.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: s.whoamiPort,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerZipkinIP,
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("entrypoint web", "basic-auth@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerZipkinIP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("entrypoint web", "basic-auth@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) startJaeger(c *check.C) {
|
||||
s.composeUp(c, "jaeger", "whoami")
|
||||
s.tracerIP = s.getComposeServiceIP(c, "jaeger")
|
||||
func (s *TracingSuite) startJaeger() {
|
||||
s.composeUp("jaeger", "whoami")
|
||||
s.tracerJaegerIP = s.getComposeServiceIP("jaeger")
|
||||
|
||||
// Wait for Jaeger to turn ready.
|
||||
err := try.GetRequest("http://"+s.tracerIP+":16686/api/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestJaegerRateLimit(c *check.C) {
|
||||
s.startJaeger(c)
|
||||
defer s.composeStop(c, "jaeger")
|
||||
func (s *TracingSuite) TestJaegerRateLimit() {
|
||||
s.startJaeger()
|
||||
// defer s.composeStop(c, "jaeger")
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: s.whoamiPort,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerJaegerIP,
|
||||
TraceContextHeaderName: "uber-trace-id",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// sleep for 4 seconds to be certain the configured time period has elapsed
|
||||
// then test another request and verify a 200 status code
|
||||
time.Sleep(4 * time.Second)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// continue requests at 3 second intervals to test the other rate limit time period
|
||||
time.Sleep(3 * time.Second)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
time.Sleep(3 * time.Second)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit-1@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit-1@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestJaegerRetry(c *check.C) {
|
||||
s.startJaeger(c)
|
||||
defer s.composeStop(c, "jaeger")
|
||||
func (s *TracingSuite) TestJaegerRetry() {
|
||||
s.startJaeger()
|
||||
// defer s.composeStop(c, "jaeger")
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: 81,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerJaegerIP,
|
||||
TraceContextHeaderName: "uber-trace-id",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/retry", 500*time.Millisecond, try.StatusCodeIs(http.StatusBadGateway))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("forward service2/router2@file", "retry@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("forward service2/router2@file", "retry@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestJaegerAuth(c *check.C) {
|
||||
s.startJaeger(c)
|
||||
defer s.composeStop(c, "jaeger")
|
||||
func (s *TracingSuite) TestJaegerAuth() {
|
||||
s.startJaeger()
|
||||
// defer s.composeStop(c, "jaeger")
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: s.whoamiPort,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerJaegerIP,
|
||||
TraceContextHeaderName: "uber-trace-id",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestJaegerCustomHeader(c *check.C) {
|
||||
s.startJaeger(c)
|
||||
defer s.composeStop(c, "jaeger")
|
||||
func (s *TracingSuite) TestJaegerCustomHeader() {
|
||||
s.startJaeger()
|
||||
// defer s.composeStop(c, "jaeger")
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: s.whoamiPort,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerJaegerIP,
|
||||
TraceContextHeaderName: "powpow",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestJaegerAuthCollector(c *check.C) {
|
||||
s.startJaeger(c)
|
||||
defer s.composeStop(c, "jaeger")
|
||||
func (s *TracingSuite) TestJaegerAuthCollector() {
|
||||
s.startJaeger()
|
||||
// defer s.composeStop(c, "jaeger")
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger-collector.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-jaeger-collector.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: s.whoamiPort,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerJaegerIP,
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -3,20 +3,32 @@ package integration
|
|||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
)
|
||||
|
||||
type UDPSuite struct{ BaseSuite }
|
||||
|
||||
func (s *UDPSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "udp")
|
||||
s.composeUp(c)
|
||||
func TestUDPSuite(t *testing.T) {
|
||||
suite.Run(t, new(UDPSuite))
|
||||
}
|
||||
|
||||
func (s *UDPSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("udp")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *UDPSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func guessWhoUDP(addr string) (string, error) {
|
||||
|
@ -46,39 +58,33 @@ func guessWhoUDP(addr string) (string, error) {
|
|||
return string(out[:n]), nil
|
||||
}
|
||||
|
||||
func (s *UDPSuite) TestWRR(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/udp/wrr.toml", struct {
|
||||
func (s *UDPSuite) TestWRR() {
|
||||
file := s.adaptFile("fixtures/udp/wrr.toml", struct {
|
||||
WhoamiAIP string
|
||||
WhoamiBIP string
|
||||
WhoamiCIP string
|
||||
WhoamiDIP string
|
||||
}{
|
||||
WhoamiAIP: s.getComposeServiceIP(c, "whoami-a"),
|
||||
WhoamiBIP: s.getComposeServiceIP(c, "whoami-b"),
|
||||
WhoamiCIP: s.getComposeServiceIP(c, "whoami-c"),
|
||||
WhoamiDIP: s.getComposeServiceIP(c, "whoami-d"),
|
||||
WhoamiAIP: s.getComposeServiceIP("whoami-a"),
|
||||
WhoamiBIP: s.getComposeServiceIP("whoami-b"),
|
||||
WhoamiCIP: s.getComposeServiceIP("whoami-c"),
|
||||
WhoamiDIP: s.getComposeServiceIP("whoami-d"),
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("whoami-a"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("whoami-a"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8093/who", 5*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
stop := make(chan struct{})
|
||||
go func() {
|
||||
call := map[string]int{}
|
||||
for i := 0; i < 8; i++ {
|
||||
out, err := guessWhoUDP("127.0.0.1:8093")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
switch {
|
||||
case strings.Contains(out, "whoami-a"):
|
||||
call["whoami-a"]++
|
||||
|
@ -90,13 +96,13 @@ func (s *UDPSuite) TestWRR(c *check.C) {
|
|||
call["unknown"]++
|
||||
}
|
||||
}
|
||||
c.Assert(call, checker.DeepEquals, map[string]int{"whoami-a": 3, "whoami-b": 2, "whoami-c": 3})
|
||||
assert.EqualValues(s.T(), call, map[string]int{"whoami-a": 3, "whoami-b": 2, "whoami-c": 3})
|
||||
close(stop)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-stop:
|
||||
case <-time.Tick(5 * time.Second):
|
||||
c.Error("Timeout")
|
||||
log.WithoutContext().Info("Timeout")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,19 +8,25 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
gorillawebsocket "github.com/gorilla/websocket"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
"golang.org/x/net/websocket"
|
||||
)
|
||||
|
||||
// WebsocketSuite tests suite.
|
||||
type WebsocketSuite struct{ BaseSuite }
|
||||
|
||||
func (s *WebsocketSuite) TestBase(c *check.C) {
|
||||
func TestWebsocketSuite(t *testing.T) {
|
||||
suite.Run(t, new(WebsocketSuite))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestBase() {
|
||||
upgrader := gorillawebsocket.Upgrader{} // use default options
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -41,36 +47,30 @@ func (s *WebsocketSuite) TestBase(c *check.C) {
|
|||
}
|
||||
}))
|
||||
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
conn, _, err := gorillawebsocket.DefaultDialer.Dial("ws://127.0.0.1:8000/ws", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = conn.WriteMessage(gorillawebsocket.TextMessage, []byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
_, msg, err := conn.ReadMessage()
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestWrongOrigin(c *check.C) {
|
||||
func (s *WebsocketSuite) TestWrongOrigin() {
|
||||
upgrader := gorillawebsocket.Upgrader{} // use default options
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -91,35 +91,28 @@ func (s *WebsocketSuite) TestWrongOrigin(c *check.C) {
|
|||
}
|
||||
}))
|
||||
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
config, err := websocket.NewConfig("ws://127.0.0.1:8000/ws", "ws://127.0.0.1:800")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
conn, err := net.DialTimeout("tcp", "127.0.0.1:8000", time.Second)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = websocket.NewClient(config, conn)
|
||||
c.Assert(err, checker.NotNil)
|
||||
c.Assert(err, checker.ErrorMatches, "bad status")
|
||||
assert.ErrorContains(s.T(), err, "bad status")
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestOrigin(c *check.C) {
|
||||
func (s *WebsocketSuite) TestOrigin() {
|
||||
// use default options
|
||||
upgrader := gorillawebsocket.Upgrader{}
|
||||
|
||||
|
@ -141,44 +134,38 @@ func (s *WebsocketSuite) TestOrigin(c *check.C) {
|
|||
}
|
||||
}))
|
||||
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
config, err := websocket.NewConfig("ws://127.0.0.1:8000/ws", "ws://127.0.0.1:8000")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
conn, err := net.DialTimeout("tcp", "127.0.0.1:8000", time.Second)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
client, err := websocket.NewClient(config, conn)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
n, err := client.Write([]byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(n, checker.Equals, 2)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), 2, n)
|
||||
|
||||
msg := make([]byte, 2)
|
||||
n, err = client.Read(msg)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(n, checker.Equals, 2)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), 2, n)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestWrongOriginIgnoredByServer(c *check.C) {
|
||||
func (s *WebsocketSuite) TestWrongOriginIgnoredByServer() {
|
||||
upgrader := gorillawebsocket.Upgrader{CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
}}
|
||||
|
@ -201,44 +188,38 @@ func (s *WebsocketSuite) TestWrongOriginIgnoredByServer(c *check.C) {
|
|||
}
|
||||
}))
|
||||
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
config, err := websocket.NewConfig("ws://127.0.0.1:8000/ws", "ws://127.0.0.1:80")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
conn, err := net.DialTimeout("tcp", "127.0.0.1:8000", time.Second)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
client, err := websocket.NewClient(config, conn)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
n, err := client.Write([]byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(n, checker.Equals, 2)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), 2, n)
|
||||
|
||||
msg := make([]byte, 2)
|
||||
n, err = client.Read(msg)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(n, checker.Equals, 2)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), 2, n)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestSSLTermination(c *check.C) {
|
||||
func (s *WebsocketSuite) TestSSLTermination() {
|
||||
upgrader := gorillawebsocket.Upgrader{} // use default options
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -258,44 +239,38 @@ func (s *WebsocketSuite) TestSSLTermination(c *check.C) {
|
|||
}
|
||||
}
|
||||
}))
|
||||
file := s.adaptFile(c, "fixtures/websocket/config_https.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config_https.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Add client self-signed cert
|
||||
roots := x509.NewCertPool()
|
||||
certContent, err := os.ReadFile("./resources/tls/local.cert")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
roots.AppendCertsFromPEM(certContent)
|
||||
gorillawebsocket.DefaultDialer.TLSClientConfig = &tls.Config{
|
||||
RootCAs: roots,
|
||||
}
|
||||
conn, _, err := gorillawebsocket.DefaultDialer.Dial("wss://127.0.0.1:8000/ws", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = conn.WriteMessage(gorillawebsocket.TextMessage, []byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
_, msg, err := conn.ReadMessage()
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestBasicAuth(c *check.C) {
|
||||
func (s *WebsocketSuite) TestBasicAuth() {
|
||||
upgrader := gorillawebsocket.Upgrader{} // use default options
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -306,8 +281,8 @@ func (s *WebsocketSuite) TestBasicAuth(c *check.C) {
|
|||
defer conn.Close()
|
||||
|
||||
user, password, _ := r.BasicAuth()
|
||||
c.Assert(user, check.Equals, "traefiker")
|
||||
c.Assert(password, check.Equals, "secret")
|
||||
assert.Equal(s.T(), "traefiker", user)
|
||||
assert.Equal(s.T(), "secret", password)
|
||||
|
||||
for {
|
||||
mt, message, err := conn.ReadMessage()
|
||||
|
@ -320,78 +295,66 @@ func (s *WebsocketSuite) TestBasicAuth(c *check.C) {
|
|||
}
|
||||
}
|
||||
}))
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
config, err := websocket.NewConfig("ws://127.0.0.1:8000/ws", "ws://127.0.0.1:8000")
|
||||
auth := "traefiker:secret"
|
||||
config.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(auth)))
|
||||
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
conn, err := net.DialTimeout("tcp", "127.0.0.1:8000", time.Second)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
client, err := websocket.NewClient(config, conn)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
n, err := client.Write([]byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(n, checker.Equals, 2)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), 2, n)
|
||||
|
||||
msg := make([]byte, 2)
|
||||
n, err = client.Read(msg)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(n, checker.Equals, 2)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), 2, n)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestSpecificResponseFromBackend(c *check.C) {
|
||||
func (s *WebsocketSuite) TestSpecificResponseFromBackend() {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
}))
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
_, resp, err := gorillawebsocket.DefaultDialer.Dial("ws://127.0.0.1:8000/ws", nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
c.Assert(resp.StatusCode, check.Equals, http.StatusUnauthorized)
|
||||
assert.Error(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusUnauthorized, resp.StatusCode)
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestURLWithURLEncodedChar(c *check.C) {
|
||||
func (s *WebsocketSuite) TestURLWithURLEncodedChar() {
|
||||
upgrader := gorillawebsocket.Upgrader{} // use default options
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
c.Assert(r.URL.EscapedPath(), check.Equals, "/ws/http%3A%2F%2Ftest")
|
||||
assert.Equal(s.T(), "/ws/http%3A%2F%2Ftest", r.URL.EscapedPath())
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -409,36 +372,30 @@ func (s *WebsocketSuite) TestURLWithURLEncodedChar(c *check.C) {
|
|||
}
|
||||
}))
|
||||
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
conn, _, err := gorillawebsocket.DefaultDialer.Dial("ws://127.0.0.1:8000/ws/http%3A%2F%2Ftest", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = conn.WriteMessage(gorillawebsocket.TextMessage, []byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
_, msg, err := conn.ReadMessage()
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestSSLhttp2(c *check.C) {
|
||||
func (s *WebsocketSuite) TestSSLhttp2() {
|
||||
upgrader := gorillawebsocket.Upgrader{} // use default options
|
||||
|
||||
ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -463,48 +420,42 @@ func (s *WebsocketSuite) TestSSLhttp2(c *check.C) {
|
|||
ts.TLS.NextProtos = append(ts.TLS.NextProtos, `h2`, `http/1.1`)
|
||||
ts.StartTLS()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/websocket/config_https.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config_https.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: ts.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG", "--accesslog")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG", "--accesslog")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Add client self-signed cert
|
||||
roots := x509.NewCertPool()
|
||||
certContent, err := os.ReadFile("./resources/tls/local.cert")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
roots.AppendCertsFromPEM(certContent)
|
||||
gorillawebsocket.DefaultDialer.TLSClientConfig = &tls.Config{
|
||||
RootCAs: roots,
|
||||
}
|
||||
conn, _, err := gorillawebsocket.DefaultDialer.Dial("wss://127.0.0.1:8000/echo", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = conn.WriteMessage(gorillawebsocket.TextMessage, []byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
_, msg, err := conn.ReadMessage()
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestHeaderAreForwarded(c *check.C) {
|
||||
func (s *WebsocketSuite) TestHeaderAreForwarded() {
|
||||
upgrader := gorillawebsocket.Upgrader{} // use default options
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
c.Assert(r.Header.Get("X-Token"), check.Equals, "my-token")
|
||||
assert.Equal(s.T(), "my-token", r.Header.Get("X-Token"))
|
||||
c, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -522,33 +473,27 @@ func (s *WebsocketSuite) TestHeaderAreForwarded(c *check.C) {
|
|||
}
|
||||
}))
|
||||
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
headers := http.Header{}
|
||||
headers.Add("X-Token", "my-token")
|
||||
conn, _, err := gorillawebsocket.DefaultDialer.Dial("ws://127.0.0.1:8000/ws", headers)
|
||||
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = conn.WriteMessage(gorillawebsocket.TextMessage, []byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
_, msg, err := conn.ReadMessage()
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
|
|
@ -8,16 +8,18 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/kvtools/valkeyrie"
|
||||
"github.com/kvtools/valkeyrie/store"
|
||||
"github.com/kvtools/zookeeper"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/api"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
)
|
||||
|
||||
// Zk test suites.
|
||||
|
@ -27,11 +29,17 @@ type ZookeeperSuite struct {
|
|||
zookeeperAddr string
|
||||
}
|
||||
|
||||
func (s *ZookeeperSuite) setupStore(c *check.C) {
|
||||
s.createComposeProject(c, "zookeeper")
|
||||
s.composeUp(c)
|
||||
func TestZookeeperSuite(t *testing.T) {
|
||||
suite.Run(t, new(ZookeeperSuite))
|
||||
}
|
||||
|
||||
s.zookeeperAddr = net.JoinHostPort(s.getComposeServiceIP(c, "zookeeper"), "2181")
|
||||
func (s *ZookeeperSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("zookeeper")
|
||||
s.composeUp()
|
||||
|
||||
s.zookeeperAddr = net.JoinHostPort(s.getComposeServiceIP("zookeeper"), "2181")
|
||||
|
||||
var err error
|
||||
s.kvClient, err = valkeyrie.NewStore(
|
||||
|
@ -42,20 +50,19 @@ func (s *ZookeeperSuite) setupStore(c *check.C) {
|
|||
ConnectionTimeout: 10 * time.Second,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
c.Fatal("Cannot create store zookeeper")
|
||||
}
|
||||
require.NoError(s.T(), err, "Cannot create store zookeeper")
|
||||
|
||||
// wait for zk
|
||||
err = try.Do(60*time.Second, try.KVExists(s.kvClient, "test"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ZookeeperSuite) TestSimpleConfiguration(c *check.C) {
|
||||
s.setupStore(c)
|
||||
func (s *ZookeeperSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/zookeeper/simple.toml", struct{ ZkAddress string }{s.zookeeperAddr})
|
||||
defer os.Remove(file)
|
||||
func (s *ZookeeperSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/zookeeper/simple.toml", struct{ ZkAddress string }{s.zookeeperAddr})
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
|
@ -105,39 +112,35 @@ func (s *ZookeeperSuite) TestSimpleConfiguration(c *check.C) {
|
|||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(context.Background(), k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second,
|
||||
try.BodyContains(`"striper@zookeeper":`, `"compressor@zookeeper":`, `"srvcA@zookeeper":`, `"srvcB@zookeeper":`),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-zk.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = os.WriteFile(expectedJSON, got, 0o666)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
expected, err := os.ReadFile(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
|
@ -149,7 +152,7 @@ func (s *ZookeeperSuite) TestSimpleConfiguration(c *check.C) {
|
|||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Error(text)
|
||||
require.NoError(s.T(), err)
|
||||
log.WithoutContext().Info(text)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue