test: upgrade docker-compose

Co-authored-by: Rémi Buisson <remi.buisson@traefik.io>
This commit is contained in:
Charlie Haley 2021-11-25 10:10:06 +00:00 committed by GitHub
parent 525a6cf5b2
commit 5a225b4196
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
81 changed files with 2094 additions and 1283 deletions

View file

@ -48,6 +48,7 @@
extensionsv1beta1 = "k8s.io/api/extensions/v1beta1"
metav1 = "k8s.io/apimachinery/pkg/apis/meta/v1"
kubeerror = "k8s.io/apimachinery/pkg/api/errors"
composeapi = "github.com/docker/compose/v2/pkg/api"
[linters-settings.gomoddirectives]
replace-allow-list = [
@ -56,6 +57,7 @@
"github.com/gorilla/mux",
"github.com/mailgun/minheap",
"github.com/mailgun/multibuf",
"github.com/jaguilar/vt100",
]
[linters]

View file

@ -32,42 +32,24 @@ global_job_config:
- cache restore traefik-$(checksum go.sum)
blocks:
- name: Test Integration Container
- name: Test Integration
dependencies: []
run:
when: "branch =~ '.*' OR pull_request =~'.*'"
task:
jobs:
- name: Test Integration Container
- name: Test Integration
commands:
- make pull-images
- mkdir -p static # Avoid to generate webui
- PRE_TARGET="" make binary
- make test-integration-container
- make test-integration
- df -h
epilogue:
always:
commands:
- cache store traefik-$(checksum go.sum) $HOME/go/pkg/mod
- name: Test Integration Host
dependencies: []
run:
when: "branch =~ '.*' OR pull_request =~'.*'"
task:
env_vars:
- name: PRE_TARGET
value: ""
jobs:
- name: Test Integration Host
commands:
- mkdir -p static # Avoid to generate webui
- make test-integration-host
epilogue:
always:
commands:
- cache store traefik-$(checksum go.sum) $HOME/go/pkg/mod
- name: Release
dependencies: []
run:

View file

