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

View file

@ -32,42 +32,24 @@ global_job_config:
- cache restore traefik-$(checksum go.sum) - cache restore traefik-$(checksum go.sum)
blocks: blocks:
- name: Test Integration Container - name: Test Integration
dependencies: [] dependencies: []
run: run:
when: "branch =~ '.*' OR pull_request =~'.*'" when: "branch =~ '.*' OR pull_request =~'.*'"
task: task:
jobs: jobs:
- name: Test Integration Container - name: Test Integration
commands: commands:
- make pull-images - make pull-images
- mkdir -p static # Avoid to generate webui - mkdir -p static # Avoid to generate webui
- PRE_TARGET="" make binary - PRE_TARGET="" make binary
- make test-integration-container - make test-integration
- df -h - df -h
epilogue: epilogue:
always: always:
commands: commands:
- cache store traefik-$(checksum go.sum) $HOME/go/pkg/mod - 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 - name: Release
dependencies: [] dependencies: []
run: 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:]') REPONAME := $(shell echo $(REPO) | tr '[:upper:]' '[:lower:]')
TRAEFIK_IMAGE := $(if $(REPONAME),$(REPONAME),"traefik/traefik") 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)",) DOCKER_BUILD_ARGS := $(if $(DOCKER_VERSION), "--build-arg=DOCKER_VERSION=$(DOCKER_VERSION)",)
TRAEFIK_ENVS := \ TRAEFIK_ENVS := \
@ -32,7 +32,8 @@ TRAEFIK_ENVS := \
TRAEFIK_MOUNT := -v "$(CURDIR)/$(BIND_DIR):/go/src/github.com/traefik/traefik/$(BIND_DIR)" 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_RUN_OPTS := $(TRAEFIK_ENVS) $(TRAEFIK_MOUNT) "$(TRAEFIK_DEV_IMAGE)"
DOCKER_NON_INTERACTIVE ?= false 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) DOCKER_RUN_TRAEFIK_NOTTY := docker run $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INTERACTIVE), , -i) $(DOCKER_RUN_OPTS)
PRE_TARGET ?= build-dev-image PRE_TARGET ?= build-dev-image
@ -81,30 +82,27 @@ crossbinary-default-parallel:
$(MAKE) build-dev-image crossbinary-default $(MAKE) build-dev-image crossbinary-default
## Run the unit and integration tests ## Run the unit and integration tests
test: build-dev-image test: $(PRE_TARGET)
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate test-unit binary test-integration -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 ## Run the unit tests
test-unit: $(PRE_TARGET) 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 all images for integration tests
pull-images: pull-images:
grep --no-filename -E '^\s+image:' ./integration/resources/compose/*.yml | awk '{print $$2}' | sort | uniq | xargs -P 6 -n 1 docker pull 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 code and docs
validate-files: $(PRE_TARGET) validate-files: $(PRE_TARGET)
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate validate-lint validate-misspell $(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/BurntSushi/toml v0.3.1
github.com/ExpediaDotCom/haystack-client-go v0.0.0-20190315171017-e7edbdf53a61 github.com/ExpediaDotCom/haystack-client-go v0.0.0-20190315171017-e7edbdf53a61
github.com/Masterminds/sprig/v3 v3.2.2 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/Shopify/sarama v1.23.1 // indirect
github.com/abbot/go-http-auth v0.0.0-00010101000000-000000000000 github.com/abbot/go-http-auth v0.0.0-00010101000000-000000000000
github.com/abronan/valkeyrie v0.2.0 github.com/abronan/valkeyrie v0.2.0
github.com/aws/aws-sdk-go v1.39.0 github.com/aws/aws-sdk-go v1.39.0
github.com/cenkalti/backoff/v4 v4.1.1 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/containous/alice v0.0.0-20181107144136-d83ebdd94cbd
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew v1.1.1
github.com/docker/cli v0.0.0-20200221155518-740919cc7fc0 github.com/docker/cli v20.10.7+incompatible
github.com/docker/distribution v2.7.1+incompatible // indirect github.com/docker/compose/v2 v2.0.1
github.com/docker/docker v17.12.0-ce-rc1.0.20200204220554-5f6d6f3f2203+incompatible github.com/docker/docker v20.10.7+incompatible
github.com/docker/docker-credential-helpers v0.6.3 // indirect
github.com/docker/go-connections v0.4.0 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/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e // indirect
github.com/eapache/channels v1.1.0 github.com/eapache/channels v1.1.0
github.com/elazarl/go-bindata-assetfs v1.0.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/consul/api v1.10.0
github.com/hashicorp/go-hclog v0.16.1 github.com/hashicorp/go-hclog v0.16.1
github.com/hashicorp/go-multierror v1.1.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/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d
github.com/instana/go-sensor v1.5.1 github.com/instana/go-sensor v1.5.1
github.com/klauspost/compress v1.13.0 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/lucas-clemente/quic-go v0.23.0
github.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f github.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f
github.com/miekg/dns v1.1.43 github.com/miekg/dns v1.1.43
github.com/mitchellh/copystructure v1.0.0 github.com/mitchellh/copystructure v1.0.0
github.com/mitchellh/hashstructure v1.0.0 github.com/mitchellh/hashstructure v1.0.0
github.com/mitchellh/mapstructure v1.4.1 github.com/mitchellh/mapstructure v1.4.2
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect github.com/opentracing/opentracing-go v1.2.0
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/openzipkin-contrib/zipkin-go-opentracing v0.4.5 github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5
github.com/openzipkin/zipkin-go v0.2.2 github.com/openzipkin/zipkin-go v0.2.2
github.com/patrickmn/go-cache v2.1.0+incompatible 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_golang v1.11.0
github.com/prometheus/client_model v0.2.0 github.com/prometheus/client_model v0.2.0
github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac 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/stretchr/testify v1.7.0
github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154 github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154
github.com/tinylib/msgp v1.0.2 // indirect 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/minheap => github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595
github.com/mailgun/multibuf => github.com/containous/multibuf v0.0.0-20190809014333-8b6c9a7e6bba 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) { func (s *AccessLogSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "access_log") s.createComposeProject(c, "access_log")
s.composeProject.Start(c) s.composeUp(c)
s.composeProject.Container(c, "server0")
s.composeProject.Container(c, "server1")
s.composeProject.Container(c, "server2")
s.composeProject.Container(c, "server3")
} }
func (s *AccessLogSuite) TearDownTest(c *check.C) { func (s *AccessLogSuite) TearDownTest(c *check.C) {
@ -122,7 +117,7 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontend(c *check.C) {
code: "200", code: "200",
user: "test", user: "test",
routerName: "rt-authFrontend", 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) checkStatsForLogFile(c)
s.composeProject.Container(c, "authFrontend")
waitForTraefik(c, "authFrontend") waitForTraefik(c, "authFrontend")
// Verify Traefik started OK // Verify Traefik started OK
@ -193,7 +186,7 @@ func (s *AccessLogSuite) TestAccessLogDigestAuthMiddleware(c *check.C) {
code: "200", code: "200",
user: "test", user: "test",
routerName: "rt-digestAuthMiddleware", 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) checkStatsForLogFile(c)
s.composeProject.Container(c, "digestAuthMiddleware")
waitForTraefik(c, "digestAuthMiddleware") waitForTraefik(c, "digestAuthMiddleware")
// Verify Traefik started OK // Verify Traefik started OK
@ -322,8 +313,6 @@ func (s *AccessLogSuite) TestAccessLogFrontendRedirect(c *check.C) {
checkStatsForLogFile(c) checkStatsForLogFile(c)
s.composeProject.Container(c, "frontendRedirect")
waitForTraefik(c, "frontendRedirect") waitForTraefik(c, "frontendRedirect")
// Verify Traefik started OK // Verify Traefik started OK
@ -375,8 +364,6 @@ func (s *AccessLogSuite) TestAccessLogRateLimit(c *check.C) {
checkStatsForLogFile(c) checkStatsForLogFile(c)
s.composeProject.Container(c, "rateLimit")
waitForTraefik(c, "rateLimit") waitForTraefik(c, "rateLimit")
// Verify Traefik started OK // Verify Traefik started OK
@ -471,8 +458,6 @@ func (s *AccessLogSuite) TestAccessLogFrontendWhitelist(c *check.C) {
checkStatsForLogFile(c) checkStatsForLogFile(c)
s.composeProject.Container(c, "frontendWhitelist")
waitForTraefik(c, "frontendWhitelist") waitForTraefik(c, "frontendWhitelist")
// Verify Traefik started OK // Verify Traefik started OK
@ -504,7 +489,7 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontendSuccess(c *check.C) {
code: "200", code: "200",
user: "test", user: "test",
routerName: "rt-authFrontend", 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) checkStatsForLogFile(c)
s.composeProject.Container(c, "authFrontend")
waitForTraefik(c, "authFrontend") waitForTraefik(c, "authFrontend")
// Verify Traefik started OK // Verify Traefik started OK
@ -548,7 +531,6 @@ func checkNoOtherTraefikProblems(c *check.C) {
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
if len(traefikLog) > 0 { if len(traefikLog) > 0 {
fmt.Printf("%s\n", string(traefikLog)) 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) c.Assert(err, checker.IsNil)
if len(traefikLog) > 0 { if len(traefikLog) > 0 {
fmt.Printf("%s\n", string(traefikLog)) fmt.Printf("%s\n", string(traefikLog))
c.Assert(traefikLog, checker.HasLen, 0)
} }
return traefikLog return traefikLog
} }

View file

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

View file

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

View file

@ -3,6 +3,8 @@ package integration
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt"
"net"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
@ -18,20 +20,24 @@ import (
checker "github.com/vdemeester/shakers" checker "github.com/vdemeester/shakers"
) )
// Consul test suites (using libcompose). // Consul test suites.
type ConsulSuite struct { type ConsulSuite struct {
BaseSuite BaseSuite
kvClient store.Store kvClient store.Store
consulURL string
} }
func (s *ConsulSuite) setupStore(c *check.C) { func (s *ConsulSuite) setupStore(c *check.C) {
s.createComposeProject(c, "consul") 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() consul.Register()
kv, err := valkeyrie.NewStore( kv, err := valkeyrie.NewStore(
store.CONSUL, store.CONSUL,
[]string{s.composeProject.Container(c, "consul").NetworkSettings.IPAddress + ":8500"}, []string{consulAddr},
&store.Config{ &store.Config{
ConnectionTimeout: 10 * time.Second, ConnectionTimeout: 10 * time.Second,
}, },
@ -46,20 +52,10 @@ func (s *ConsulSuite) setupStore(c *check.C) {
c.Assert(err, checker.IsNil) 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) { func (s *ConsulSuite) TestSimpleConfiguration(c *check.C) {
s.setupStore(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 }{s.consulURL})
file := s.adaptFile(c, "fixtures/consul/simple.toml", struct{ ConsulAddress string }{address})
defer os.Remove(file) defer os.Remove(file)
data := map[string]string{ data := map[string]string{

View file

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

View file

@ -6,80 +6,24 @@ import (
"io" "io"
"net/http" "net/http"
"os" "os"
"strings"
"time" "time"
"github.com/docker/docker/pkg/namesgenerator"
"github.com/go-check/check" "github.com/go-check/check"
d "github.com/libkermit/docker"
"github.com/libkermit/docker-check"
"github.com/traefik/traefik/v2/integration/try" "github.com/traefik/traefik/v2/integration/try"
checker "github.com/vdemeester/shakers" 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. // Docker tests suite.
type DockerSuite struct { type DockerSuite struct {
BaseSuite BaseSuite
project *docker.Project
} }
func (s *DockerSuite) startContainer(c *check.C, image string, args ...string) string { func (s *DockerSuite) SetUpTest(c *check.C) {
return s.startContainerWithConfig(c, image, d.ContainerConfig{ s.createComposeProject(c, "docker")
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) TearDownTest(c *check.C) { 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) { 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) file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
defer os.Remove(file) defer os.Remove(file)
s.composeUp(c)
cmd, display := s.traefikCmd(withConfigFile(file)) cmd, display := s.traefikCmd(withConfigFile(file))
defer display(c) defer display(c)
err := cmd.Start() err := cmd.Start()
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
defer s.killCmd(cmd) defer s.killCmd(cmd)
// TODO validate : run on 80
// Expected a 404 as we did not configure anything // 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)) err = try.GetRequest("http://127.0.0.1:8000/", 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
c.Assert(err, checker.IsNil) 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) file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
defer os.Remove(file) defer os.Remove(file)
name := s.startContainer(c, "swarm:1.0.0", "manage", "token://blablabla") s.composeUp(c, "simple")
// Start traefik // Start traefik
cmd, display := s.traefikCmd(withConfigFile(file)) cmd, display := s.traefikCmd(withConfigFile(file))
defer display(c) defer display(c)
err := cmd.Start() err := cmd.Start()
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
defer s.killCmd(cmd) defer s.killCmd(cmd)
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil) req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil)
c.Assert(err, checker.IsNil) 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 ?) // 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) 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) file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
defer os.Remove(file) defer os.Remove(file)
// Start a container with some labels s.composeUp(c, "withtcplabels")
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")
// Start traefik // Start traefik
cmd, display := s.traefikCmd(withConfigFile(file)) cmd, display := s.traefikCmd(withConfigFile(file))
defer display(c) defer display(c)
err := cmd.Start() err := cmd.Start()
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
defer s.killCmd(cmd) defer s.killCmd(cmd)
@ -193,17 +134,7 @@ func (s *DockerSuite) TestDockerContainersWithLabels(c *check.C) {
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects) file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
defer os.Remove(file) defer os.Remove(file)
// Start a container with some labels s.composeUp(c, "withlabels1", "withlabels2")
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")
// Start traefik // Start traefik
cmd, display := s.traefikCmd(withConfigFile(file)) 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) file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
defer os.Remove(file) defer os.Remove(file)
// Start a container with some labels s.composeUp(c, "withonelabelmissing")
labels := map[string]string{
"traefik.random.value": "my.super.host",
}
s.startContainerWithLabels(c, "swarm:1.0.0", labels, "manage", "token://blabla")
// Start traefik // Start traefik
cmd, display := s.traefikCmd(withConfigFile(file)) cmd, display := s.traefikCmd(withConfigFile(file))
defer display(c) defer display(c)
err := cmd.Start() err := cmd.Start()
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
defer s.killCmd(cmd) defer s.killCmd(cmd)
@ -285,16 +213,12 @@ func (s *DockerSuite) TestRestartDockerContainers(c *check.C) {
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects) file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
defer os.Remove(file) defer os.Remove(file)
// Start a container with some labels s.composeUp(c, "powpow")
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")
// Start traefik // Start traefik
cmd, display := s.traefikCmd(withConfigFile(file)) cmd, display := s.traefikCmd(withConfigFile(file))
defer display(c) defer display(c)
err := cmd.Start() err := cmd.Start()
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
defer s.killCmd(cmd) 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")) err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("powpow"))
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
s.stopAndRemoveContainerByName(c, "powpow") s.composeStop(c, "powpow")
defer s.project.Remove(c, "powpow")
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("powpow")) err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("powpow"))
c.Assert(err, checker.NotNil) 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")) err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("powpow"))
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
} }

View file

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

View file

@ -3,6 +3,7 @@ package integration
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"net"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
@ -18,20 +19,24 @@ import (
checker "github.com/vdemeester/shakers" checker "github.com/vdemeester/shakers"
) )
// etcd test suites (using libcompose). // etcd test suites.
type EtcdSuite struct { type EtcdSuite struct {
BaseSuite BaseSuite
kvClient store.Store kvClient store.Store
etcdAddr string
} }
func (s *EtcdSuite) setupStore(c *check.C) { func (s *EtcdSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "etcd") s.createComposeProject(c, "etcd")
s.composeProject.Start(c) s.composeUp(c)
etcdv3.Register() 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, store.ETCDV3,
[]string{s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress + ":2379"}, []string{s.etcdAddr},
&store.Config{ &store.Config{
ConnectionTimeout: 10 * time.Second, ConnectionTimeout: 10 * time.Second,
}, },
@ -39,27 +44,14 @@ func (s *EtcdSuite) setupStore(c *check.C) {
if err != nil { if err != nil {
c.Fatal("Cannot create store etcd") c.Fatal("Cannot create store etcd")
} }
s.kvClient = kv
// wait for etcd // 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) 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) { func (s *EtcdSuite) TestSimpleConfiguration(c *check.C) {
s.setupStore(c) file := s.adaptFile(c, "fixtures/etcd/simple.toml", struct{ EtcdAddress string }{s.etcdAddr})
address := s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress + ":2379"
file := s.adaptFile(c, "fixtures/etcd/simple.toml", struct{ EtcdAddress string }{address})
defer os.Remove(file) defer os.Remove(file)
data := map[string]string{ data := map[string]string{

View file

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

View file

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

View file

@ -6,4 +6,4 @@
[http.services] [http.services]
[http.services.service2.loadBalancer] [http.services.service2.loadBalancer]
[[http.services.service2.loadBalancer.servers]] [[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]
[[http.services.service1.loadBalancer.servers]] [[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoamiEndpoint}}:8080" url = "http://{{ .WhoamiIP }}:8080"
[[http.services.service1.loadBalancer.servers]] [[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoamiEndpoint}}:8081" url = "http://{{ .WhoamiIP }}:8081"
[[http.services.service1.loadBalancer.servers]] [[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoamiEndpoint}}:8082" url = "http://{{ .WhoamiIP }}:8082"
[[http.services.service1.loadBalancer.servers]] [[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]
[[http.services.service1.loadBalancer.servers]] [[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoamiEndpoint}}:8080" url = "http://{{ .WhoamiIP }}:8080"
[[http.services.service1.loadBalancer.servers]] [[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoamiEndpoint}}:80" url = "http://{{ .WhoamiIP }}:80"

View file

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

View file

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

View file

@ -38,18 +38,14 @@
[tcp.services] [tcp.services]
[tcp.services.whoami-a.loadBalancer] [tcp.services.whoami-a.loadBalancer]
[[tcp.services.whoami-a.loadBalancer.servers]] [[tcp.services.whoami-a.loadBalancer.servers]]
address = "localhost:8081" address = "whoami-a:8080"
[tcp.services.whoami-b.loadBalancer] [tcp.services.whoami-b.loadBalancer]
[[tcp.services.whoami-b.loadBalancer.servers]] [[tcp.services.whoami-b.loadBalancer.servers]]
address = "localhost:8082" address = "whoami-b:8080"
[tcp.middlewares] [tcp.middlewares]
[tcp.middlewares.allowing-ipwhitelist.ipWhiteList] [tcp.middlewares.allowing-ipwhitelist.ipWhiteList]
sourceRange = ["127.0.0.1/32"] sourceRange = ["127.0.0.1/32"]
[tcp.middlewares.blocking-ipwhitelist.ipWhiteList] [tcp.middlewares.blocking-ipwhitelist.ipWhiteList]
sourceRange = ["127.127.127.127/32"] 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/`)" rule = "Path(`/whoami/`)"
service = "whoami" service = "whoami"
[http.routers.my-https-router.tls] [http.routers.my-https-router.tls]
[http.routers.api]
rule = "PathPrefix(`/api`)"
service = "api@internal"
entryPoints = ["traefik"]
[http.services] [http.services]
[http.services.whoami.loadBalancer] [http.services.whoami.loadBalancer]
[[http.services.whoami.loadBalancer.servers]] [[http.services.whoami.loadBalancer.servers]]
url = "http://localhost:8085" url = "http://whoami:80"
[tcp] [tcp]
[tcp.routers] [tcp.routers]
[tcp.routers.to-whoami-a] [tcp.routers.to-whoami-a]
@ -58,15 +62,15 @@
[tcp.services.whoami-a.loadBalancer] [tcp.services.whoami-a.loadBalancer]
[[tcp.services.whoami-a.loadBalancer.servers]] [[tcp.services.whoami-a.loadBalancer.servers]]
address = "localhost:8081" address = "whoami-a:8080"
[tcp.services.whoami-b.loadBalancer] [tcp.services.whoami-b.loadBalancer]
[[tcp.services.whoami-b.loadBalancer.servers]] [[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]
[[tcp.services.whoami-no-cert.loadBalancer.servers]] [[tcp.services.whoami-no-cert.loadBalancer.servers]]
address = "localhost:8083" address = "whoami-no-cert:8080"
[[tls.certificates]] [[tls.certificates]]
certFile = "fixtures/tcp/whoami-c.crt" certFile = "fixtures/tcp/whoami-c.crt"

View file

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

View file

@ -47,16 +47,17 @@
[tcp.services] [tcp.services]
[tcp.services.whoami-no-tls.loadBalancer] [tcp.services.whoami-no-tls.loadBalancer]
[[tcp.services.whoami-no-tls.loadBalancer.servers]] [[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]
[[tcp.services.whoami-a.loadBalancer.servers]] [[tcp.services.whoami-a.loadBalancer.servers]]
address = "localhost:8081" address = "whoami-a:8080"
[tcp.services.whoami-b.loadBalancer] [tcp.services.whoami-b.loadBalancer]
[[tcp.services.whoami-b.loadBalancer.servers]] [[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]
[[tcp.services.whoami-no-cert.loadBalancer.servers]] [[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]
[tcp.services.whoami-no-tls.loadBalancer] [tcp.services.whoami-no-tls.loadBalancer]
[[tcp.services.whoami-no-tls.loadBalancer.servers]] [[tcp.services.whoami-no-tls.loadBalancer.servers]]
address = "localhost:8084" address = "whoami-no-tls:8080"

View file

@ -18,25 +18,24 @@
## dynamic configuration ## ## dynamic configuration ##
[tcp] [tcp]
[tcp.routers] [tcp.routers]
[tcp.routers.to-whoami-a] [tcp.routers.to-whoami-b]
rule = "HostSNI(`whoami-a.test`)" rule = "HostSNI(`whoami-b.test`)"
service = "whoami" service = "whoami"
entryPoints = [ "tcp" ] entryPoints = [ "tcp" ]
[tcp.routers.to-whoami-a.tls] [tcp.routers.to-whoami-b.tls]
passthrough=true passthrough=true
[[tcp.services.whoami.weighted.services]] [[tcp.services.whoami.weighted.services]]
name="whoami-a" name="whoami-b"
weight=3 weight=3
[[tcp.services.whoami.weighted.services]] [[tcp.services.whoami.weighted.services]]
name="whoami-b" name="whoami-ab"
weight=1 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]
[[tcp.services.whoami-b.loadBalancer.servers]] [[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] [http.services.service1.loadBalancer]
passHostHeader = true passHostHeader = true
[[http.services.service1.loadBalancer.servers]] [[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}" url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
[http.services.service2] [http.services.service2]
[http.services.service2.loadBalancer] [http.services.service2.loadBalancer]
passHostHeader = true passHostHeader = true
[[http.services.service2.loadBalancer.servers]] [[http.services.service2.loadBalancer.servers]]
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}" url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
[http.services.service3] [http.services.service3]
[http.services.service3.loadBalancer] [http.services.service3.loadBalancer]
passHostHeader = true passHostHeader = true
[[http.services.service3.loadBalancer.servers]] [[http.services.service3.loadBalancer.servers]]
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}" url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"

View file

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

View file

@ -50,16 +50,16 @@
[http.services.service1.loadBalancer] [http.services.service1.loadBalancer]
passHostHeader = true passHostHeader = true
[[http.services.service1.loadBalancer.servers]] [[http.services.service1.loadBalancer.servers]]
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}" url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
[http.services.service2] [http.services.service2]
[http.services.service2.loadBalancer] [http.services.service2.loadBalancer]
passHostHeader = true passHostHeader = true
[[http.services.service2.loadBalancer.servers]] [[http.services.service2.loadBalancer.servers]]
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}" url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
[http.services.service3] [http.services.service3]
[http.services.service3.loadBalancer] [http.services.service3.loadBalancer]
passHostHeader = true passHostHeader = true
[[http.services.service3.loadBalancer.servers]] [[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" checker "github.com/vdemeester/shakers"
) )
// HealthCheck test suites (using libcompose). // HealthCheck test suites.
type HealthCheckSuite struct { type HealthCheckSuite struct {
BaseSuite BaseSuite
whoami1IP string whoami1IP string
@ -24,12 +24,12 @@ type HealthCheckSuite struct {
func (s *HealthCheckSuite) SetUpSuite(c *check.C) { func (s *HealthCheckSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "healthcheck") s.createComposeProject(c, "healthcheck")
s.composeProject.Start(c) s.composeUp(c)
s.whoami1IP = s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress s.whoami1IP = s.getComposeServiceIP(c, "whoami1")
s.whoami2IP = s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress s.whoami2IP = s.getComposeServiceIP(c, "whoami2")
s.whoami3IP = s.composeProject.Container(c, "whoami3").NetworkSettings.IPAddress s.whoami3IP = s.getComposeServiceIP(c, "whoami3")
s.whoami4IP = s.composeProject.Container(c, "whoami4").NetworkSettings.IPAddress s.whoami4IP = s.getComposeServiceIP(c, "whoami4")
} }
func (s *HealthCheckSuite) TestSimpleConfiguration(c *check.C) { 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. // Check if the service with bad health check (whoami2) never respond.
err = try.Request(frontendReq, 2*time.Second, try.BodyContains(s.whoami2IP)) 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 // TODO validate : run on 80
resp, err := http.Get("http://127.0.0.1:8000/") 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) { func (s *HostResolverSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "hostresolver") s.createComposeProject(c, "hostresolver")
s.composeUp(c)
s.composeProject.Start(c)
s.composeProject.Container(c, "server1")
} }
func (s *HostResolverSuite) TestSimpleConfig(c *check.C) { func (s *HostResolverSuite) TestSimpleConfig(c *check.C) {
@ -48,7 +46,7 @@ func (s *HostResolverSuite) TestSimpleConfig(c *check.C) {
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
req.Host = test.host 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) c.Assert(err, checker.IsNil)
} }
} }

View file

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

View file

@ -3,9 +3,9 @@ package integration
import ( import (
"bytes" "bytes"
"context"
"flag" "flag"
"fmt" "fmt"
"net"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@ -14,17 +14,23 @@ import (
"text/template" "text/template"
"time" "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/fatih/structs"
"github.com/go-check/check" "github.com/go-check/check"
compose "github.com/libkermit/compose/check"
"github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/log"
checker "github.com/vdemeester/shakers" checker "github.com/vdemeester/shakers"
) )
var ( var (
integration = flag.Bool("integration", false, "run integration tests") 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") showLog = flag.Bool("tlog", false, "always show Traefik logs")
) )
@ -34,45 +40,39 @@ func Test(t *testing.T) {
return return
} }
if *container {
// tests launched from a container
check.Suite(&AccessLogSuite{}) check.Suite(&AccessLogSuite{})
check.Suite(&AcmeSuite{}) check.Suite(&AcmeSuite{})
check.Suite(&EtcdSuite{})
check.Suite(&ConsulSuite{})
check.Suite(&ConsulCatalogSuite{}) check.Suite(&ConsulCatalogSuite{})
check.Suite(&ConsulSuite{})
check.Suite(&DockerComposeSuite{}) check.Suite(&DockerComposeSuite{})
check.Suite(&DockerSuite{}) check.Suite(&DockerSuite{})
check.Suite(&ErrorPagesSuite{}) check.Suite(&ErrorPagesSuite{})
check.Suite(&EtcdSuite{})
check.Suite(&FileSuite{}) check.Suite(&FileSuite{})
check.Suite(&GRPCSuite{}) check.Suite(&GRPCSuite{})
check.Suite(&HealthCheckSuite{})
check.Suite(&HeadersSuite{}) check.Suite(&HeadersSuite{})
check.Suite(&HealthCheckSuite{})
check.Suite(&HostResolverSuite{}) check.Suite(&HostResolverSuite{})
check.Suite(&HTTPSuite{})
check.Suite(&HTTPSSuite{}) check.Suite(&HTTPSSuite{})
check.Suite(&HTTPSuite{})
check.Suite(&K8sSuite{})
check.Suite(&KeepAliveSuite{}) check.Suite(&KeepAliveSuite{})
check.Suite(&LogRotationSuite{}) check.Suite(&LogRotationSuite{})
check.Suite(&MarathonSuite{})
check.Suite(&MarathonSuite15{}) check.Suite(&MarathonSuite15{})
check.Suite(&MarathonSuite{})
check.Suite(&ProxyProtocolSuite{})
check.Suite(&RateLimitSuite{}) check.Suite(&RateLimitSuite{})
check.Suite(&RedisSuite{}) check.Suite(&RedisSuite{})
check.Suite(&RestSuite{}) check.Suite(&RestSuite{})
check.Suite(&RetrySuite{}) check.Suite(&RetrySuite{})
check.Suite(&SimpleSuite{}) check.Suite(&SimpleSuite{})
check.Suite(&TCPSuite{})
check.Suite(&TimeoutSuite{}) check.Suite(&TimeoutSuite{})
check.Suite(&TLSClientHeadersSuite{}) check.Suite(&TLSClientHeadersSuite{})
check.Suite(&TracingSuite{}) check.Suite(&TracingSuite{})
check.Suite(&UDPSuite{}) check.Suite(&UDPSuite{})
check.Suite(&WebsocketSuite{}) check.Suite(&WebsocketSuite{})
check.Suite(&ZookeeperSuite{}) check.Suite(&ZookeeperSuite{})
}
if *host {
// tests launched from the host
check.Suite(&K8sSuite{})
check.Suite(&ProxyProtocolSuite{})
check.Suite(&TCPSuite{})
}
check.TestingT(t) check.TestingT(t)
} }
@ -80,36 +80,72 @@ func Test(t *testing.T) {
var traefikBinary = "../dist/traefik" var traefikBinary = "../dist/traefik"
type BaseSuite struct { type BaseSuite struct {
composeProject *compose.Project composeProject *types.Project
dockerComposeService composeapi.Service
dockerClient *client.Client
} }
func (s *BaseSuite) TearDownSuite(c *check.C) { func (s *BaseSuite) TearDownSuite(c *check.C) {
// shutdown and delete compose project if s.composeProject != nil && s.dockerComposeService != nil {
if s.composeProject != nil { s.composeDown(c)
s.composeProject.Stop(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) { 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) 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) c.Assert(err, checker.IsNil)
for _, addr := range addrs {
ip, _, err := net.ParseCIDR(addr.String()) 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) 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) // 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)
} }
func withConfigFile(file string) string { // composeStop stops the given services of the current docker compose project and removes the corresponding containers.
return "--configFile=" + file 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) { 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) { return cmd, func(c *check.C) {
if c.Failed() || *showLog { if c.Failed() || *showLog {
s.displayLogK3S(c) s.displayLogK3S(c)
s.displayLogCompose(c)
s.displayTraefikLog(c, out) s.displayTraefikLog(c, out)
} }
} }
@ -153,6 +190,25 @@ func (s *BaseSuite) displayLogK3S(c *check.C) {
log.WithoutContext().Println() 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) { func (s *BaseSuite) displayTraefikLog(c *check.C, output *bytes.Buffer) {
if output == nil || output.Len() == 0 { if output == nil || output.Len() == 0 {
log.WithoutContext().Infof("%s: No Traefik logs.", c.TestName()) log.WithoutContext().Infof("%s: No Traefik logs.", c.TestName())
@ -168,6 +224,7 @@ func (s *BaseSuite) getDockerHost() string {
// Default docker socket // Default docker socket
dockerHost = "unix:///var/run/docker.sock" dockerHost = "unix:///var/run/docker.sock"
} }
return dockerHost return dockerHost
} }
@ -192,3 +249,38 @@ func (s *BaseSuite) adaptFile(c *check.C, path string, tempObjects interface{})
return tmpFile.Name() 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) { func (s *K8sSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "k8s") s.createComposeProject(c, "k8s")
s.composeProject.Start(c) s.composeUp(c)
abs, err := filepath.Abs("./fixtures/k8s/config.skip/kubeconfig.yaml") abs, err := filepath.Abs("./fixtures/k8s/config.skip/kubeconfig.yaml")
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
@ -44,7 +44,7 @@ func (s *K8sSuite) SetUpSuite(c *check.C) {
} }
func (s *K8sSuite) TearDownSuite(c *check.C) { func (s *K8sSuite) TearDownSuite(c *check.C) {
s.composeProject.Stop(c) s.composeDown(c)
generatedFiles := []string{ generatedFiles := []string{
"./fixtures/k8s/config.skip/kubeconfig.yaml", "./fixtures/k8s/config.skip/kubeconfig.yaml",
@ -56,8 +56,7 @@ func (s *K8sSuite) TearDownSuite(c *check.C) {
} }
for _, filename := range generatedFiles { for _, filename := range generatedFiles {
err := os.Remove(filename) if err := os.Remove(filename); err != nil {
if err != nil {
log.WithoutContext().Warning(err) log.WithoutContext().Warning(err)
} }
} }

View file

@ -13,17 +13,38 @@ import (
"github.com/go-check/check" "github.com/go-check/check"
"github.com/traefik/traefik/v2/integration/try" "github.com/traefik/traefik/v2/integration/try"
"github.com/traefik/traefik/v2/pkg/log"
checker "github.com/vdemeester/shakers" checker "github.com/vdemeester/shakers"
) )
const (
traefikTestLogFileRotated = traefikTestLogFile + ".rotated"
traefikTestAccessLogFileRotated = traefikTestAccessLogFile + ".rotated"
)
// Log rotation integration test suite. // Log rotation integration test suite.
type LogRotationSuite struct{ BaseSuite } type LogRotationSuite struct{ BaseSuite }
func (s *LogRotationSuite) SetUpSuite(c *check.C) { func (s *LogRotationSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "access_log") 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) { func (s *LogRotationSuite) TestAccessLogRotation(c *check.C) {
@ -36,8 +57,6 @@ func (s *LogRotationSuite) TestAccessLogRotation(c *check.C) {
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
defer s.killCmd(cmd) defer s.killCmd(cmd)
defer os.Remove(traefikTestAccessLogFile)
// Verify Traefik started ok // Verify Traefik started ok
verifyEmptyErrorLog(c, "traefik.log") verifyEmptyErrorLog(c, "traefik.log")
@ -52,7 +71,7 @@ func (s *LogRotationSuite) TestAccessLogRotation(c *check.C) {
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
// Rename access log // Rename access log
err = os.Rename(traefikTestAccessLogFile, traefikTestAccessLogFile+".rotated") err = os.Rename(traefikTestAccessLogFile, traefikTestAccessLogFileRotated)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
// in the midst of the requests, issue SIGUSR1 signal to server process // 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) c.Assert(err, checker.IsNil)
// Verify access.log.rotated output as expected // Verify access.log.rotated output as expected
logAccessLogFile(c, traefikTestAccessLogFile+".rotated") logAccessLogFile(c, traefikTestAccessLogFileRotated)
lineCount := verifyLogLines(c, traefikTestAccessLogFile+".rotated", 0, true) lineCount := verifyLogLines(c, traefikTestAccessLogFileRotated, 0, true)
c.Assert(lineCount, checker.GreaterOrEqualThan, 1) c.Assert(lineCount, checker.GreaterOrEqualThan, 1)
// make sure that the access log file is at least created before we do assertions on it // 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) c.Assert(err, checker.IsNil)
defer s.killCmd(cmd) defer s.killCmd(cmd)
defer os.Remove(traefikTestAccessLogFile)
waitForTraefik(c, "server1") waitForTraefik(c, "server1")
// Rename traefik log // Rename traefik log
err = os.Rename(traefikTestLogFile, traefikTestLogFile+".rotated") err = os.Rename(traefikTestLogFile, traefikTestLogFileRotated)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
// issue SIGUSR1 signal to server process // issue SIGUSR1 signal to server process
@ -118,7 +135,7 @@ func (s *LogRotationSuite) TestTraefikLogRotation(c *check.C) {
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
// we have at least 6 lines in traefik.log.rotated // 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 // GreaterOrEqualThan used to ensure test doesn't break
// If more log entries are output on startup // If more log entries are output on startup

View file

@ -1,7 +1,6 @@
package integration package integration
import ( import (
"fmt"
"net/http" "net/http"
"os" "os"
"time" "time"
@ -12,7 +11,7 @@ import (
checker "github.com/vdemeester/shakers" checker "github.com/vdemeester/shakers"
) )
// Marathon test suites (using libcompose). // Marathon test suites.
type MarathonSuite15 struct { type MarathonSuite15 struct {
BaseSuite BaseSuite
marathonURL string marathonURL string
@ -20,53 +19,15 @@ type MarathonSuite15 struct {
func (s *MarathonSuite15) SetUpSuite(c *check.C) { func (s *MarathonSuite15) SetUpSuite(c *check.C) {
s.createComposeProject(c, "marathon15") s.createComposeProject(c, "marathon15")
s.composeProject.Start(c) s.composeUp(c)
marathonIPAddr := s.composeProject.Container(c, containerNameMarathon).NetworkSettings.IPAddress s.marathonURL = "http://" + containerNameMarathon + ":8080"
c.Assert(marathonIPAddr, checker.Not(checker.HasLen), 0)
s.marathonURL = "http://" + marathonIPAddr + ":8080"
// Wait for Marathon readiness prior to creating the client so that we // 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 // don't run into the "all cluster members down" state right from the
// start. // start.
err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK)) err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil) 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) { func (s *MarathonSuite15) TestConfigurationUpdate(c *check.C) {

View file

@ -1,7 +1,6 @@
package integration package integration
import ( import (
"fmt"
"net/http" "net/http"
"os" "os"
"time" "time"
@ -12,12 +11,9 @@ import (
checker "github.com/vdemeester/shakers" checker "github.com/vdemeester/shakers"
) )
const ( const containerNameMarathon = "marathon"
containerNameMesosSlave = "mesos-slave"
containerNameMarathon = "marathon"
)
// Marathon test suites (using libcompose). // Marathon test suites.
type MarathonSuite struct { type MarathonSuite struct {
BaseSuite BaseSuite
marathonURL string marathonURL string
@ -25,53 +21,15 @@ type MarathonSuite struct {
func (s *MarathonSuite) SetUpSuite(c *check.C) { func (s *MarathonSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "marathon") s.createComposeProject(c, "marathon")
s.composeProject.Start(c) s.composeUp(c)
marathonIPAddr := s.composeProject.Container(c, containerNameMarathon).NetworkSettings.IPAddress s.marathonURL = "http://" + containerNameMarathon + ":8080"
c.Assert(marathonIPAddr, checker.Not(checker.HasLen), 0)
s.marathonURL = "http://" + marathonIPAddr + ":8080"
// Wait for Marathon readiness prior to creating the client so that we // 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 // don't run into the "all cluster members down" state right from the
// start. // start.
err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK)) err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil) 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) { func deployApplication(c *check.C, client marathon.Marathon, application *marathon.Application) {

View file

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

View file

@ -17,9 +17,9 @@ type RateLimitSuite struct {
func (s *RateLimitSuite) SetUpSuite(c *check.C) { func (s *RateLimitSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "ratelimit") 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) { func (s *RateLimitSuite) TestSimpleConfiguration(c *check.C) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,5 +1,10 @@
version: "3.8"
services:
etcd: etcd:
image: quay.io/coreos/etcd:v3.3.18 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 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 @@
version: "3.8"
services:
whoami1: whoami1:
image: traefik/whoami image: traefik/whoami
ports:
- "8881:80"
whoami2: whoami2:
image: traefik/whoami image: traefik/whoami
ports:
- "8882:80"
whoami3: whoami3:
image: traefik/whoami image: traefik/whoami
ports:
- "8883:80"
whoami4: whoami4:
image: traefik/whoami image: traefik/whoami
ports:
- "8884:80"
whoami5: whoami5:
image: traefik/whoami image: traefik/whoami
ports:
- "8885:80" networks:
default:
name: traefik-test-network
external: true

View file

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

View file

@ -1,6 +1,13 @@
version: "3.8"
services:
server1: server1:
image: traefik/whoami image: traefik/whoami
labels: labels:
- traefik.enable=true traefik.enable: true
- traefik.http.services.service1.loadbalancer.server.port=80 traefik.http.services.service1.loadbalancer.server.port: 80
- traefik.http.routers.router1.rule=Host("github.com") traefik.http.routers.router1.rule: Host(`github.com`)
networks:
default:
name: traefik-test-network
external: true

View file

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

View file

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

View file

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

View file

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

View file

@ -1,10 +1,15 @@
version: "3.8"
services:
pebble: pebble:
image: letsencrypt/pebble:v2.3.1 image: letsencrypt/pebble:v2.3.1
command: pebble --dnsserver ${DOCKER_HOST_IP}:5053 command: pebble --dnsserver traefik:5053
ports:
- 14000:14000
environment: environment:
# https://github.com/letsencrypt/pebble#testing-at-full-speed # 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 # 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 @@
version: "3.8"
services:
haproxy: haproxy:
image: haproxy:2.2 image: haproxy:2.2
volumes: 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 image: traefik/whoami
networks:
default:
name: traefik-test-network
external: true

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,14 @@
version: "3.8"
services:
whoami: whoami:
image: traefik/whoami image: traefik/whoami
labels: labels:
- traefik.http.routers.route1.rule=PathPrefix(`/foo`) traefik.http.routers.route1.rule: PathPrefix(`/foo`)
- traefik.http.routers.route1.middlewares=passtls traefik.http.routers.route1.middlewares: passtls
- traefik.http.routers.route1.tls=true traefik.http.routers.route1.tls: true
- traefik.http.middlewares.passtls.passtlsclientcert.pem=true traefik.http.middlewares.passtls.passtlsclientcert.pem: true
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,21 +1,20 @@
version: "3.8"
services:
zipkin: zipkin:
image: openzipkin/zipkin:2.16.2 image: openzipkin/zipkin:2.16.2
environment: environment:
STORAGE_TYPE: mem STORAGE_TYPE: mem
JAVA_OPTS: -Dlogging.level.zipkin=DEBUG JAVA_OPTS: -Dlogging.level.zipkin=DEBUG
ports:
- 9411:9411
jaeger: jaeger:
image: jaegertracing/all-in-one:1.14 image: jaegertracing/all-in-one:1.14
environment: environment:
COLLECTOR_ZIPKIN_HTTP_PORT: 9411 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 image: traefik/whoami
networks:
default:
name: traefik-test-network
external: true

View file

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

View file

@ -1,34 +1,41 @@
version: "3.8"
services:
noOverrideWhitelist: noOverrideWhitelist:
image: traefik/whoami image: traefik/whoami
labels: labels:
- traefik.enable=true traefik.enable: true
- traefik.http.routers.rt1.rule=Host("no.override.whitelist.docker.local") traefik.http.routers.rt1.rule: Host(`no.override.whitelist.docker.local`)
- traefik.http.routers.rt1.middlewares=wl1 traefik.http.routers.rt1.middlewares: wl1
- traefik.http.middlewares.wl1.ipwhiteList.sourceRange=8.8.8.8 traefik.http.middlewares.wl1.ipwhiteList.sourceRange: 8.8.8.8
overrideIPStrategyRemoteAddrWhitelist: overrideIPStrategyRemoteAddrWhitelist:
image: traefik/whoami image: traefik/whoami
labels: labels:
- traefik.enable=true traefik.enable: true
- traefik.http.routers.rt2.rule=Host("override.remoteaddr.whitelist.docker.local") traefik.http.routers.rt2.rule: Host(`override.remoteaddr.whitelist.docker.local`)
- traefik.http.routers.rt2.middlewares=wl2 traefik.http.routers.rt2.middlewares: wl2
- traefik.http.middlewares.wl2.ipwhitelist.sourceRange=8.8.8.8 traefik.http.middlewares.wl2.ipwhitelist.sourceRange: 8.8.8.8
- traefik.http.middlewares.wl2.ipwhitelist.ipStrategy=true traefik.http.middlewares.wl2.ipwhitelist.ipStrategy: true
overrideIPStrategyDepthWhitelist: overrideIPStrategyDepthWhitelist:
image: traefik/whoami image: traefik/whoami
labels: labels:
- traefik.enable=true traefik.enable: true
- traefik.http.routers.rt3.rule=Host("override.depth.whitelist.docker.local") traefik.http.routers.rt3.rule: Host(`override.depth.whitelist.docker.local`)
- traefik.http.routers.rt3.middlewares=wl3 traefik.http.routers.rt3.middlewares: wl3
- traefik.http.middlewares.wl3.ipwhitelist.sourceRange=8.8.8.8 traefik.http.middlewares.wl3.ipwhitelist.sourceRange: 8.8.8.8
- traefik.http.middlewares.wl3.ipwhitelist.ipStrategy.depth=3 traefik.http.middlewares.wl3.ipwhitelist.ipStrategy.depth: 3
overrideIPStrategyExcludedIPsWhitelist: overrideIPStrategyExcludedIPsWhitelist:
image: traefik/whoami image: traefik/whoami
labels: labels:
- traefik.enable=true traefik.enable: true
- traefik.http.routers.rt4.rule=Host("override.excludedips.whitelist.docker.local") traefik.http.routers.rt4.rule: Host(`override.excludedips.whitelist.docker.local`)
- traefik.http.routers.rt4.middlewares=wl4 traefik.http.routers.rt4.middlewares: wl4
- traefik.http.middlewares.wl4.ipwhitelist.sourceRange=8.8.8.8 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.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 @@
version: "3.8"
services:
zookeeper: zookeeper:
image: zookeeper:3.5 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 backend TestServerNodes
mode tcp mode tcp
server TestServer01 172.17.0.1:8000 send-proxy server TestServer01 traefik:8000 send-proxy
backend TestServerNodesV2 backend TestServerNodesV2
mode tcp 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 ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"net"
"net/http" "net/http"
"os" "os"
"strings" "strings"
@ -14,12 +15,16 @@ import (
checker "github.com/vdemeester/shakers" checker "github.com/vdemeester/shakers"
) )
type RestSuite struct{ BaseSuite } type RestSuite struct {
BaseSuite
whoamiAddr string
}
func (s *RestSuite) SetUpSuite(c *check.C) { func (s *RestSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "rest") 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) { func (s *RestSuite) TestSimpleConfigurationInsecure(c *check.C) {
@ -60,7 +65,7 @@ func (s *RestSuite) TestSimpleConfigurationInsecure(c *check.C) {
LoadBalancer: &dynamic.ServersLoadBalancer{ LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{ 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{ LoadBalancer: &dynamic.TCPServersLoadBalancer{
Servers: []dynamic.TCPServer{ 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{ LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{ 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{ LoadBalancer: &dynamic.TCPServersLoadBalancer{
Servers: []dynamic.TCPServer{ 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(err, checker.IsNil)
c.Assert(response.StatusCode, checker.Equals, http.StatusOK) 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) 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) c.Assert(err, checker.IsNil)
} }
} }

View file

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

View file

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

View file

@ -2,6 +2,9 @@ package integration
import ( import (
"crypto/tls" "crypto/tls"
"crypto/x509"
"errors"
"fmt"
"net" "net"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
@ -18,7 +21,7 @@ type TCPSuite struct{ BaseSuite }
func (s *TCPSuite) SetUpSuite(c *check.C) { func (s *TCPSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "tcp") s.createComposeProject(c, "tcp")
s.composeProject.Start(c) s.composeUp(c)
} }
func (s *TCPSuite) TestMixed(c *check.C) { func (s *TCPSuite) TestMixed(c *check.C) {
@ -36,12 +39,12 @@ func (s *TCPSuite) TestMixed(c *check.C) {
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
// Traefik passes through, termination handled by whoami-a // 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(err, checker.IsNil)
c.Assert(out, checker.Contains, "whoami-a") c.Assert(out, checker.Contains, "whoami-a")
// Traefik passes through, termination handled by whoami-b // 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(err, checker.IsNil)
c.Assert(out, checker.Contains, "whoami-b") c.Assert(out, checker.Contains, "whoami-b")
@ -116,12 +119,12 @@ func (s *TCPSuite) TestNonTLSFallback(c *check.C) {
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
// Traefik passes through, termination handled by whoami-a // 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(err, checker.IsNil)
c.Assert(out, checker.Contains, "whoami-a") c.Assert(out, checker.Contains, "whoami-a")
// Traefik passes through, termination handled by whoami-b // 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(err, checker.IsNil)
c.Assert(out, checker.Contains, "whoami-b") c.Assert(out, checker.Contains, "whoami-b")
@ -211,19 +214,52 @@ func (s *TCPSuite) TestMiddlewareWhiteList(c *check.C) {
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
defer s.killCmd(cmd) defer s.killCmd(cmd)
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 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) c.Assert(err, checker.IsNil)
// Traefik not passes through, ipWhitelist closes connection // Traefik not passes through, ipWhitelist closes connection
_, err = guessWho("127.0.0.1:8093", "whoami-a.test", true) _, err = guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-a.test")
c.Assert(err, checker.NotNil) c.Assert(err, checker.ErrorMatches, "EOF")
// Traefik passes through, termination handled by whoami-b // 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(err, checker.IsNil)
c.Assert(out, checker.Contains, "whoami-b") 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) { func welcome(addr string) (string, error) {
tcpAddr, err := net.ResolveTCPAddr("tcp", addr) tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil { if err != nil {
@ -291,34 +327,54 @@ func guessWhoTLSMaxVersion(addr, serverName string, tlsCall bool, tlsMaxVersion
return string(out[:n]), nil return string(out[:n]), nil
} }
func (s *TCPSuite) TestWRR(c *check.C) { // guessWhoTLSPassthrough guesses service identity and ensures that the
file := s.adaptFile(c, "fixtures/tcp/wrr.toml", struct{}{}) // certificate is valid for the given server name.
defer os.Remove(file) func guessWhoTLSPassthrough(addr, serverName string) (string, error) {
var conn net.Conn
var err error
cmd, display := s.traefikCmd(withConfigFile(file)) conn, err = tls.Dial("tcp", addr, &tls.Config{
defer display(c) ServerName: serverName,
InsecureSkipVerify: true,
err := cmd.Start() MinVersion: 0,
c.Assert(err, checker.IsNil) MaxVersion: 0,
defer s.killCmd(cmd) VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
if len(rawCerts) > 1 {
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI")) return errors.New("tls: more than one certificates from peer")
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"]++
}
} }
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) { func (s *TimeoutSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "timeout") s.createComposeProject(c, "timeout")
s.composeProject.Start(c) s.composeUp(c)
} }
func (s *TimeoutSuite) TestForwardingTimeouts(c *check.C) { func (s *TimeoutSuite) TestForwardingTimeouts(c *check.C) {
httpTimeoutEndpoint := s.composeProject.Container(c, "timeoutEndpoint").NetworkSettings.IPAddress timeoutEndpointIP := s.getComposeServiceIP(c, "timeoutEndpoint")
file := s.adaptFile(c, "fixtures/timeout/forwarding_timeouts.toml", struct { file := s.adaptFile(c, "fixtures/timeout/forwarding_timeouts.toml", struct{ TimeoutEndpoint string }{timeoutEndpointIP})
TimeoutEndpoint string
}{httpTimeoutEndpoint})
defer os.Remove(file) defer os.Remove(file)
cmd, display := s.traefikCmd(withConfigFile(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) c.Assert(response.StatusCode, checker.Equals, http.StatusGatewayTimeout)
// Check that timeout service is available // 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) c.Assert(try.GetRequest(statusURL, 60*time.Second, try.StatusCodeIs(http.StatusOK)), checker.IsNil)
// This simulates a ResponseHeaderTimeout. // This simulates a ResponseHeaderTimeout.

View file

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

View file

@ -12,47 +12,49 @@ import (
type TracingSuite struct { type TracingSuite struct {
BaseSuite BaseSuite
WhoAmiIP string whoamiIP string
WhoAmiPort int whoamiPort int
IP string tracerIP string
} }
type TracingTemplate struct { type TracingTemplate struct {
WhoAmiIP string WhoamiIP string
WhoAmiPort int WhoamiPort int
IP string IP string
TraceContextHeaderName string TraceContextHeaderName string
} }
func (s *TracingSuite) SetUpSuite(c *check.C) { func (s *TracingSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "tracing") s.createComposeProject(c, "tracing")
s.composeProject.Start(c, "whoami") s.composeUp(c)
s.WhoAmiIP = s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress s.whoamiIP = s.getComposeServiceIP(c, "whoami")
s.WhoAmiPort = 80 s.whoamiPort = 80
} }
func (s *TracingSuite) startZipkin(c *check.C) { func (s *TracingSuite) startZipkin(c *check.C) {
s.composeProject.Start(c, "zipkin") s.composeUp(c, "zipkin")
s.IP = s.composeProject.Container(c, "zipkin").NetworkSettings.IPAddress s.tracerIP = s.getComposeServiceIP(c, "zipkin")
// Wait for Zipkin to turn ready. // 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) c.Assert(err, checker.IsNil)
} }
func (s *TracingSuite) TestZipkinRateLimit(c *check.C) { func (s *TracingSuite) TestZipkinRateLimit(c *check.C) {
s.startZipkin(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{ file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP, WhoamiIP: s.whoamiIP,
WhoAmiPort: s.WhoAmiPort, WhoamiPort: s.whoamiPort,
IP: s.IP, IP: s.tracerIP,
}) })
defer os.Remove(file) defer os.Remove(file)
cmd, display := s.traefikCmd(withConfigFile(file)) cmd, display := s.traefikCmd(withConfigFile(file))
defer display(c) defer display(c)
err := cmd.Start() err := cmd.Start()
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
defer s.killCmd(cmd) 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)) err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests))
c.Assert(err, checker.IsNil) 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) c.Assert(err, checker.IsNil)
} }
func (s *TracingSuite) TestZipkinRetry(c *check.C) { func (s *TracingSuite) TestZipkinRetry(c *check.C) {
s.startZipkin(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{ file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP, WhoamiIP: s.whoamiIP,
WhoAmiPort: 81, WhoamiPort: 81,
IP: s.IP, IP: s.tracerIP,
}) })
defer os.Remove(file) 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)) err = try.GetRequest("http://127.0.0.1:8000/retry", 500*time.Millisecond, try.StatusCodeIs(http.StatusBadGateway))
c.Assert(err, checker.IsNil) 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) c.Assert(err, checker.IsNil)
} }
func (s *TracingSuite) TestZipkinAuth(c *check.C) { func (s *TracingSuite) TestZipkinAuth(c *check.C) {
s.startZipkin(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{ file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP, WhoamiIP: s.whoamiIP,
WhoAmiPort: s.WhoAmiPort, WhoamiPort: s.whoamiPort,
IP: s.IP, IP: s.tracerIP,
}) })
defer os.Remove(file) 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)) err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
c.Assert(err, checker.IsNil) 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) c.Assert(err, checker.IsNil)
} }
func (s *TracingSuite) startJaeger(c *check.C) { func (s *TracingSuite) startJaeger(c *check.C) {
s.composeProject.Start(c, "jaeger") s.composeUp(c, "jaeger", "whoami")
s.IP = s.composeProject.Container(c, "jaeger").NetworkSettings.IPAddress s.tracerIP = s.getComposeServiceIP(c, "jaeger")
// Wait for Jaeger to turn ready. // 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) c.Assert(err, checker.IsNil)
} }
func (s *TracingSuite) TestJaegerRateLimit(c *check.C) { func (s *TracingSuite) TestJaegerRateLimit(c *check.C) {
s.startJaeger(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{ file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP, WhoamiIP: s.whoamiIP,
WhoAmiPort: s.WhoAmiPort, WhoamiPort: s.whoamiPort,
IP: s.IP, IP: s.tracerIP,
TraceContextHeaderName: "uber-trace-id", TraceContextHeaderName: "uber-trace-id",
}) })
defer os.Remove(file) 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)) err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests))
c.Assert(err, checker.IsNil) 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) c.Assert(err, checker.IsNil)
} }
func (s *TracingSuite) TestJaegerRetry(c *check.C) { func (s *TracingSuite) TestJaegerRetry(c *check.C) {
s.startJaeger(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{ file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP, WhoamiIP: s.whoamiIP,
WhoAmiPort: 81, WhoamiPort: 81,
IP: s.IP, IP: s.tracerIP,
TraceContextHeaderName: "uber-trace-id", TraceContextHeaderName: "uber-trace-id",
}) })
defer os.Remove(file) 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)) err = try.GetRequest("http://127.0.0.1:8000/retry", 500*time.Millisecond, try.StatusCodeIs(http.StatusBadGateway))
c.Assert(err, checker.IsNil) 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) c.Assert(err, checker.IsNil)
} }
func (s *TracingSuite) TestJaegerAuth(c *check.C) { func (s *TracingSuite) TestJaegerAuth(c *check.C) {
s.startJaeger(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{ file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP, WhoamiIP: s.whoamiIP,
WhoAmiPort: s.WhoAmiPort, WhoamiPort: s.whoamiPort,
IP: s.IP, IP: s.tracerIP,
TraceContextHeaderName: "uber-trace-id", TraceContextHeaderName: "uber-trace-id",
}) })
defer os.Remove(file) 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)) err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
c.Assert(err, checker.IsNil) 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) c.Assert(err, checker.IsNil)
} }
func (s *TracingSuite) TestJaegerCustomHeader(c *check.C) { func (s *TracingSuite) TestJaegerCustomHeader(c *check.C) {
s.startJaeger(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{ file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP, WhoamiIP: s.whoamiIP,
WhoAmiPort: s.WhoAmiPort, WhoamiPort: s.whoamiPort,
IP: s.IP, IP: s.tracerIP,
TraceContextHeaderName: "powpow", TraceContextHeaderName: "powpow",
}) })
defer os.Remove(file) 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)) err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
c.Assert(err, checker.IsNil) 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) c.Assert(err, checker.IsNil)
} }
func (s *TracingSuite) TestJaegerAuthCollector(c *check.C) { func (s *TracingSuite) TestJaegerAuthCollector(c *check.C) {
s.startJaeger(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{ file := s.adaptFile(c, "fixtures/tracing/simple-jaeger-collector.toml", TracingTemplate{
WhoAmiIP: s.WhoAmiIP, WhoamiIP: s.whoamiIP,
WhoAmiPort: s.WhoAmiPort, WhoamiPort: s.whoamiPort,
IP: s.IP, IP: s.tracerIP,
}) })
defer os.Remove(file) 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)) err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
c.Assert(err, checker.IsNil) 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) c.Assert(err, checker.IsNil)
} }

View file

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

View file

@ -3,6 +3,7 @@ package integration
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"net"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
@ -18,20 +19,25 @@ import (
checker "github.com/vdemeester/shakers" checker "github.com/vdemeester/shakers"
) )
// Zk test suites (using libcompose). // Zk test suites.
type ZookeeperSuite struct { type ZookeeperSuite struct {
BaseSuite BaseSuite
kvClient store.Store kvClient store.Store
zookeeperAddr string
} }
func (s *ZookeeperSuite) setupStore(c *check.C) { func (s *ZookeeperSuite) setupStore(c *check.C) {
s.createComposeProject(c, "zookeeper") s.createComposeProject(c, "zookeeper")
s.composeProject.Start(c) s.composeUp(c)
zookeeper.Register() 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, store.ZK,
[]string{s.composeProject.Container(c, "zookeeper").NetworkSettings.IPAddress + ":2181"}, []string{s.zookeeperAddr},
&store.Config{ &store.Config{
ConnectionTimeout: 10 * time.Second, ConnectionTimeout: 10 * time.Second,
}, },
@ -39,27 +45,16 @@ func (s *ZookeeperSuite) setupStore(c *check.C) {
if err != nil { if err != nil {
c.Fatal("Cannot create store zookeeper") c.Fatal("Cannot create store zookeeper")
} }
s.kvClient = kv
// wait for zk // 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) 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) { func (s *ZookeeperSuite) TestSimpleConfiguration(c *check.C) {
s.setupStore(c) s.setupStore(c)
address := s.composeProject.Container(c, "zookeeper").NetworkSettings.IPAddress + ":2181" file := s.adaptFile(c, "fixtures/zookeeper/simple.toml", struct{ ZkAddress string }{s.zookeeperAddr})
file := s.adaptFile(c, "fixtures/zookeeper/simple.toml", struct{ ZkAddress string }{address})
defer os.Remove(file) defer os.Remove(file)
data := map[string]string{ 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] [global]
checkNewVersion = true checkNewVersion = true
sendAnonymousUsage = true sendAnonymousUsage = true

View file

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