@ -15,7 +15,7 @@ TRAEFIK_DEV_IMAGE := traefik-dev$(if $(GIT_BRANCH),:$(subst /,-,$(GIT_BRANCH)))
REPONAME := $(shell echo $(REPO) | tr '[:upper:]' '[:lower:]')
TRAEFIK_IMAGE := $(if $(REPONAME),$(REPONAME),"traefik/traefik")
INTEGRATION_OPTS := $(if $(MAKE_DOCKER_HOST),-e "DOCKER_HOST=$(MAKE_DOCKER_HOST)", -e "TEST_CONTAINER=1" -v "/var/run/docker.sock:/var/run/docker.sock")
INTEGRATION_OPTS := $(if $(MAKE_DOCKER_HOST),-e "DOCKER_HOST=$(MAKE_DOCKER_HOST)",-v "/var/run/docker.sock:/var/run/docker.sock")
DOCKER_BUILD_ARGS := $(if $(DOCKER_VERSION), "--build-arg=DOCKER_VERSION=$(DOCKER_VERSION)",)
TRAEFIK_ENVS := \
@ -32,7 +32,8 @@ TRAEFIK_ENVS := \
TRAEFIK_MOUNT := -v "$(CURDIR)/$(BIND_DIR):/go/src/github.com/traefik/traefik/$(BIND_DIR)"
DOCKER_RUN_OPTS := $(TRAEFIK_ENVS) $(TRAEFIK_MOUNT) "$(TRAEFIK_DEV_IMAGE)"
DOCKER_NON_INTERACTIVE ?= false
DOCKER_RUN_TRAEFIK := docker run --add-host=host.docker.internal:127.0.0.1 $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INTERACTIVE), , -it) $(DOCKER_RUN_OPTS)
DOCKER_RUN_TRAEFIK := docker run $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INTERACTIVE), , -it) $(DOCKER_RUN_OPTS)
DOCKER_RUN_TRAEFIK_TEST := docker run --add-host=host.docker.internal:127.0.0.1 --rm --name=traefik --network traefik-test-network -v $(PWD):$(PWD) -w $(PWD) $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INTERACTIVE), , -it) $(DOCKER_RUN_OPTS)
DOCKER_RUN_TRAEFIK_NOTTY := docker run $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INTERACTIVE), , -i) $(DOCKER_RUN_OPTS)
PRE_TARGET ?= build-dev-image
@ -81,30 +82,27 @@ crossbinary-default-parallel:
$(MAKE) build-dev-image crossbinary-default
## Run the unit and integration tests
test: build-dev-image
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate test-unit binary test-integration
test: $(PRE_TARGET)
-docker network create traefik-test-network --driver bridge --subnet 172.31.42.0/24
trap 'docker network rm traefik-test-network' EXIT; \
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK_TEST),) ./script/make.sh generate test-unit binary test-integration
## Run the unit tests
test-unit: $(PRE_TARGET)
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate test-unit
-docker network create traefik-test-network --driver bridge --subnet 172.31.42.0/24
trap 'docker network rm traefik-test-network' EXIT; \
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK_TEST)) ./script/make.sh generate test-unit
## Run the integration tests
test-integration: $(PRE_TARGET)
-docker network create traefik-test-network --driver bridge --subnet 172.31.42.0/24
trap 'docker network rm traefik-test-network' EXIT; \
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK_TEST),) ./script/make.sh generate binary test-integration
## Pull all images for integration tests
pull-images:
grep --no-filename -E '^\s+image:' ./integration/resources/compose/*.yml | awk '{print $$2}' | sort | uniq | xargs -P 6 -n 1 docker pull
## Run the integration tests
test-integration: $(PRE_TARGET) binary
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK),TEST_CONTAINER=1) ./script/make.sh test-integration
TEST_HOST=1 ./script/make.sh test-integration
## Run the container integration tests
test-integration-container: $(PRE_TARGET) binary
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK),TEST_CONTAINER=1) ./script/make.sh test-integration
## Run the host integration tests
test-integration-host: $(PRE_TARGET) binary
TEST_HOST=1 ./script/make.sh test-integration
## Validate code and docs
validate-files: $(PRE_TARGET)
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate validate-lint validate-misspell

31
go.mod
View file

@ -7,24 +7,19 @@ require (
github.com/BurntSushi/toml v0.3.1
github.com/ExpediaDotCom/haystack-client-go v0.0.0-20190315171017-e7edbdf53a61
github.com/Masterminds/sprig/v3 v3.2.2
github.com/Microsoft/hcsshim v0.8.7 // indirect
github.com/Shopify/sarama v1.23.1 // indirect
github.com/abbot/go-http-auth v0.0.0-00010101000000-000000000000
github.com/abronan/valkeyrie v0.2.0
github.com/aws/aws-sdk-go v1.39.0
github.com/cenkalti/backoff/v4 v4.1.1
github.com/containerd/containerd v1.3.2 // indirect
github.com/compose-spec/compose-go v1.0.3
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
github.com/davecgh/go-spew v1.1.1
github.com/docker/cli v0.0.0-20200221155518-740919cc7fc0
github.com/docker/distribution v2.7.1+incompatible // indirect
github.com/docker/docker v17.12.0-ce-rc1.0.20200204220554-5f6d6f3f2203+incompatible
github.com/docker/docker-credential-helpers v0.6.3 // indirect
github.com/docker/cli v20.10.7+incompatible
github.com/docker/compose/v2 v2.0.1
github.com/docker/docker v20.10.7+incompatible
github.com/docker/go-connections v0.4.0
github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82 // indirect
github.com/docker/libcompose v0.0.0-20190805081528-eac9fe1b8b03 // indirect
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e // indirect
github.com/eapache/channels v1.1.0
github.com/elazarl/go-bindata-assetfs v1.0.0
@ -41,24 +36,17 @@ require (
github.com/hashicorp/consul/api v1.10.0
github.com/hashicorp/go-hclog v0.16.1
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-version v1.2.1
github.com/hashicorp/go-version v1.3.0
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d
github.com/instana/go-sensor v1.5.1
github.com/klauspost/compress v1.13.0
github.com/libkermit/compose v0.0.0-20171122111507-c04e39c026ad
github.com/libkermit/docker v0.0.0-20171122101128-e6674d32b807
github.com/libkermit/docker-check v0.0.0-20171122104347-1113af38e591
github.com/lucas-clemente/quic-go v0.23.0
github.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f
github.com/miekg/dns v1.1.43
github.com/mitchellh/copystructure v1.0.0
github.com/mitchellh/hashstructure v1.0.0
github.com/mitchellh/mapstructure v1.4.1
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/opencontainers/runc v1.0.0-rc10 // indirect
github.com/opentracing/opentracing-go v1.1.0
github.com/mitchellh/mapstructure v1.4.2
github.com/opentracing/opentracing-go v1.2.0
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5
github.com/openzipkin/zipkin-go v0.2.2
github.com/patrickmn/go-cache v2.1.0+incompatible
@ -68,7 +56,7 @@ require (
github.com/prometheus/client_golang v1.11.0
github.com/prometheus/client_model v0.2.0
github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac
github.com/sirupsen/logrus v1.7.0
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.0
github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154
github.com/tinylib/msgp v1.0.2 // indirect
@ -109,3 +97,6 @@ replace (
github.com/mailgun/minheap => github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595
github.com/mailgun/multibuf => github.com/containous/multibuf v0.0.0-20190809014333-8b6c9a7e6bba
)
// https://github.com/docker/compose/blob/e44222664abd07ce1d1fe6796d84d93cbc7468c3/go.mod#L131
replace github.com/jaguilar/vt100 => github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305

770
go.sum

File diff suppressed because it is too large Load diff

View file

@ -36,12 +36,7 @@ type accessLogValue struct {
func (s *AccessLogSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "access_log")
s.composeProject.Start(c)
s.composeProject.Container(c, "server0")
s.composeProject.Container(c, "server1")
s.composeProject.Container(c, "server2")
s.composeProject.Container(c, "server3")
s.composeUp(c)
}
func (s *AccessLogSuite) TearDownTest(c *check.C) {
@ -122,7 +117,7 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontend(c *check.C) {
code: "200",
user: "test",
routerName: "rt-authFrontend",
serviceURL: "http://172.17.0",
serviceURL: "http://172.31.42",
},
}
@ -136,8 +131,6 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontend(c *check.C) {
checkStatsForLogFile(c)
s.composeProject.Container(c, "authFrontend")
waitForTraefik(c, "authFrontend")
// Verify Traefik started OK
@ -193,7 +186,7 @@ func (s *AccessLogSuite) TestAccessLogDigestAuthMiddleware(c *check.C) {
code: "200",
user: "test",
routerName: "rt-digestAuthMiddleware",
serviceURL: "http://172.17.0",
serviceURL: "http://172.31.42",
},
}
@ -207,8 +200,6 @@ func (s *AccessLogSuite) TestAccessLogDigestAuthMiddleware(c *check.C) {
checkStatsForLogFile(c)
s.composeProject.Container(c, "digestAuthMiddleware")
waitForTraefik(c, "digestAuthMiddleware")
// Verify Traefik started OK
@ -322,8 +313,6 @@ func (s *AccessLogSuite) TestAccessLogFrontendRedirect(c *check.C) {
checkStatsForLogFile(c)
s.composeProject.Container(c, "frontendRedirect")
waitForTraefik(c, "frontendRedirect")
// Verify Traefik started OK
@ -375,8 +364,6 @@ func (s *AccessLogSuite) TestAccessLogRateLimit(c *check.C) {
checkStatsForLogFile(c)
s.composeProject.Container(c, "rateLimit")
waitForTraefik(c, "rateLimit")
// Verify Traefik started OK
@ -471,8 +458,6 @@ func (s *AccessLogSuite) TestAccessLogFrontendWhitelist(c *check.C) {
checkStatsForLogFile(c)
s.composeProject.Container(c, "frontendWhitelist")
waitForTraefik(c, "frontendWhitelist")
// Verify Traefik started OK
@ -504,7 +489,7 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontendSuccess(c *check.C) {
code: "200",
user: "test",
routerName: "rt-authFrontend",
serviceURL: "http://172.17.0",
serviceURL: "http://172.31.42",
},
}
@ -518,8 +503,6 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontendSuccess(c *check.C) {
checkStatsForLogFile(c)
s.composeProject.Container(c, "authFrontend")
waitForTraefik(c, "authFrontend")
// Verify Traefik started OK
@ -548,7 +531,6 @@ func checkNoOtherTraefikProblems(c *check.C) {
c.Assert(err, checker.IsNil)
if len(traefikLog) > 0 {
fmt.Printf("%s\n", string(traefikLog))
c.Assert(traefikLog, checker.HasLen, 0)
}
}
@ -616,7 +598,6 @@ func checkTraefikStarted(c *check.C) []byte {
c.Assert(err, checker.IsNil)
if len(traefikLog) > 0 {
fmt.Printf("%s\n", string(traefikLog))
c.Assert(traefikLog, checker.HasLen, 0)
}
return traefikLog
}

View file

@ -4,6 +4,7 @@ import (
"crypto/tls"
"crypto/x509"
"fmt"
"net"
"net/http"
"os"
"path/filepath"
@ -19,7 +20,7 @@ import (
checker "github.com/vdemeester/shakers"
)
// ACME test suites (using libcompose).
// ACME test suites.
type AcmeSuite struct {
BaseSuite
pebbleIP string
@ -54,7 +55,8 @@ const (
)
func (s *AcmeSuite) getAcmeURL() string {
return fmt.Sprintf("https://%s:14000/dir", s.pebbleIP)
return fmt.Sprintf("https://%s/dir",
net.JoinHostPort(s.pebbleIP, "14000"))
}
func setupPebbleRootCA() (*http.Transport, error) {
@ -86,11 +88,10 @@ func setupPebbleRootCA() (*http.Transport, error) {
func (s *AcmeSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "pebble")
s.composeProject.Start(c)
s.composeUp(c)
s.fakeDNSServer = startFakeDNSServer()
s.pebbleIP = s.composeProject.Container(c, "pebble").NetworkSettings.IPAddress
s.fakeDNSServer = startFakeDNSServer(s.getContainerIP(c, "traefik"))
s.pebbleIP = s.getComposeServiceIP(c, "pebble")
pebbleTransport, err := setupPebbleRootCA()
if err != nil {
@ -115,15 +116,14 @@ func (s *AcmeSuite) SetUpSuite(c *check.C) {
}
func (s *AcmeSuite) TearDownSuite(c *check.C) {
if s.fakeDNSServer != nil {
err := s.fakeDNSServer.Shutdown()
if err != nil {
c.Log(err)
}
// shutdown and delete compose project
if s.composeProject != nil {
s.composeProject.Stop(c)
}
s.composeDown(c)
}
func (s *AcmeSuite) TestHTTP01Domains(c *check.C) {

View file

@ -2,6 +2,7 @@ package integration
import (
"fmt"
"net"
"net/http"
"os"
"time"
@ -16,30 +17,29 @@ type ConsulCatalogSuite struct {
BaseSuite
consulClient *api.Client
consulAgentClient *api.Client
consulAddress string
consulAgentAddress string
consulURL string
}
func (s *ConsulCatalogSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "consul_catalog")
s.composeProject.Start(c)
s.consulAddress = "http://" + s.composeProject.Container(c, "consul").NetworkSettings.IPAddress + ":8500"
client, err := api.NewClient(&api.Config{
Address: s.consulAddress,
s.composeUp(c)
s.consulURL = "http://" + net.JoinHostPort(s.getComposeServiceIP(c, "consul"), "8500")
var err error
s.consulClient, err = api.NewClient(&api.Config{
Address: s.consulURL,
})
c.Check(err, check.IsNil)
s.consulClient = client
// Wait for consul to elect itself leader
err = s.waitToElectConsulLeader()
c.Assert(err, checker.IsNil)
s.consulAgentAddress = "http://" + s.composeProject.Container(c, "consul-agent").NetworkSettings.IPAddress + ":8500"
clientAgent, err := api.NewClient(&api.Config{
Address: s.consulAgentAddress,
s.consulAgentClient, err = api.NewClient(&api.Config{
Address: "http://" + net.JoinHostPort(s.getComposeServiceIP(c, "consul-agent"), "8500"),
})
c.Check(err, check.IsNil)
s.consulAgentClient = clientAgent
}
func (s *ConsulCatalogSuite) waitToElectConsulLeader() error {
@ -66,13 +66,6 @@ func (s *ConsulCatalogSuite) waitForConnectCA() error {
})
}
func (s *ConsulCatalogSuite) TearDownSuite(c *check.C) {
// shutdown and delete compose project
if s.composeProject != nil {
s.composeProject.Stop(c)
}
}
func (s *ConsulCatalogSuite) registerService(reg *api.AgentServiceRegistration, onAgent bool) error {
client := s.consulClient
if onAgent {
@ -96,7 +89,7 @@ func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *c
Name: "whoami",
Tags: []string{"traefik.enable=true"},
Port: 80,
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
Address: s.getComposeServiceIP(c, "whoami1"),
}
err := s.registerService(reg1, false)
c.Assert(err, checker.IsNil)
@ -106,7 +99,7 @@ func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *c
Name: "whoami",
Tags: []string{"traefik.enable=true"},
Port: 80,
Address: s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress,
Address: s.getComposeServiceIP(c, "whoami2"),
}
err = s.registerService(reg2, false)
c.Assert(err, checker.IsNil)
@ -116,7 +109,7 @@ func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *c
Name: "whoami",
Tags: []string{"traefik.enable=true"},
Port: 80,
Address: s.composeProject.Container(c, "whoami3").NetworkSettings.IPAddress,
Address: s.getComposeServiceIP(c, "whoami3"),
}
err = s.registerService(reg3, false)
c.Assert(err, checker.IsNil)
@ -124,7 +117,7 @@ func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *c
tempObjects := struct {
ConsulAddress string
}{
ConsulAddress: s.consulAddress,
ConsulAddress: s.consulURL,
}
file := s.adaptFile(c, "fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
@ -163,7 +156,7 @@ func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *c
}
func (s *ConsulCatalogSuite) TestByLabels(c *check.C) {
containerIP := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
containerIP := s.getComposeServiceIP(c, "whoami1")
reg := &api.AgentServiceRegistration{
ID: "whoami1",
@ -183,7 +176,7 @@ func (s *ConsulCatalogSuite) TestByLabels(c *check.C) {
tempObjects := struct {
ConsulAddress string
}{
ConsulAddress: s.consulAddress,
ConsulAddress: s.consulURL,
}
file := s.adaptFile(c, "fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
@ -195,7 +188,7 @@ func (s *ConsulCatalogSuite) TestByLabels(c *check.C) {
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
err = try.GetRequest("http://127.0.0.1:8000/whoami", 2*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContainsOr("Hostname: whoami1", "Hostname: whoami2", "Hostname: whoami3"))
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)
err = s.deregisterService("whoami1", false)
@ -207,7 +200,7 @@ func (s *ConsulCatalogSuite) TestSimpleConfiguration(c *check.C) {
ConsulAddress string
DefaultRule string
}{
ConsulAddress: s.consulAddress,
ConsulAddress: s.consulURL,
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
}
@ -219,7 +212,7 @@ func (s *ConsulCatalogSuite) TestSimpleConfiguration(c *check.C) {
Name: "whoami",
Tags: []string{"traefik.enable=true"},
Port: 80,
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
Address: s.getComposeServiceIP(c, "whoami1"),
}
err := s.registerService(reg, false)
c.Assert(err, checker.IsNil)
@ -246,7 +239,7 @@ func (s *ConsulCatalogSuite) TestRegisterServiceWithoutIP(c *check.C) {
ConsulAddress string
DefaultRule string
}{
ConsulAddress: s.consulAddress,
ConsulAddress: s.consulURL,
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
}
@ -285,7 +278,7 @@ func (s *ConsulCatalogSuite) TestDefaultConsulService(c *check.C) {
DefaultRule string
}{
ConsulAddress: s.consulAddress,
ConsulAddress: s.consulURL,
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
}
@ -296,7 +289,7 @@ func (s *ConsulCatalogSuite) TestDefaultConsulService(c *check.C) {
ID: "whoami1",
Name: "whoami",
Port: 80,
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
Address: s.getComposeServiceIP(c, "whoami1"),
}
err := s.registerService(reg, false)
c.Assert(err, checker.IsNil)
@ -324,7 +317,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithTCPLabels(c *check.C) {
ConsulAddress string
DefaultRule string
}{
ConsulAddress: s.consulAddress,
ConsulAddress: s.consulURL,
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
}
@ -341,7 +334,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithTCPLabels(c *check.C) {
"traefik.tcp.Services.Super.Loadbalancer.server.port=8080",
},
Port: 8080,
Address: s.composeProject.Container(c, "whoamitcp").NetworkSettings.IPAddress,
Address: s.getComposeServiceIP(c, "whoamitcp"),
}
err := s.registerService(reg, false)
@ -371,7 +364,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithLabels(c *check.C) {
ConsulAddress string
DefaultRule string
}{
ConsulAddress: s.consulAddress,
ConsulAddress: s.consulURL,
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
}
@ -386,7 +379,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithLabels(c *check.C) {
"traefik.http.Routers.Super.Rule=Host(`my.super.host`)",
},
Port: 80,
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
Address: s.getComposeServiceIP(c, "whoami1"),
}
err := s.registerService(reg1, false)
@ -400,7 +393,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithLabels(c *check.C) {
"traefik.http.Routers.SuperHost.Rule=Host(`my-super.host`)",
},
Port: 80,
Address: s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress,
Address: s.getComposeServiceIP(c, "whoami2"),
}
err = s.registerService(reg2, false)
c.Assert(err, checker.IsNil)
@ -438,7 +431,7 @@ func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent(c *check.C)
ConsulAddress string
DefaultRule string
}{
ConsulAddress: s.consulAddress,
ConsulAddress: s.consulURL,
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
}
@ -457,7 +450,7 @@ func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent(c *check.C)
Name: "whoami",
Tags: tags,
Port: 80,
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
Address: s.getComposeServiceIP(c, "whoami1"),
}
err := s.registerService(reg1, false)
c.Assert(err, checker.IsNil)
@ -467,7 +460,7 @@ func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent(c *check.C)
Name: "whoami",
Tags: tags,
Port: 80,
Address: s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress,
Address: s.getComposeServiceIP(c, "whoami2"),
}
err = s.registerService(reg2, true)
c.Assert(err, checker.IsNil)
@ -490,8 +483,7 @@ func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent(c *check.C)
c.Assert(err, checker.IsNil)
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200),
try.BodyContainsOr(s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress))
try.BodyContainsOr(s.getComposeServiceIP(c, "whoami1"), s.getComposeServiceIP(c, "whoami2")))
c.Assert(err, checker.IsNil)
err = s.deregisterService("whoami", false)
@ -506,7 +498,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithOneMissingLabels(c *check.C) {
ConsulAddress string
DefaultRule string
}{
ConsulAddress: s.consulAddress,
ConsulAddress: s.consulURL,
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
}
@ -521,7 +513,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithOneMissingLabels(c *check.C) {
"traefik.random.value=my.super.host",
},
Port: 80,
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
Address: s.getComposeServiceIP(c, "whoami1"),
}
err := s.registerService(reg, false)
@ -546,11 +538,12 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithOneMissingLabels(c *check.C) {
}
func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
whoamiIP := s.getComposeServiceIP(c, "whoami1")
tags := []string{
"traefik.enable=true",
"traefik.http.routers.router1.rule=Path(`/whoami`)",
"traefik.http.routers.router1.service=service1",
"traefik.http.services.service1.loadBalancer.server.url=http://" + s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
"traefik.http.services.service1.loadBalancer.server.url=http://" + whoamiIP,
}
reg1 := &api.AgentServiceRegistration{
@ -558,7 +551,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
Name: "whoami",
Tags: tags,
Port: 80,
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
Address: whoamiIP,
Check: &api.AgentServiceCheck{
CheckID: "some-failed-check",
TCP: "127.0.0.1:1234",
@ -574,7 +567,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
tempObjects := struct {
ConsulAddress string
}{
ConsulAddress: s.consulAddress,
ConsulAddress: s.consulURL,
}
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
@ -592,17 +585,16 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
err = s.deregisterService("whoami1", false)
c.Assert(err, checker.IsNil)
containerIP := s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress
whoami2IP := s.getComposeServiceIP(c, "whoami2")
reg2 := &api.AgentServiceRegistration{
ID: "whoami2",
Name: "whoami",
Tags: tags,
Port: 80,
Address: containerIP,
Address: whoami2IP,
Check: &api.AgentServiceCheck{
CheckID: "some-ok-check",
TCP: containerIP + ":80",
TCP: whoami2IP + ":80",
Name: "some-ok-check",
Interval: "1s",
Timeout: "1s",
@ -629,7 +621,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect(c *check.C) {
err := s.waitForConnectCA()
c.Assert(err, checker.IsNil)
connectIP := s.composeProject.Container(c, "connect").NetworkSettings.IPAddress
connectIP := s.getComposeServiceIP(c, "connect")
reg := &api.AgentServiceRegistration{
ID: "uuid-api1",
Name: "uuid-api",
@ -649,7 +641,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect(c *check.C) {
err = s.registerService(reg, false)
c.Assert(err, checker.IsNil)
whoamiIP := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
whoamiIP := s.getComposeServiceIP(c, "whoami1")
regWhoami := &api.AgentServiceRegistration{
ID: "whoami1",
Name: "whoami",
@ -667,7 +659,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect(c *check.C) {
tempObjects := struct {
ConsulAddress string
}{
ConsulAddress: s.consulAddress,
ConsulAddress: s.consulURL,
}
file := s.adaptFile(c, "fixtures/consul_catalog/connect.toml", tempObjects)
defer os.Remove(file)
@ -695,7 +687,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
err := s.waitForConnectCA()
c.Assert(err, checker.IsNil)
connectIP := s.composeProject.Container(c, "connect").NetworkSettings.IPAddress
connectIP := s.getComposeServiceIP(c, "connect")
reg := &api.AgentServiceRegistration{
ID: "uuid-api1",
Name: "uuid-api",
@ -714,7 +706,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
err = s.registerService(reg, false)
c.Assert(err, checker.IsNil)
whoamiIP := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
whoamiIP := s.getComposeServiceIP(c, "whoami1")
regWhoami := &api.AgentServiceRegistration{
ID: "whoami1",
Name: "whoami1",
@ -729,7 +721,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
err = s.registerService(regWhoami, false)
c.Assert(err, checker.IsNil)
whoami2IP := s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress
whoami2IP := s.getComposeServiceIP(c, "whoami2")
regWhoami2 := &api.AgentServiceRegistration{
ID: "whoami2",
Name: "whoami2",
@ -748,7 +740,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
tempObjects := struct {
ConsulAddress string
}{
ConsulAddress: s.consulAddress,
ConsulAddress: s.consulURL,
}
file := s.adaptFile(c, "fixtures/consul_catalog/connect_by_default.toml", tempObjects)
defer os.Remove(file)
@ -781,7 +773,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect_NotAware(c *check.C) {
err := s.waitForConnectCA()
c.Assert(err, checker.IsNil)
connectIP := s.composeProject.Container(c, "connect").NetworkSettings.IPAddress
connectIP := s.getComposeServiceIP(c, "connect")
reg := &api.AgentServiceRegistration{
ID: "uuid-api1",
Name: "uuid-api",
@ -801,7 +793,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect_NotAware(c *check.C) {
err = s.registerService(reg, false)
c.Assert(err, checker.IsNil)
whoamiIP := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
whoamiIP := s.getComposeServiceIP(c, "whoami1")
regWhoami := &api.AgentServiceRegistration{
ID: "whoami1",
Name: "whoami",
@ -819,7 +811,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect_NotAware(c *check.C) {
tempObjects := struct {
ConsulAddress string
}{
ConsulAddress: s.consulAddress,
ConsulAddress: s.consulURL,
}
file := s.adaptFile(c, "fixtures/consul_catalog/connect_not_aware.toml", tempObjects)
defer os.Remove(file)

View file

@ -3,6 +3,8 @@ package integration
import (
"bytes"
"encoding/json"
"fmt"
"net"
"net/http"
"os"
"path/filepath"
@ -18,20 +20,24 @@ import (
checker "github.com/vdemeester/shakers"
)
// Consul test suites (using libcompose).
// Consul test suites.
type ConsulSuite struct {
BaseSuite
kvClient store.Store
consulURL string
}
func (s *ConsulSuite) setupStore(c *check.C) {
s.createComposeProject(c, "consul")
s.composeProject.Start(c)
s.composeUp(c)
consulAddr := net.JoinHostPort(s.getComposeServiceIP(c, "consul"), "8500")
s.consulURL = fmt.Sprintf("http://%s", consulAddr)
consul.Register()
kv, err := valkeyrie.NewStore(
store.CONSUL,
[]string{s.composeProject.Container(c, "consul").NetworkSettings.IPAddress + ":8500"},
[]string{consulAddr},
&store.Config{
ConnectionTimeout: 10 * time.Second,
},
@ -46,20 +52,10 @@ func (s *ConsulSuite) setupStore(c *check.C) {
c.Assert(err, checker.IsNil)
}
func (s *ConsulSuite) TearDownTest(c *check.C) {
// shutdown and delete compose project
if s.composeProject != nil {
s.composeProject.Stop(c)
}
}
func (s *ConsulSuite) TearDownSuite(c *check.C) {}
func (s *ConsulSuite) TestSimpleConfiguration(c *check.C) {
s.setupStore(c)
address := "http://" + s.composeProject.Container(c, "consul").NetworkSettings.IPAddress + ":8500"
file := s.adaptFile(c, "fixtures/consul/simple.toml", struct{ ConsulAddress string }{address})
file := s.adaptFile(c, "fixtures/consul/simple.toml", struct{ ConsulAddress string }{s.consulURL})
defer os.Remove(file)
data := map[string]string{

View file

@ -14,33 +14,17 @@ import (
checker "github.com/vdemeester/shakers"
)
const (
composeProject = "minimal"
)
// Docker tests suite.
type DockerComposeSuite struct {
BaseSuite
}
func (s *DockerComposeSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, composeProject)
s.composeProject.Start(c)
}
func (s *DockerComposeSuite) TearDownSuite(c *check.C) {
// shutdown and delete compose project
if s.composeProject != nil {
s.composeProject.Stop(c)
}
s.createComposeProject(c, "minimal")
s.composeUp(c)
}
func (s *DockerComposeSuite) TestComposeScale(c *check.C) {
serviceCount := 2
composeService := "whoami1"
s.composeProject.Scale(c, composeService, serviceCount)
tempObjects := struct {
DockerHost string
DefaultRule string
@ -81,8 +65,8 @@ func (s *DockerComposeSuite) TestComposeScale(c *check.C) {
if strings.HasSuffix(name, "@internal") {
continue
}
c.Assert(name, checker.Equals, composeService+"-integrationtest"+composeProject+"@docker")
c.Assert(service.LoadBalancer.Servers, checker.HasLen, serviceCount)
c.Assert(name, checker.Equals, "whoami1-"+s.composeProject.Name+"@docker")
c.Assert(service.LoadBalancer.Servers, checker.HasLen, 2)
// We could break here, but we don't just to keep us honest.
}
}

View file

@ -6,80 +6,24 @@ import (
"io"
"net/http"
"os"
"strings"
"time"
"github.com/docker/docker/pkg/namesgenerator"
"github.com/go-check/check"
d "github.com/libkermit/docker"
"github.com/libkermit/docker-check"
"github.com/traefik/traefik/v2/integration/try"
checker "github.com/vdemeester/shakers"
)
// Images to have or pull before the build in order to make it work.
// FIXME handle this offline but loading them before build.
var RequiredImages = map[string]string{
"swarm": "1.0.0",
"traefik/whoami": "latest",
}
// Docker tests suite.
type DockerSuite struct {
BaseSuite
project *docker.Project
}
func (s *DockerSuite) startContainer(c *check.C, image string, args ...string) string {
return s.startContainerWithConfig(c, image, d.ContainerConfig{
Cmd: args,
})
}
func (s *DockerSuite) startContainerWithLabels(c *check.C, image string, labels map[string]string, args ...string) string {
return s.startContainerWithConfig(c, image, d.ContainerConfig{
Cmd: args,
Labels: labels,
})
}
func (s *DockerSuite) startContainerWithNameAndLabels(c *check.C, name, image string, labels map[string]string, args ...string) string {
return s.startContainerWithConfig(c, image, d.ContainerConfig{
Name: name,
Cmd: args,
Labels: labels,
})
}
func (s *DockerSuite) startContainerWithConfig(c *check.C, image string, config d.ContainerConfig) string {
if config.Name == "" {
config.Name = namesgenerator.GetRandomName(10)
}
container := s.project.StartWithConfig(c, image, config)
// FIXME(vdemeester) this is ugly (it's because of the / in front of the name in docker..)
return strings.SplitAfter(container.Name, "/")[1]
}
func (s *DockerSuite) stopAndRemoveContainerByName(c *check.C, name string) {
s.project.Stop(c, name)
s.project.Remove(c, name)
}
func (s *DockerSuite) SetUpSuite(c *check.C) {
project := docker.NewProjectFromEnv(c)
s.project = project
// Pull required images
for repository, tag := range RequiredImages {
image := fmt.Sprintf("%s:%s", repository, tag)
s.project.Pull(c, image)
}
func (s *DockerSuite) SetUpTest(c *check.C) {
s.createComposeProject(c, "docker")
}
func (s *DockerSuite) TearDownTest(c *check.C) {
s.project.Clean(c, os.Getenv("CIRCLECI") != "") // FIXME
s.composeDown(c)
}
func (s *DockerSuite) TestSimpleConfiguration(c *check.C) {
@ -94,13 +38,15 @@ func (s *DockerSuite) TestSimpleConfiguration(c *check.C) {
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
defer os.Remove(file)
s.composeUp(c)
cmd, display := s.traefikCmd(withConfigFile(file))
defer display(c)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
// TODO validate : run on 80
// 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)
@ -118,18 +64,19 @@ func (s *DockerSuite) TestDefaultDockerContainers(c *check.C) {
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
defer os.Remove(file)
name := s.startContainer(c, "swarm:1.0.0", "manage", "token://blablabla")
s.composeUp(c, "simple")
// Start traefik
cmd, display := s.traefikCmd(withConfigFile(file))
defer display(c)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil)
c.Assert(err, checker.IsNil)
req.Host = fmt.Sprintf("%s.docker.localhost", strings.ReplaceAll(name, "_", "-"))
req.Host = fmt.Sprintf("simple-%s.docker.localhost", s.composeProject.Name)
// FIXME Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
resp, err := try.ResponseUntilStatusCode(req, 1500*time.Millisecond, http.StatusOK)
@ -156,18 +103,12 @@ func (s *DockerSuite) TestDockerContainersWithTCPLabels(c *check.C) {
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
defer os.Remove(file)
// Start a container with some labels
labels := map[string]string{
"traefik.tcp.Routers.Super.Rule": "HostSNI(`my.super.host`)",
"traefik.tcp.Routers.Super.tls": "true",
"traefik.tcp.Services.Super.Loadbalancer.server.port": "8080",
}
s.startContainerWithLabels(c, "traefik/whoamitcp", labels, "-name", "my.super.host")
s.composeUp(c, "withtcplabels")
// Start traefik
cmd, display := s.traefikCmd(withConfigFile(file))
defer display(c)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
@ -193,17 +134,7 @@ func (s *DockerSuite) TestDockerContainersWithLabels(c *check.C) {
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
defer os.Remove(file)
// Start a container with some labels
labels := map[string]string{
"traefik.http.Routers.Super.Rule": "Host(`my.super.host`)",
}
s.startContainerWithLabels(c, "swarm:1.0.0", labels, "manage", "token://blabla")
// Start another container by replacing a '.' by a '-'
labels = map[string]string{
"traefik.http.Routers.SuperHost.Rule": "Host(`my-super.host`)",
}
s.startContainerWithLabels(c, "swarm:1.0.0", labels, "manage", "token://blablabla")
s.composeUp(c, "withlabels1", "withlabels2")
// Start traefik
cmd, display := s.traefikCmd(withConfigFile(file))
@ -249,15 +180,12 @@ func (s *DockerSuite) TestDockerContainersWithOneMissingLabels(c *check.C) {
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
defer os.Remove(file)
// Start a container with some labels
labels := map[string]string{
"traefik.random.value": "my.super.host",
}
s.startContainerWithLabels(c, "swarm:1.0.0", labels, "manage", "token://blabla")
s.composeUp(c, "withonelabelmissing")
// Start traefik
cmd, display := s.traefikCmd(withConfigFile(file))
defer display(c)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
@ -285,16 +213,12 @@ func (s *DockerSuite) TestRestartDockerContainers(c *check.C) {
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
defer os.Remove(file)
// Start a container with some labels
labels := map[string]string{
"traefik.http.Routers.Super.Rule": "Host(`my.super.host`)",
"traefik.http.Services.powpow.LoadBalancer.server.Port": "2375",
}
s.startContainerWithNameAndLabels(c, "powpow", "swarm:1.0.0", labels, "manage", "token://blabla")
s.composeUp(c, "powpow")
// Start traefik
cmd, display := s.traefikCmd(withConfigFile(file))
defer display(c)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
@ -318,16 +242,14 @@ func (s *DockerSuite) TestRestartDockerContainers(c *check.C) {
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("powpow"))
c.Assert(err, checker.IsNil)
s.stopAndRemoveContainerByName(c, "powpow")
defer s.project.Remove(c, "powpow")
s.composeStop(c, "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)
s.startContainerWithNameAndLabels(c, "powpow", "swarm:1.0.0", labels, "manage", "token://blabla")
s.composeUp(c, "powpow")
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("powpow"))
c.Assert(err, checker.IsNil)
}

View file

@ -10,7 +10,7 @@ import (
checker "github.com/vdemeester/shakers"
)
// ErrorPagesSuite test suites (using libcompose).
// ErrorPagesSuite test suites.
type ErrorPagesSuite struct {
BaseSuite
ErrorPageIP string
@ -19,10 +19,10 @@ type ErrorPagesSuite struct {
func (s *ErrorPagesSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "error_pages")
s.composeProject.Start(c)
s.composeUp(c)
s.ErrorPageIP = s.composeProject.Container(c, "nginx2").NetworkSettings.IPAddress
s.BackendIP = s.composeProject.Container(c, "nginx1").NetworkSettings.IPAddress
s.ErrorPageIP = s.getComposeServiceIP(c, "nginx2")
s.BackendIP = s.getComposeServiceIP(c, "nginx1")
}
func (s *ErrorPagesSuite) TestSimpleConfiguration(c *check.C) {

View file

@ -3,6 +3,7 @@ package integration
import (
"bytes"
"encoding/json"
"net"
"net/http"
"os"
"path/filepath"
@ -18,20 +19,24 @@ import (
checker "github.com/vdemeester/shakers"
)
// etcd test suites (using libcompose).
// etcd test suites.
type EtcdSuite struct {
BaseSuite
kvClient store.Store
etcdAddr string
}
func (s *EtcdSuite) setupStore(c *check.C) {
func (s *EtcdSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "etcd")
s.composeProject.Start(c)
s.composeUp(c)
etcdv3.Register()
kv, err := valkeyrie.NewStore(
var err error
s.etcdAddr = net.JoinHostPort(s.getComposeServiceIP(c, "etcd"), "2379")
s.kvClient, err = valkeyrie.NewStore(
store.ETCDV3,
[]string{s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress + ":2379"},
[]string{s.etcdAddr},
&store.Config{
ConnectionTimeout: 10 * time.Second,
},
@ -39,27 +44,14 @@ func (s *EtcdSuite) setupStore(c *check.C) {
if err != nil {
c.Fatal("Cannot create store etcd")
}
s.kvClient = kv
// wait for etcd
err = try.Do(60*time.Second, try.KVExists(kv, "test"))
err = try.Do(60*time.Second, try.KVExists(s.kvClient, "test"))
c.Assert(err, checker.IsNil)
}
func (s *EtcdSuite) TearDownTest(c *check.C) {
// shutdown and delete compose project
if s.composeProject != nil {
s.composeProject.Stop(c)
}
}
func (s *EtcdSuite) TearDownSuite(c *check.C) {}
func (s *EtcdSuite) TestSimpleConfiguration(c *check.C) {
s.setupStore(c)
address := s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress + ":2379"
file := s.adaptFile(c, "fixtures/etcd/simple.toml", struct{ EtcdAddress string }{address})
file := s.adaptFile(c, "fixtures/etcd/simple.toml", struct{ EtcdAddress string }{s.etcdAddr})
defer os.Remove(file)
data := map[string]string{

View file

@ -9,7 +9,9 @@ import (
"github.com/traefik/traefik/v2/pkg/log"
)
type handler struct{}
type handler struct {
traefikIP string
}
// ServeDNS a fake DNS server
// Simplified version of the Challenge Test Server from Boulder
@ -21,11 +23,6 @@ func (s *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
m.SetReply(r)
m.Compress = false
fakeDNS := os.Getenv("DOCKER_HOST_IP")
if fakeDNS == "" {
fakeDNS = "127.0.0.1"
}
for _, q := range r.Question {
logger.Infof("Query -- [%s] %s", q.Name, dns.TypeToString[q.Qtype])
@ -38,7 +35,7 @@ func (s *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
Class: dns.ClassINET,
Ttl: 0,
}
record.A = net.ParseIP(fakeDNS)
record.A = net.ParseIP(s.traefikIP)
m.Answer = append(m.Answer, record)
case dns.TypeCAA:
@ -101,11 +98,11 @@ func (s *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
}
}
func startFakeDNSServer() *dns.Server {
func startFakeDNSServer(traefikIP string) *dns.Server {
srv := &dns.Server{
Addr: ":5053",
Net: "udp",
Handler: &handler{},
Handler: &handler{traefikIP},
}
go func() {

View file

@ -15,7 +15,7 @@ type FileSuite struct{ BaseSuite }
func (s *FileSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "file")
s.composeProject.Start(c)
s.composeUp(c)
}
func (s *FileSuite) TestSimpleConfiguration(c *check.C) {

View file

@ -6,4 +6,4 @@
[http.services]
[http.services.service2.loadBalancer]
[[http.services.service2.loadBalancer.servers]]
url = "http://172.17.0.123:80"
url = "http://127.0.0.1:80"

View file

@ -33,13 +33,13 @@
[http.services.service1.loadBalancer]
[[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoamiEndpoint}}:8080"
url = "http://{{ .WhoamiIP }}:8080"
[[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoamiEndpoint}}:8081"
url = "http://{{ .WhoamiIP }}:8081"
[[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoamiEndpoint}}:8082"
url = "http://{{ .WhoamiIP }}:8082"
[[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoamiEndpoint}}:80"
url = "http://{{ .WhoamiIP }}:80"

View file

@ -31,7 +31,7 @@
[http.services.service1.loadBalancer]
[[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoamiEndpoint}}:8080"
url = "http://{{ .WhoamiIP }}:8080"
[[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoamiEndpoint}}:80"
url = "http://{{ .WhoamiIP }}:80"

View file

@ -27,7 +27,7 @@
[tcp.services]
[tcp.services.whoami-no-tls.loadBalancer]
[[tcp.services.whoami-no-tls.loadBalancer.servers]]
address = "localhost:8086"
address = "whoami-no-tls:8080"
[http]
[http.routers]
@ -40,4 +40,4 @@
[http.services]
[http.services.whoami.loadBalancer]
[[http.services.whoami.loadBalancer.servers]]
url = "http://localhost:8085"
url = "http://whoami:80"

View file

@ -27,4 +27,4 @@
[tcp.services]
[tcp.services.whoami-no-tls.loadBalancer]
[[tcp.services.whoami-no-tls.loadBalancer.servers]]
address = "localhost:8086"
address = "whoami-banner:8080"

View file

@ -38,18 +38,14 @@
[tcp.services]
[tcp.services.whoami-a.loadBalancer]
[[tcp.services.whoami-a.loadBalancer.servers]]
address = "localhost:8081"
address = "whoami-a:8080"
[tcp.services.whoami-b.loadBalancer]
[[tcp.services.whoami-b.loadBalancer.servers]]
address = "localhost:8082"
address = "whoami-b:8080"
[tcp.middlewares]
[tcp.middlewares.allowing-ipwhitelist.ipWhiteList]
sourceRange = ["127.0.0.1/32"]
[tcp.middlewares.blocking-ipwhitelist.ipWhiteList]
sourceRange = ["127.127.127.127/32"]
[[tls.certificates]]
certFile = "fixtures/tcp/whoami-c.crt"
keyFile = "fixtures/tcp/whoami-c.key"

View file

@ -29,11 +29,15 @@
rule = "Path(`/whoami/`)"
service = "whoami"
[http.routers.my-https-router.tls]
[http.routers.api]
rule = "PathPrefix(`/api`)"
service = "api@internal"
entryPoints = ["traefik"]
[http.services]
[http.services.whoami.loadBalancer]
[[http.services.whoami.loadBalancer.servers]]
url = "http://localhost:8085"
url = "http://whoami:80"
[tcp]
[tcp.routers]
[tcp.routers.to-whoami-a]
@ -58,15 +62,15 @@
[tcp.services.whoami-a.loadBalancer]
[[tcp.services.whoami-a.loadBalancer.servers]]
address = "localhost:8081"
address = "whoami-a:8080"
[tcp.services.whoami-b.loadBalancer]
[[tcp.services.whoami-b.loadBalancer.servers]]
address = "localhost:8082"
address = "whoami-b:8080"
[tcp.services.whoami-no-cert.loadBalancer]
[[tcp.services.whoami-no-cert.loadBalancer.servers]]
address = "localhost:8083"
address = "whoami-no-cert:8080"
[[tls.certificates]]
certFile = "fixtures/tcp/whoami-c.crt"

View file

@ -36,7 +36,7 @@
[tcp.services.whoami-no-cert]
[tcp.services.whoami-no-cert.loadBalancer]
[[tcp.services.whoami-no-cert.loadBalancer.servers]]
address = "localhost:8083"
address = "whoami-no-cert:8080"
[tls.options]

View file

@ -24,14 +24,14 @@
service = "whoami-a"
entryPoints = [ "tcp" ]
[tcp.routers.to-whoami-a.tls]
passthrough=true
passthrough = true
[tcp.routers.to-whoami-b]
rule = "HostSNI(`whoami-b.test`)"
service = "whoami-b"
entryPoints = [ "tcp" ]
[tcp.routers.to-whoami-b.tls]
passthrough=true
passthrough = true
[tcp.routers.to-whoami-no-cert]
rule = "HostSNI(`whoami-c.test`)"
@ -47,16 +47,17 @@
[tcp.services]
[tcp.services.whoami-no-tls.loadBalancer]
[[tcp.services.whoami-no-tls.loadBalancer.servers]]
address = "localhost:8084"
address = "whoami-no-tls:8080"
[tcp.services.whoami-a.loadBalancer]
[[tcp.services.whoami-a.loadBalancer.servers]]
address = "localhost:8081"
address = "whoami-a:8080"
[tcp.services.whoami-b.loadBalancer]
[[tcp.services.whoami-b.loadBalancer.servers]]
address = "localhost:8082"
address = "whoami-b:8080"
[tcp.services.whoami-no-cert.loadBalancer]
[[tcp.services.whoami-no-cert.loadBalancer.servers]]
address = "localhost:8083"
address = "whoami-no-cert:8080"

View file

@ -27,4 +27,4 @@
[tcp.services]
[tcp.services.whoami-no-tls.loadBalancer]
[[tcp.services.whoami-no-tls.loadBalancer.servers]]
address = "localhost:8084"
address = "whoami-no-tls:8080"

View file

@ -18,25 +18,24 @@
## dynamic configuration ##
[tcp]
[tcp.routers]
[tcp.routers.to-whoami-a]
rule = "HostSNI(`whoami-a.test`)"
[tcp.routers.to-whoami-b]
rule = "HostSNI(`whoami-b.test`)"
service = "whoami"
entryPoints = [ "tcp" ]
[tcp.routers.to-whoami-a.tls]
[tcp.routers.to-whoami-b.tls]
passthrough=true
[[tcp.services.whoami.weighted.services]]
name="whoami-a"
name="whoami-b"
weight=3
[[tcp.services.whoami.weighted.services]]
name="whoami-b"
name="whoami-ab"
weight=1
[tcp.services.whoami-a.loadBalancer]
[[tcp.services.whoami-a.loadBalancer.servers]]
address = "localhost:8081"
[tcp.services.whoami-b.loadBalancer]
[[tcp.services.whoami-b.loadBalancer.servers]]
address = "localhost:8082"
address = "whoami-b:8080"
[tcp.services.whoami-ab.loadBalancer]
[[tcp.services.whoami-ab.loadBalancer.servers]]
address = "whoami-ab:8080"

View file

@ -55,16 +55,16 @@
[http.services.service1.loadBalancer]
passHostHeader = true
[[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
[http.services.service2]
[http.services.service2.loadBalancer]
passHostHeader = true
[[http.services.service2.loadBalancer.servers]]
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
[http.services.service3]
[http.services.service3.loadBalancer]
passHostHeader = true
[[http.services.service3.loadBalancer.servers]]
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"

View file

@ -54,16 +54,16 @@
[http.services.service1.loadBalancer]
passHostHeader = true
[[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
[http.services.service2]
[http.services.service2.loadBalancer]
passHostHeader = true
[[http.services.service2.loadBalancer.servers]]
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
[http.services.service3]
[http.services.service3.loadBalancer]
passHostHeader = true
[[http.services.service3.loadBalancer.servers]]
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"

View file

@ -50,16 +50,16 @@
[http.services.service1.loadBalancer]
passHostHeader = true
[[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
[http.services.service2]
[http.services.service2.loadBalancer]
passHostHeader = true
[[http.services.service2.loadBalancer.servers]]
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
[http.services.service3]
[http.services.service3.loadBalancer]
passHostHeader = true
[[http.services.service3.loadBalancer.servers]]
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"

View file

@ -13,7 +13,7 @@ import (
checker "github.com/vdemeester/shakers"
)
// HealthCheck test suites (using libcompose).
// HealthCheck test suites.
type HealthCheckSuite struct {
BaseSuite
whoami1IP string
@ -24,12 +24,12 @@ type HealthCheckSuite struct {
func (s *HealthCheckSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "healthcheck")
s.composeProject.Start(c)
s.composeUp(c)
s.whoami1IP = s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
s.whoami2IP = s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress
s.whoami3IP = s.composeProject.Container(c, "whoami3").NetworkSettings.IPAddress
s.whoami4IP = s.composeProject.Container(c, "whoami4").NetworkSettings.IPAddress
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 (s *HealthCheckSuite) TestSimpleConfiguration(c *check.C) {
@ -90,7 +90,7 @@ func (s *HealthCheckSuite) TestSimpleConfiguration(c *check.C) {
// 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.Not(checker.IsNil))
c.Assert(err, checker.NotNil)
// TODO validate : run on 80
resp, err := http.Get("http://127.0.0.1:8000/")

View file

@ -13,9 +13,7 @@ type HostResolverSuite struct{ BaseSuite }
func (s *HostResolverSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "hostresolver")
s.composeProject.Start(c)
s.composeProject.Container(c, "server1")
s.composeUp(c)
}
func (s *HostResolverSuite) TestSimpleConfig(c *check.C) {
@ -48,7 +46,7 @@ func (s *HostResolverSuite) TestSimpleConfig(c *check.C) {
c.Assert(err, checker.IsNil)
req.Host = test.host
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(test.status), try.HasBody())
err = try.Request(req, 1*time.Second, try.StatusCodeIs(test.status), try.HasBody())
c.Assert(err, checker.IsNil)
}
}

View file

@ -1063,13 +1063,13 @@ func (s *HTTPSSuite) TestEntryPointHttpsRedirectAndPathModification(c *check.C)
for _, test := range testCases {
sourceURL := fmt.Sprintf("http://127.0.0.1:8888%s", test.path)
for _, host := range test.hosts {
req, err := http.NewRequest("GET", sourceURL, nil)
req, err := http.NewRequest(http.MethodGet, sourceURL, nil)
c.Assert(err, checker.IsNil)
req.Host = host
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
defer resp.Body.Close()
resp.Body.Close()
location := resp.Header.Get("Location")
expected := fmt.Sprintf("https://%s:8443%s", host, test.path)

View file

@ -3,9 +3,9 @@ package integration
import (
"bytes"
"context"
"flag"
"fmt"
"net"
"os"
"os/exec"
"path/filepath"
@ -14,17 +14,23 @@ import (
"text/template"
"time"
"github.com/compose-spec/compose-go/cli"
"github.com/compose-spec/compose-go/types"
"github.com/docker/cli/cli/config/configfile"
"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/fatih/structs"
"github.com/go-check/check"
compose "github.com/libkermit/compose/check"
"github.com/traefik/traefik/v2/pkg/log"
checker "github.com/vdemeester/shakers"
)
var (
integration = flag.Bool("integration", false, "run integration tests")
container = flag.Bool("container", false, "run container integration tests")
host = flag.Bool("host", false, "run host integration tests")
showLog = flag.Bool("tlog", false, "always show Traefik logs")
)
@ -34,45 +40,39 @@ func Test(t *testing.T) {
return
}
if *container {
// tests launched from a container
check.Suite(&AccessLogSuite{})
check.Suite(&AcmeSuite{})
check.Suite(&EtcdSuite{})
check.Suite(&ConsulSuite{})
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(&HealthCheckSuite{})
check.Suite(&HeadersSuite{})
check.Suite(&HealthCheckSuite{})
check.Suite(&HostResolverSuite{})
check.Suite(&HTTPSuite{})
check.Suite(&HTTPSSuite{})
check.Suite(&HTTPSuite{})
check.Suite(&K8sSuite{})
check.Suite(&KeepAliveSuite{})
check.Suite(&LogRotationSuite{})
check.Suite(&MarathonSuite{})
check.Suite(&MarathonSuite15{})
check.Suite(&MarathonSuite{})
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(&TLSClientHeadersSuite{})
check.Suite(&TracingSuite{})
check.Suite(&UDPSuite{})
check.Suite(&WebsocketSuite{})
check.Suite(&ZookeeperSuite{})
}
if *host {
// tests launched from the host
check.Suite(&K8sSuite{})
check.Suite(&ProxyProtocolSuite{})
check.Suite(&TCPSuite{})
}
check.TestingT(t)
}
@ -80,36 +80,72 @@ func Test(t *testing.T) {
var traefikBinary = "../dist/traefik"
type BaseSuite struct {
composeProject *compose.Project
composeProject *types.Project
dockerComposeService composeapi.Service
dockerClient *client.Client
}
func (s *BaseSuite) TearDownSuite(c *check.C) {
// shutdown and delete compose project
if s.composeProject != nil {
s.composeProject.Stop(c)
if s.composeProject != nil && s.dockerComposeService != nil {
s.composeDown(c)
}
}
// 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("integration-test-%s", name)
projectName := fmt.Sprintf("traefik-integration-test-%s", name)
composeFile := fmt.Sprintf("resources/compose/%s.yml", name)
addrs, err := net.InterfaceAddrs()
var err error
s.dockerClient, err = client.NewClientWithOpts()
c.Assert(err, checker.IsNil)
for _, addr := range addrs {
ip, _, err := net.ParseCIDR(addr.String())
c.Assert(err, checker.IsNil)
if !ip.IsLoopback() && ip.To4() != nil {
_ = os.Setenv("DOCKER_HOST_IP", ip.String())
break
}
}
s.composeProject = compose.CreateProject(c, projectName, composeFile)
s.dockerComposeService = compose.NewComposeService(s.dockerClient, &configfile.ConfigFile{})
ops, err := cli.NewProjectOptions([]string{composeFile}, cli.WithName(projectName))
c.Assert(err, checker.IsNil)
s.composeProject, err = cli.ProjectFromOptions(ops)
c.Assert(err, checker.IsNil)
}
func withConfigFile(file string) string {
return "--configFile=" + file
// 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.composeProject, check.NotNil)
c.Assert(s.dockerComposeService, check.NotNil)
// 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(), s.composeProject, composeapi.CreateOptions{})
c.Assert(err, checker.IsNil)
err = s.dockerComposeService.Restart(context.Background(), s.composeProject, composeapi.RestartOptions{Services: services})
c.Assert(err, checker.IsNil)
}
// 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.dockerComposeService, check.NotNil)
c.Assert(s.composeProject, check.NotNil)
err := s.dockerComposeService.Stop(context.Background(), s.composeProject, composeapi.StopOptions{Services: services})
c.Assert(err, checker.IsNil)
err = s.dockerComposeService.Remove(context.Background(), s.composeProject, composeapi.RemoveOptions{
Services: services,
Force: true,
})
c.Assert(err, checker.IsNil)
}
// composeDown stops all compose project services and removes the corresponding containers.
func (s *BaseSuite) composeDown(c *check.C) {
c.Assert(s.dockerComposeService, check.NotNil)
c.Assert(s.composeProject, check.NotNil)
err := s.dockerComposeService.Down(context.Background(), s.composeProject.Name, composeapi.DownOptions{})
c.Assert(err, checker.IsNil)
}
func (s *BaseSuite) cmdTraefik(args ...string) (*exec.Cmd, *bytes.Buffer) {
@ -134,6 +170,7 @@ func (s *BaseSuite) traefikCmd(args ...string) (*exec.Cmd, func(*check.C)) {
return cmd, func(c *check.C) {
if c.Failed() || *showLog {
s.displayLogK3S(c)
s.displayLogCompose(c)
s.displayTraefikLog(c, out)
}
}
@ -153,6 +190,25 @@ func (s *BaseSuite) displayLogK3S(c *check.C) {
log.WithoutContext().Println()
}
func (s *BaseSuite) displayLogCompose(c *check.C) {
if s.dockerComposeService == nil || s.composeProject == nil {
log.WithoutContext().Infof("%s: No docker compose logs.", c.TestName())
return
}
log.WithoutContext().Infof("%s: docker compose logs: ", c.TestName())
logWriter := log.WithoutContext().WriterLevel(log.GetLevel())
logConsumer := formatter.NewLogConsumer(context.Background(), logWriter, false, true)
err := s.dockerComposeService.Logs(context.Background(), s.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) {
if output == nil || output.Len() == 0 {
log.WithoutContext().Infof("%s: No Traefik logs.", c.TestName())
@ -168,6 +224,7 @@ func (s *BaseSuite) getDockerHost() string {
// Default docker socket
dockerHost = "unix:///var/run/docker.sock"
}
return dockerHost
}
@ -192,3 +249,38 @@ func (s *BaseSuite) adaptFile(c *check.C, path string, tempObjects interface{})
return tmpFile.Name()
}
func (s *BaseSuite) getComposeServiceIP(c *check.C, name string) string {
filter := filters.NewArgs(
filters.Arg("label", fmt.Sprintf("%s=%s", composeapi.ProjectLabel, s.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 := s.composeProject.NetworkNames()
c.Assert(networkNames, checker.HasLen, 1)
network := s.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
}
// Should never happen.
c.Error("No network found")
return ""
}
func withConfigFile(file string) string {
return "--configFile=" + file
}

View file

@ -28,7 +28,7 @@ type K8sSuite struct{ BaseSuite }
func (s *K8sSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "k8s")
s.composeProject.Start(c)
s.composeUp(c)
abs, err := filepath.Abs("./fixtures/k8s/config.skip/kubeconfig.yaml")
c.Assert(err, checker.IsNil)
@ -44,7 +44,7 @@ func (s *K8sSuite) SetUpSuite(c *check.C) {
}
func (s *K8sSuite) TearDownSuite(c *check.C) {
s.composeProject.Stop(c)
s.composeDown(c)
generatedFiles := []string{
"./fixtures/k8s/config.skip/kubeconfig.yaml",
@ -56,8 +56,7 @@ func (s *K8sSuite) TearDownSuite(c *check.C) {
}
for _, filename := range generatedFiles {
err := os.Remove(filename)
if err != nil {
if err := os.Remove(filename); err != nil {
log.WithoutContext().Warning(err)
}
}

View file

@ -13,17 +13,38 @@ import (
"github.com/go-check/check"
"github.com/traefik/traefik/v2/integration/try"
"github.com/traefik/traefik/v2/pkg/log"
checker "github.com/vdemeester/shakers"
)
const (
traefikTestLogFileRotated = traefikTestLogFile + ".rotated"
traefikTestAccessLogFileRotated = traefikTestAccessLogFile + ".rotated"
)
// Log rotation integration test suite.
type LogRotationSuite struct{ BaseSuite }
func (s *LogRotationSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "access_log")
s.composeProject.Start(c)
s.composeUp(c)
}
s.composeProject.Container(c, "server1")
func (s *LogRotationSuite) TearDownSuite(c *check.C) {
s.composeDown(c)
generatedFiles := []string{
traefikTestLogFile,
traefikTestLogFileRotated,
traefikTestAccessLogFile,
traefikTestAccessLogFileRotated,
}
for _, filename := range generatedFiles {
if err := os.Remove(filename); err != nil {
log.WithoutContext().Warning(err)
}
}
}
func (s *LogRotationSuite) TestAccessLogRotation(c *check.C) {
@ -36,8 +57,6 @@ func (s *LogRotationSuite) TestAccessLogRotation(c *check.C) {
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
defer os.Remove(traefikTestAccessLogFile)
// Verify Traefik started ok
verifyEmptyErrorLog(c, "traefik.log")
@ -52,7 +71,7 @@ func (s *LogRotationSuite) TestAccessLogRotation(c *check.C) {
c.Assert(err, checker.IsNil)
// Rename access log
err = os.Rename(traefikTestAccessLogFile, traefikTestAccessLogFile+".rotated")
err = os.Rename(traefikTestAccessLogFile, traefikTestAccessLogFileRotated)
c.Assert(err, checker.IsNil)
// in the midst of the requests, issue SIGUSR1 signal to server process
@ -66,8 +85,8 @@ func (s *LogRotationSuite) TestAccessLogRotation(c *check.C) {
c.Assert(err, checker.IsNil)
// Verify access.log.rotated output as expected
logAccessLogFile(c, traefikTestAccessLogFile+".rotated")
lineCount := verifyLogLines(c, traefikTestAccessLogFile+".rotated", 0, true)
logAccessLogFile(c, traefikTestAccessLogFileRotated)
lineCount := verifyLogLines(c, traefikTestAccessLogFileRotated, 0, true)
c.Assert(lineCount, checker.GreaterOrEqualThan, 1)
// make sure that the access log file is at least created before we do assertions on it
@ -95,12 +114,10 @@ func (s *LogRotationSuite) TestTraefikLogRotation(c *check.C) {
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
defer os.Remove(traefikTestAccessLogFile)
waitForTraefik(c, "server1")
// Rename traefik log
err = os.Rename(traefikTestLogFile, traefikTestLogFile+".rotated")
err = os.Rename(traefikTestLogFile, traefikTestLogFileRotated)
c.Assert(err, checker.IsNil)
// issue SIGUSR1 signal to server process
@ -118,7 +135,7 @@ func (s *LogRotationSuite) TestTraefikLogRotation(c *check.C) {
c.Assert(err, checker.IsNil)
// we have at least 6 lines in traefik.log.rotated
lineCount := verifyLogLines(c, traefikTestLogFile+".rotated", 0, false)
lineCount := verifyLogLines(c, traefikTestLogFileRotated, 0, false)
// GreaterOrEqualThan used to ensure test doesn't break
// If more log entries are output on startup

View file

@ -1,7 +1,6 @@
package integration
import (
"fmt"
"net/http"
"os"
"time"
@ -12,7 +11,7 @@ import (
checker "github.com/vdemeester/shakers"
)
// Marathon test suites (using libcompose).
// Marathon test suites.
type MarathonSuite15 struct {
BaseSuite
marathonURL string
@ -20,53 +19,15 @@ type MarathonSuite15 struct {
func (s *MarathonSuite15) SetUpSuite(c *check.C) {
s.createComposeProject(c, "marathon15")
s.composeProject.Start(c)
s.composeUp(c)
marathonIPAddr := s.composeProject.Container(c, containerNameMarathon).NetworkSettings.IPAddress
c.Assert(marathonIPAddr, checker.Not(checker.HasLen), 0)
s.marathonURL = "http://" + marathonIPAddr + ":8080"
s.marathonURL = "http://" + 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)
// Add entry for Mesos slave container IP address in the hosts file so
// that Traefik can properly forward traffic.
// This is necessary as long as we are still using the docker-compose v1
// spec. Once we switch to v2 or higher, we can have both the test/builder
// container and the Mesos slave container join the same custom network and
// enjoy DNS-discoverable container host names.
mesosSlaveIPAddr := s.composeProject.Container(c, containerNameMesosSlave).NetworkSettings.IPAddress
c.Assert(mesosSlaveIPAddr, checker.Not(checker.HasLen), 0)
err = s.extendDockerHostsFile(containerNameMesosSlave, mesosSlaveIPAddr)
c.Assert(err, checker.IsNil)
}
// extendDockerHostsFile extends the hosts file (/etc/hosts) by the given
// host/IP address mapping if we are running inside a container.
func (s *MarathonSuite15) extendDockerHostsFile(host, ipAddr string) error {
const hostsFile = "/etc/hosts"
// Determine if the run inside a container. The most reliable way to
// do this is to inject an indicator, which we do in terms of an
// environment variable.
// (See also https://groups.google.com/d/topic/docker-user/JOGE7AnJ3Gw/discussion.)
if os.Getenv("CONTAINER") == "DOCKER" {
// We are running inside a container -- extend the hosts file.
file, err := os.OpenFile(hostsFile, os.O_APPEND|os.O_WRONLY, 0o600)
if err != nil {
return err
}
defer file.Close()
if _, err = file.WriteString(fmt.Sprintf("%s\t%s\n", ipAddr, host)); err != nil {
return err
}
}
return nil
}
func (s *MarathonSuite15) TestConfigurationUpdate(c *check.C) {

View file

@ -1,7 +1,6 @@
package integration
import (
"fmt"
"net/http"
"os"
"time"
@ -12,12 +11,9 @@ import (
checker "github.com/vdemeester/shakers"
)
const (
containerNameMesosSlave = "mesos-slave"
containerNameMarathon = "marathon"
)
const containerNameMarathon = "marathon"
// Marathon test suites (using libcompose).
// Marathon test suites.
type MarathonSuite struct {
BaseSuite
marathonURL string
@ -25,53 +21,15 @@ type MarathonSuite struct {
func (s *MarathonSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "marathon")
s.composeProject.Start(c)
s.composeUp(c)
marathonIPAddr := s.composeProject.Container(c, containerNameMarathon).NetworkSettings.IPAddress
c.Assert(marathonIPAddr, checker.Not(checker.HasLen), 0)
s.marathonURL = "http://" + marathonIPAddr + ":8080"
s.marathonURL = "http://" + 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)
// Add entry for Mesos slave container IP address in the hosts file so
// that Traefik can properly forward traffic.
// This is necessary as long as we are still using the docker-compose v1
// spec. Once we switch to v2 or higher, we can have both the test/builder
// container and the Mesos slave container join the same custom network and
// enjoy DNS-discoverable container host names.
mesosSlaveIPAddr := s.composeProject.Container(c, containerNameMesosSlave).NetworkSettings.IPAddress
c.Assert(mesosSlaveIPAddr, checker.Not(checker.HasLen), 0)
err = s.extendDockerHostsFile(containerNameMesosSlave, mesosSlaveIPAddr)
c.Assert(err, checker.IsNil)
}
// extendDockerHostsFile extends the hosts file (/etc/hosts) by the given
// host/IP address mapping if we are running inside a container.
func (s *MarathonSuite) extendDockerHostsFile(host, ipAddr string) error {
const hostsFile = "/etc/hosts"
// Determine if the run inside a container. The most reliable way to
// do this is to inject an indicator, which we do in terms of an
// environment variable.
// (See also https://groups.google.com/d/topic/docker-user/JOGE7AnJ3Gw/discussion.)
if os.Getenv("CONTAINER") == "DOCKER" {
// We are running inside a container -- extend the hosts file.
file, err := os.OpenFile(hostsFile, os.O_APPEND|os.O_WRONLY, 0o600)
if err != nil {
return err
}
defer file.Close()
if _, err = file.WriteString(fmt.Sprintf("%s\t%s\n", ipAddr, host)); err != nil {
return err
}
}
return nil
}
func deployApplication(c *check.C, client marathon.Marathon, application *marathon.Application) {

View file

@ -10,22 +10,27 @@ import (
checker "github.com/vdemeester/shakers"
)
type ProxyProtocolSuite struct{ BaseSuite }
type ProxyProtocolSuite struct {
BaseSuite
gatewayIP string
haproxyIP string
whoamiIP string
}
func (s *ProxyProtocolSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "proxy-protocol")
s.composeProject.Start(c)
s.composeUp(c)
s.gatewayIP = s.getContainerIP(c, "traefik")
s.haproxyIP = s.getComposeServiceIP(c, "haproxy")
s.whoamiIP = s.getComposeServiceIP(c, "whoami")
}
func (s *ProxyProtocolSuite) TestProxyProtocolTrusted(c *check.C) {
gatewayIP := s.composeProject.Container(c, "haproxy").NetworkSettings.Gateway
haproxyIP := s.composeProject.Container(c, "haproxy").NetworkSettings.IPAddress
whoamiIP := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/proxy-protocol/with.toml", struct {
HaproxyIP string
WhoamiIP string
}{HaproxyIP: haproxyIP, WhoamiIP: whoamiIP})
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
defer os.Remove(file)
cmd, display := s.traefikCmd(withConfigFile(file))
@ -34,21 +39,17 @@ func (s *ProxyProtocolSuite) TestProxyProtocolTrusted(c *check.C) {
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
err = try.GetRequest("http://"+haproxyIP+"/whoami", 1*time.Second,
err = try.GetRequest("http://"+s.haproxyIP+"/whoami", 1*time.Second,
try.StatusCodeIs(http.StatusOK),
try.BodyContains("X-Forwarded-For: "+gatewayIP))
try.BodyContains("X-Forwarded-For: "+s.gatewayIP))
c.Assert(err, checker.IsNil)
}
func (s *ProxyProtocolSuite) TestProxyProtocolV2Trusted(c *check.C) {
gatewayIP := s.composeProject.Container(c, "haproxy").NetworkSettings.Gateway
haproxyIP := s.composeProject.Container(c, "haproxy").NetworkSettings.IPAddress
whoamiIP := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/proxy-protocol/with.toml", struct {
HaproxyIP string
WhoamiIP string
}{HaproxyIP: haproxyIP, WhoamiIP: whoamiIP})
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
defer os.Remove(file)
cmd, display := s.traefikCmd(withConfigFile(file))
@ -57,20 +58,17 @@ func (s *ProxyProtocolSuite) TestProxyProtocolV2Trusted(c *check.C) {
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
err = try.GetRequest("http://"+haproxyIP+":81/whoami", 1*time.Second,
err = try.GetRequest("http://"+s.haproxyIP+":81/whoami", 1*time.Second,
try.StatusCodeIs(http.StatusOK),
try.BodyContains("X-Forwarded-For: "+gatewayIP))
try.BodyContains("X-Forwarded-For: "+s.gatewayIP))
c.Assert(err, checker.IsNil)
}
func (s *ProxyProtocolSuite) TestProxyProtocolNotTrusted(c *check.C) {
haproxyIP := s.composeProject.Container(c, "haproxy").NetworkSettings.IPAddress
whoamiIP := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/proxy-protocol/without.toml", struct {
HaproxyIP string
WhoamiIP string
}{HaproxyIP: haproxyIP, WhoamiIP: whoamiIP})
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
defer os.Remove(file)
cmd, display := s.traefikCmd(withConfigFile(file))
@ -79,20 +77,17 @@ func (s *ProxyProtocolSuite) TestProxyProtocolNotTrusted(c *check.C) {
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
err = try.GetRequest("http://"+haproxyIP+"/whoami", 1*time.Second,
err = try.GetRequest("http://"+s.haproxyIP+"/whoami", 1*time.Second,
try.StatusCodeIs(http.StatusOK),
try.BodyContains("X-Forwarded-For: "+haproxyIP))
try.BodyContains("X-Forwarded-For: "+s.haproxyIP))
c.Assert(err, checker.IsNil)
}
func (s *ProxyProtocolSuite) TestProxyProtocolV2NotTrusted(c *check.C) {
haproxyIP := s.composeProject.Container(c, "haproxy").NetworkSettings.IPAddress
whoamiIP := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/proxy-protocol/without.toml", struct {
HaproxyIP string
WhoamiIP string
}{HaproxyIP: haproxyIP, WhoamiIP: whoamiIP})
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
defer os.Remove(file)
cmd, display := s.traefikCmd(withConfigFile(file))
@ -101,8 +96,8 @@ func (s *ProxyProtocolSuite) TestProxyProtocolV2NotTrusted(c *check.C) {
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
err = try.GetRequest("http://"+haproxyIP+":81/whoami", 1*time.Second,
err = try.GetRequest("http://"+s.haproxyIP+":81/whoami", 1*time.Second,
try.StatusCodeIs(http.StatusOK),
try.BodyContains("X-Forwarded-For: "+haproxyIP))
try.BodyContains("X-Forwarded-For: "+s.haproxyIP))
c.Assert(err, checker.IsNil)
}

View file

@ -17,9 +17,9 @@ type RateLimitSuite struct {
func (s *RateLimitSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "ratelimit")
s.composeProject.Start(c)
s.composeUp(c)
s.ServerIP = s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
s.ServerIP = s.getComposeServiceIP(c, "whoami1")
}
func (s *RateLimitSuite) TestSimpleConfiguration(c *check.C) {

View file

@ -3,6 +3,7 @@ package integration
import (
"bytes"
"encoding/json"
"net"
"net/http"
"os"
"path/filepath"
@ -18,20 +19,22 @@ import (
checker "github.com/vdemeester/shakers"
)
// Redis test suites (using libcompose).
// Redis test suites.
type RedisSuite struct {
BaseSuite
kvClient store.Store
redisAddr string
}
func (s *RedisSuite) setupStore(c *check.C) {
s.createComposeProject(c, "redis")
s.composeProject.Start(c)
s.composeUp(c)
s.redisAddr = net.JoinHostPort(s.getComposeServiceIP(c, "redis"), "6379")
redis.Register()
kv, err := valkeyrie.NewStore(
store.REDIS,
[]string{s.composeProject.Container(c, "redis").NetworkSettings.IPAddress + ":6379"},
[]string{s.redisAddr},
&store.Config{
ConnectionTimeout: 10 * time.Second,
},
@ -46,20 +49,10 @@ func (s *RedisSuite) setupStore(c *check.C) {
c.Assert(err, checker.IsNil)
}
func (s *RedisSuite) TearDownTest(c *check.C) {
// shutdown and delete compose project
if s.composeProject != nil {
s.composeProject.Stop(c)
}
}
func (s *RedisSuite) TearDownSuite(c *check.C) {}
func (s *RedisSuite) TestSimpleConfiguration(c *check.C) {
s.setupStore(c)
address := s.composeProject.Container(c, "redis").NetworkSettings.IPAddress + ":6379"
file := s.adaptFile(c, "fixtures/redis/simple.toml", struct{ RedisAddress string }{address})
file := s.adaptFile(c, "fixtures/redis/simple.toml", struct{ RedisAddress string }{s.redisAddr})
defer os.Remove(file)
data := map[string]string{

View file

@ -1,77 +1,91 @@
server0:
version: "3.8"
services:
server0:
image: traefik/whoami
labels:
- traefik.enable=true
- traefik.http.routers.rt-server0.entryPoints=web
- traefik.http.routers.rt-server0.rule=Path("/test")
- traefik.http.services.service1.loadbalancer.server.port=80
server1:
traefik.enable: true
traefik.http.routers.rt-server0.entryPoints: web
traefik.http.routers.rt-server0.rule: Path(`/test`)
traefik.http.services.service1.loadbalancer.server.port: 80
server1:
image: traefik/whoami
labels:
- traefik.enable=true
- traefik.http.routers.rt-server1.entryPoints=web
- traefik.http.routers.rt-server1.rule=Host("frontend1.docker.local")
- traefik.http.routers.rt-server1.service=service1
- traefik.http.services.service1.loadbalancer.server.port=80
server2:
traefik.enable: true
traefik.http.routers.rt-server1.entryPoints: web
traefik.http.routers.rt-server1.rule: Host(`frontend1.docker.local`)
traefik.http.routers.rt-server1.service: service1
traefik.http.services.service1.loadbalancer.server.port: 80
server2:
image: traefik/whoami
labels:
- traefik.enable=true
- traefik.http.routers.rt-server2.entryPoints=web
- traefik.http.routers.rt-server2.rule=Host("frontend2.docker.local")
- traefik.http.services.service2.loadbalancer.server.port=80
server3:
traefik.enable: true
traefik.http.routers.rt-server2.entryPoints: web
traefik.http.routers.rt-server2.rule: Host(`frontend2.docker.local`)
traefik.http.services.service2.loadbalancer.server.port: 80
server3:
image: traefik/whoami
labels:
- traefik.enable=true
- traefik.http.routers.rt-server3.entryPoints=web
- traefik.http.routers.rt-server3.rule=Host("frontend2.docker.local")
- traefik.http.services.service2.loadbalancer.server.port=80
authFrontend:
traefik.enable: true
traefik.http.routers.rt-server3.entryPoints: web
traefik.http.routers.rt-server3.rule: Host(`frontend2.docker.local`)
traefik.http.services.service2.loadbalancer.server.port: 80
authFrontend:
image: traefik/whoami
labels:
- traefik.enable=true
- 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.services.service3.loadbalancer.server.port=80
digestAuthMiddleware:
traefik.enable: true
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.services.service3.loadbalancer.server.port: 80
digestAuthMiddleware:
image: traefik/whoami
labels:
- traefik.enable=true
- traefik.http.routers.rt-digestAuthMiddleware.entryPoints=digestAuth
- traefik.http.routers.rt-digestAuthMiddleware.rule=Host("entrypoint.digest.auth.docker.local")
- traefik.http.routers.rt-digestAuthMiddleware.middlewares=digestauth
- traefik.http.middlewares.digestauth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05, test2:traefik:518845800f9e2bfb1f1f740ec24f074e
- traefik.http.services.service3.loadbalancer.server.port=80
frontendRedirect:
traefik.enable: true
traefik.http.routers.rt-digestAuthMiddleware.entryPoints: digestAuth
traefik.http.routers.rt-digestAuthMiddleware.rule: Host(`entrypoint.digest.auth.docker.local`)
traefik.http.routers.rt-digestAuthMiddleware.middlewares: digestauth
traefik.http.middlewares.digestauth.digestauth.users: test:traefik:a2688e031edb4be6a3797f3882655c05, test2:traefik:518845800f9e2bfb1f1f740ec24f074e
traefik.http.services.service3.loadbalancer.server.port: 80
frontendRedirect:
image: traefik/whoami
labels:
- traefik.enable=true
- traefik.http.routers.rt-frontendRedirect.entryPoints=frontendRedirect
- traefik.http.routers.rt-frontendRedirect.rule=Path("/test")
- traefik.http.routers.rt-frontendRedirect.middlewares=redirecthttp
- traefik.http.middlewares.redirecthttp.redirectScheme.scheme=http
- traefik.http.middlewares.redirecthttp.redirectScheme.port=8000
- traefik.http.services.service3.loadbalancer.server.port=80
rateLimit:
traefik.enable: true
traefik.http.routers.rt-frontendRedirect.entryPoints: frontendRedirect
traefik.http.routers.rt-frontendRedirect.rule: Path(`/test`)
traefik.http.routers.rt-frontendRedirect.middlewares: redirecthttp
traefik.http.middlewares.redirecthttp.redirectScheme.scheme: http
traefik.http.middlewares.redirecthttp.redirectScheme.port: 8000
traefik.http.services.service3.loadbalancer.server.port: 80
rateLimit:
image: traefik/whoami
labels:
- traefik.enable=true
- traefik.http.routers.rt-rateLimit.entryPoints=httpRateLimit
- traefik.http.routers.rt-rateLimit.rule=Host("ratelimit.docker.local")
- traefik.http.routers.rt-rateLimit.middlewares=rate
- traefik.http.middlewares.rate.ratelimit
- traefik.http.middlewares.rate.ratelimit.average=1
- traefik.http.middlewares.rate.ratelimit.burst=2
- traefik.http.services.service3.loadbalancer.server.port=80
frontendWhitelist:
traefik.enable: true
traefik.http.routers.rt-rateLimit.entryPoints: httpRateLimit
traefik.http.routers.rt-rateLimit.rule: Host(`ratelimit.docker.local`)
traefik.http.routers.rt-rateLimit.middlewares: rate
traefik.http.middlewares.rate.ratelimit.average: 1
traefik.http.middlewares.rate.ratelimit.burst: 2
traefik.http.services.service3.loadbalancer.server.port: 80
frontendWhitelist:
image: traefik/whoami
labels:
- traefik.enable=true
- traefik.http.routers.rt-frontendWhitelist.entryPoints=web
- traefik.http.routers.rt-frontendWhitelist.rule=Host("frontend.whitelist.docker.local")
- traefik.http.routers.rt-frontendWhitelist.middlewares=wl
- traefik.http.middlewares.wl.ipwhitelist.sourcerange=8.8.8.8/32
- traefik.http.services.service3.loadbalancer.server.port=80
traefik.enable: true
traefik.http.routers.rt-frontendWhitelist.entryPoints: web
traefik.http.routers.rt-frontendWhitelist.rule: Host(`frontend.whitelist.docker.local`)
traefik.http.routers.rt-frontendWhitelist.middlewares: wl
traefik.http.middlewares.wl.ipwhitelist.sourcerange: 8.8.8.8/32
traefik.http.services.service3.loadbalancer.server.port: 80
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,11 +1,18 @@
whoami1:
version: "3.8"
services:
whoami1:
image: traefik/whoami
labels:
- traefik.enable=true
- traefik.http.routers.router1.rule=PathPrefix("/whoami")
- traefik.http.routers.router2.rule=PathPrefix("/whoami2")
traefik.enable: true
traefik.http.routers.router1.rule: PathPrefix(`/whoami`)
traefik.http.routers.router2.rule: PathPrefix(`/whoami2`)
whoami2:
whoami2:
image: traefik/whoami
labels:
- traefik.enable=false
traefik.enable: false
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,4 +1,9 @@
consul:
version: "3.8"
services:
consul:
image: consul:1.6
ports:
- "8500:8500"
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,32 +1,37 @@
consul:
version: "3.8"
services:
consul:
image: consul:1.6.2
ports:
- 8500:8500
command: "agent -server -bootstrap -ui -client 0.0.0.0 -hcl 'connect { enabled = true }'"
consul-agent:
command: agent -server -bootstrap -ui -client 0.0.0.0 -hcl 'connect { enabled = true }'
consul-agent:
image: consul:1.6.2
ports:
- 8501:8500
command: "agent -retry-join consul -client 0.0.0.0"
links:
- consul
whoami1:
command: agent -retry-join consul -client 0.0.0.0
whoami1:
image: traefik/whoami
hostname: whoami1
whoami2:
whoami2:
image: traefik/whoami
hostname: whoami2
whoami3:
whoami3:
image: traefik/whoami
hostname: whoami3
whoamitcp:
whoamitcp:
image: traefik/whoamitcp
hostname: whoamitcp
connect:
connect:
image: hashicorpnomad/uuid-api:v5
links:
- consul
environment:
PORT: 443
BIND: 0.0.0.0
CONSUL_HTTP_ADDR: http://consul:8500
networks:
default:
name: traefik-test-network
external: true

View file

@ -0,0 +1,43 @@
version: "3.8"
services:
simple:
image: swarm:1.0.0
command: [ "manage", "token://blablabla" ]
withtcplabels:
image: traefik/whoamitcp
command: [ "-name", "my.super.host" ]
labels:
traefik.tcp.Routers.Super.Rule: HostSNI(`my.super.host`)
traefik.tcp.Routers.Super.tls: true
traefik.tcp.Services.Super.Loadbalancer.server.port: 8080
withlabels1:
image: swarm:1.0.0
command: [ "manage", "token://blabla" ]
labels:
traefik.http.Routers.Super.Rule: Host(`my.super.host`)
withlabels2:
image: swarm:1.0.0
command: [ "manage", "token://blablabla" ]
labels:
traefik.http.Routers.SuperHost.Rule: Host(`my-super.host`)
withonelabelmissing:
image: swarm:1.0.0
command: [ "manage", "token://blabla" ]
labels:
traefik.random.value: my.super.host
powpow:
image: swarm:1.0.0
command: [ "manage", "token://blabla" ]
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

View file

@ -1,4 +1,12 @@
nginx1:
version: "3.8"
services:
nginx1:
image: nginx:1.13.8-alpine
nginx2:
nginx2:
image: nginx:1.13.8-alpine
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,5 +1,10 @@
etcd:
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
ports:
- "2379:2379"
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,20 +1,21 @@
whoami1:
version: "3.8"
services:
whoami1:
image: traefik/whoami
ports:
- "8881:80"
whoami2:
whoami2:
image: traefik/whoami
ports:
- "8882:80"
whoami3:
whoami3:
image: traefik/whoami
ports:
- "8883:80"
whoami4:
whoami4:
image: traefik/whoami
ports:
- "8884:80"
whoami5:
whoami5:
image: traefik/whoami
ports:
- "8885:80"
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,11 +1,18 @@
whoami1:
version: "3.8"
services:
whoami1:
image: traefik/whoami
whoami2:
whoami2:
image: traefik/whoami
whoami3:
whoami3:
image: traefik/whoami
whoami4:
whoami4:
image: traefik/whoami
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,6 +1,13 @@
server1:
version: "3.8"
services:
server1:
image: traefik/whoami
labels:
- traefik.enable=true
- traefik.http.services.service1.loadbalancer.server.port=80
- traefik.http.routers.router1.rule=Host("github.com")
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

View file

@ -1,21 +1,24 @@
server:
version: "3.8"
services:
server:
image: rancher/k3s:v1.18.20-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
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
environment:
- K3S_CLUSTER_SECRET=somethingtotallyrandom
- K3S_KUBECONFIG_OUTPUT=/output/kubeconfig.yaml
- K3S_KUBECONFIG_MODE=666
K3S_CLUSTER_SECRET: somethingtotallyrandom
K3S_KUBECONFIG_OUTPUT: /output/kubeconfig.yaml
K3S_KUBECONFIG_MODE: 666
volumes:
- ../../fixtures/k8s/config.skip:/output
- ../../fixtures/k8s:/var/lib/rancher/k3s/server/manifests
ports:
- 6443:6443
- ./fixtures/k8s/config.skip:/output
- ./fixtures/k8s:/var/lib/rancher/k3s/server/manifests
node:
node:
image: rancher/k3s:v1.18.20-k3s1
privileged: true
links:
- server
environment:
- K3S_URL=https://server:6443
- K3S_CLUSTER_SECRET=somethingtotallyrandom
K3S_URL: https://server:6443
K3S_CLUSTER_SECRET: somethingtotallyrandom
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,54 +1,60 @@
zookeeper:
version: "3.8"
services:
zookeeper:
image: zookeeper:3.4.10
mesos-master:
links:
- zookeeper
mesos-master:
image: mesosphere/mesos-master:1.0.1-2.0.93.ubuntu1404
# Uncomment published ports for interactive debugging.
# ports:
# - "5050:5050"
environment:
- MESOS_HOSTNAME=mesos-master
- MESOS_CLUSTER=local
- MESOS_REGISTRY=in_memory
- MESOS_LOG_DIR=/var/log
- MESOS_WORK_DIR=/var/lib/mesos
- MESOS_ZK=zk://zookeeper:2181/mesos
MESOS_HOSTNAME: mesos-master
MESOS_CLUSTER: local
MESOS_REGISTRY: in_memory
MESOS_LOG_DIR: /var/log
MESOS_WORK_DIR: /var/lib/mesos
MESOS_ZK: zk://zookeeper:2181/mesos
mesos-slave:
links:
- zookeeper
- mesos-master
image: mesosphere/mesos-slave-dind:0.3.0_mesos-1.0.1_docker-1.10.3_ubuntu-14.04.5
mesos-slave:
image: docker:dind
privileged: true
# Uncomment published ports for interactive debugging.
# ports:
# - "5051:5051"
environment:
- MESOS_HOSTNAME=mesos-slave
- MESOS_CONTAINERIZERS=docker,mesos
- MESOS_ISOLATOR=cgroups/cpu,cgroups/mem
- MESOS_LOG_DIR=/var/log
- MESOS_MASTER=zk://zookeeper:2181/mesos
- MESOS_PORT=5051
- MESOS_WORK_DIR=/var/lib/mesos
- MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins
- MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs
- MESOS_DOCKER_STOP_TIMEOUT=60secs
- MESOS_RESOURCES=cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]
# docker version in mesosphere/mesos-slave-dind:0.3.0_mesos-1.0.1_docker-1.10.3_ubuntu-14.04.5 is too old and can't
# pull images on new kernels.
command:
- "/bin/sh"
- "-c"
- "(/usr/local/bin/dockerd-entrypoint.sh &); sleep 10; set -x; \
docker -H unix:///var/run/docker.sock run -d --net=host --privileged \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /cgroup:/cgroup -v /sys:/sys \
-v /usr/local/bin/docker:/usr/local/bin/docker \
-e MESOS_HOSTNAME=mesos-slave \
-e MESOS_CONTAINERIZERS=docker,mesos \
-e MESOS_ISOLATOR=cgroups/cpu,cgroups/mem \
-e MESOS_LOG_DIR=/var/log \
-e MESOS_MASTER=zk://zookeeper:2181/mesos \
-e MESOS_PORT=5051 \
-e MESOS_WORK_DIR=/var/lib/mesos \
-e MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins \
-e MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs \
-e MESOS_DOCKER_STOP_TIMEOUT=60secs \
-e MESOS_RESOURCES='cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]' \
mesosphere/mesos-slave:1.0.3; sleep 600"
marathon:
links:
- zookeeper
- mesos-master
- mesos-slave
marathon:
image: mesosphere/marathon:v1.3.12
# Uncomment published ports for interactive debugging.
# ports:
# - "8080:8080"
extra_hosts:
- "mesos-slave:172.17.0.1"
environment:
- MARATHON_ZK=zk://zookeeper:2181/marathon
- MARATHON_MASTER=zk://zookeeper:2181/mesos
MARATHON_ZK: zk://zookeeper:2181/marathon
MARATHON_MASTER: zk://zookeeper:2181/mesos
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,55 +1,51 @@
zookeeper:
version: "3.8"
services:
zookeeper:
image: zookeeper:3.4.10
mesos-master:
links:
- zookeeper
mesos-master:
image: mesosphere/mesos-master:1.4.1
# Uncomment published ports for interactive debugging.
# ports:
# - "5050:5050"
environment:
- MESOS_HOSTNAME=mesos-master
- MESOS_CLUSTER=local
- MESOS_REGISTRY=in_memory
- MESOS_LOG_DIR=/var/log
- MESOS_WORK_DIR=/var/lib/mesos
- MESOS_ZK=zk://zookeeper:2181/mesos
MESOS_HOSTNAME: mesos-master
MESOS_CLUSTER: local
MESOS_REGISTRY: in_memory
MESOS_LOG_DIR: /var/log
MESOS_WORK_DIR: /var/lib/mesos
MESOS_ZK: zk://zookeeper:2181/mesos
mesos-slave:
links:
- zookeeper
- mesos-master
mesos-slave:
image: mesosphere/mesos-slave-dind:0.4.0_mesos-1.4.1_docker-17.05.0_ubuntu-16.04.3
privileged: true
# Uncomment published ports for interactive debugging.
# ports:
# - "5051:5051"
environment:
- MESOS_HOSTNAME=mesos-slave
- MESOS_CONTAINERIZERS=docker,mesos
- MESOS_ISOLATOR=cgroups/cpu,cgroups/mem
- MESOS_LOG_DIR=/var/log
- MESOS_MASTER=zk://zookeeper:2181/mesos
- MESOS_PORT=5051
- MESOS_WORK_DIR=/var/lib/mesos
- MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins
- MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs
- MESOS_DOCKER_STOP_TIMEOUT=60secs
- MESOS_RESOURCES=cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]
- MESOS_SYSTEMD_ENABLE_SUPPORT=false
MESOS_HOSTNAME: mesos-slave
MESOS_CONTAINERIZERS: docker,mesos
MESOS_ISOLATOR: cgroups/cpu,cgroups/mem
MESOS_LOG_DIR: /var/log
MESOS_MASTER: zk://zookeeper:2181/mesos
MESOS_PORT: 5051
MESOS_WORK_DIR: /var/lib/mesos
MESOS_EXECUTOR_REGISTRATION_TIMEOUT: 5mins
MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD: 90secs
MESOS_DOCKER_STOP_TIMEOUT: 60secs
MESOS_RESOURCES: cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]
MESOS_SYSTEMD_ENABLE_SUPPORT: false
marathon:
links:
- zookeeper
- mesos-master
- mesos-slave
marathon:
image: mesosphere/marathon:v1.5.9
# Uncomment published ports for interactive debugging.
# ports:
# - "8080:8080"
extra_hosts:
- "mesos-slave:172.17.0.1"
environment:
- MARATHON_ZK=zk://zookeeper:2181/marathon
- MARATHON_MASTER=zk://zookeeper:2181/mesos
MARATHON_ZK: zk://zookeeper:2181/marathon
MARATHON_MASTER: zk://zookeeper:2181/mesos
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,6 +1,14 @@
whoami1:
version: "3.8"
services:
whoami1:
image: traefik/whoami
labels:
- traefik.http.Routers.RouterMini.Rule=PathPrefix("/whoami")
- traefik.enable=true
traefik.http.Routers.RouterMini.Rule: PathPrefix(`/whoami`)
traefik.enable: true
deploy:
replicas: 2
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,10 +1,15 @@
pebble:
version: "3.8"
services:
pebble:
image: letsencrypt/pebble:v2.3.1
command: pebble --dnsserver ${DOCKER_HOST_IP}:5053
ports:
- 14000:14000
command: pebble --dnsserver traefik:5053
environment:
# https://github.com/letsencrypt/pebble#testing-at-full-speed
- PEBBLE_VA_NOSLEEP=1
PEBBLE_VA_NOSLEEP: 1
# https://github.com/letsencrypt/pebble#invalid-anti-replay-nonce-errors
- PEBBLE_WFE_NONCEREJECT=0
PEBBLE_WFE_NONCEREJECT: 0
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,7 +1,14 @@
haproxy:
version: "3.8"
services:
haproxy:
image: haproxy:2.2
volumes:
- ../haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
- ./resources/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
whoami:
whoami:
image: traefik/whoami
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,2 +1,9 @@
whoami1:
version: "3.8"
services:
whoami1:
image: traefik/whoami
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,4 +1,9 @@
redis:
version: "3.8"
services:
redis:
image: redis:5.0
ports:
- "6379:6379"
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,2 +1,9 @@
whoami:
version: "3.8"
services:
whoami:
image: traefik/whoami
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,4 +1,9 @@
whoami1:
version: "3.8"
services:
whoami1:
image: traefik/whoami
ports:
- "8881:80"
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,2 +1,9 @@
whoami:
version: "3.8"
services:
whoami:
image: traefik/whoami
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,4 +1,12 @@
whoami1:
version: "3.8"
services:
whoami1:
image: traefik/whoami
whoami2:
whoami2:
image: traefik/whoami
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,38 +1,39 @@
whoami-a:
version: "3.8"
services:
whoami-a:
image: traefik/whoamitcp
command: -name whoami-a -certFile /certs/whoami-a.crt -keyFile /certs/whoami-a.key
volumes:
- ../../fixtures/tcp:/certs
ports:
- "8081:8080"
- ./fixtures/tcp:/certs
whoami-b:
whoami-b:
image: traefik/whoamitcp
command: -name whoami-b -certFile /certs/whoami-b.crt -keyFile /certs/whoami-b.key
volumes:
- ../../fixtures/tcp:/certs
ports:
- "8082:8080"
- ./fixtures/tcp:/certs
whoami-no-cert:
whoami-ab:
image: traefik/whoamitcp
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
ports:
- "8083:8080"
whoami-no-tls:
whoami-no-tls:
image: traefik/whoamitcp
command: -name whoami-no-tls
ports:
- "8084:8080"
whoami:
whoami:
image: traefik/whoami
ports:
- "8085:80"
whoami-banner:
whoami-banner:
image: traefik/whoamitcp
command: -name whoami-banner --banner
ports:
- "8086:8080"
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,7 +1,12 @@
timeoutEndpoint:
version: "3.8"
services:
timeoutEndpoint:
image: yaman/timeout
environment:
- PROTO=http
- PORT=9000
ports:
- "9000:9000"
PROTO: http
PORT: 9000
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,7 +1,14 @@
whoami:
version: "3.8"
services:
whoami:
image: traefik/whoami
labels:
- traefik.http.routers.route1.rule=PathPrefix(`/foo`)
- traefik.http.routers.route1.middlewares=passtls
- traefik.http.routers.route1.tls=true
- traefik.http.middlewares.passtls.passtlsclientcert.pem=true
traefik.http.routers.route1.rule: PathPrefix(`/foo`)
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

View file

@ -1,21 +1,20 @@
zipkin:
version: "3.8"
services:
zipkin:
image: openzipkin/zipkin:2.16.2
environment:
STORAGE_TYPE: mem
JAVA_OPTS: -Dlogging.level.zipkin=DEBUG
ports:
- 9411:9411
jaeger:
jaeger:
image: jaegertracing/all-in-one:1.14
environment:
COLLECTOR_ZIPKIN_HTTP_PORT: 9411
ports:
- "5775:5775/udp"
- "6831:6831/udp"
- "6832:6832/udp"
- "5778:5778"
- "16686:16686"
- "14268:14268"
- "9411:9411"
whoami:
whoami:
image: traefik/whoami
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,14 +1,21 @@
whoami-a:
version: "3.8"
services:
whoami-a:
image: traefik/whoamiudp:latest
command: -name whoami-a
whoami-b:
whoami-b:
image: traefik/whoamiudp:latest
command: -name whoami-b
whoami-c:
whoami-c:
image: traefik/whoamiudp:latest
command: -name whoami-c
whoami-d:
whoami-d:
image: traefik/whoami
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,34 +1,41 @@
noOverrideWhitelist:
version: "3.8"
services:
noOverrideWhitelist:
image: traefik/whoami
labels:
- traefik.enable=true
- traefik.http.routers.rt1.rule=Host("no.override.whitelist.docker.local")
- traefik.http.routers.rt1.middlewares=wl1
- traefik.http.middlewares.wl1.ipwhiteList.sourceRange=8.8.8.8
traefik.enable: true
traefik.http.routers.rt1.rule: Host(`no.override.whitelist.docker.local`)
traefik.http.routers.rt1.middlewares: wl1
traefik.http.middlewares.wl1.ipwhiteList.sourceRange: 8.8.8.8
overrideIPStrategyRemoteAddrWhitelist:
overrideIPStrategyRemoteAddrWhitelist:
image: traefik/whoami
labels:
- traefik.enable=true
- traefik.http.routers.rt2.rule=Host("override.remoteaddr.whitelist.docker.local")
- traefik.http.routers.rt2.middlewares=wl2
- traefik.http.middlewares.wl2.ipwhitelist.sourceRange=8.8.8.8
- traefik.http.middlewares.wl2.ipwhitelist.ipStrategy=true
traefik.enable: true
traefik.http.routers.rt2.rule: Host(`override.remoteaddr.whitelist.docker.local`)
traefik.http.routers.rt2.middlewares: wl2
traefik.http.middlewares.wl2.ipwhitelist.sourceRange: 8.8.8.8
traefik.http.middlewares.wl2.ipwhitelist.ipStrategy: true
overrideIPStrategyDepthWhitelist:
overrideIPStrategyDepthWhitelist:
image: traefik/whoami
labels:
- traefik.enable=true
- traefik.http.routers.rt3.rule=Host("override.depth.whitelist.docker.local")
- traefik.http.routers.rt3.middlewares=wl3
- traefik.http.middlewares.wl3.ipwhitelist.sourceRange=8.8.8.8
- traefik.http.middlewares.wl3.ipwhitelist.ipStrategy.depth=3
traefik.enable: true
traefik.http.routers.rt3.rule: Host(`override.depth.whitelist.docker.local`)
traefik.http.routers.rt3.middlewares: wl3
traefik.http.middlewares.wl3.ipwhitelist.sourceRange: 8.8.8.8
traefik.http.middlewares.wl3.ipwhitelist.ipStrategy.depth: 3
overrideIPStrategyExcludedIPsWhitelist:
overrideIPStrategyExcludedIPsWhitelist:
image: traefik/whoami
labels:
- traefik.enable=true
- traefik.http.routers.rt4.rule=Host("override.excludedips.whitelist.docker.local")
- traefik.http.routers.rt4.middlewares=wl4
- traefik.http.middlewares.wl4.ipwhitelist.sourceRange=8.8.8.8
- traefik.http.middlewares.wl4.ipwhitelist.ipStrategy.excludedIPs=10.0.0.1,10.0.0.2
traefik.enable: true
traefik.http.routers.rt4.rule: Host(`override.excludedips.whitelist.docker.local`)
traefik.http.routers.rt4.middlewares: wl4
traefik.http.middlewares.wl4.ipwhitelist.sourceRange: 8.8.8.8
traefik.http.middlewares.wl4.ipwhitelist.ipStrategy.excludedIPs: 10.0.0.1,10.0.0.2
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,4 +1,9 @@
zookeeper:
version: "3.8"
services:
zookeeper:
image: zookeeper:3.5
ports:
- "2181:2181"
networks:
default:
name: traefik-test-network
external: true

View file

@ -23,8 +23,8 @@ frontend TestServerTestV2
backend TestServerNodes
mode tcp
server TestServer01 172.17.0.1:8000 send-proxy
server TestServer01 traefik:8000 send-proxy
backend TestServerNodesV2
mode tcp
server TestServer01 172.17.0.1:8000 send-proxy-v2
server TestServer01 traefik:8000 send-proxy-v2

View file

@ -3,6 +3,7 @@ package integration
import (
"bytes"
"encoding/json"
"net"
"net/http"
"os"
"strings"
@ -14,12 +15,16 @@ import (
checker "github.com/vdemeester/shakers"
)
type RestSuite struct{ BaseSuite }
type RestSuite struct {
BaseSuite
whoamiAddr string
}
func (s *RestSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "rest")
s.composeUp(c)
s.composeProject.Start(c)
s.whoamiAddr = net.JoinHostPort(s.getComposeServiceIP(c, "whoami1"), "80")
}
func (s *RestSuite) TestSimpleConfigurationInsecure(c *check.C) {
@ -60,7 +65,7 @@ func (s *RestSuite) TestSimpleConfigurationInsecure(c *check.C) {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://" + s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80",
URL: "http://" + s.whoamiAddr,
},
},
},
@ -86,7 +91,7 @@ func (s *RestSuite) TestSimpleConfigurationInsecure(c *check.C) {
LoadBalancer: &dynamic.TCPServersLoadBalancer{
Servers: []dynamic.TCPServer{
{
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80",
Address: s.whoamiAddr,
},
},
},
@ -164,7 +169,7 @@ func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://" + s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80",
URL: "http://" + s.whoamiAddr,
},
},
},
@ -190,7 +195,7 @@ func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
LoadBalancer: &dynamic.TCPServersLoadBalancer{
Servers: []dynamic.TCPServer{
{
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80",
Address: s.whoamiAddr,
},
},
},
@ -213,10 +218,10 @@ func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
c.Assert(err, checker.IsNil)
c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1000*time.Millisecond, try.BodyContains(test.ruleMatch))
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains(test.ruleMatch))
c.Assert(err, checker.IsNil)
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusOK))
err = try.GetRequest("http://127.0.0.1:8000/", time.Second, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil)
}
}

View file

@ -11,18 +11,20 @@ import (
checker "github.com/vdemeester/shakers"
)
type RetrySuite struct{ BaseSuite }
type RetrySuite struct {
BaseSuite
whoamiIP string
}
func (s *RetrySuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "retry")
s.composeProject.Start(c)
s.composeUp(c)
s.whoamiIP = s.getComposeServiceIP(c, "whoami")
}
func (s *RetrySuite) TestRetry(c *check.C) {
whoamiEndpoint := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/retry/simple.toml", struct {
WhoamiEndpoint string
}{whoamiEndpoint})
file := s.adaptFile(c, "fixtures/retry/simple.toml", struct{ WhoamiIP string }{s.whoamiIP})
defer os.Remove(file)
cmd, display := s.traefikCmd(withConfigFile(file))
@ -44,10 +46,7 @@ func (s *RetrySuite) TestRetry(c *check.C) {
}
func (s *RetrySuite) TestRetryBackoff(c *check.C) {
whoamiEndpoint := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/retry/backoff.toml", struct {
WhoamiEndpoint string
}{whoamiEndpoint})
file := s.adaptFile(c, "fixtures/retry/backoff.toml", struct{ WhoamiIP string }{s.whoamiIP})
defer os.Remove(file)
cmd, display := s.traefikCmd(withConfigFile(file))
@ -72,10 +71,7 @@ func (s *RetrySuite) TestRetryBackoff(c *check.C) {
}
func (s *RetrySuite) TestRetryWebsocket(c *check.C) {
whoamiEndpoint := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/retry/simple.toml", struct {
WhoamiEndpoint string
}{whoamiEndpoint})
file := s.adaptFile(c, "fixtures/retry/simple.toml", struct{ WhoamiIP string }{s.whoamiIP})
defer os.Remove(file)
cmd, display := s.traefikCmd(withConfigFile(file))

View file

@ -6,6 +6,7 @@ import (
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"net/http/httptest"
"os"
@ -50,7 +51,6 @@ func (s *SimpleSuite) TestSimpleDefaultConfig(c *check.C) {
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
// TODO validate : run on 80
// Expected a 404 as we did not configure anything
err = try.GetRequest("http://127.0.0.1:8000/", 1*time.Second, try.StatusCodeIs(http.StatusNotFound))
c.Assert(err, checker.IsNil)
@ -93,17 +93,20 @@ func (s *SimpleSuite) TestPrintHelp(c *check.C) {
func (s *SimpleSuite) TestRequestAcceptGraceTimeout(c *check.C) {
s.createComposeProject(c, "reqacceptgrace")
s.composeProject.Start(c)
whoami := "http://" + s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress + ":80"
s.composeUp(c)
defer s.composeDown(c)
whoamiURL := "http://" + net.JoinHostPort(s.getComposeServiceIP(c, "whoami"), "80")
file := s.adaptFile(c, "fixtures/reqacceptgrace.toml", struct {
Server string
}{whoami})
}{whoamiURL})
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)
@ -193,15 +196,17 @@ func (s *SimpleSuite) TestCustomPingTerminationStatusCode(c *check.C) {
func (s *SimpleSuite) TestStatsWithMultipleEntryPoint(c *check.C) {
c.Skip("Stats is missing")
s.createComposeProject(c, "stats")
s.composeProject.Start(c)
whoami1 := "http://" + s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80"
whoami2 := "http://" + s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress + ":80"
s.composeUp(c)
defer s.composeDown(c)
whoami1URL := "http://" + net.JoinHostPort(s.getComposeServiceIP(c, "whoami1"), "80")
whoami2URL := "http://" + net.JoinHostPort(s.getComposeServiceIP(c, "whoami2"), "80")
file := s.adaptFile(c, "fixtures/simple_stats.toml", struct {
Server1 string
Server2 string
}{whoami1, whoami2})
}{whoami1URL, whoami2URL})
cmd, output := s.traefikCmd(withConfigFile(file))
defer output(c)
@ -229,7 +234,9 @@ func (s *SimpleSuite) TestNoAuthOnPing(c *check.C) {
c.Skip("Waiting for new api handler implementation")
s.createComposeProject(c, "base")
s.composeProject.Start(c)
s.composeUp(c)
defer s.composeDown(c)
file := s.adaptFile(c, "./fixtures/simple_auth.toml", struct{}{})
defer os.Remove(file)
@ -249,7 +256,9 @@ func (s *SimpleSuite) TestNoAuthOnPing(c *check.C) {
func (s *SimpleSuite) TestDefaultEntryPointHTTP(c *check.C) {
s.createComposeProject(c, "base")
s.composeProject.Start(c)
s.composeUp(c)
defer s.composeDown(c)
cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--log.level=DEBUG", "--providers.docker", "--api.insecure")
defer output(c)
@ -267,7 +276,9 @@ func (s *SimpleSuite) TestDefaultEntryPointHTTP(c *check.C) {
func (s *SimpleSuite) TestWithNonExistingEntryPoint(c *check.C) {
s.createComposeProject(c, "base")
s.composeProject.Start(c)
s.composeUp(c)
defer s.composeDown(c)
cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--log.level=DEBUG", "--providers.docker", "--api.insecure")
defer output(c)
@ -285,7 +296,9 @@ func (s *SimpleSuite) TestWithNonExistingEntryPoint(c *check.C) {
func (s *SimpleSuite) TestMetricsPrometheusDefaultEntryPoint(c *check.C) {
s.createComposeProject(c, "base")
s.composeProject.Start(c)
s.composeUp(c)
defer s.composeDown(c)
cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--api.insecure", "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0", "--providers.docker", "--metrics.prometheus.addrouterslabels=true", "--log.level=DEBUG")
defer output(c)
@ -315,7 +328,9 @@ func (s *SimpleSuite) TestMetricsPrometheusDefaultEntryPoint(c *check.C) {
func (s *SimpleSuite) TestMetricsPrometheusTwoRoutersOneService(c *check.C) {
s.createComposeProject(c, "base")
s.composeProject.Start(c)
s.composeUp(c)
defer s.composeDown(c)
cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--api.insecure", "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0", "--providers.docker", "--metrics.prometheus.addentrypointslabels=false", "--metrics.prometheus.addrouterslabels=true", "--log.level=DEBUG")
defer output(c)
@ -346,22 +361,22 @@ func (s *SimpleSuite) TestMetricsPrometheusTwoRoutersOneService(c *check.C) {
c.Assert(err, checker.IsNil)
// Reqs count of 1 for both routers
c.Assert(string(body), checker.Contains, "traefik_router_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",router=\"router1@docker\",service=\"whoami1-integrationtestbase@docker\"} 1")
c.Assert(string(body), checker.Contains, "traefik_router_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",router=\"router2@docker\",service=\"whoami1-integrationtestbase@docker\"} 1")
c.Assert(string(body), checker.Contains, "traefik_router_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",router=\"router1@docker\",service=\"whoami1-traefik-integration-test-base@docker\"} 1")
c.Assert(string(body), checker.Contains, "traefik_router_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",router=\"router2@docker\",service=\"whoami1-traefik-integration-test-base@docker\"} 1")
// Reqs count of 2 for service behind both routers
c.Assert(string(body), checker.Contains, "traefik_service_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"whoami1-integrationtestbase@docker\"} 2")
c.Assert(string(body), checker.Contains, "traefik_service_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"whoami1-traefik-integration-test-base@docker\"} 2")
}
}
func (s *SimpleSuite) TestMultipleProviderSameBackendName(c *check.C) {
s.createComposeProject(c, "base")
s.composeProject.Start(c)
ipWhoami01 := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
ipWhoami02 := s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/multiple_provider.toml", struct{ IP string }{
IP: ipWhoami02,
})
s.composeUp(c)
defer s.composeDown(c)
whoami1IP := s.getComposeServiceIP(c, "whoami1")
whoami2IP := s.getComposeServiceIP(c, "whoami2")
file := s.adaptFile(c, "fixtures/multiple_provider.toml", struct{ IP string }{IP: whoami2IP})
defer os.Remove(file)
cmd, output := s.traefikCmd(withConfigFile(file))
@ -374,16 +389,18 @@ func (s *SimpleSuite) TestMultipleProviderSameBackendName(c *check.C) {
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("PathPrefix"))
c.Assert(err, checker.IsNil)
err = try.GetRequest("http://127.0.0.1:8000/whoami", 1*time.Second, try.BodyContains(ipWhoami01))
err = try.GetRequest("http://127.0.0.1:8000/whoami", 1*time.Second, try.BodyContains(whoami1IP))
c.Assert(err, checker.IsNil)
err = try.GetRequest("http://127.0.0.1:8000/file", 1*time.Second, try.BodyContains(ipWhoami02))
err = try.GetRequest("http://127.0.0.1:8000/file", 1*time.Second, try.BodyContains(whoami2IP))
c.Assert(err, checker.IsNil)
}
func (s *SimpleSuite) TestIPStrategyWhitelist(c *check.C) {
s.createComposeProject(c, "whitelist")
s.composeProject.Start(c)
s.composeUp(c)
defer s.composeDown(c)
cmd, output := s.traefikCmd(withConfigFile("fixtures/simple_whitelist.toml"))
defer output(c)
@ -451,7 +468,9 @@ func (s *SimpleSuite) TestIPStrategyWhitelist(c *check.C) {
func (s *SimpleSuite) TestXForwardedHeaders(c *check.C) {
s.createComposeProject(c, "whitelist")
s.composeProject.Start(c)
s.composeUp(c)
defer s.composeDown(c)
cmd, output := s.traefikCmd(withConfigFile("fixtures/simple_whitelist.toml"))
defer output(c)
@ -479,13 +498,13 @@ func (s *SimpleSuite) TestXForwardedHeaders(c *check.C) {
func (s *SimpleSuite) TestMultiProvider(c *check.C) {
s.createComposeProject(c, "base")
s.composeProject.Start(c)
server := "http://" + s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
s.composeUp(c)
defer s.composeDown(c)
file := s.adaptFile(c, "fixtures/multiprovider.toml", struct {
Server string
}{Server: server})
whoamiURL := "http://" + net.JoinHostPort(s.getComposeServiceIP(c, "whoami1"), "80")
file := s.adaptFile(c, "fixtures/multiprovider.toml", struct{ Server string }{Server: whoamiURL})
defer os.Remove(file)
cmd, output := s.traefikCmd(withConfigFile(file))
@ -530,13 +549,13 @@ func (s *SimpleSuite) TestMultiProvider(c *check.C) {
func (s *SimpleSuite) TestSimpleConfigurationHostRequestTrailingPeriod(c *check.C) {
s.createComposeProject(c, "base")
s.composeProject.Start(c)
server := "http://" + s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
s.composeUp(c)
defer s.composeDown(c)
file := s.adaptFile(c, "fixtures/file/simple-hosts.toml", struct {
Server string
}{Server: server})
whoamiURL := "http://" + net.JoinHostPort(s.getComposeServiceIP(c, "whoami1"), "80")
file := s.adaptFile(c, "fixtures/file/simple-hosts.toml", struct{ Server string }{Server: whoamiURL})
defer os.Remove(file)
cmd, output := s.traefikCmd(withConfigFile(file))
@ -707,15 +726,17 @@ func (s *SimpleSuite) TestUDPServiceConfigErrors(c *check.C) {
func (s *SimpleSuite) TestWRR(c *check.C) {
s.createComposeProject(c, "base")
s.composeProject.Start(c)
server1 := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
server2 := s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress
s.composeUp(c)
defer s.composeDown(c)
whoami1IP := s.getComposeServiceIP(c, "whoami1")
whoami2IP := s.getComposeServiceIP(c, "whoami2")
file := s.adaptFile(c, "fixtures/wrr.toml", struct {
Server1 string
Server2 string
}{Server1: "http://" + server1, Server2: "http://" + server2})
}{Server1: "http://" + whoami1IP, Server2: "http://" + whoami2IP})
defer os.Remove(file)
cmd, output := s.traefikCmd(withConfigFile(file))
@ -740,29 +761,31 @@ func (s *SimpleSuite) TestWRR(c *check.C) {
body, err := io.ReadAll(response.Body)
c.Assert(err, checker.IsNil)
if strings.Contains(string(body), server1) {
repartition[server1]++
if strings.Contains(string(body), whoami1IP) {
repartition[whoami1IP]++
}
if strings.Contains(string(body), server2) {
repartition[server2]++
if strings.Contains(string(body), whoami2IP) {
repartition[whoami2IP]++
}
}
c.Assert(repartition[server1], checker.Equals, 3)
c.Assert(repartition[server2], checker.Equals, 1)
c.Assert(repartition[whoami1IP], checker.Equals, 3)
c.Assert(repartition[whoami2IP], checker.Equals, 1)
}
func (s *SimpleSuite) TestWRRSticky(c *check.C) {
s.createComposeProject(c, "base")
s.composeProject.Start(c)
server1 := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
server2 := s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress
s.composeUp(c)
defer s.composeDown(c)
whoami1IP := s.getComposeServiceIP(c, "whoami1")
whoami2IP := s.getComposeServiceIP(c, "whoami2")
file := s.adaptFile(c, "fixtures/wrr_sticky.toml", struct {
Server1 string
Server2 string
}{Server1: "http://" + server1, Server2: "http://" + server2})
}{Server1: "http://" + whoami1IP, Server2: "http://" + whoami2IP})
defer os.Remove(file)
cmd, output := s.traefikCmd(withConfigFile(file))
@ -791,16 +814,16 @@ func (s *SimpleSuite) TestWRRSticky(c *check.C) {
body, err := io.ReadAll(response.Body)
c.Assert(err, checker.IsNil)
if strings.Contains(string(body), server1) {
repartition[server1]++
if strings.Contains(string(body), whoami1IP) {
repartition[whoami1IP]++
}
if strings.Contains(string(body), server2) {
repartition[server2]++
if strings.Contains(string(body), whoami2IP) {
repartition[whoami2IP]++
}
}
c.Assert(repartition[server1], checker.Equals, 4)
c.Assert(repartition[server2], checker.Equals, 0)
c.Assert(repartition[whoami1IP], checker.Equals, 4)
c.Assert(repartition[whoami2IP], checker.Equals, 0)
}
func (s *SimpleSuite) TestMirror(c *check.C) {
@ -1037,7 +1060,9 @@ func (s *SimpleSuite) TestMirrorCanceled(c *check.C) {
func (s *SimpleSuite) TestSecureAPI(c *check.C) {
s.createComposeProject(c, "base")
s.composeProject.Start(c)
s.composeUp(c)
defer s.composeDown(c)
file := s.adaptFile(c, "./fixtures/simple_secure_api.toml", struct{}{})
defer os.Remove(file)

View file

@ -2,6 +2,9 @@ package integration
import (
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"net"
"net/http"
"net/http/httptest"
@ -18,7 +21,7 @@ type TCPSuite struct{ BaseSuite }
func (s *TCPSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "tcp")
s.composeProject.Start(c)
s.composeUp(c)
}
func (s *TCPSuite) TestMixed(c *check.C) {
@ -36,12 +39,12 @@ func (s *TCPSuite) TestMixed(c *check.C) {
c.Assert(err, checker.IsNil)
// Traefik passes through, termination handled by whoami-a
out, err := guessWho("127.0.0.1:8093", "whoami-a.test", true)
out, err := guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-a.test")
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "whoami-a")
// Traefik passes through, termination handled by whoami-b
out, err = guessWho("127.0.0.1:8093", "whoami-b.test", true)
out, err = guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-b.test")
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "whoami-b")
@ -116,12 +119,12 @@ func (s *TCPSuite) TestNonTLSFallback(c *check.C) {
c.Assert(err, checker.IsNil)
// Traefik passes through, termination handled by whoami-a
out, err := guessWho("127.0.0.1:8093", "whoami-a.test", true)
out, err := guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-a.test")
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "whoami-a")
// Traefik passes through, termination handled by whoami-b
out, err = guessWho("127.0.0.1:8093", "whoami-b.test", true)
out, err = guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-b.test")
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "whoami-b")
@ -211,19 +214,52 @@ func (s *TCPSuite) TestMiddlewareWhiteList(c *check.C) {
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 50*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`whoami-a.test`)"))
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)
// Traefik not passes through, ipWhitelist closes connection
_, err = guessWho("127.0.0.1:8093", "whoami-a.test", true)
c.Assert(err, checker.NotNil)
_, err = guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-a.test")
c.Assert(err, checker.ErrorMatches, "EOF")
// Traefik passes through, termination handled by whoami-b
out, err := guessWho("127.0.0.1:8093", "whoami-b.test", true)
out, err := guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-b.test")
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "whoami-b")
}
func (s *TCPSuite) TestWRR(c *check.C) {
file := s.adaptFile(c, "fixtures/tcp/wrr.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)
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)
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)
switch {
case strings.Contains(out, "whoami-b"):
call["whoami-b"]++
case strings.Contains(out, "whoami-ab"):
call["whoami-ab"]++
default:
call["unknown"]++
}
time.Sleep(time.Second)
}
c.Assert(call, checker.DeepEquals, map[string]int{"whoami-b": 3, "whoami-ab": 1})
}
func welcome(addr string) (string, error) {
tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
@ -291,34 +327,54 @@ func guessWhoTLSMaxVersion(addr, serverName string, tlsCall bool, tlsMaxVersion
return string(out[:n]), nil
}
func (s *TCPSuite) TestWRR(c *check.C) {
file := s.adaptFile(c, "fixtures/tcp/wrr.toml", struct{}{})
defer os.Remove(file)
// guessWhoTLSPassthrough guesses service identity and ensures that the
// certificate is valid for the given server name.
func guessWhoTLSPassthrough(addr, serverName string) (string, error) {
var conn net.Conn
var err error
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://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI"))
c.Assert(err, checker.IsNil)
call := map[string]int{}
for i := 0; i < 4; i++ {
// Traefik passes through, termination handled by whoami-a
out, err := guessWho("127.0.0.1:8093", "whoami-a.test", true)
c.Assert(err, checker.IsNil)
switch {
case strings.Contains(out, "whoami-a"):
call["whoami-a"]++
case strings.Contains(out, "whoami-b"):
call["whoami-b"]++
default:
call["unknown"]++
}
conn, err = tls.Dial("tcp", addr, &tls.Config{
ServerName: serverName,
InsecureSkipVerify: true,
MinVersion: 0,
MaxVersion: 0,
VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
if len(rawCerts) > 1 {
return errors.New("tls: more than one certificates from peer")
}
c.Assert(call, checker.DeepEquals, map[string]int{"whoami-a": 3, "whoami-b": 1})
cert, err := x509.ParseCertificate(rawCerts[0])
if err != nil {
return fmt.Errorf("tls: failed to parse certificate from peer: %w", err)
}
if cert.Subject.CommonName == serverName {
return nil
}
if err = cert.VerifyHostname(serverName); err == nil {
return nil
}
return fmt.Errorf("tls: no valid certificate for serverName %s", serverName)
},
})
if err != nil {
return "", err
}
defer conn.Close()
_, err = conn.Write([]byte("WHO"))
if err != nil {
return "", err
}
out := make([]byte, 2048)
n, err := conn.Read(out)
if err != nil {
return "", err
}
return string(out[:n]), nil
}

View file

@ -15,14 +15,12 @@ type TimeoutSuite struct{ BaseSuite }
func (s *TimeoutSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "timeout")
s.composeProject.Start(c)
s.composeUp(c)
}
func (s *TimeoutSuite) TestForwardingTimeouts(c *check.C) {
httpTimeoutEndpoint := s.composeProject.Container(c, "timeoutEndpoint").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/timeout/forwarding_timeouts.toml", struct {
TimeoutEndpoint string
}{httpTimeoutEndpoint})
timeoutEndpointIP := s.getComposeServiceIP(c, "timeoutEndpoint")
file := s.adaptFile(c, "fixtures/timeout/forwarding_timeouts.toml", struct{ TimeoutEndpoint string }{timeoutEndpointIP})
defer os.Remove(file)
cmd, display := s.traefikCmd(withConfigFile(file))
@ -40,7 +38,7 @@ func (s *TimeoutSuite) TestForwardingTimeouts(c *check.C) {
c.Assert(response.StatusCode, checker.Equals, http.StatusGatewayTimeout)
// Check that timeout service is available
statusURL := fmt.Sprintf("http://%s:9000/statusTest?status=200", httpTimeoutEndpoint)
statusURL := fmt.Sprintf("http://%s:9000/statusTest?status=200", timeoutEndpointIP)
c.Assert(try.GetRequest(statusURL, 60*time.Second, try.StatusCodeIs(http.StatusOK)), checker.IsNil)
// This simulates a ResponseHeaderTimeout.

View file

@ -21,7 +21,7 @@ type TLSClientHeadersSuite struct{ BaseSuite }
func (s *TLSClientHeadersSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "tlsclientheaders")
s.composeProject.Start(c)
s.composeUp(c)
}
func (s *TLSClientHeadersSuite) TestTLSClientHeaders(c *check.C) {

View file

@ -12,47 +12,49 @@ import (
type TracingSuite struct {
BaseSuite
WhoAmiIP string
WhoAmiPort int
IP string
whoamiIP string
whoamiPort int
tracerIP string
}
type TracingTemplate struct {
WhoAmiIP string
WhoAmiPort int
WhoamiIP string
WhoamiPort int
IP string
TraceContextHeaderName string
}
func (s *TracingSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "tracing")
s.composeProject.Start(c, "whoami")
s.composeUp(c)
s.WhoAmiIP = s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress
s.WhoAmiPort = 80
s.whoamiIP = s.getComposeServiceIP(c, "whoami")
s.whoamiPort = 80
}
func (s *TracingSuite) startZipkin(c *check.C) {
s.composeProject.Start(c, "zipkin")
s.IP = s.composeProject.Container(c, "zipkin").NetworkSettings.IPAddress
s.composeUp(c, "zipkin")
s.tracerIP = s.getComposeServiceIP(c, "zipkin")
// Wait for Zipkin to turn ready.
err := try.GetRequest("http://"+s.IP+":9411/api/v2/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
err := try.GetRequest("http://"+s.tracerIP+":9411/api/v2/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil)
}
func (s *TracingSuite) TestZipkinRateLimit(c *check.C) {
s.startZipkin(c)
defer s.composeProject.Stop(c, "zipkin")
// defer s.composeStop(c, "zipkin")
file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP,
WhoAmiPort: s.WhoAmiPort,
IP: s.IP,
WhoamiIP: s.whoamiIP,
WhoamiPort: s.whoamiPort,
IP: s.tracerIP,
})
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)
@ -87,17 +89,18 @@ func (s *TracingSuite) TestZipkinRateLimit(c *check.C) {
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests))
c.Assert(err, checker.IsNil)
err = try.GetRequest("http://"+s.IP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit-1@file"))
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)
}
func (s *TracingSuite) TestZipkinRetry(c *check.C) {
s.startZipkin(c)
defer s.composeProject.Stop(c, "zipkin")
defer s.composeStop(c, "zipkin")
file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP,
WhoAmiPort: 81,
IP: s.IP,
WhoamiIP: s.whoamiIP,
WhoamiPort: 81,
IP: s.tracerIP,
})
defer os.Remove(file)
@ -114,17 +117,18 @@ func (s *TracingSuite) TestZipkinRetry(c *check.C) {
err = try.GetRequest("http://127.0.0.1:8000/retry", 500*time.Millisecond, try.StatusCodeIs(http.StatusBadGateway))
c.Assert(err, checker.IsNil)
err = try.GetRequest("http://"+s.IP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("forward service2/router2@file", "retry@file"))
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)
}
func (s *TracingSuite) TestZipkinAuth(c *check.C) {
s.startZipkin(c)
defer s.composeProject.Stop(c, "zipkin")
defer s.composeStop(c, "zipkin")
file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP,
WhoAmiPort: s.WhoAmiPort,
IP: s.IP,
WhoamiIP: s.whoamiIP,
WhoamiPort: s.whoamiPort,
IP: s.tracerIP,
})
defer os.Remove(file)
@ -141,26 +145,27 @@ func (s *TracingSuite) TestZipkinAuth(c *check.C) {
err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
c.Assert(err, checker.IsNil)
err = try.GetRequest("http://"+s.IP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("entrypoint web", "basic-auth@file"))
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)
}
func (s *TracingSuite) startJaeger(c *check.C) {
s.composeProject.Start(c, "jaeger")
s.IP = s.composeProject.Container(c, "jaeger").NetworkSettings.IPAddress
s.composeUp(c, "jaeger", "whoami")
s.tracerIP = s.getComposeServiceIP(c, "jaeger")
// Wait for Jaeger to turn ready.
err := try.GetRequest("http://"+s.IP+":16686/api/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
err := try.GetRequest("http://"+s.tracerIP+":16686/api/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil)
}
func (s *TracingSuite) TestJaegerRateLimit(c *check.C) {
s.startJaeger(c)
defer s.composeProject.Stop(c, "jaeger")
defer s.composeStop(c, "jaeger")
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP,
WhoAmiPort: s.WhoAmiPort,
IP: s.IP,
WhoamiIP: s.whoamiIP,
WhoamiPort: s.whoamiPort,
IP: s.tracerIP,
TraceContextHeaderName: "uber-trace-id",
})
defer os.Remove(file)
@ -200,17 +205,18 @@ func (s *TracingSuite) TestJaegerRateLimit(c *check.C) {
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests))
c.Assert(err, checker.IsNil)
err = try.GetRequest("http://"+s.IP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit-1@file"))
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)
}
func (s *TracingSuite) TestJaegerRetry(c *check.C) {
s.startJaeger(c)
defer s.composeProject.Stop(c, "jaeger")
defer s.composeStop(c, "jaeger")
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP,
WhoAmiPort: 81,
IP: s.IP,
WhoamiIP: s.whoamiIP,
WhoamiPort: 81,
IP: s.tracerIP,
TraceContextHeaderName: "uber-trace-id",
})
defer os.Remove(file)
@ -228,17 +234,18 @@ func (s *TracingSuite) TestJaegerRetry(c *check.C) {
err = try.GetRequest("http://127.0.0.1:8000/retry", 500*time.Millisecond, try.StatusCodeIs(http.StatusBadGateway))
c.Assert(err, checker.IsNil)
err = try.GetRequest("http://"+s.IP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("forward service2/router2@file", "retry@file"))
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)
}
func (s *TracingSuite) TestJaegerAuth(c *check.C) {
s.startJaeger(c)
defer s.composeProject.Stop(c, "jaeger")
defer s.composeStop(c, "jaeger")
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP,
WhoAmiPort: s.WhoAmiPort,
IP: s.IP,
WhoamiIP: s.whoamiIP,
WhoamiPort: s.whoamiPort,
IP: s.tracerIP,
TraceContextHeaderName: "uber-trace-id",
})
defer os.Remove(file)
@ -256,17 +263,18 @@ func (s *TracingSuite) TestJaegerAuth(c *check.C) {
err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
c.Assert(err, checker.IsNil)
err = try.GetRequest("http://"+s.IP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
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)
}
func (s *TracingSuite) TestJaegerCustomHeader(c *check.C) {
s.startJaeger(c)
defer s.composeProject.Stop(c, "jaeger")
defer s.composeStop(c, "jaeger")
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP,
WhoAmiPort: s.WhoAmiPort,
IP: s.IP,
WhoamiIP: s.whoamiIP,
WhoamiPort: s.whoamiPort,
IP: s.tracerIP,
TraceContextHeaderName: "powpow",
})
defer os.Remove(file)
@ -284,17 +292,18 @@ func (s *TracingSuite) TestJaegerCustomHeader(c *check.C) {
err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
c.Assert(err, checker.IsNil)
err = try.GetRequest("http://"+s.IP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
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)
}
func (s *TracingSuite) TestJaegerAuthCollector(c *check.C) {
s.startJaeger(c)
defer s.composeProject.Stop(c, "jaeger")
defer s.composeStop(c, "jaeger")
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger-collector.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP,
WhoAmiPort: s.WhoAmiPort,
IP: s.IP,
WhoamiIP: s.whoamiIP,
WhoamiPort: s.whoamiPort,
IP: s.tracerIP,
})
defer os.Remove(file)
@ -311,6 +320,6 @@ func (s *TracingSuite) TestJaegerAuthCollector(c *check.C) {
err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
c.Assert(err, checker.IsNil)
err = try.GetRequest("http://"+s.IP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
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)
}

View file

@ -16,7 +16,7 @@ type UDPSuite struct{ BaseSuite }
func (s *UDPSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "udp")
s.composeProject.Start(c)
s.composeUp(c)
}
func guessWhoUDP(addr string) (string, error) {
@ -47,21 +47,16 @@ func guessWhoUDP(addr string) (string, error) {
}
func (s *UDPSuite) TestWRR(c *check.C) {
whoamiAIP := s.composeProject.Container(c, "whoami-a").NetworkSettings.IPAddress
whoamiBIP := s.composeProject.Container(c, "whoami-b").NetworkSettings.IPAddress
whoamiCIP := s.composeProject.Container(c, "whoami-c").NetworkSettings.IPAddress
whoamiDIP := s.composeProject.Container(c, "whoami-d").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/udp/wrr.toml", struct {
WhoamiAIP string
WhoamiBIP string
WhoamiCIP string
WhoamiDIP string
}{
WhoamiAIP: whoamiAIP,
WhoamiBIP: whoamiBIP,
WhoamiCIP: whoamiCIP,
WhoamiDIP: whoamiDIP,
WhoamiAIP: s.getComposeServiceIP(c, "whoami-a"),
WhoamiBIP: s.getComposeServiceIP(c, "whoami-b"),
WhoamiCIP: s.getComposeServiceIP(c, "whoami-c"),
WhoamiDIP: s.getComposeServiceIP(c, "whoami-d"),
})
defer os.Remove(file)

View file

@ -3,6 +3,7 @@ package integration
import (
"bytes"
"encoding/json"
"net"
"net/http"
"os"
"path/filepath"
@ -18,20 +19,25 @@ import (
checker "github.com/vdemeester/shakers"
)
// Zk test suites (using libcompose).
// Zk test suites.
type ZookeeperSuite struct {
BaseSuite
kvClient store.Store
zookeeperAddr string
}
func (s *ZookeeperSuite) setupStore(c *check.C) {
s.createComposeProject(c, "zookeeper")
s.composeProject.Start(c)
s.composeUp(c)
zookeeper.Register()
kv, err := valkeyrie.NewStore(
s.zookeeperAddr = net.JoinHostPort(s.getComposeServiceIP(c, "zookeeper"), "2181")
var err error
s.kvClient, err = valkeyrie.NewStore(
store.ZK,
[]string{s.composeProject.Container(c, "zookeeper").NetworkSettings.IPAddress + ":2181"},
[]string{s.zookeeperAddr},
&store.Config{
ConnectionTimeout: 10 * time.Second,
},
@ -39,27 +45,16 @@ func (s *ZookeeperSuite) setupStore(c *check.C) {
if err != nil {
c.Fatal("Cannot create store zookeeper")
}
s.kvClient = kv
// wait for zk
err = try.Do(60*time.Second, try.KVExists(kv, "test"))
err = try.Do(60*time.Second, try.KVExists(s.kvClient, "test"))
c.Assert(err, checker.IsNil)
}
func (s *ZookeeperSuite) TearDownTest(c *check.C) {
// shutdown and delete compose project
if s.composeProject != nil {
s.composeProject.Stop(c)
}
}
func (s *ZookeeperSuite) TearDownSuite(c *check.C) {}
func (s *ZookeeperSuite) TestSimpleConfiguration(c *check.C) {
s.setupStore(c)
address := s.composeProject.Container(c, "zookeeper").NetworkSettings.IPAddress + ":2181"
file := s.adaptFile(c, "fixtures/zookeeper/simple.toml", struct{ ZkAddress string }{address})
file := s.adaptFile(c, "fixtures/zookeeper/simple.toml", struct{ ZkAddress string }{s.zookeeperAddr})
defer os.Remove(file)
data := map[string]string{

View file

@ -1,3 +1,5 @@
# This file is not meant as a usable Traefik configuration.
# It is only used in tests as a sample for serialization.
[global]
checkNewVersion = true
sendAnonymousUsage = true

View file

@ -15,14 +15,5 @@ cd integration
echo "Testing against..."
docker version
if [ -n "$TEST_CONTAINER" ]; then
echo "Testing from container…"
# shellcheck disable=SC2086
CGO_ENABLED=0 go test -integration -container ${TESTFLAGS[*]}
fi
if [ -n "$TEST_HOST" ]; then
echo "Testing from host…"
# shellcheck disable=SC2086
CGO_ENABLED=0 go test -integration -host ${TESTFLAGS[*]}
fi
# shellcheck disable=SC2086
CGO_ENABLED=0 go test -integration ${TESTFLAGS[*]}