forked from Ivasoft/traefik
Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f34ea7a34a | ||
|
|
a70b864c55 | ||
|
|
e5e48d1cc1 | ||
|
|
42a110dd69 | ||
|
|
cf14b8fa92 | ||
|
|
e7dc6ec025 | ||
|
|
67483c1b17 | ||
|
|
4071f1e7f2 | ||
|
|
577709fff3 | ||
|
|
8cd45476ac | ||
|
|
a9776ceafc | ||
|
|
e471239955 | ||
|
|
2e8156bfaa | ||
|
|
5e2c929322 | ||
|
|
2b5355c849 | ||
|
|
f21f71786a | ||
|
|
a711f0d037 | ||
|
|
98fc6ca441 | ||
|
|
c10f1a3a36 | ||
|
|
79a14ce992 | ||
|
|
99ce26f7b1 | ||
|
|
16250361c3 | ||
|
|
be44385b42 | ||
|
|
54c77ecb54 | ||
|
|
a30f0dcabd | ||
|
|
efef7dce4f | ||
|
|
1c9e4c6050 | ||
|
|
92093a8c09 | ||
|
|
f69982aa9d | ||
|
|
82fdc569c2 | ||
|
|
def0c1a526 | ||
|
|
ef2d03d96e | ||
|
|
321c9421ea | ||
|
|
5a225b4196 | ||
|
|
525a6cf5b2 | ||
|
|
27ec0912d5 | ||
|
|
0a31225e65 | ||
|
|
db4a92d877 | ||
|
|
9df053e3f5 |
@@ -48,6 +48,7 @@
|
||||
extensionsv1beta1 = "k8s.io/api/extensions/v1beta1"
|
||||
metav1 = "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kubeerror = "k8s.io/apimachinery/pkg/api/errors"
|
||||
composeapi = "github.com/docker/compose/v2/pkg/api"
|
||||
|
||||
[linters-settings.gomoddirectives]
|
||||
replace-allow-list = [
|
||||
@@ -56,6 +57,7 @@
|
||||
"github.com/gorilla/mux",
|
||||
"github.com/mailgun/minheap",
|
||||
"github.com/mailgun/multibuf",
|
||||
"github.com/jaguilar/vt100",
|
||||
]
|
||||
|
||||
[linters]
|
||||
|
||||
@@ -26,48 +26,30 @@ global_job_config:
|
||||
- mkdir -vp "${SEMAPHORE_GIT_DIR}" "${GOPATH}/bin"
|
||||
- export GOPROXY=https://proxy.golang.org,direct
|
||||
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "${GOPATH}/bin" v1.43.0
|
||||
- curl -sfL https://install.goreleaser.com/github.com/goreleaser/goreleaser.sh | bash -s -- -b "${GOPATH}/bin"
|
||||
- curl -sSfL https://gist.githubusercontent.com/traefiker/6d7ac019c11d011e4f131bb2cca8900e/raw/goreleaser.sh | bash -s -- -b "${GOPATH}/bin"
|
||||
- go install github.com/containous/go-bindata/go-bindata@v1.0.0
|
||||
- checkout
|
||||
- cache restore traefik-$(checksum go.sum)
|
||||
|
||||
blocks:
|
||||
- name: Test Integration Container
|
||||
- name: Test Integration
|
||||
dependencies: []
|
||||
run:
|
||||
when: "branch =~ '.*' OR pull_request =~'.*'"
|
||||
task:
|
||||
jobs:
|
||||
- name: Test Integration Container
|
||||
- name: Test Integration
|
||||
commands:
|
||||
- make pull-images
|
||||
- mkdir -p static # Avoid to generate webui
|
||||
- PRE_TARGET="" make binary
|
||||
- make test-integration-container
|
||||
- make test-integration
|
||||
- df -h
|
||||
epilogue:
|
||||
always:
|
||||
commands:
|
||||
- cache store traefik-$(checksum go.sum) $HOME/go/pkg/mod
|
||||
|
||||
- name: Test Integration Host
|
||||
dependencies: []
|
||||
run:
|
||||
when: "branch =~ '.*' OR pull_request =~'.*'"
|
||||
task:
|
||||
env_vars:
|
||||
- name: PRE_TARGET
|
||||
value: ""
|
||||
jobs:
|
||||
- name: Test Integration Host
|
||||
commands:
|
||||
- mkdir -p static # Avoid to generate webui
|
||||
- make test-integration-host
|
||||
epilogue:
|
||||
always:
|
||||
commands:
|
||||
- cache store traefik-$(checksum go.sum) $HOME/go/pkg/mod
|
||||
|
||||
- name: Release
|
||||
dependencies: []
|
||||
run:
|
||||
@@ -83,7 +65,7 @@ blocks:
|
||||
- name: GH_VERSION
|
||||
value: 1.12.1
|
||||
- name: CODENAME
|
||||
value: "livarot"
|
||||
value: "brie"
|
||||
- name: PRE_TARGET
|
||||
value: ""
|
||||
prologue:
|
||||
|
||||
50
CHANGELOG.md
50
CHANGELOG.md
@@ -1,3 +1,53 @@
|
||||
## [v2.5.7](https://github.com/traefik/traefik/tree/v2.5.7) (2022-01-20)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.5.6...v2.5.7)
|
||||
|
||||
**Bug fixes:**
|
||||
- **[acme]** Update go-acme/lego to v4.6.0 ([#8716](https://github.com/traefik/traefik/pull/8716) by [ldez](https://github.com/ldez))
|
||||
- **[logs]** Adjust log level from info to debug ([#8718](https://github.com/traefik/traefik/pull/8718) by [tomMoulard](https://github.com/tomMoulard))
|
||||
- **[plugins]** Fix middleware plugins memory leak ([#8702](https://github.com/traefik/traefik/pull/8702) by [ldez](https://github.com/ldez))
|
||||
- **[server]** Mitigate memory leak ([#8706](https://github.com/traefik/traefik/pull/8706) by [mpl](https://github.com/mpl))
|
||||
- **[webui,middleware]** Fix middleware regexp's display ([#8697](https://github.com/traefik/traefik/pull/8697) by [tomMoulard](https://github.com/tomMoulard))
|
||||
|
||||
**Documentation:**
|
||||
- **[http]** Fix HTTP provider endpoint config example ([#8715](https://github.com/traefik/traefik/pull/8715) by [kevinpollet](https://github.com/kevinpollet))
|
||||
- **[k8s]** Remove typo in Kubernetes providers labelSelector examples ([#8676](https://github.com/traefik/traefik/pull/8676) by [colinwilson](https://github.com/colinwilson))
|
||||
- **[rules]** Improve regexp matcher documentation ([#8686](https://github.com/traefik/traefik/pull/8686) by [Hades32](https://github.com/Hades32))
|
||||
- **[tracing]** Fix broken jaeger documentation link ([#8665](https://github.com/traefik/traefik/pull/8665) by [tomMoulard](https://github.com/tomMoulard))
|
||||
- Update copyright for 2022 ([#8679](https://github.com/traefik/traefik/pull/8679) by [kevinpollet](https://github.com/kevinpollet))
|
||||
|
||||
## [v2.5.6](https://github.com/traefik/traefik/tree/v2.5.6) (2021-12-22)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.5.5...v2.5.6)
|
||||
|
||||
**Bug fixes:**
|
||||
- **[middleware]** Process all X-Forwarded-For headers in the request ([#8596](https://github.com/traefik/traefik/pull/8596) by [kevinpollet](https://github.com/kevinpollet))
|
||||
- **[plugins]** Update Yaegi to v0.11.2 ([#8650](https://github.com/traefik/traefik/pull/8650) by [ldez](https://github.com/ldez))
|
||||
- **[server]** Update golang.org/x/net dependency version ([#8635](https://github.com/traefik/traefik/pull/8635) by [kevinpollet](https://github.com/kevinpollet))
|
||||
|
||||
**Documentation:**
|
||||
- **[api]** Add missing API endpoints documentation ([#8649](https://github.com/traefik/traefik/pull/8649) by [ichxxx](https://github.com/ichxxx))
|
||||
- **[middleware]** Fix passTLSClientCert CRD example name ([#8637](https://github.com/traefik/traefik/pull/8637) by [ddtmachado](https://github.com/ddtmachado))
|
||||
- **[middleware]** Correct documentation in middleware overview ([#8636](https://github.com/traefik/traefik/pull/8636) by [Alestrix](https://github.com/Alestrix))
|
||||
|
||||
## [v2.5.5](https://github.com/traefik/traefik/tree/v2.5.5) (2021-12-09)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.5.4...v2.5.5)
|
||||
|
||||
**Bug fixes:**
|
||||
- **[acme]** Update go-acme/lego to v4.5.3 ([#8607](https://github.com/traefik/traefik/pull/8607) by [lippertmarkus](https://github.com/lippertmarkus))
|
||||
- **[k8s/crd,k8s]** fix: propagate source criterion config to RateLimit middleware in Kubernetes CRD ([#8591](https://github.com/traefik/traefik/pull/8591) by [rbailly-talend](https://github.com/rbailly-talend))
|
||||
- **[plugins]** plugins: start the go routine before calling Provide ([#8620](https://github.com/traefik/traefik/pull/8620) by [ldez](https://github.com/ldez))
|
||||
- **[plugins]** Update yaegi to v0.11.1 ([#8600](https://github.com/traefik/traefik/pull/8600) by [tomMoulard](https://github.com/tomMoulard))
|
||||
- **[plugins]** Update yaegi v0.11.0 ([#8564](https://github.com/traefik/traefik/pull/8564) by [ldez](https://github.com/ldez))
|
||||
- **[udp]** fix: increase UDP read buffer length to max datagram size ([#8560](https://github.com/traefik/traefik/pull/8560) by [kevinpollet](https://github.com/kevinpollet))
|
||||
|
||||
**Documentation:**
|
||||
- **[consul]** docs: removing typo in consul-catalog provider doc ([#8603](https://github.com/traefik/traefik/pull/8603) by [tomMoulard](https://github.com/tomMoulard))
|
||||
- **[metrics]** docs: remove misleading metrics overview configuration ([#8579](https://github.com/traefik/traefik/pull/8579) by [gsilvapt](https://github.com/gsilvapt))
|
||||
- **[middleware]** docs: align docker configuration example notes in basicauth HTTP middleware ([#8615](https://github.com/traefik/traefik/pull/8615) by [tomMoulard](https://github.com/tomMoulard))
|
||||
- **[service]** docs: health check use readiness probe in k8s ([#8575](https://github.com/traefik/traefik/pull/8575) by [Vampouille](https://github.com/Vampouille))
|
||||
- **[tls]** docs: uniformize client TLS config documentation ([#8602](https://github.com/traefik/traefik/pull/8602) by [kevinpollet](https://github.com/kevinpollet))
|
||||
- Update CODE_OF_CONDUCT.md ([#8619](https://github.com/traefik/traefik/pull/8619) by [tfny](https://github.com/tfny))
|
||||
- fixed minor spelling error in Regexp Syntax section ([#8565](https://github.com/traefik/traefik/pull/8565) by [kerrsmith](https://github.com/kerrsmith))
|
||||
|
||||
## [v2.5.4](https://github.com/traefik/traefik/tree/v2.5.4) (2021-11-08)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.5.3...v2.5.4)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience,nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
@@ -30,15 +30,19 @@ Project maintainers have the right and responsibility to remove, edit, or reject
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or our community.
|
||||
|
||||
Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
|
||||
Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contact@traefik.io
|
||||
|
||||
All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
|
||||
|
||||
The project team is obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016-2020 Containous SAS; 2020-2021 Traefik Labs
|
||||
Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
34
Makefile
34
Makefile
@@ -15,7 +15,7 @@ TRAEFIK_DEV_IMAGE := traefik-dev$(if $(GIT_BRANCH),:$(subst /,-,$(GIT_BRANCH)))
|
||||
REPONAME := $(shell echo $(REPO) | tr '[:upper:]' '[:lower:]')
|
||||
TRAEFIK_IMAGE := $(if $(REPONAME),$(REPONAME),"traefik/traefik")
|
||||
|
||||
INTEGRATION_OPTS := $(if $(MAKE_DOCKER_HOST),-e "DOCKER_HOST=$(MAKE_DOCKER_HOST)", -e "TEST_CONTAINER=1" -v "/var/run/docker.sock:/var/run/docker.sock")
|
||||
INTEGRATION_OPTS := $(if $(MAKE_DOCKER_HOST),-e "DOCKER_HOST=$(MAKE_DOCKER_HOST)",-v "/var/run/docker.sock:/var/run/docker.sock")
|
||||
DOCKER_BUILD_ARGS := $(if $(DOCKER_VERSION), "--build-arg=DOCKER_VERSION=$(DOCKER_VERSION)",)
|
||||
|
||||
TRAEFIK_ENVS := \
|
||||
@@ -32,7 +32,8 @@ TRAEFIK_ENVS := \
|
||||
TRAEFIK_MOUNT := -v "$(CURDIR)/$(BIND_DIR):/go/src/github.com/traefik/traefik/$(BIND_DIR)"
|
||||
DOCKER_RUN_OPTS := $(TRAEFIK_ENVS) $(TRAEFIK_MOUNT) "$(TRAEFIK_DEV_IMAGE)"
|
||||
DOCKER_NON_INTERACTIVE ?= false
|
||||
DOCKER_RUN_TRAEFIK := docker run --add-host=host.docker.internal:127.0.0.1 $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INTERACTIVE), , -it) $(DOCKER_RUN_OPTS)
|
||||
DOCKER_RUN_TRAEFIK := docker run $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INTERACTIVE), , -it) $(DOCKER_RUN_OPTS)
|
||||
DOCKER_RUN_TRAEFIK_TEST := docker run --add-host=host.docker.internal:127.0.0.1 --rm --name=traefik --network traefik-test-network -v $(PWD):$(PWD) -w $(PWD) $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INTERACTIVE), , -it) $(DOCKER_RUN_OPTS)
|
||||
DOCKER_RUN_TRAEFIK_NOTTY := docker run $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INTERACTIVE), , -i) $(DOCKER_RUN_OPTS)
|
||||
|
||||
PRE_TARGET ?= build-dev-image
|
||||
@@ -81,30 +82,27 @@ crossbinary-default-parallel:
|
||||
$(MAKE) build-dev-image crossbinary-default
|
||||
|
||||
## Run the unit and integration tests
|
||||
test: build-dev-image
|
||||
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate test-unit binary test-integration
|
||||
test: $(PRE_TARGET)
|
||||
-docker network create traefik-test-network --driver bridge --subnet 172.31.42.0/24
|
||||
trap 'docker network rm traefik-test-network' EXIT; \
|
||||
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK_TEST),) ./script/make.sh generate test-unit binary test-integration
|
||||
|
||||
## Run the unit tests
|
||||
test-unit: $(PRE_TARGET)
|
||||
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate test-unit
|
||||
-docker network create traefik-test-network --driver bridge --subnet 172.31.42.0/24
|
||||
trap 'docker network rm traefik-test-network' EXIT; \
|
||||
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK_TEST)) ./script/make.sh generate test-unit
|
||||
|
||||
## Run the integration tests
|
||||
test-integration: $(PRE_TARGET)
|
||||
-docker network create traefik-test-network --driver bridge --subnet 172.31.42.0/24
|
||||
trap 'docker network rm traefik-test-network' EXIT; \
|
||||
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK_TEST),) ./script/make.sh generate binary test-integration
|
||||
|
||||
## Pull all images for integration tests
|
||||
pull-images:
|
||||
grep --no-filename -E '^\s+image:' ./integration/resources/compose/*.yml | awk '{print $$2}' | sort | uniq | xargs -P 6 -n 1 docker pull
|
||||
|
||||
## Run the integration tests
|
||||
test-integration: $(PRE_TARGET) binary
|
||||
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK),TEST_CONTAINER=1) ./script/make.sh test-integration
|
||||
TEST_HOST=1 ./script/make.sh test-integration
|
||||
|
||||
## Run the container integration tests
|
||||
test-integration-container: $(PRE_TARGET) binary
|
||||
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK),TEST_CONTAINER=1) ./script/make.sh test-integration
|
||||
|
||||
## Run the host integration tests
|
||||
test-integration-host: $(PRE_TARGET) binary
|
||||
TEST_HOST=1 ./script/make.sh test-integration
|
||||
|
||||
## Validate code and docs
|
||||
validate-files: $(PRE_TARGET)
|
||||
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate validate-lint validate-misspell
|
||||
|
||||
@@ -19,13 +19,13 @@ RUN mkdir -p /usr/local/bin \
|
||||
&& chmod +x /usr/local/bin/go-bindata
|
||||
|
||||
# Download golangci-lint binary to bin folder in $GOPATH
|
||||
RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.43.0
|
||||
RUN curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- -b $GOPATH/bin v1.43.0
|
||||
|
||||
# Download misspell binary to bin folder in $GOPATH
|
||||
RUN curl -sfL https://raw.githubusercontent.com/client9/misspell/master/install-misspell.sh | bash -s -- -b $GOPATH/bin v0.3.4
|
||||
|
||||
# Download goreleaser binary to bin folder in $GOPATH
|
||||
RUN curl -sfL https://install.goreleaser.com/github.com/goreleaser/goreleaser.sh | sh
|
||||
RUN curl -sfL https://gist.githubusercontent.com/traefiker/6d7ac019c11d011e4f131bb2cca8900e/raw/goreleaser.sh | sh
|
||||
|
||||
WORKDIR /go/src/github.com/traefik/traefik
|
||||
|
||||
|
||||
@@ -367,7 +367,9 @@ For complete details, refer to your provider's _Additional configuration_ link.
|
||||
| [Simply.com](https://www.simply.com/en/domains/) | `simply` | `SIMPLY_ACCOUNT_NAME`, `SIMPLY_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/simply) |
|
||||
| [Sonic](https://www.sonic.com/) | `sonic` | `SONIC_USER_ID`, `SONIC_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/sonic) |
|
||||
| [Stackpath](https://www.stackpath.com/) | `stackpath` | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/stackpath) |
|
||||
| [Tencent Cloud DNS](https://cloud.tencent.com/product/cns) | `tencentcloud` | `TENCENTCLOUD_SECRET_ID`, `TENCENTCLOUD_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/tencentcloud) |
|
||||
| [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/transip) |
|
||||
| [UKFast SafeDNS](https://www.ukfast.co.uk/dns-hosting.html) | `safedns` | `SAFEDNS_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/safedns) |
|
||||
| [VegaDNS](https://github.com/shupp/VegaDNS-API) | `vegadns` | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/vegadns) |
|
||||
| [Versio](https://www.versio.nl/domeinnamen) | `versio` | `VERSIO_USERNAME`, `VERSIO_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/versio) |
|
||||
| [VinylDNS](https://www.vinyldns.io) | `vinyldns` | `VINYLDNS_ACCESS_KEY`, `VINYLDNS_SECRET_KEY`, `VINYLDNS_HOST` | [Additional configuration](https://go-acme.github.io/lego/dns/vinyldns) |
|
||||
|
||||
@@ -91,9 +91,11 @@ The `users` option is an array of authorized users. Each user must be declared u
|
||||
```yaml tab="Docker"
|
||||
# Declaring the user list
|
||||
#
|
||||
# Note: all dollar signs in the hash need to be doubled for escaping.
|
||||
# Note: when used in docker-compose.yml all dollar signs in the hash need to be doubled for escaping.
|
||||
# To create a user:password pair, the following command can be used:
|
||||
# echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g
|
||||
#
|
||||
# Also note that dollar signs should NOT be doubled when they not evaluated (e.g. Ansible docker_container module).
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
|
||||
```
|
||||
|
||||
@@ -349,12 +349,16 @@ http:
|
||||
|
||||
### `tls`
|
||||
|
||||
The `tls` option is the TLS configuration from Traefik to the authentication server.
|
||||
_Optional_
|
||||
|
||||
#### `tls.ca`
|
||||
Defines the TLS configuration used for the secure connection to the authentication server.
|
||||
|
||||
Certificate Authority used for the secured connection to the authentication server,
|
||||
defaults to the system bundle.
|
||||
#### `ca`
|
||||
|
||||
_Optional_
|
||||
|
||||
`ca` is the path to the certificate authority used for the secured connection to the authentication server,
|
||||
it defaults to the system bundle.
|
||||
|
||||
```yaml tab="Docker"
|
||||
labels:
|
||||
@@ -417,13 +421,15 @@ http:
|
||||
ca = "path/to/local.crt"
|
||||
```
|
||||
|
||||
#### `tls.caOptional`
|
||||
#### `caOptional`
|
||||
|
||||
The value of `tls.caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to the authentication server.
|
||||
_Optional_
|
||||
|
||||
The value of `caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to the authentication server.
|
||||
|
||||
!!! warning ""
|
||||
|
||||
If `tls.ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
If `ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
|
||||
When this option is set to `true`, a client certificate is requested during the handshake but is not required. If a certificate is sent, it is required to be valid.
|
||||
|
||||
@@ -479,9 +485,12 @@ http:
|
||||
caOptional = true
|
||||
```
|
||||
|
||||
#### `tls.cert`
|
||||
#### `cert`
|
||||
|
||||
The public certificate used for the secure connection to the authentication server.
|
||||
_Optional_
|
||||
|
||||
`cert` is the path to the public certificate used for the secure connection to the authentication server.
|
||||
When using this option, setting the `key` option is required.
|
||||
|
||||
```yaml tab="Docker"
|
||||
labels:
|
||||
@@ -554,9 +563,12 @@ http:
|
||||
|
||||
For security reasons, the field does not exist for Kubernetes IngressRoute, and one should use the `secret` field instead.
|
||||
|
||||
#### `tls.key`
|
||||
#### `key`
|
||||
|
||||
The private certificate used for the secure connection to the authentication server.
|
||||
_Optional_
|
||||
|
||||
`key` is the path to the private key used for the secure connection to the authentication server.
|
||||
When using this option, setting the `cert` option is required.
|
||||
|
||||
```yaml tab="Docker"
|
||||
labels:
|
||||
@@ -629,7 +641,9 @@ http:
|
||||
|
||||
For security reasons, the field does not exist for Kubernetes IngressRoute, and one should use the `secret` field instead.
|
||||
|
||||
#### `tls.insecureSkipVerify`
|
||||
#### `insecureSkipVerify`
|
||||
|
||||
_Optional, Default=false_
|
||||
|
||||
If `insecureSkipVerify` is `true`, the TLS connection to the authentication server accepts any certificate presented by the server regardless of the hostnames it covers.
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ labels:
|
||||
# As TOML Configuration File
|
||||
[http.routers]
|
||||
[http.routers.router1]
|
||||
service = "myService"
|
||||
service = "service1"
|
||||
middlewares = ["foo-add-prefix"]
|
||||
rule = "Host(`example.com`)"
|
||||
|
||||
@@ -105,7 +105,7 @@ labels:
|
||||
http:
|
||||
routers:
|
||||
router1:
|
||||
service: myService
|
||||
service: service1
|
||||
middlewares:
|
||||
- "foo-add-prefix"
|
||||
rule: "Host(`example.com`)"
|
||||
|
||||
@@ -23,7 +23,7 @@ labels:
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: addprefix
|
||||
name: test-passtlsclientcert
|
||||
spec:
|
||||
passTLSClientCert:
|
||||
pem: true
|
||||
|
||||
@@ -7,22 +7,6 @@ Traefik supports 4 metrics backends:
|
||||
- [Prometheus](./prometheus.md)
|
||||
- [StatsD](./statsd.md)
|
||||
|
||||
## Configuration
|
||||
|
||||
To enable metrics:
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
metrics: {}
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[metrics]
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--metrics=true
|
||||
```
|
||||
|
||||
## Server Metrics
|
||||
|
||||
| Metric | DataDog | InfluxDB | Prometheus | StatsD |
|
||||
@@ -39,7 +23,7 @@ The total count of configuration reloads.
|
||||
config.reload.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluDB"
|
||||
```influxdb tab="InfluxDB"
|
||||
traefik.config.reload.total
|
||||
```
|
||||
|
||||
@@ -59,7 +43,7 @@ The total count of configuration reload failures.
|
||||
config.reload.total (with tag "failure" to true)
|
||||
```
|
||||
|
||||
```influxdb tab="InfluDB"
|
||||
```influxdb tab="InfluxDB"
|
||||
traefik.config.reload.total.failure
|
||||
```
|
||||
|
||||
@@ -79,7 +63,7 @@ The timestamp of the last configuration reload success.
|
||||
config.reload.lastSuccessTimestamp
|
||||
```
|
||||
|
||||
```influxdb tab="InfluDB"
|
||||
```influxdb tab="InfluxDB"
|
||||
traefik.config.reload.lastSuccessTimestamp
|
||||
```
|
||||
|
||||
@@ -99,7 +83,7 @@ The timestamp of the last configuration reload failure.
|
||||
config.reload.lastFailureTimestamp
|
||||
```
|
||||
|
||||
```influxdb tab="InfluDB"
|
||||
```influxdb tab="InfluxDB"
|
||||
traefik.config.reload.lastFailureTimestamp
|
||||
```
|
||||
|
||||
@@ -130,7 +114,7 @@ Available labels: `code`, `method`, `protocol`, `entrypoint`.
|
||||
entrypoint.request.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluDB"
|
||||
```influxdb tab="InfluxDB"
|
||||
traefik.entrypoint.requests.total
|
||||
```
|
||||
|
||||
@@ -161,7 +145,7 @@ Available labels: `code`, `method`, `protocol`, `entrypoint`.
|
||||
entrypoint.request.duration
|
||||
```
|
||||
|
||||
```influxdb tab="InfluDB"
|
||||
```influxdb tab="InfluxDB"
|
||||
traefik.entrypoint.request.duration
|
||||
```
|
||||
|
||||
@@ -183,7 +167,7 @@ Available labels: `method`, `protocol`, `entrypoint`.
|
||||
entrypoint.connections.open
|
||||
```
|
||||
|
||||
```influxdb tab="InfluDB"
|
||||
```influxdb tab="InfluxDB"
|
||||
traefik.entrypoint.connections.open
|
||||
```
|
||||
|
||||
@@ -216,7 +200,7 @@ Available labels: `code`, `method`, `protocol`, `service`.
|
||||
service.request.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluDB"
|
||||
```influxdb tab="InfluxDB"
|
||||
traefik.service.requests.total
|
||||
```
|
||||
|
||||
@@ -247,7 +231,7 @@ Available labels: `code`, `method`, `protocol`, `service`.
|
||||
service.request.duration
|
||||
```
|
||||
|
||||
```influxdb tab="InfluDB"
|
||||
```influxdb tab="InfluxDB"
|
||||
traefik.service.request.duration
|
||||
```
|
||||
|
||||
@@ -269,7 +253,7 @@ Available labels: `method`, `protocol`, `service`.
|
||||
service.connections.open
|
||||
```
|
||||
|
||||
```influxdb tab="InfluDB"
|
||||
```influxdb tab="InfluxDB"
|
||||
traefik.service.connections.open
|
||||
```
|
||||
|
||||
@@ -291,7 +275,7 @@ Available labels: `service`.
|
||||
service.retries.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluDB"
|
||||
```influxdb tab="InfluxDB"
|
||||
traefik.service.retries.total
|
||||
```
|
||||
|
||||
@@ -313,7 +297,7 @@ Available labels: `service`, `url`.
|
||||
service.server.up
|
||||
```
|
||||
|
||||
```influxdb tab="InfluDB"
|
||||
```influxdb tab="InfluxDB"
|
||||
traefik.service.server.up
|
||||
```
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ tracing:
|
||||
|
||||
!!! warning
|
||||
Traefik is able to send data over the compact thrift protocol to the [Jaeger agent](https://www.jaegertracing.io/docs/deployment/#agent)
|
||||
or a [Jaeger collector](https://www.jaegertracing.io/docs/deployment/#collectors).
|
||||
or a [Jaeger collector](https://www.jaegertracing.io/docs/deployment/#collector).
|
||||
|
||||
!!! info
|
||||
All Jaeger configuration can be overridden by [environment variables](https://github.com/jaegertracing/jaeger-client-go#environment-variables)
|
||||
|
||||
@@ -147,9 +147,16 @@ All the following endpoints must be accessed with a `GET` HTTP request.
|
||||
| `/api/tcp/routers/{name}` | Returns the information of the TCP router specified by `name`. |
|
||||
| `/api/tcp/services` | Lists all the TCP services information. |
|
||||
| `/api/tcp/services/{name}` | Returns the information of the TCP service specified by `name`. |
|
||||
| `/api/tcp/middlewares` | Lists all the TCP middlewares information. |
|
||||
| `/api/tcp/middlewares/{name}` | Returns the information of the TCP middleware specified by `name`. |
|
||||
| `/api/udp/routers` | Lists all the UDP routers information. |
|
||||
| `/api/udp/routers/{name}` | Returns the information of the UDP router specified by `name`. |
|
||||
| `/api/udp/services` | Lists all the UDP services information. |
|
||||
| `/api/udp/services/{name}` | Returns the information of the UDP service specified by `name`. |
|
||||
| `/api/entrypoints` | Lists all the entry points information. |
|
||||
| `/api/entrypoints/{name}` | Returns the information of the entry point specified by `name`. |
|
||||
| `/api/overview` | Returns statistic information about http and tcp as well as enabled features and providers. |
|
||||
| `/api/rawdata` | Returns information about dynamic configurations, errors, status and dependency relations. |
|
||||
| `/api/version` | Returns information about Traefik version. |
|
||||
| `/debug/vars` | See the [expvar](https://golang.org/pkg/expvar/) Go documentation. |
|
||||
| `/debug/pprof/` | See the [pprof Index](https://golang.org/pkg/net/http/pprof/#Index) Go documentation. |
|
||||
|
||||
@@ -362,14 +362,14 @@ providers:
|
||||
|
||||
_Optional_
|
||||
|
||||
Defines TLS options for Consul server endpoint.
|
||||
Defines the TLS configuration used for the secure connection to Consul Catalog.
|
||||
|
||||
##### `ca`
|
||||
|
||||
_Optional_
|
||||
|
||||
Certificate Authority used for the secure connection to Consul,
|
||||
defaults to the system bundle.
|
||||
`ca` is the path to the certificate authority used for the secure connection to Consul Catalog,
|
||||
it defaults to the system bundle.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -392,11 +392,11 @@ providers:
|
||||
|
||||
_Optional_
|
||||
|
||||
The value of `tls.caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to Consul.
|
||||
The value of `caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to Consul Catalog.
|
||||
|
||||
!!! warning ""
|
||||
|
||||
If `tls.ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
If `ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
|
||||
When this option is set to `true`, a client certificate is requested during the handshake but is not required. If a certificate is sent, it is required to be valid.
|
||||
|
||||
@@ -423,8 +423,7 @@ providers:
|
||||
|
||||
_Optional_
|
||||
|
||||
`cert` is the path to the public certificate to use for Consul communication.
|
||||
|
||||
`cert` is the path to the public certificate used for the secure connection to Consul Catalog.
|
||||
When using this option, setting the `key` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
@@ -451,8 +450,7 @@ providers:
|
||||
|
||||
_Optional_
|
||||
|
||||
`key` is the path to the private key for Consul communication.
|
||||
|
||||
`key` is the path to the private key used for the secure connection to Consul Catalog.
|
||||
When using this option, setting the `cert` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
@@ -477,7 +475,7 @@ providers:
|
||||
|
||||
##### `insecureSkipVerify`
|
||||
|
||||
_Optional_
|
||||
_Optional, Default=false_
|
||||
|
||||
If `insecureSkipVerify` is `true`, the TLS connection to Consul accepts any certificate presented by the server regardless of the hostnames it covers.
|
||||
|
||||
|
||||
@@ -104,10 +104,14 @@ providers:
|
||||
|
||||
_Optional_
|
||||
|
||||
#### `tls.ca`
|
||||
Defines the TLS configuration used for the secure connection to Consul.
|
||||
|
||||
Certificate Authority used for the secure connection to Consul,
|
||||
defaults to the system bundle.
|
||||
#### `ca`
|
||||
|
||||
_Optional_
|
||||
|
||||
`ca` is the path to the certificate authority used for the secure connection to Consul,
|
||||
it defaults to the system bundle.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -125,13 +129,15 @@ providers:
|
||||
--providers.consul.tls.ca=path/to/ca.crt
|
||||
```
|
||||
|
||||
#### `tls.caOptional`
|
||||
#### `caOptional`
|
||||
|
||||
The value of `tls.caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to Consul.
|
||||
_Optional_
|
||||
|
||||
The value of `caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to Consul.
|
||||
|
||||
!!! warning ""
|
||||
|
||||
If `tls.ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
If `ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
|
||||
When this option is set to `true`, a client certificate is requested during the handshake but is not required. If a certificate is sent, it is required to be valid.
|
||||
|
||||
@@ -153,9 +159,12 @@ providers:
|
||||
--providers.consul.tls.caOptional=true
|
||||
```
|
||||
|
||||
#### `tls.cert`
|
||||
#### `cert`
|
||||
|
||||
Public certificate used for the secure connection to Consul.
|
||||
_Optional_
|
||||
|
||||
`cert` is the path to the public certificate used for the secure connection to Consul.
|
||||
When using this option, setting the `key` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -176,9 +185,12 @@ providers:
|
||||
--providers.consul.tls.key=path/to/foo.key
|
||||
```
|
||||
|
||||
#### `tls.key`
|
||||
#### `key`
|
||||
|
||||
Private certificate used for the secure connection to Consul.
|
||||
_Optional_
|
||||
|
||||
`key` is the path to the private key used for the secure connection to Consul.
|
||||
When using this option, setting the `cert` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -199,7 +211,9 @@ providers:
|
||||
--providers.consul.tls.key=path/to/foo.key
|
||||
```
|
||||
|
||||
#### `tls.insecureSkipVerify`
|
||||
#### `insecureSkipVerify`
|
||||
|
||||
_Optional, Default=false_
|
||||
|
||||
If `insecureSkipVerify` is `true`, the TLS connection to Consul accepts any certificate presented by the server regardless of the hostnames it covers.
|
||||
|
||||
|
||||
@@ -613,10 +613,14 @@ providers:
|
||||
|
||||
_Optional_
|
||||
|
||||
#### `tls.ca`
|
||||
Defines the TLS configuration used for the secure connection to Docker.
|
||||
|
||||
Certificate Authority used for the secure connection to Docker,
|
||||
defaults to the system bundle.
|
||||
#### `ca`
|
||||
|
||||
_Optional_
|
||||
|
||||
`ca` is the path to the certificate authority used for the secure connection to Docker,
|
||||
it defaults to the system bundle.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -634,13 +638,15 @@ providers:
|
||||
--providers.docker.tls.ca=path/to/ca.crt
|
||||
```
|
||||
|
||||
#### `tls.caOptional`
|
||||
#### `caOptional`
|
||||
|
||||
The value of `tls.caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to Docker.
|
||||
_Optional_
|
||||
|
||||
The value of `caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to Docker.
|
||||
|
||||
!!! warning ""
|
||||
|
||||
If `tls.ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
If `ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
|
||||
When this option is set to `true`, a client certificate is requested during the handshake but is not required. If a certificate is sent, it is required to be valid.
|
||||
|
||||
@@ -662,9 +668,10 @@ providers:
|
||||
--providers.docker.tls.caOptional=true
|
||||
```
|
||||
|
||||
#### `tls.cert`
|
||||
#### `cert`
|
||||
|
||||
Public certificate used for the secure connection to Docker.
|
||||
`cert` is the path to the public certificate used for the secure connection to Docker.
|
||||
When using this option, setting the `key` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -685,9 +692,12 @@ providers:
|
||||
--providers.docker.tls.key=path/to/foo.key
|
||||
```
|
||||
|
||||
#### `tls.key`
|
||||
#### `key`
|
||||
|
||||
Private certificate used for the secure connection to Docker.
|
||||
_Optional_
|
||||
|
||||
`key` is the path to the private key used for the secure connection Docker.
|
||||
When using this option, setting the `cert` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -708,7 +718,9 @@ providers:
|
||||
--providers.docker.tls.key=path/to/foo.key
|
||||
```
|
||||
|
||||
#### `tls.insecureSkipVerify`
|
||||
#### `insecureSkipVerify`
|
||||
|
||||
_Optional, Default=false_
|
||||
|
||||
If `insecureSkipVerify` is `true`, the TLS connection to Docker accepts any certificate presented by the server regardless of the hostnames it covers.
|
||||
|
||||
|
||||
@@ -104,10 +104,14 @@ providers:
|
||||
|
||||
_Optional_
|
||||
|
||||
#### `tls.ca`
|
||||
Defines the TLS configuration used for the secure connection to etcd.
|
||||
|
||||
Certificate Authority used for the secure connection to etcd,
|
||||
defaults to the system bundle.
|
||||
#### `ca`
|
||||
|
||||
_Optional_
|
||||
|
||||
`ca` is the path to the certificate authority used for the secure connection to etcd,
|
||||
it defaults to the system bundle.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -125,13 +129,15 @@ providers:
|
||||
--providers.etcd.tls.ca=path/to/ca.crt
|
||||
```
|
||||
|
||||
#### `tls.caOptional`
|
||||
#### `caOptional`
|
||||
|
||||
The value of `tls.caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to etcd.
|
||||
_Optional_
|
||||
|
||||
The value of `caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to etcd.
|
||||
|
||||
!!! warning ""
|
||||
|
||||
If `tls.ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
If `ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
|
||||
When this option is set to `true`, a client certificate is requested during the handshake but is not required. If a certificate is sent, it is required to be valid.
|
||||
|
||||
@@ -153,9 +159,12 @@ providers:
|
||||
--providers.etcd.tls.caOptional=true
|
||||
```
|
||||
|
||||
#### `tls.cert`
|
||||
#### `cert`
|
||||
|
||||
Public certificate used for the secure connection to etcd.
|
||||
_Optional_
|
||||
|
||||
`cert` is the path to the public certificate used for the secure connection to etcd.
|
||||
When using this option, setting the `key` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -176,9 +185,12 @@ providers:
|
||||
--providers.etcd.tls.key=path/to/foo.key
|
||||
```
|
||||
|
||||
#### `tls.key`
|
||||
#### `key`
|
||||
|
||||
Private certificate used for the secure connection to etcd.
|
||||
_Optional_
|
||||
|
||||
`key` is the path to the private key used for the secure connection to etcd.
|
||||
When using this option, setting the `cert` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -199,7 +211,9 @@ providers:
|
||||
--providers.etcd.tls.key=path/to/foo.key
|
||||
```
|
||||
|
||||
#### `tls.insecureSkipVerify`
|
||||
#### `insecureSkipVerify`
|
||||
|
||||
_Optional, Default=false_
|
||||
|
||||
If `insecureSkipVerify` is `true`, the TLS connection to etcd accepts any certificate presented by the server regardless of the hostnames it covers.
|
||||
|
||||
|
||||
@@ -17,8 +17,7 @@ Defines the HTTP(S) endpoint to poll.
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
http:
|
||||
endpoint:
|
||||
- "http://127.0.0.1:9000/api"
|
||||
endpoint: "http://127.0.0.1:9000/api"
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
@@ -55,7 +54,7 @@ providers:
|
||||
|
||||
_Optional, Default="5s"_
|
||||
|
||||
Defines the polling timeout when connecting to the configured endpoint.
|
||||
Defines the polling timeout when connecting to the endpoint.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -76,10 +75,14 @@ providers:
|
||||
|
||||
_Optional_
|
||||
|
||||
#### `tls.ca`
|
||||
Defines the TLS configuration used for the secure connection to the endpoint.
|
||||
|
||||
Certificate Authority used for the secure connection to the configured endpoint,
|
||||
defaults to the system bundle.
|
||||
#### `ca`
|
||||
|
||||
_Optional_
|
||||
|
||||
`ca` is the path to the certificate authority used for the secure connection to the endpoint,
|
||||
it defaults to the system bundle.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -97,13 +100,15 @@ providers:
|
||||
--providers.http.tls.ca=path/to/ca.crt
|
||||
```
|
||||
|
||||
#### `tls.caOptional`
|
||||
#### `caOptional`
|
||||
|
||||
The value of `tls.caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to the configured endpoint.
|
||||
_Optional_
|
||||
|
||||
The value of `caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to the endpoint.
|
||||
|
||||
!!! warning ""
|
||||
|
||||
If `tls.ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
If `ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
|
||||
When this option is set to `true`, a client certificate is requested during the handshake but is not required. If a certificate is sent, it is required to be valid.
|
||||
|
||||
@@ -125,9 +130,12 @@ providers:
|
||||
--providers.http.tls.caOptional=true
|
||||
```
|
||||
|
||||
#### `tls.cert`
|
||||
#### `cert`
|
||||
|
||||
Public certificate used for the secure connection to the configured endpoint.
|
||||
_Optional_
|
||||
|
||||
`cert` is the path to the public certificate used for the secure connection to the endpoint.
|
||||
When using this option, setting the `key` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -148,9 +156,12 @@ providers:
|
||||
--providers.http.tls.key=path/to/foo.key
|
||||
```
|
||||
|
||||
#### `tls.key`
|
||||
#### `key`
|
||||
|
||||
Private certificate used for the secure connection to the configured endpoint.
|
||||
_Optional_
|
||||
|
||||
`key` is the path to the private key used for the secure connection to the endpoint.
|
||||
When using this option, setting the `cert` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -171,7 +182,9 @@ providers:
|
||||
--providers.http.tls.key=path/to/foo.key
|
||||
```
|
||||
|
||||
#### `tls.insecureSkipVerify`
|
||||
#### `insecureSkipVerify`
|
||||
|
||||
_Optional, Default=false_
|
||||
|
||||
If `insecureSkipVerify` is `true`, the TLS connection to the endpoint accepts any certificate presented by the server regardless of the hostnames it covers.
|
||||
|
||||
|
||||
@@ -195,13 +195,13 @@ See [label-selectors](https://kubernetes.io/docs/concepts/overview/working-with-
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
kubernetesCRD:
|
||||
labelselector: "app=traefik"
|
||||
labelSelector: "app=traefik"
|
||||
# ...
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[providers.kubernetesCRD]
|
||||
labelselector = "app=traefik"
|
||||
labelSelector = "app=traefik"
|
||||
# ...
|
||||
```
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ See [label-selectors](https://kubernetes.io/docs/concepts/overview/working-with-
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
kubernetesIngress:
|
||||
labelselector: "app=traefik"
|
||||
labelSelector: "app=traefik"
|
||||
# ...
|
||||
```
|
||||
|
||||
|
||||
@@ -404,10 +404,12 @@ providers:
|
||||
|
||||
_Optional_
|
||||
|
||||
#### `tls.ca`
|
||||
Defines the TLS configuration used for the secure connection to Marathon.
|
||||
|
||||
Certificate Authority used for the secure connection to Marathon,
|
||||
defaults to the system bundle.
|
||||
#### `ca`
|
||||
|
||||
`ca` is the path to the certificate authority used for the secure connection to Marathon,
|
||||
it defaults to the system bundle.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -425,13 +427,15 @@ providers:
|
||||
--providers.marathon.tls.ca=path/to/ca.crt
|
||||
```
|
||||
|
||||
#### `tls.caOptional`
|
||||
#### `caOptional`
|
||||
|
||||
The value of `tls.caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to Marathon.
|
||||
_Optional_
|
||||
|
||||
The value of `caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to Marathon.
|
||||
|
||||
!!! warning ""
|
||||
|
||||
If `tls.ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
If `ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
|
||||
When this option is set to `true`, a client certificate is requested during the handshake but is not required. If a certificate is sent, it is required to be valid.
|
||||
|
||||
@@ -453,9 +457,12 @@ providers:
|
||||
--providers.marathon.tls.caOptional=true
|
||||
```
|
||||
|
||||
#### `tls.cert`
|
||||
#### `cert`
|
||||
|
||||
Public certificate used for the secure connection to Marathon.
|
||||
_Optional_
|
||||
|
||||
`cert` is the path to the public certificate used for the secure connection to Marathon.
|
||||
When using this option, setting the `key` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -476,9 +483,12 @@ providers:
|
||||
--providers.marathon.tls.key=path/to/foo.key
|
||||
```
|
||||
|
||||
#### `tls.key`
|
||||
#### `key`
|
||||
|
||||
Private certificate used for the secure connection to Marathon.
|
||||
_Optional_
|
||||
|
||||
`key` is the path to the private key used for the secure connection to Marathon.
|
||||
When using this option, setting the `cert` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -499,7 +509,9 @@ providers:
|
||||
--providers.marathon.tls.key=path/to/foo.key
|
||||
```
|
||||
|
||||
#### `tls.insecureSkipVerify`
|
||||
#### `insecureSkipVerify`
|
||||
|
||||
_Optional, Default=false_
|
||||
|
||||
If `insecureSkipVerify` is `true`, the TLS connection to Marathon accepts any certificate presented by the server regardless of the hostnames it covers.
|
||||
|
||||
@@ -532,18 +544,18 @@ see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration).
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
marathon:
|
||||
responseHeaderTimeout: "10s"
|
||||
tlsHandshakeTimeout: "10s"
|
||||
# ...
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[providers.marathon]
|
||||
responseHeaderTimeout = "10s"
|
||||
tlsHandshakeTimeout = "10s"
|
||||
# ...
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--providers.marathon.responseHeaderTimeout=10s
|
||||
--providers.marathon.tlsHandshakeTimeout=10s
|
||||
# ...
|
||||
```
|
||||
|
||||
|
||||
@@ -104,10 +104,14 @@ providers:
|
||||
|
||||
_Optional_
|
||||
|
||||
#### `tls.ca`
|
||||
Defines the TLS configuration used for the secure connection to Redis.
|
||||
|
||||
Certificate Authority used for the secure connection to Redis,
|
||||
defaults to the system bundle.
|
||||
#### `ca`
|
||||
|
||||
_Optional_
|
||||
|
||||
`ca` is the path to the certificate authority used for the secure connection to Redis,
|
||||
it defaults to the system bundle.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -125,13 +129,15 @@ providers:
|
||||
--providers.redis.tls.ca=path/to/ca.crt
|
||||
```
|
||||
|
||||
#### `tls.caOptional`
|
||||
#### `caOptional`
|
||||
|
||||
The value of `tls.caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to Redis.
|
||||
_Optional_
|
||||
|
||||
The value of `caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to Redis.
|
||||
|
||||
!!! warning ""
|
||||
|
||||
If `tls.ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
If `ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
|
||||
When this option is set to `true`, a client certificate is requested during the handshake but is not required. If a certificate is sent, it is required to be valid.
|
||||
|
||||
@@ -153,9 +159,12 @@ providers:
|
||||
--providers.redis.tls.caOptional=true
|
||||
```
|
||||
|
||||
#### `tls.cert`
|
||||
#### `cert`
|
||||
|
||||
Public certificate used for the secure connection to Redis.
|
||||
_Optional_
|
||||
|
||||
`cert` is the path to the public certificate used for the secure connection to Redis.
|
||||
When using this option, setting the `key` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -176,9 +185,12 @@ providers:
|
||||
--providers.redis.tls.key=path/to/foo.key
|
||||
```
|
||||
|
||||
#### `tls.key`
|
||||
#### `key`
|
||||
|
||||
Private certificate used for the secure connection to Redis.
|
||||
_Optional_
|
||||
|
||||
`key` is the path to the private key used for the secure connection to Redis.
|
||||
When using this option, setting the `cert` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -199,7 +211,9 @@ providers:
|
||||
--providers.redis.tls.key=path/to/foo.key
|
||||
```
|
||||
|
||||
#### `tls.insecureSkipVerify`
|
||||
#### `insecureSkipVerify`
|
||||
|
||||
_Optional, Default=false_
|
||||
|
||||
If `insecureSkipVerify` is `true`, the TLS connection to Redis accepts any certificate presented by the server regardless of the hostnames it covers.
|
||||
|
||||
|
||||
@@ -104,10 +104,14 @@ providers:
|
||||
|
||||
_Optional_
|
||||
|
||||
#### `tls.ca`
|
||||
Defines the TLS configuration used for the secure connection to ZooKeeper.
|
||||
|
||||
Certificate Authority used for the secure connection to ZooKeeper,
|
||||
defaults to the system bundle.
|
||||
#### `ca`
|
||||
|
||||
_Optional_
|
||||
|
||||
`ca` is the path to the certificate authority used for the secure connection to ZooKeeper,
|
||||
it defaults to the system bundle.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -125,13 +129,15 @@ providers:
|
||||
--providers.zookeeper.tls.ca=path/to/ca.crt
|
||||
```
|
||||
|
||||
#### `tls.caOptional`
|
||||
#### `caOptional`
|
||||
|
||||
The value of `tls.caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to Zookeeper.
|
||||
_Optional_
|
||||
|
||||
The value of `caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to Zookeeper.
|
||||
|
||||
!!! warning ""
|
||||
|
||||
If `tls.ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
If `ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.
|
||||
|
||||
When this option is set to `true`, a client certificate is requested during the handshake but is not required. If a certificate is sent, it is required to be valid.
|
||||
|
||||
@@ -153,9 +159,12 @@ providers:
|
||||
--providers.zookeeper.tls.caOptional=true
|
||||
```
|
||||
|
||||
#### `tls.cert`
|
||||
#### `cert`
|
||||
|
||||
Public certificate used for the secure connection to ZooKeeper.
|
||||
_Optional_
|
||||
|
||||
`cert` is the path to the public certificate used for the secure connection to ZooKeeper.
|
||||
When using this option, setting the `key` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -176,9 +185,12 @@ providers:
|
||||
--providers.zookeeper.tls.key=path/to/foo.key
|
||||
```
|
||||
|
||||
#### `tls.key`
|
||||
#### `key`
|
||||
|
||||
Private certificate used for the secure connection to ZooKeeper.
|
||||
_Optional_
|
||||
|
||||
`key` is the path to the private key used for the secure connection to ZooKeeper.
|
||||
When using this option, setting the `cert` option is required.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -199,7 +211,9 @@ providers:
|
||||
--providers.zookeeper.tls.key=path/to/foo.key
|
||||
```
|
||||
|
||||
#### `tls.insecureSkipVerify`
|
||||
#### `insecureSkipVerify`
|
||||
|
||||
_Optional, Default=false_
|
||||
|
||||
If `insecureSkipVerify` is `true`, the TLS connection to Zookeeper accepts any certificate presented by the server regardless of the hostnames it covers.
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ For example, to change the rule, you could add the tag ```traefik.http.routers.m
|
||||
See [tls](../routers/index.md#tls) for more information.
|
||||
|
||||
```yaml
|
||||
traefik.http.routers.myrouter>.tls=true
|
||||
traefik.http.routers.myrouter.tls=true
|
||||
```
|
||||
|
||||
??? info "`traefik.http.routers.<router_name>.tls.certresolver`"
|
||||
@@ -136,7 +136,7 @@ you'd add the tag `traefik.http.services.{name-of-your-choice}.loadbalancer.pass
|
||||
See [serverstransport](../services/index.md#serverstransport) for more information.
|
||||
|
||||
```yaml
|
||||
traefik.http.services.<service_name>.loadbalancer.serverstransport=foobar@file
|
||||
traefik.http.services.myservice.loadbalancer.serverstransport=foobar@file
|
||||
```
|
||||
|
||||
??? info "`traefik.http.services.<service_name>.loadbalancer.passhostheader`"
|
||||
|
||||
@@ -233,11 +233,11 @@ The table below lists all the available matchers:
|
||||
| ```Headers(`key`, `value`)``` | Check if there is a key `key`defined in the headers, with the value `value` |
|
||||
| ```HeadersRegexp(`key`, `regexp`)``` | Check if there is a key `key`defined in the headers, with a value that matches the regular expression `regexp` |
|
||||
| ```Host(`example.com`, ...)``` | Check if the request domain (host header value) targets one of the given `domains`. |
|
||||
| ```HostHeader(`example.com`, ...)``` | Check if the request domain (host header value) targets one of the given `domains`. |
|
||||
| ```HostRegexp(`example.com`, `{subdomain:[a-z]+}.example.com`, ...)``` | Check if the request domain matches the given `regexp`. |
|
||||
| ```HostHeader(`example.com`, ...)``` | Same as `Host`, only exists for historical reasons. |
|
||||
| ```HostRegexp(`example.com`, `{subdomain:[a-z]+}.example.com`, ...)``` | Match the request domain. See "Regexp Syntax" below. |
|
||||
| ```Method(`GET`, ...)``` | Check if the request method is one of the given `methods` (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`) |
|
||||
| ```Path(`/path`, `/articles/{cat:[a-z]+}/{id:[0-9]+}`, ...)``` | Match exact request path. It accepts a sequence of literal and regular expression paths. |
|
||||
| ```PathPrefix(`/products/`, `/articles/{cat:[a-z]+}/{id:[0-9]+}`)``` | Match request prefix path. It accepts a sequence of literal and regular expression prefix paths. |
|
||||
| ```Path(`/path`, `/articles/{cat:[a-z]+}/{id:[0-9]+}`, ...)``` | Match exact request path. See "Regexp Syntax" below. |
|
||||
| ```PathPrefix(`/products/`, `/articles/{cat:[a-z]+}/{id:[0-9]+}`)``` | Match request prefix path. See "Regexp Syntax" below. |
|
||||
| ```Query(`foo=bar`, `bar=baz`)``` | Match Query String parameters. It accepts a sequence of key=value pairs. |
|
||||
| ```ClientIP(`10.0.0.0/16`, `::1`)``` | Match if the request client IP is one of the given IP/CIDR. It accepts IPv4, IPv6 and CIDR formats. |
|
||||
|
||||
@@ -249,10 +249,11 @@ The table below lists all the available matchers:
|
||||
|
||||
!!! important "Regexp Syntax"
|
||||
|
||||
`HostRegexp` and `Path` accept an expression with zero or more groups enclosed by curly braces.
|
||||
Named groups can be like `{name:pattern}` that matches the given regexp pattern or like `{name}` that matches anything until the next dot.
|
||||
The group name (`name` is the above examples) is an arbitrary value.
|
||||
Any pattern supported by [Go's regexp package](https://golang.org/pkg/regexp/) may be used (example: `{subdomain:[a-z]+}.{domain}.com`).
|
||||
`HostRegexp`, `PathPrefix`, and `Path` accept an expression with zero or more groups enclosed by curly braces, which are called named regexps.
|
||||
Named regexps, of the form `{name:regexp}`, are the only expressions considered for regexp matching.
|
||||
The regexp name (`name` in the above example) is an arbitrary value, that exists only for historical reasons.
|
||||
|
||||
Any `regexp` supported by [Go's regexp package](https://golang.org/pkg/regexp/) may be used.
|
||||
|
||||
!!! info "Combining Matchers Using Operators and Parenthesis"
|
||||
|
||||
|
||||
@@ -336,11 +336,11 @@ Below are the available options for the health check mechanism:
|
||||
Traefik keeps monitoring the health of unhealthy servers.
|
||||
If a server has recovered (returning `2xx` -> `3xx` responses again), it will be added back to the load balancer rotation pool.
|
||||
|
||||
!!! warning "Health check in Kubernetes"
|
||||
!!! warning "Health check with Kubernetes"
|
||||
|
||||
The Traefik health check is not available for `kubernetesCRD` and `kubernetesIngress` providers because Kubernetes
|
||||
already has a health check mechanism.
|
||||
Unhealthy pods will be removed by kubernetes. (cf [liveness documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-liveness-http-request))
|
||||
Kubernetes has an health check mechanism to remove unhealthy pods from Kubernetes services (cf [readiness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-readiness-probes)).
|
||||
As unhealthy pods have no Kubernetes endpoints, Traefik will not forward traffic to them.
|
||||
Therefore, Traefik health check is not available for `kubernetesCRD` and `kubernetesIngress` providers.
|
||||
|
||||
??? example "Custom Interval & Timeout -- Using the [File Provider](../../providers/file.md)"
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ theme:
|
||||
prev: 'Previous'
|
||||
next: 'Next'
|
||||
|
||||
copyright: "Copyright © 2016-2020 Containous; 2020-2021 Traefik Labs"
|
||||
copyright: "Copyright © 2016-2020 Containous; 2020-2022 Traefik Labs"
|
||||
|
||||
extra_javascript:
|
||||
- assets/js/hljs/highlight.pack.js # Download from https://highlightjs.org/download/ and enable YAML, TOML and Dockerfile
|
||||
|
||||
@@ -4,3 +4,4 @@ mkdocs-bootswatch==1.0
|
||||
mkdocs-traefiklabs>=100.0.7
|
||||
markdown-include==0.5.1
|
||||
mkdocs-exclude==1.0.2
|
||||
Jinja2==3.0.0
|
||||
|
||||
@@ -22,7 +22,7 @@ find "${PATH_TO_SITE}" -type f -not -path "/app/site/theme/*" \
|
||||
--alt_ignore="/traefikproxy-vertical-logo-color.svg/" \
|
||||
--http_status_ignore="0,500,501,503" \
|
||||
--file_ignore="/404.html/" \
|
||||
--url_ignore="/https://groups.google.com/a/traefik.io/forum/#!forum/security/,/localhost:/,/127.0.0.1:/,/fonts.gstatic.com/,/.minikube/,/github.com\/traefik\/traefik\/*edit*/,/github.com\/traefik\/traefik/,/doc.traefik.io/,/github\.com\/golang\/oauth2\/blob\/36a7019397c4c86cf59eeab3bc0d188bac444277\/.+/,/www.akamai.com/,/pilot.traefik.io\/profile/,/traefik.io/,/doc.traefik.io\/traefik-mesh/,/www.mkdocs.org/,/squidfunk.github.io/,/ietf.org/,/www.namesilo.com/,/www.youtube.com/,/www.linode.com/,/www.alibabacloud.com/" \
|
||||
--url_ignore="/https://groups.google.com/a/traefik.io/forum/#!forum/security/,/localhost:/,/127.0.0.1:/,/fonts.gstatic.com/,/.minikube/,/github.com\/traefik\/traefik\/*edit*/,/github.com\/traefik\/traefik/,/doc.traefik.io/,/github\.com\/golang\/oauth2\/blob\/36a7019397c4c86cf59eeab3bc0d188bac444277\/.+/,/www.akamai.com/,/pilot.traefik.io\/profile/,/traefik.io/,/doc.traefik.io\/traefik-mesh/,/www.mkdocs.org/,/squidfunk.github.io/,/ietf.org/,/www.namesilo.com/,/www.youtube.com/,/www.linode.com/,/www.alibabacloud.com/,/www.cloudxns.net/" \
|
||||
'{}' 1>/dev/null
|
||||
## HTML-proofer options at https://github.com/gjtorikian/html-proofer#configuration
|
||||
|
||||
|
||||
44
go.mod
44
go.mod
@@ -7,30 +7,26 @@ require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/ExpediaDotCom/haystack-client-go v0.0.0-20190315171017-e7edbdf53a61
|
||||
github.com/Masterminds/sprig/v3 v3.2.2
|
||||
github.com/Microsoft/hcsshim v0.8.7 // indirect
|
||||
github.com/Shopify/sarama v1.23.1 // indirect
|
||||
github.com/abbot/go-http-auth v0.0.0-00010101000000-000000000000
|
||||
github.com/abronan/valkeyrie v0.2.0
|
||||
github.com/aws/aws-sdk-go v1.39.0
|
||||
github.com/cenkalti/backoff/v4 v4.1.1
|
||||
github.com/containerd/containerd v1.3.2 // indirect
|
||||
github.com/compose-spec/compose-go v1.0.3
|
||||
github.com/containerd/containerd v1.5.8 // indirect
|
||||
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/docker/cli v0.0.0-20200221155518-740919cc7fc0
|
||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200204220554-5f6d6f3f2203+incompatible
|
||||
github.com/docker/docker-credential-helpers v0.6.3 // indirect
|
||||
github.com/docker/cli v20.10.11+incompatible
|
||||
github.com/docker/compose/v2 v2.0.1
|
||||
github.com/docker/docker v20.10.7+incompatible
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82 // indirect
|
||||
github.com/docker/libcompose v0.0.0-20190805081528-eac9fe1b8b03 // indirect
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
|
||||
github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e // indirect
|
||||
github.com/eapache/channels v1.1.0
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.0
|
||||
github.com/fatih/structs v1.1.0
|
||||
github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2
|
||||
github.com/go-acme/lego/v4 v4.5.0
|
||||
github.com/go-acme/lego/v4 v4.6.0
|
||||
github.com/go-check/check v0.0.0-00010101000000-000000000000
|
||||
github.com/go-kit/kit v0.10.1-0.20200915143503-439c4d2ed3ea
|
||||
github.com/golang/protobuf v1.5.2
|
||||
@@ -41,24 +37,17 @@ require (
|
||||
github.com/hashicorp/consul/api v1.10.0
|
||||
github.com/hashicorp/go-hclog v0.16.1
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/hashicorp/go-version v1.2.1
|
||||
github.com/hashicorp/go-version v1.3.0
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d
|
||||
github.com/instana/go-sensor v1.5.1
|
||||
github.com/klauspost/compress v1.13.0
|
||||
github.com/libkermit/compose v0.0.0-20171122111507-c04e39c026ad
|
||||
github.com/libkermit/docker v0.0.0-20171122101128-e6674d32b807
|
||||
github.com/libkermit/docker-check v0.0.0-20171122104347-1113af38e591
|
||||
github.com/lucas-clemente/quic-go v0.23.0
|
||||
github.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f
|
||||
github.com/miekg/dns v1.1.43
|
||||
github.com/mitchellh/copystructure v1.0.0
|
||||
github.com/mitchellh/hashstructure v1.0.0
|
||||
github.com/mitchellh/mapstructure v1.4.1
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
||||
github.com/opencontainers/runc v1.0.0-rc10 // indirect
|
||||
github.com/opentracing/opentracing-go v1.1.0
|
||||
github.com/mitchellh/mapstructure v1.4.2
|
||||
github.com/opentracing/opentracing-go v1.2.0
|
||||
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5
|
||||
github.com/openzipkin/zipkin-go v0.2.2
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
@@ -68,12 +57,12 @@ require (
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/prometheus/client_model v0.2.0
|
||||
github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154
|
||||
github.com/tinylib/msgp v1.0.2 // indirect
|
||||
github.com/traefik/paerser v0.1.4
|
||||
github.com/traefik/yaegi v0.10.0
|
||||
github.com/traefik/yaegi v0.11.2
|
||||
github.com/uber/jaeger-client-go v2.29.1+incompatible
|
||||
github.com/uber/jaeger-lib v2.2.0+incompatible
|
||||
github.com/unrolled/render v1.0.2
|
||||
@@ -84,7 +73,7 @@ require (
|
||||
go.elastic.co/apm v1.13.1
|
||||
go.elastic.co/apm/module/apmot v1.13.1
|
||||
golang.org/x/mod v0.4.2
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e
|
||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63
|
||||
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 // indirect
|
||||
golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6
|
||||
golang.org/x/tools v0.1.2
|
||||
@@ -105,7 +94,14 @@ require (
|
||||
replace (
|
||||
github.com/abbot/go-http-auth => github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e
|
||||
github.com/go-check/check => github.com/containous/check v0.0.0-20170915194414-ca0bf163426a
|
||||
github.com/gorilla/mux => github.com/containous/mux v0.0.0-20181024131434-c33f32e26898
|
||||
github.com/gorilla/mux => github.com/containous/mux v0.0.0-20220113180107-8ffa4f6d063c
|
||||
github.com/mailgun/minheap => github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595
|
||||
github.com/mailgun/multibuf => github.com/containous/multibuf v0.0.0-20190809014333-8b6c9a7e6bba
|
||||
)
|
||||
|
||||
// https://github.com/docker/compose/blob/e44222664abd07ce1d1fe6796d84d93cbc7468c3/go.mod#L131
|
||||
replace github.com/jaguilar/vt100 => github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305
|
||||
|
||||
// ambiguous import: found package github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/http in multiple modules
|
||||
// tencentcloud uses monorepo with multimodule but the go.mod files are incomplete.
|
||||
exclude github.com/tencentcloud/tencentcloud-sdk-go v3.0.83+incompatible
|
||||
|
||||
@@ -36,12 +36,7 @@ type accessLogValue struct {
|
||||
|
||||
func (s *AccessLogSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "access_log")
|
||||
s.composeProject.Start(c)
|
||||
|
||||
s.composeProject.Container(c, "server0")
|
||||
s.composeProject.Container(c, "server1")
|
||||
s.composeProject.Container(c, "server2")
|
||||
s.composeProject.Container(c, "server3")
|
||||
s.composeUp(c)
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TearDownTest(c *check.C) {
|
||||
@@ -122,7 +117,7 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontend(c *check.C) {
|
||||
code: "200",
|
||||
user: "test",
|
||||
routerName: "rt-authFrontend",
|
||||
serviceURL: "http://172.17.0",
|
||||
serviceURL: "http://172.31.42",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -136,8 +131,6 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontend(c *check.C) {
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
s.composeProject.Container(c, "authFrontend")
|
||||
|
||||
waitForTraefik(c, "authFrontend")
|
||||
|
||||
// Verify Traefik started OK
|
||||
@@ -193,7 +186,7 @@ func (s *AccessLogSuite) TestAccessLogDigestAuthMiddleware(c *check.C) {
|
||||
code: "200",
|
||||
user: "test",
|
||||
routerName: "rt-digestAuthMiddleware",
|
||||
serviceURL: "http://172.17.0",
|
||||
serviceURL: "http://172.31.42",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -207,8 +200,6 @@ func (s *AccessLogSuite) TestAccessLogDigestAuthMiddleware(c *check.C) {
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
s.composeProject.Container(c, "digestAuthMiddleware")
|
||||
|
||||
waitForTraefik(c, "digestAuthMiddleware")
|
||||
|
||||
// Verify Traefik started OK
|
||||
@@ -322,8 +313,6 @@ func (s *AccessLogSuite) TestAccessLogFrontendRedirect(c *check.C) {
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
s.composeProject.Container(c, "frontendRedirect")
|
||||
|
||||
waitForTraefik(c, "frontendRedirect")
|
||||
|
||||
// Verify Traefik started OK
|
||||
@@ -375,8 +364,6 @@ func (s *AccessLogSuite) TestAccessLogRateLimit(c *check.C) {
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
s.composeProject.Container(c, "rateLimit")
|
||||
|
||||
waitForTraefik(c, "rateLimit")
|
||||
|
||||
// Verify Traefik started OK
|
||||
@@ -471,8 +458,6 @@ func (s *AccessLogSuite) TestAccessLogFrontendWhitelist(c *check.C) {
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
s.composeProject.Container(c, "frontendWhitelist")
|
||||
|
||||
waitForTraefik(c, "frontendWhitelist")
|
||||
|
||||
// Verify Traefik started OK
|
||||
@@ -504,7 +489,7 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontendSuccess(c *check.C) {
|
||||
code: "200",
|
||||
user: "test",
|
||||
routerName: "rt-authFrontend",
|
||||
serviceURL: "http://172.17.0",
|
||||
serviceURL: "http://172.31.42",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -518,8 +503,6 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontendSuccess(c *check.C) {
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
s.composeProject.Container(c, "authFrontend")
|
||||
|
||||
waitForTraefik(c, "authFrontend")
|
||||
|
||||
// Verify Traefik started OK
|
||||
@@ -548,7 +531,6 @@ func checkNoOtherTraefikProblems(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
if len(traefikLog) > 0 {
|
||||
fmt.Printf("%s\n", string(traefikLog))
|
||||
c.Assert(traefikLog, checker.HasLen, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -616,7 +598,6 @@ func checkTraefikStarted(c *check.C) []byte {
|
||||
c.Assert(err, checker.IsNil)
|
||||
if len(traefikLog) > 0 {
|
||||
fmt.Printf("%s\n", string(traefikLog))
|
||||
c.Assert(traefikLog, checker.HasLen, 0)
|
||||
}
|
||||
return traefikLog
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -19,7 +20,7 @@ import (
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// ACME test suites (using libcompose).
|
||||
// ACME test suites.
|
||||
type AcmeSuite struct {
|
||||
BaseSuite
|
||||
pebbleIP string
|
||||
@@ -54,7 +55,8 @@ const (
|
||||
)
|
||||
|
||||
func (s *AcmeSuite) getAcmeURL() string {
|
||||
return fmt.Sprintf("https://%s:14000/dir", s.pebbleIP)
|
||||
return fmt.Sprintf("https://%s/dir",
|
||||
net.JoinHostPort(s.pebbleIP, "14000"))
|
||||
}
|
||||
|
||||
func setupPebbleRootCA() (*http.Transport, error) {
|
||||
@@ -86,11 +88,10 @@ func setupPebbleRootCA() (*http.Transport, error) {
|
||||
|
||||
func (s *AcmeSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "pebble")
|
||||
s.composeProject.Start(c)
|
||||
s.composeUp(c)
|
||||
|
||||
s.fakeDNSServer = startFakeDNSServer()
|
||||
|
||||
s.pebbleIP = s.composeProject.Container(c, "pebble").NetworkSettings.IPAddress
|
||||
s.fakeDNSServer = startFakeDNSServer(s.getContainerIP(c, "traefik"))
|
||||
s.pebbleIP = s.getComposeServiceIP(c, "pebble")
|
||||
|
||||
pebbleTransport, err := setupPebbleRootCA()
|
||||
if err != nil {
|
||||
@@ -115,15 +116,14 @@ func (s *AcmeSuite) SetUpSuite(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TearDownSuite(c *check.C) {
|
||||
err := s.fakeDNSServer.Shutdown()
|
||||
if err != nil {
|
||||
c.Log(err)
|
||||
if s.fakeDNSServer != nil {
|
||||
err := s.fakeDNSServer.Shutdown()
|
||||
if err != nil {
|
||||
c.Log(err)
|
||||
}
|
||||
}
|
||||
|
||||
// shutdown and delete compose project
|
||||
if s.composeProject != nil {
|
||||
s.composeProject.Stop(c)
|
||||
}
|
||||
s.composeDown(c)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01Domains(c *check.C) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package integration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
@@ -14,32 +15,31 @@ import (
|
||||
|
||||
type ConsulCatalogSuite struct {
|
||||
BaseSuite
|
||||
consulClient *api.Client
|
||||
consulAgentClient *api.Client
|
||||
consulAddress string
|
||||
consulAgentAddress string
|
||||
consulClient *api.Client
|
||||
consulAgentClient *api.Client
|
||||
consulURL string
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "consul_catalog")
|
||||
s.composeProject.Start(c)
|
||||
s.consulAddress = "http://" + s.composeProject.Container(c, "consul").NetworkSettings.IPAddress + ":8500"
|
||||
client, err := api.NewClient(&api.Config{
|
||||
Address: s.consulAddress,
|
||||
s.composeUp(c)
|
||||
|
||||
s.consulURL = "http://" + net.JoinHostPort(s.getComposeServiceIP(c, "consul"), "8500")
|
||||
|
||||
var err error
|
||||
s.consulClient, err = api.NewClient(&api.Config{
|
||||
Address: s.consulURL,
|
||||
})
|
||||
c.Check(err, check.IsNil)
|
||||
s.consulClient = client
|
||||
|
||||
// Wait for consul to elect itself leader
|
||||
err = s.waitToElectConsulLeader()
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
s.consulAgentAddress = "http://" + s.composeProject.Container(c, "consul-agent").NetworkSettings.IPAddress + ":8500"
|
||||
clientAgent, err := api.NewClient(&api.Config{
|
||||
Address: s.consulAgentAddress,
|
||||
s.consulAgentClient, err = api.NewClient(&api.Config{
|
||||
Address: "http://" + net.JoinHostPort(s.getComposeServiceIP(c, "consul-agent"), "8500"),
|
||||
})
|
||||
c.Check(err, check.IsNil)
|
||||
s.consulAgentClient = clientAgent
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) waitToElectConsulLeader() error {
|
||||
@@ -66,13 +66,6 @@ func (s *ConsulCatalogSuite) waitForConnectCA() error {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TearDownSuite(c *check.C) {
|
||||
// shutdown and delete compose project
|
||||
if s.composeProject != nil {
|
||||
s.composeProject.Stop(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) registerService(reg *api.AgentServiceRegistration, onAgent bool) error {
|
||||
client := s.consulClient
|
||||
if onAgent {
|
||||
@@ -96,7 +89,7 @@ func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *c
|
||||
Name: "whoami",
|
||||
Tags: []string{"traefik.enable=true"},
|
||||
Port: 80,
|
||||
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
}
|
||||
err := s.registerService(reg1, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
@@ -106,7 +99,7 @@ func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *c
|
||||
Name: "whoami",
|
||||
Tags: []string{"traefik.enable=true"},
|
||||
Port: 80,
|
||||
Address: s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress,
|
||||
Address: s.getComposeServiceIP(c, "whoami2"),
|
||||
}
|
||||
err = s.registerService(reg2, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
@@ -116,7 +109,7 @@ func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *c
|
||||
Name: "whoami",
|
||||
Tags: []string{"traefik.enable=true"},
|
||||
Port: 80,
|
||||
Address: s.composeProject.Container(c, "whoami3").NetworkSettings.IPAddress,
|
||||
Address: s.getComposeServiceIP(c, "whoami3"),
|
||||
}
|
||||
err = s.registerService(reg3, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
@@ -124,7 +117,7 @@ func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *c
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
}{
|
||||
ConsulAddress: s.consulAddress,
|
||||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
|
||||
@@ -163,7 +156,7 @@ func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *c
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestByLabels(c *check.C) {
|
||||
containerIP := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
|
||||
containerIP := s.getComposeServiceIP(c, "whoami1")
|
||||
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
@@ -183,7 +176,7 @@ func (s *ConsulCatalogSuite) TestByLabels(c *check.C) {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
}{
|
||||
ConsulAddress: s.consulAddress,
|
||||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
|
||||
@@ -195,7 +188,7 @@ func (s *ConsulCatalogSuite) TestByLabels(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/whoami", 2*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContainsOr("Hostname: whoami1", "Hostname: whoami2", "Hostname: whoami3"))
|
||||
err = try.GetRequest("http://127.0.0.1:8000/whoami", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContainsOr("Hostname: whoami1", "Hostname: whoami2", "Hostname: whoami3"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
@@ -207,7 +200,7 @@ func (s *ConsulCatalogSuite) TestSimpleConfiguration(c *check.C) {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
}{
|
||||
ConsulAddress: s.consulAddress,
|
||||
ConsulAddress: s.consulURL,
|
||||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
@@ -219,7 +212,7 @@ func (s *ConsulCatalogSuite) TestSimpleConfiguration(c *check.C) {
|
||||
Name: "whoami",
|
||||
Tags: []string{"traefik.enable=true"},
|
||||
Port: 80,
|
||||
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
}
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
@@ -246,7 +239,7 @@ func (s *ConsulCatalogSuite) TestRegisterServiceWithoutIP(c *check.C) {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
}{
|
||||
ConsulAddress: s.consulAddress,
|
||||
ConsulAddress: s.consulURL,
|
||||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
@@ -285,7 +278,7 @@ func (s *ConsulCatalogSuite) TestDefaultConsulService(c *check.C) {
|
||||
DefaultRule string
|
||||
}{
|
||||
|
||||
ConsulAddress: s.consulAddress,
|
||||
ConsulAddress: s.consulURL,
|
||||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
@@ -296,7 +289,7 @@ func (s *ConsulCatalogSuite) TestDefaultConsulService(c *check.C) {
|
||||
ID: "whoami1",
|
||||
Name: "whoami",
|
||||
Port: 80,
|
||||
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
}
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
@@ -324,7 +317,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithTCPLabels(c *check.C) {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
}{
|
||||
ConsulAddress: s.consulAddress,
|
||||
ConsulAddress: s.consulURL,
|
||||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
@@ -341,7 +334,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithTCPLabels(c *check.C) {
|
||||
"traefik.tcp.Services.Super.Loadbalancer.server.port=8080",
|
||||
},
|
||||
Port: 8080,
|
||||
Address: s.composeProject.Container(c, "whoamitcp").NetworkSettings.IPAddress,
|
||||
Address: s.getComposeServiceIP(c, "whoamitcp"),
|
||||
}
|
||||
|
||||
err := s.registerService(reg, false)
|
||||
@@ -371,7 +364,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithLabels(c *check.C) {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
}{
|
||||
ConsulAddress: s.consulAddress,
|
||||
ConsulAddress: s.consulURL,
|
||||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
@@ -386,7 +379,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithLabels(c *check.C) {
|
||||
"traefik.http.Routers.Super.Rule=Host(`my.super.host`)",
|
||||
},
|
||||
Port: 80,
|
||||
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
}
|
||||
|
||||
err := s.registerService(reg1, false)
|
||||
@@ -400,7 +393,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithLabels(c *check.C) {
|
||||
"traefik.http.Routers.SuperHost.Rule=Host(`my-super.host`)",
|
||||
},
|
||||
Port: 80,
|
||||
Address: s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress,
|
||||
Address: s.getComposeServiceIP(c, "whoami2"),
|
||||
}
|
||||
err = s.registerService(reg2, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
@@ -438,7 +431,7 @@ func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent(c *check.C)
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
}{
|
||||
ConsulAddress: s.consulAddress,
|
||||
ConsulAddress: s.consulURL,
|
||||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
@@ -457,7 +450,7 @@ func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent(c *check.C)
|
||||
Name: "whoami",
|
||||
Tags: tags,
|
||||
Port: 80,
|
||||
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
}
|
||||
err := s.registerService(reg1, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
@@ -467,7 +460,7 @@ func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent(c *check.C)
|
||||
Name: "whoami",
|
||||
Tags: tags,
|
||||
Port: 80,
|
||||
Address: s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress,
|
||||
Address: s.getComposeServiceIP(c, "whoami2"),
|
||||
}
|
||||
err = s.registerService(reg2, true)
|
||||
c.Assert(err, checker.IsNil)
|
||||
@@ -490,8 +483,7 @@ func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent(c *check.C)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200),
|
||||
try.BodyContainsOr(s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
|
||||
s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress))
|
||||
try.BodyContainsOr(s.getComposeServiceIP(c, "whoami1"), s.getComposeServiceIP(c, "whoami2")))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = s.deregisterService("whoami", false)
|
||||
@@ -506,7 +498,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithOneMissingLabels(c *check.C) {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
}{
|
||||
ConsulAddress: s.consulAddress,
|
||||
ConsulAddress: s.consulURL,
|
||||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
@@ -521,7 +513,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithOneMissingLabels(c *check.C) {
|
||||
"traefik.random.value=my.super.host",
|
||||
},
|
||||
Port: 80,
|
||||
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
}
|
||||
|
||||
err := s.registerService(reg, false)
|
||||
@@ -546,11 +538,12 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithOneMissingLabels(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
|
||||
whoamiIP := s.getComposeServiceIP(c, "whoami1")
|
||||
tags := []string{
|
||||
"traefik.enable=true",
|
||||
"traefik.http.routers.router1.rule=Path(`/whoami`)",
|
||||
"traefik.http.routers.router1.service=service1",
|
||||
"traefik.http.services.service1.loadBalancer.server.url=http://" + s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
|
||||
"traefik.http.services.service1.loadBalancer.server.url=http://" + whoamiIP,
|
||||
}
|
||||
|
||||
reg1 := &api.AgentServiceRegistration{
|
||||
@@ -558,7 +551,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
|
||||
Name: "whoami",
|
||||
Tags: tags,
|
||||
Port: 80,
|
||||
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress,
|
||||
Address: whoamiIP,
|
||||
Check: &api.AgentServiceCheck{
|
||||
CheckID: "some-failed-check",
|
||||
TCP: "127.0.0.1:1234",
|
||||
@@ -574,7 +567,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
}{
|
||||
ConsulAddress: s.consulAddress,
|
||||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
@@ -592,17 +585,16 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
containerIP := s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress
|
||||
|
||||
whoami2IP := s.getComposeServiceIP(c, "whoami2")
|
||||
reg2 := &api.AgentServiceRegistration{
|
||||
ID: "whoami2",
|
||||
Name: "whoami",
|
||||
Tags: tags,
|
||||
Port: 80,
|
||||
Address: containerIP,
|
||||
Address: whoami2IP,
|
||||
Check: &api.AgentServiceCheck{
|
||||
CheckID: "some-ok-check",
|
||||
TCP: containerIP + ":80",
|
||||
TCP: whoami2IP + ":80",
|
||||
Name: "some-ok-check",
|
||||
Interval: "1s",
|
||||
Timeout: "1s",
|
||||
@@ -629,7 +621,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect(c *check.C) {
|
||||
err := s.waitForConnectCA()
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
connectIP := s.composeProject.Container(c, "connect").NetworkSettings.IPAddress
|
||||
connectIP := s.getComposeServiceIP(c, "connect")
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "uuid-api1",
|
||||
Name: "uuid-api",
|
||||
@@ -649,7 +641,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect(c *check.C) {
|
||||
err = s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
whoamiIP := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
|
||||
whoamiIP := s.getComposeServiceIP(c, "whoami1")
|
||||
regWhoami := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami",
|
||||
@@ -667,7 +659,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect(c *check.C) {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
}{
|
||||
ConsulAddress: s.consulAddress,
|
||||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/connect.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
@@ -695,7 +687,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
|
||||
err := s.waitForConnectCA()
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
connectIP := s.composeProject.Container(c, "connect").NetworkSettings.IPAddress
|
||||
connectIP := s.getComposeServiceIP(c, "connect")
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "uuid-api1",
|
||||
Name: "uuid-api",
|
||||
@@ -714,7 +706,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
|
||||
err = s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
whoamiIP := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
|
||||
whoamiIP := s.getComposeServiceIP(c, "whoami1")
|
||||
regWhoami := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami1",
|
||||
@@ -729,7 +721,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
|
||||
err = s.registerService(regWhoami, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
whoami2IP := s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress
|
||||
whoami2IP := s.getComposeServiceIP(c, "whoami2")
|
||||
regWhoami2 := &api.AgentServiceRegistration{
|
||||
ID: "whoami2",
|
||||
Name: "whoami2",
|
||||
@@ -748,7 +740,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
}{
|
||||
ConsulAddress: s.consulAddress,
|
||||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/connect_by_default.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
@@ -781,7 +773,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect_NotAware(c *check.C) {
|
||||
err := s.waitForConnectCA()
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
connectIP := s.composeProject.Container(c, "connect").NetworkSettings.IPAddress
|
||||
connectIP := s.getComposeServiceIP(c, "connect")
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "uuid-api1",
|
||||
Name: "uuid-api",
|
||||
@@ -801,7 +793,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect_NotAware(c *check.C) {
|
||||
err = s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
whoamiIP := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
|
||||
whoamiIP := s.getComposeServiceIP(c, "whoami1")
|
||||
regWhoami := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami",
|
||||
@@ -819,7 +811,7 @@ func (s *ConsulCatalogSuite) TestConsulConnect_NotAware(c *check.C) {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
}{
|
||||
ConsulAddress: s.consulAddress,
|
||||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/connect_not_aware.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
|
||||
@@ -3,6 +3,8 @@ package integration
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -18,20 +20,24 @@ import (
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Consul test suites (using libcompose).
|
||||
// Consul test suites.
|
||||
type ConsulSuite struct {
|
||||
BaseSuite
|
||||
kvClient store.Store
|
||||
kvClient store.Store
|
||||
consulURL string
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) setupStore(c *check.C) {
|
||||
s.createComposeProject(c, "consul")
|
||||
s.composeProject.Start(c)
|
||||
s.composeUp(c)
|
||||
|
||||
consulAddr := net.JoinHostPort(s.getComposeServiceIP(c, "consul"), "8500")
|
||||
s.consulURL = fmt.Sprintf("http://%s", consulAddr)
|
||||
|
||||
consul.Register()
|
||||
kv, err := valkeyrie.NewStore(
|
||||
store.CONSUL,
|
||||
[]string{s.composeProject.Container(c, "consul").NetworkSettings.IPAddress + ":8500"},
|
||||
[]string{consulAddr},
|
||||
&store.Config{
|
||||
ConnectionTimeout: 10 * time.Second,
|
||||
},
|
||||
@@ -46,20 +52,10 @@ func (s *ConsulSuite) setupStore(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) TearDownTest(c *check.C) {
|
||||
// shutdown and delete compose project
|
||||
if s.composeProject != nil {
|
||||
s.composeProject.Stop(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) TearDownSuite(c *check.C) {}
|
||||
|
||||
func (s *ConsulSuite) TestSimpleConfiguration(c *check.C) {
|
||||
s.setupStore(c)
|
||||
|
||||
address := "http://" + s.composeProject.Container(c, "consul").NetworkSettings.IPAddress + ":8500"
|
||||
file := s.adaptFile(c, "fixtures/consul/simple.toml", struct{ ConsulAddress string }{address})
|
||||
file := s.adaptFile(c, "fixtures/consul/simple.toml", struct{ ConsulAddress string }{s.consulURL})
|
||||
defer os.Remove(file)
|
||||
|
||||
data := map[string]string{
|
||||
|
||||
@@ -14,33 +14,17 @@ import (
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
const (
|
||||
composeProject = "minimal"
|
||||
)
|
||||
|
||||
// Docker tests suite.
|
||||
type DockerComposeSuite struct {
|
||||
BaseSuite
|
||||
}
|
||||
|
||||
func (s *DockerComposeSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, composeProject)
|
||||
s.composeProject.Start(c)
|
||||
}
|
||||
|
||||
func (s *DockerComposeSuite) TearDownSuite(c *check.C) {
|
||||
// shutdown and delete compose project
|
||||
if s.composeProject != nil {
|
||||
s.composeProject.Stop(c)
|
||||
}
|
||||
s.createComposeProject(c, "minimal")
|
||||
s.composeUp(c)
|
||||
}
|
||||
|
||||
func (s *DockerComposeSuite) TestComposeScale(c *check.C) {
|
||||
serviceCount := 2
|
||||
composeService := "whoami1"
|
||||
|
||||
s.composeProject.Scale(c, composeService, serviceCount)
|
||||
|
||||
tempObjects := struct {
|
||||
DockerHost string
|
||||
DefaultRule string
|
||||
@@ -81,8 +65,8 @@ func (s *DockerComposeSuite) TestComposeScale(c *check.C) {
|
||||
if strings.HasSuffix(name, "@internal") {
|
||||
continue
|
||||
}
|
||||
c.Assert(name, checker.Equals, composeService+"-integrationtest"+composeProject+"@docker")
|
||||
c.Assert(service.LoadBalancer.Servers, checker.HasLen, serviceCount)
|
||||
c.Assert(name, checker.Equals, "whoami1-"+s.composeProject.Name+"@docker")
|
||||
c.Assert(service.LoadBalancer.Servers, checker.HasLen, 2)
|
||||
// We could break here, but we don't just to keep us honest.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,80 +6,24 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/namesgenerator"
|
||||
"github.com/go-check/check"
|
||||
d "github.com/libkermit/docker"
|
||||
"github.com/libkermit/docker-check"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Images to have or pull before the build in order to make it work.
|
||||
// FIXME handle this offline but loading them before build.
|
||||
var RequiredImages = map[string]string{
|
||||
"swarm": "1.0.0",
|
||||
"traefik/whoami": "latest",
|
||||
}
|
||||
|
||||
// Docker tests suite.
|
||||
type DockerSuite struct {
|
||||
BaseSuite
|
||||
project *docker.Project
|
||||
}
|
||||
|
||||
func (s *DockerSuite) startContainer(c *check.C, image string, args ...string) string {
|
||||
return s.startContainerWithConfig(c, image, d.ContainerConfig{
|
||||
Cmd: args,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *DockerSuite) startContainerWithLabels(c *check.C, image string, labels map[string]string, args ...string) string {
|
||||
return s.startContainerWithConfig(c, image, d.ContainerConfig{
|
||||
Cmd: args,
|
||||
Labels: labels,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *DockerSuite) startContainerWithNameAndLabels(c *check.C, name, image string, labels map[string]string, args ...string) string {
|
||||
return s.startContainerWithConfig(c, image, d.ContainerConfig{
|
||||
Name: name,
|
||||
Cmd: args,
|
||||
Labels: labels,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *DockerSuite) startContainerWithConfig(c *check.C, image string, config d.ContainerConfig) string {
|
||||
if config.Name == "" {
|
||||
config.Name = namesgenerator.GetRandomName(10)
|
||||
}
|
||||
|
||||
container := s.project.StartWithConfig(c, image, config)
|
||||
|
||||
// FIXME(vdemeester) this is ugly (it's because of the / in front of the name in docker..)
|
||||
return strings.SplitAfter(container.Name, "/")[1]
|
||||
}
|
||||
|
||||
func (s *DockerSuite) stopAndRemoveContainerByName(c *check.C, name string) {
|
||||
s.project.Stop(c, name)
|
||||
s.project.Remove(c, name)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) SetUpSuite(c *check.C) {
|
||||
project := docker.NewProjectFromEnv(c)
|
||||
s.project = project
|
||||
|
||||
// Pull required images
|
||||
for repository, tag := range RequiredImages {
|
||||
image := fmt.Sprintf("%s:%s", repository, tag)
|
||||
s.project.Pull(c, image)
|
||||
}
|
||||
func (s *DockerSuite) SetUpTest(c *check.C) {
|
||||
s.createComposeProject(c, "docker")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TearDownTest(c *check.C) {
|
||||
s.project.Clean(c, os.Getenv("CIRCLECI") != "") // FIXME
|
||||
s.composeDown(c)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestSimpleConfiguration(c *check.C) {
|
||||
@@ -94,13 +38,15 @@ func (s *DockerSuite) TestSimpleConfiguration(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
|
||||
s.composeUp(c)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
// TODO validate : run on 80
|
||||
// Expected a 404 as we did not configure anything
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
@@ -118,18 +64,19 @@ func (s *DockerSuite) TestDefaultDockerContainers(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
|
||||
name := s.startContainer(c, "swarm:1.0.0", "manage", "token://blablabla")
|
||||
s.composeUp(c, "simple")
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
req.Host = fmt.Sprintf("%s.docker.localhost", strings.ReplaceAll(name, "_", "-"))
|
||||
req.Host = fmt.Sprintf("simple-%s.docker.localhost", s.composeProject.Name)
|
||||
|
||||
// FIXME Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
|
||||
resp, err := try.ResponseUntilStatusCode(req, 1500*time.Millisecond, http.StatusOK)
|
||||
@@ -156,18 +103,12 @@ func (s *DockerSuite) TestDockerContainersWithTCPLabels(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
|
||||
// Start a container with some labels
|
||||
labels := map[string]string{
|
||||
"traefik.tcp.Routers.Super.Rule": "HostSNI(`my.super.host`)",
|
||||
"traefik.tcp.Routers.Super.tls": "true",
|
||||
"traefik.tcp.Services.Super.Loadbalancer.server.port": "8080",
|
||||
}
|
||||
|
||||
s.startContainerWithLabels(c, "traefik/whoamitcp", labels, "-name", "my.super.host")
|
||||
s.composeUp(c, "withtcplabels")
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
@@ -193,17 +134,7 @@ func (s *DockerSuite) TestDockerContainersWithLabels(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
|
||||
// Start a container with some labels
|
||||
labels := map[string]string{
|
||||
"traefik.http.Routers.Super.Rule": "Host(`my.super.host`)",
|
||||
}
|
||||
s.startContainerWithLabels(c, "swarm:1.0.0", labels, "manage", "token://blabla")
|
||||
|
||||
// Start another container by replacing a '.' by a '-'
|
||||
labels = map[string]string{
|
||||
"traefik.http.Routers.SuperHost.Rule": "Host(`my-super.host`)",
|
||||
}
|
||||
s.startContainerWithLabels(c, "swarm:1.0.0", labels, "manage", "token://blablabla")
|
||||
s.composeUp(c, "withlabels1", "withlabels2")
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
@@ -249,15 +180,12 @@ func (s *DockerSuite) TestDockerContainersWithOneMissingLabels(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
|
||||
// Start a container with some labels
|
||||
labels := map[string]string{
|
||||
"traefik.random.value": "my.super.host",
|
||||
}
|
||||
s.startContainerWithLabels(c, "swarm:1.0.0", labels, "manage", "token://blabla")
|
||||
s.composeUp(c, "withonelabelmissing")
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
@@ -285,16 +213,12 @@ func (s *DockerSuite) TestRestartDockerContainers(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
|
||||
// Start a container with some labels
|
||||
labels := map[string]string{
|
||||
"traefik.http.Routers.Super.Rule": "Host(`my.super.host`)",
|
||||
"traefik.http.Services.powpow.LoadBalancer.server.Port": "2375",
|
||||
}
|
||||
s.startContainerWithNameAndLabels(c, "powpow", "swarm:1.0.0", labels, "manage", "token://blabla")
|
||||
s.composeUp(c, "powpow")
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
@@ -318,16 +242,14 @@ func (s *DockerSuite) TestRestartDockerContainers(c *check.C) {
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("powpow"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
s.stopAndRemoveContainerByName(c, "powpow")
|
||||
defer s.project.Remove(c, "powpow")
|
||||
s.composeStop(c, "powpow")
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("powpow"))
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
s.startContainerWithNameAndLabels(c, "powpow", "swarm:1.0.0", labels, "manage", "token://blabla")
|
||||
|
||||
s.composeUp(c, "powpow")
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("powpow"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// ErrorPagesSuite test suites (using libcompose).
|
||||
// ErrorPagesSuite test suites.
|
||||
type ErrorPagesSuite struct {
|
||||
BaseSuite
|
||||
ErrorPageIP string
|
||||
@@ -19,10 +19,10 @@ type ErrorPagesSuite struct {
|
||||
|
||||
func (s *ErrorPagesSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "error_pages")
|
||||
s.composeProject.Start(c)
|
||||
s.composeUp(c)
|
||||
|
||||
s.ErrorPageIP = s.composeProject.Container(c, "nginx2").NetworkSettings.IPAddress
|
||||
s.BackendIP = s.composeProject.Container(c, "nginx1").NetworkSettings.IPAddress
|
||||
s.ErrorPageIP = s.getComposeServiceIP(c, "nginx2")
|
||||
s.BackendIP = s.getComposeServiceIP(c, "nginx1")
|
||||
}
|
||||
|
||||
func (s *ErrorPagesSuite) TestSimpleConfiguration(c *check.C) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package integration
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -18,20 +19,24 @@ import (
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// etcd test suites (using libcompose).
|
||||
// etcd test suites.
|
||||
type EtcdSuite struct {
|
||||
BaseSuite
|
||||
kvClient store.Store
|
||||
etcdAddr string
|
||||
}
|
||||
|
||||
func (s *EtcdSuite) setupStore(c *check.C) {
|
||||
func (s *EtcdSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "etcd")
|
||||
s.composeProject.Start(c)
|
||||
s.composeUp(c)
|
||||
|
||||
etcdv3.Register()
|
||||
kv, err := valkeyrie.NewStore(
|
||||
|
||||
var err error
|
||||
s.etcdAddr = net.JoinHostPort(s.getComposeServiceIP(c, "etcd"), "2379")
|
||||
s.kvClient, err = valkeyrie.NewStore(
|
||||
store.ETCDV3,
|
||||
[]string{s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress + ":2379"},
|
||||
[]string{s.etcdAddr},
|
||||
&store.Config{
|
||||
ConnectionTimeout: 10 * time.Second,
|
||||
},
|
||||
@@ -39,27 +44,14 @@ func (s *EtcdSuite) setupStore(c *check.C) {
|
||||
if err != nil {
|
||||
c.Fatal("Cannot create store etcd")
|
||||
}
|
||||
s.kvClient = kv
|
||||
|
||||
// wait for etcd
|
||||
err = try.Do(60*time.Second, try.KVExists(kv, "test"))
|
||||
err = try.Do(60*time.Second, try.KVExists(s.kvClient, "test"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *EtcdSuite) TearDownTest(c *check.C) {
|
||||
// shutdown and delete compose project
|
||||
if s.composeProject != nil {
|
||||
s.composeProject.Stop(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *EtcdSuite) TearDownSuite(c *check.C) {}
|
||||
|
||||
func (s *EtcdSuite) TestSimpleConfiguration(c *check.C) {
|
||||
s.setupStore(c)
|
||||
|
||||
address := s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress + ":2379"
|
||||
file := s.adaptFile(c, "fixtures/etcd/simple.toml", struct{ EtcdAddress string }{address})
|
||||
file := s.adaptFile(c, "fixtures/etcd/simple.toml", struct{ EtcdAddress string }{s.etcdAddr})
|
||||
defer os.Remove(file)
|
||||
|
||||
data := map[string]string{
|
||||
|
||||
@@ -9,7 +9,9 @@ import (
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
)
|
||||
|
||||
type handler struct{}
|
||||
type handler struct {
|
||||
traefikIP string
|
||||
}
|
||||
|
||||
// ServeDNS a fake DNS server
|
||||
// Simplified version of the Challenge Test Server from Boulder
|
||||
@@ -21,11 +23,6 @@ func (s *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
|
||||
m.SetReply(r)
|
||||
m.Compress = false
|
||||
|
||||
fakeDNS := os.Getenv("DOCKER_HOST_IP")
|
||||
if fakeDNS == "" {
|
||||
fakeDNS = "127.0.0.1"
|
||||
}
|
||||
|
||||
for _, q := range r.Question {
|
||||
logger.Infof("Query -- [%s] %s", q.Name, dns.TypeToString[q.Qtype])
|
||||
|
||||
@@ -38,7 +35,7 @@ func (s *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
|
||||
Class: dns.ClassINET,
|
||||
Ttl: 0,
|
||||
}
|
||||
record.A = net.ParseIP(fakeDNS)
|
||||
record.A = net.ParseIP(s.traefikIP)
|
||||
|
||||
m.Answer = append(m.Answer, record)
|
||||
case dns.TypeCAA:
|
||||
@@ -101,11 +98,11 @@ func (s *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
|
||||
}
|
||||
}
|
||||
|
||||
func startFakeDNSServer() *dns.Server {
|
||||
func startFakeDNSServer(traefikIP string) *dns.Server {
|
||||
srv := &dns.Server{
|
||||
Addr: ":5053",
|
||||
Net: "udp",
|
||||
Handler: &handler{},
|
||||
Handler: &handler{traefikIP},
|
||||
}
|
||||
|
||||
go func() {
|
||||
|
||||
@@ -15,7 +15,7 @@ type FileSuite struct{ BaseSuite }
|
||||
|
||||
func (s *FileSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "file")
|
||||
s.composeProject.Start(c)
|
||||
s.composeUp(c)
|
||||
}
|
||||
|
||||
func (s *FileSuite) TestSimpleConfiguration(c *check.C) {
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
[http.services]
|
||||
[http.services.service2.loadBalancer]
|
||||
[[http.services.service2.loadBalancer.servers]]
|
||||
url = "http://172.17.0.123:80"
|
||||
url = "http://127.0.0.1:80"
|
||||
|
||||
@@ -33,13 +33,13 @@
|
||||
[http.services.service1.loadBalancer]
|
||||
|
||||
[[http.services.service1.loadBalancer.servers]]
|
||||
url = "http://{{.WhoamiEndpoint}}:8080"
|
||||
url = "http://{{ .WhoamiIP }}:8080"
|
||||
|
||||
[[http.services.service1.loadBalancer.servers]]
|
||||
url = "http://{{.WhoamiEndpoint}}:8081"
|
||||
url = "http://{{ .WhoamiIP }}:8081"
|
||||
|
||||
[[http.services.service1.loadBalancer.servers]]
|
||||
url = "http://{{.WhoamiEndpoint}}:8082"
|
||||
url = "http://{{ .WhoamiIP }}:8082"
|
||||
|
||||
[[http.services.service1.loadBalancer.servers]]
|
||||
url = "http://{{.WhoamiEndpoint}}:80"
|
||||
url = "http://{{ .WhoamiIP }}:80"
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
[http.services.service1.loadBalancer]
|
||||
|
||||
[[http.services.service1.loadBalancer.servers]]
|
||||
url = "http://{{.WhoamiEndpoint}}:8080"
|
||||
url = "http://{{ .WhoamiIP }}:8080"
|
||||
|
||||
[[http.services.service1.loadBalancer.servers]]
|
||||
url = "http://{{.WhoamiEndpoint}}:80"
|
||||
url = "http://{{ .WhoamiIP }}:80"
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
[tcp.services]
|
||||
[tcp.services.whoami-no-tls.loadBalancer]
|
||||
[[tcp.services.whoami-no-tls.loadBalancer.servers]]
|
||||
address = "localhost:8086"
|
||||
address = "whoami-no-tls:8080"
|
||||
|
||||
[http]
|
||||
[http.routers]
|
||||
@@ -40,4 +40,4 @@
|
||||
[http.services]
|
||||
[http.services.whoami.loadBalancer]
|
||||
[[http.services.whoami.loadBalancer.servers]]
|
||||
url = "http://localhost:8085"
|
||||
url = "http://whoami:80"
|
||||
|
||||
@@ -27,4 +27,4 @@
|
||||
[tcp.services]
|
||||
[tcp.services.whoami-no-tls.loadBalancer]
|
||||
[[tcp.services.whoami-no-tls.loadBalancer.servers]]
|
||||
address = "localhost:8086"
|
||||
address = "whoami-banner:8080"
|
||||
|
||||
@@ -38,18 +38,14 @@
|
||||
[tcp.services]
|
||||
[tcp.services.whoami-a.loadBalancer]
|
||||
[[tcp.services.whoami-a.loadBalancer.servers]]
|
||||
address = "localhost:8081"
|
||||
address = "whoami-a:8080"
|
||||
|
||||
[tcp.services.whoami-b.loadBalancer]
|
||||
[[tcp.services.whoami-b.loadBalancer.servers]]
|
||||
address = "localhost:8082"
|
||||
address = "whoami-b:8080"
|
||||
|
||||
[tcp.middlewares]
|
||||
[tcp.middlewares.allowing-ipwhitelist.ipWhiteList]
|
||||
sourceRange = ["127.0.0.1/32"]
|
||||
[tcp.middlewares.blocking-ipwhitelist.ipWhiteList]
|
||||
sourceRange = ["127.127.127.127/32"]
|
||||
|
||||
[[tls.certificates]]
|
||||
certFile = "fixtures/tcp/whoami-c.crt"
|
||||
keyFile = "fixtures/tcp/whoami-c.key"
|
||||
|
||||
@@ -29,11 +29,15 @@
|
||||
rule = "Path(`/whoami/`)"
|
||||
service = "whoami"
|
||||
[http.routers.my-https-router.tls]
|
||||
[http.routers.api]
|
||||
rule = "PathPrefix(`/api`)"
|
||||
service = "api@internal"
|
||||
entryPoints = ["traefik"]
|
||||
|
||||
[http.services]
|
||||
[http.services.whoami.loadBalancer]
|
||||
[[http.services.whoami.loadBalancer.servers]]
|
||||
url = "http://localhost:8085"
|
||||
url = "http://whoami:80"
|
||||
[tcp]
|
||||
[tcp.routers]
|
||||
[tcp.routers.to-whoami-a]
|
||||
@@ -58,15 +62,15 @@
|
||||
|
||||
[tcp.services.whoami-a.loadBalancer]
|
||||
[[tcp.services.whoami-a.loadBalancer.servers]]
|
||||
address = "localhost:8081"
|
||||
address = "whoami-a:8080"
|
||||
|
||||
[tcp.services.whoami-b.loadBalancer]
|
||||
[[tcp.services.whoami-b.loadBalancer.servers]]
|
||||
address = "localhost:8082"
|
||||
address = "whoami-b:8080"
|
||||
|
||||
[tcp.services.whoami-no-cert.loadBalancer]
|
||||
[[tcp.services.whoami-no-cert.loadBalancer.servers]]
|
||||
address = "localhost:8083"
|
||||
address = "whoami-no-cert:8080"
|
||||
|
||||
[[tls.certificates]]
|
||||
certFile = "fixtures/tcp/whoami-c.crt"
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
[tcp.services.whoami-no-cert]
|
||||
[tcp.services.whoami-no-cert.loadBalancer]
|
||||
[[tcp.services.whoami-no-cert.loadBalancer.servers]]
|
||||
address = "localhost:8083"
|
||||
address = "whoami-no-cert:8080"
|
||||
|
||||
[tls.options]
|
||||
|
||||
|
||||
@@ -24,14 +24,14 @@
|
||||
service = "whoami-a"
|
||||
entryPoints = [ "tcp" ]
|
||||
[tcp.routers.to-whoami-a.tls]
|
||||
passthrough=true
|
||||
passthrough = true
|
||||
|
||||
[tcp.routers.to-whoami-b]
|
||||
rule = "HostSNI(`whoami-b.test`)"
|
||||
service = "whoami-b"
|
||||
entryPoints = [ "tcp" ]
|
||||
[tcp.routers.to-whoami-b.tls]
|
||||
passthrough=true
|
||||
passthrough = true
|
||||
|
||||
[tcp.routers.to-whoami-no-cert]
|
||||
rule = "HostSNI(`whoami-c.test`)"
|
||||
@@ -47,16 +47,17 @@
|
||||
[tcp.services]
|
||||
[tcp.services.whoami-no-tls.loadBalancer]
|
||||
[[tcp.services.whoami-no-tls.loadBalancer.servers]]
|
||||
address = "localhost:8084"
|
||||
address = "whoami-no-tls:8080"
|
||||
|
||||
[tcp.services.whoami-a.loadBalancer]
|
||||
[[tcp.services.whoami-a.loadBalancer.servers]]
|
||||
address = "localhost:8081"
|
||||
address = "whoami-a:8080"
|
||||
|
||||
[tcp.services.whoami-b.loadBalancer]
|
||||
[[tcp.services.whoami-b.loadBalancer.servers]]
|
||||
address = "localhost:8082"
|
||||
address = "whoami-b:8080"
|
||||
|
||||
[tcp.services.whoami-no-cert.loadBalancer]
|
||||
[[tcp.services.whoami-no-cert.loadBalancer.servers]]
|
||||
address = "localhost:8083"
|
||||
address = "whoami-no-cert:8080"
|
||||
|
||||
|
||||
@@ -27,4 +27,4 @@
|
||||
[tcp.services]
|
||||
[tcp.services.whoami-no-tls.loadBalancer]
|
||||
[[tcp.services.whoami-no-tls.loadBalancer.servers]]
|
||||
address = "localhost:8084"
|
||||
address = "whoami-no-tls:8080"
|
||||
|
||||
@@ -18,25 +18,24 @@
|
||||
## dynamic configuration ##
|
||||
[tcp]
|
||||
[tcp.routers]
|
||||
[tcp.routers.to-whoami-a]
|
||||
rule = "HostSNI(`whoami-a.test`)"
|
||||
[tcp.routers.to-whoami-b]
|
||||
rule = "HostSNI(`whoami-b.test`)"
|
||||
service = "whoami"
|
||||
entryPoints = [ "tcp" ]
|
||||
[tcp.routers.to-whoami-a.tls]
|
||||
[tcp.routers.to-whoami-b.tls]
|
||||
passthrough=true
|
||||
|
||||
[[tcp.services.whoami.weighted.services]]
|
||||
name="whoami-a"
|
||||
name="whoami-b"
|
||||
weight=3
|
||||
[[tcp.services.whoami.weighted.services]]
|
||||
name="whoami-b"
|
||||
name="whoami-ab"
|
||||
weight=1
|
||||
|
||||
[tcp.services.whoami-a.loadBalancer]
|
||||
[[tcp.services.whoami-a.loadBalancer.servers]]
|
||||
address = "localhost:8081"
|
||||
|
||||
[tcp.services.whoami-b.loadBalancer]
|
||||
[[tcp.services.whoami-b.loadBalancer.servers]]
|
||||
address = "localhost:8082"
|
||||
address = "whoami-b:8080"
|
||||
|
||||
[tcp.services.whoami-ab.loadBalancer]
|
||||
[[tcp.services.whoami-ab.loadBalancer.servers]]
|
||||
address = "whoami-ab:8080"
|
||||
|
||||
@@ -55,16 +55,16 @@
|
||||
[http.services.service1.loadBalancer]
|
||||
passHostHeader = true
|
||||
[[http.services.service1.loadBalancer.servers]]
|
||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
|
||||
|
||||
[http.services.service2]
|
||||
[http.services.service2.loadBalancer]
|
||||
passHostHeader = true
|
||||
[[http.services.service2.loadBalancer.servers]]
|
||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
|
||||
|
||||
[http.services.service3]
|
||||
[http.services.service3.loadBalancer]
|
||||
passHostHeader = true
|
||||
[[http.services.service3.loadBalancer.servers]]
|
||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
|
||||
|
||||
@@ -54,16 +54,16 @@
|
||||
[http.services.service1.loadBalancer]
|
||||
passHostHeader = true
|
||||
[[http.services.service1.loadBalancer.servers]]
|
||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
|
||||
|
||||
[http.services.service2]
|
||||
[http.services.service2.loadBalancer]
|
||||
passHostHeader = true
|
||||
[[http.services.service2.loadBalancer.servers]]
|
||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
|
||||
|
||||
[http.services.service3]
|
||||
[http.services.service3.loadBalancer]
|
||||
passHostHeader = true
|
||||
[[http.services.service3.loadBalancer.servers]]
|
||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
|
||||
|
||||
@@ -50,16 +50,16 @@
|
||||
[http.services.service1.loadBalancer]
|
||||
passHostHeader = true
|
||||
[[http.services.service1.loadBalancer.servers]]
|
||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
|
||||
|
||||
[http.services.service2]
|
||||
[http.services.service2.loadBalancer]
|
||||
passHostHeader = true
|
||||
[[http.services.service2.loadBalancer.servers]]
|
||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
|
||||
|
||||
[http.services.service3]
|
||||
[http.services.service3.loadBalancer]
|
||||
passHostHeader = true
|
||||
[[http.services.service3.loadBalancer.servers]]
|
||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||
url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}"
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// HealthCheck test suites (using libcompose).
|
||||
// HealthCheck test suites.
|
||||
type HealthCheckSuite struct {
|
||||
BaseSuite
|
||||
whoami1IP string
|
||||
@@ -24,12 +24,12 @@ type HealthCheckSuite struct {
|
||||
|
||||
func (s *HealthCheckSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "healthcheck")
|
||||
s.composeProject.Start(c)
|
||||
s.composeUp(c)
|
||||
|
||||
s.whoami1IP = s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
|
||||
s.whoami2IP = s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress
|
||||
s.whoami3IP = s.composeProject.Container(c, "whoami3").NetworkSettings.IPAddress
|
||||
s.whoami4IP = s.composeProject.Container(c, "whoami4").NetworkSettings.IPAddress
|
||||
s.whoami1IP = s.getComposeServiceIP(c, "whoami1")
|
||||
s.whoami2IP = s.getComposeServiceIP(c, "whoami2")
|
||||
s.whoami3IP = s.getComposeServiceIP(c, "whoami3")
|
||||
s.whoami4IP = s.getComposeServiceIP(c, "whoami4")
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestSimpleConfiguration(c *check.C) {
|
||||
@@ -90,7 +90,7 @@ func (s *HealthCheckSuite) TestSimpleConfiguration(c *check.C) {
|
||||
|
||||
// Check if the service with bad health check (whoami2) never respond.
|
||||
err = try.Request(frontendReq, 2*time.Second, try.BodyContains(s.whoami2IP))
|
||||
c.Assert(err, checker.Not(checker.IsNil))
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
// TODO validate : run on 80
|
||||
resp, err := http.Get("http://127.0.0.1:8000/")
|
||||
|
||||
@@ -13,9 +13,7 @@ type HostResolverSuite struct{ BaseSuite }
|
||||
|
||||
func (s *HostResolverSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "hostresolver")
|
||||
|
||||
s.composeProject.Start(c)
|
||||
s.composeProject.Container(c, "server1")
|
||||
s.composeUp(c)
|
||||
}
|
||||
|
||||
func (s *HostResolverSuite) TestSimpleConfig(c *check.C) {
|
||||
@@ -48,7 +46,7 @@ func (s *HostResolverSuite) TestSimpleConfig(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
req.Host = test.host
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(test.status), try.HasBody())
|
||||
err = try.Request(req, 1*time.Second, try.StatusCodeIs(test.status), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1063,13 +1063,13 @@ func (s *HTTPSSuite) TestEntryPointHttpsRedirectAndPathModification(c *check.C)
|
||||
for _, test := range testCases {
|
||||
sourceURL := fmt.Sprintf("http://127.0.0.1:8888%s", test.path)
|
||||
for _, host := range test.hosts {
|
||||
req, err := http.NewRequest("GET", sourceURL, nil)
|
||||
req, err := http.NewRequest(http.MethodGet, sourceURL, nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
req.Host = host
|
||||
|
||||
resp, err := client.Do(req)
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer resp.Body.Close()
|
||||
resp.Body.Close()
|
||||
|
||||
location := resp.Header.Get("Location")
|
||||
expected := fmt.Sprintf("https://%s:8443%s", host, test.path)
|
||||
|
||||
@@ -3,9 +3,9 @@ package integration
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -14,17 +14,23 @@ import (
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/compose-spec/compose-go/cli"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/compose/v2/cmd/formatter"
|
||||
composeapi "github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/compose"
|
||||
dockertypes "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/fatih/structs"
|
||||
"github.com/go-check/check"
|
||||
compose "github.com/libkermit/compose/check"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
var (
|
||||
integration = flag.Bool("integration", false, "run integration tests")
|
||||
container = flag.Bool("container", false, "run container integration tests")
|
||||
host = flag.Bool("host", false, "run host integration tests")
|
||||
showLog = flag.Bool("tlog", false, "always show Traefik logs")
|
||||
)
|
||||
|
||||
@@ -34,45 +40,39 @@ func Test(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
if *container {
|
||||
// tests launched from a container
|
||||
check.Suite(&AccessLogSuite{})
|
||||
check.Suite(&AcmeSuite{})
|
||||
check.Suite(&EtcdSuite{})
|
||||
check.Suite(&ConsulSuite{})
|
||||
check.Suite(&ConsulCatalogSuite{})
|
||||
check.Suite(&DockerComposeSuite{})
|
||||
check.Suite(&DockerSuite{})
|
||||
check.Suite(&ErrorPagesSuite{})
|
||||
check.Suite(&FileSuite{})
|
||||
check.Suite(&GRPCSuite{})
|
||||
check.Suite(&HealthCheckSuite{})
|
||||
check.Suite(&HeadersSuite{})
|
||||
check.Suite(&HostResolverSuite{})
|
||||
check.Suite(&HTTPSuite{})
|
||||
check.Suite(&HTTPSSuite{})
|
||||
check.Suite(&KeepAliveSuite{})
|
||||
check.Suite(&LogRotationSuite{})
|
||||
check.Suite(&MarathonSuite{})
|
||||
check.Suite(&MarathonSuite15{})
|
||||
check.Suite(&RateLimitSuite{})
|
||||
check.Suite(&RedisSuite{})
|
||||
check.Suite(&RestSuite{})
|
||||
check.Suite(&RetrySuite{})
|
||||
check.Suite(&SimpleSuite{})
|
||||
check.Suite(&TimeoutSuite{})
|
||||
check.Suite(&TLSClientHeadersSuite{})
|
||||
check.Suite(&TracingSuite{})
|
||||
check.Suite(&UDPSuite{})
|
||||
check.Suite(&WebsocketSuite{})
|
||||
check.Suite(&ZookeeperSuite{})
|
||||
}
|
||||
if *host {
|
||||
// tests launched from the host
|
||||
check.Suite(&K8sSuite{})
|
||||
check.Suite(&ProxyProtocolSuite{})
|
||||
check.Suite(&TCPSuite{})
|
||||
}
|
||||
check.Suite(&AccessLogSuite{})
|
||||
check.Suite(&AcmeSuite{})
|
||||
check.Suite(&ConsulCatalogSuite{})
|
||||
check.Suite(&ConsulSuite{})
|
||||
check.Suite(&DockerComposeSuite{})
|
||||
check.Suite(&DockerSuite{})
|
||||
check.Suite(&ErrorPagesSuite{})
|
||||
check.Suite(&EtcdSuite{})
|
||||
check.Suite(&FileSuite{})
|
||||
check.Suite(&GRPCSuite{})
|
||||
check.Suite(&HeadersSuite{})
|
||||
check.Suite(&HealthCheckSuite{})
|
||||
check.Suite(&HostResolverSuite{})
|
||||
check.Suite(&HTTPSSuite{})
|
||||
check.Suite(&HTTPSuite{})
|
||||
check.Suite(&K8sSuite{})
|
||||
check.Suite(&KeepAliveSuite{})
|
||||
check.Suite(&LogRotationSuite{})
|
||||
check.Suite(&MarathonSuite15{})
|
||||
check.Suite(&MarathonSuite{})
|
||||
check.Suite(&ProxyProtocolSuite{})
|
||||
check.Suite(&RateLimitSuite{})
|
||||
check.Suite(&RedisSuite{})
|
||||
check.Suite(&RestSuite{})
|
||||
check.Suite(&RetrySuite{})
|
||||
check.Suite(&SimpleSuite{})
|
||||
check.Suite(&TCPSuite{})
|
||||
check.Suite(&TimeoutSuite{})
|
||||
check.Suite(&TLSClientHeadersSuite{})
|
||||
check.Suite(&TracingSuite{})
|
||||
check.Suite(&UDPSuite{})
|
||||
check.Suite(&WebsocketSuite{})
|
||||
check.Suite(&ZookeeperSuite{})
|
||||
|
||||
check.TestingT(t)
|
||||
}
|
||||
@@ -80,36 +80,72 @@ func Test(t *testing.T) {
|
||||
var traefikBinary = "../dist/traefik"
|
||||
|
||||
type BaseSuite struct {
|
||||
composeProject *compose.Project
|
||||
composeProject *types.Project
|
||||
dockerComposeService composeapi.Service
|
||||
dockerClient *client.Client
|
||||
}
|
||||
|
||||
func (s *BaseSuite) TearDownSuite(c *check.C) {
|
||||
// shutdown and delete compose project
|
||||
if s.composeProject != nil {
|
||||
s.composeProject.Stop(c)
|
||||
if s.composeProject != nil && s.dockerComposeService != nil {
|
||||
s.composeDown(c)
|
||||
}
|
||||
}
|
||||
|
||||
// createComposeProject creates the docker compose project stored as a field in the BaseSuite.
|
||||
// This method should be called before starting and/or stopping compose services.
|
||||
func (s *BaseSuite) createComposeProject(c *check.C, name string) {
|
||||
projectName := fmt.Sprintf("integration-test-%s", name)
|
||||
projectName := fmt.Sprintf("traefik-integration-test-%s", name)
|
||||
composeFile := fmt.Sprintf("resources/compose/%s.yml", name)
|
||||
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
var err error
|
||||
s.dockerClient, err = client.NewClientWithOpts()
|
||||
c.Assert(err, checker.IsNil)
|
||||
for _, addr := range addrs {
|
||||
ip, _, err := net.ParseCIDR(addr.String())
|
||||
c.Assert(err, checker.IsNil)
|
||||
if !ip.IsLoopback() && ip.To4() != nil {
|
||||
_ = os.Setenv("DOCKER_HOST_IP", ip.String())
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
s.composeProject = compose.CreateProject(c, projectName, composeFile)
|
||||
s.dockerComposeService = compose.NewComposeService(s.dockerClient, &configfile.ConfigFile{})
|
||||
ops, err := cli.NewProjectOptions([]string{composeFile}, cli.WithName(projectName))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
s.composeProject, err = cli.ProjectFromOptions(ops)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func withConfigFile(file string) string {
|
||||
return "--configFile=" + file
|
||||
// composeUp starts the given services of the current docker compose project, if they are not already started.
|
||||
// Already running services are not affected (i.e. not stopped).
|
||||
func (s *BaseSuite) composeUp(c *check.C, services ...string) {
|
||||
c.Assert(s.composeProject, check.NotNil)
|
||||
c.Assert(s.dockerComposeService, check.NotNil)
|
||||
|
||||
// We use Create and Restart instead of Up, because the only option that actually works to control which containers
|
||||
// are started is within the RestartOptions.
|
||||
err := s.dockerComposeService.Create(context.Background(), s.composeProject, composeapi.CreateOptions{})
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = s.dockerComposeService.Restart(context.Background(), s.composeProject, composeapi.RestartOptions{Services: services})
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
// composeStop stops the given services of the current docker compose project and removes the corresponding containers.
|
||||
func (s *BaseSuite) composeStop(c *check.C, services ...string) {
|
||||
c.Assert(s.dockerComposeService, check.NotNil)
|
||||
c.Assert(s.composeProject, check.NotNil)
|
||||
|
||||
err := s.dockerComposeService.Stop(context.Background(), s.composeProject, composeapi.StopOptions{Services: services})
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = s.dockerComposeService.Remove(context.Background(), s.composeProject, composeapi.RemoveOptions{
|
||||
Services: services,
|
||||
Force: true,
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
// composeDown stops all compose project services and removes the corresponding containers.
|
||||
func (s *BaseSuite) composeDown(c *check.C) {
|
||||
c.Assert(s.dockerComposeService, check.NotNil)
|
||||
c.Assert(s.composeProject, check.NotNil)
|
||||
|
||||
err := s.dockerComposeService.Down(context.Background(), s.composeProject.Name, composeapi.DownOptions{})
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *BaseSuite) cmdTraefik(args ...string) (*exec.Cmd, *bytes.Buffer) {
|
||||
@@ -134,6 +170,7 @@ func (s *BaseSuite) traefikCmd(args ...string) (*exec.Cmd, func(*check.C)) {
|
||||
return cmd, func(c *check.C) {
|
||||
if c.Failed() || *showLog {
|
||||
s.displayLogK3S(c)
|
||||
s.displayLogCompose(c)
|
||||
s.displayTraefikLog(c, out)
|
||||
}
|
||||
}
|
||||
@@ -153,6 +190,25 @@ func (s *BaseSuite) displayLogK3S(c *check.C) {
|
||||
log.WithoutContext().Println()
|
||||
}
|
||||
|
||||
func (s *BaseSuite) displayLogCompose(c *check.C) {
|
||||
if s.dockerComposeService == nil || s.composeProject == nil {
|
||||
log.WithoutContext().Infof("%s: No docker compose logs.", c.TestName())
|
||||
return
|
||||
}
|
||||
|
||||
log.WithoutContext().Infof("%s: docker compose logs: ", c.TestName())
|
||||
|
||||
logWriter := log.WithoutContext().WriterLevel(log.GetLevel())
|
||||
logConsumer := formatter.NewLogConsumer(context.Background(), logWriter, false, true)
|
||||
|
||||
err := s.dockerComposeService.Logs(context.Background(), s.composeProject.Name, logConsumer, composeapi.LogOptions{})
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
log.WithoutContext().Println()
|
||||
log.WithoutContext().Println("################################")
|
||||
log.WithoutContext().Println()
|
||||
}
|
||||
|
||||
func (s *BaseSuite) displayTraefikLog(c *check.C, output *bytes.Buffer) {
|
||||
if output == nil || output.Len() == 0 {
|
||||
log.WithoutContext().Infof("%s: No Traefik logs.", c.TestName())
|
||||
@@ -168,6 +224,7 @@ func (s *BaseSuite) getDockerHost() string {
|
||||
// Default docker socket
|
||||
dockerHost = "unix:///var/run/docker.sock"
|
||||
}
|
||||
|
||||
return dockerHost
|
||||
}
|
||||
|
||||
@@ -192,3 +249,38 @@ func (s *BaseSuite) adaptFile(c *check.C, path string, tempObjects interface{})
|
||||
|
||||
return tmpFile.Name()
|
||||
}
|
||||
|
||||
func (s *BaseSuite) getComposeServiceIP(c *check.C, name string) string {
|
||||
filter := filters.NewArgs(
|
||||
filters.Arg("label", fmt.Sprintf("%s=%s", composeapi.ProjectLabel, s.composeProject.Name)),
|
||||
filters.Arg("label", fmt.Sprintf("%s=%s", composeapi.ServiceLabel, name)),
|
||||
)
|
||||
|
||||
containers, err := s.dockerClient.ContainerList(context.Background(), dockertypes.ContainerListOptions{Filters: filter})
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(containers, checker.HasLen, 1)
|
||||
|
||||
networkNames := s.composeProject.NetworkNames()
|
||||
c.Assert(networkNames, checker.HasLen, 1)
|
||||
|
||||
network := s.composeProject.Networks[networkNames[0]]
|
||||
return containers[0].NetworkSettings.Networks[network.Name].IPAddress
|
||||
}
|
||||
|
||||
func (s *BaseSuite) getContainerIP(c *check.C, name string) string {
|
||||
container, err := s.dockerClient.ContainerInspect(context.Background(), name)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(container.NetworkSettings.Networks, check.NotNil)
|
||||
|
||||
for _, network := range container.NetworkSettings.Networks {
|
||||
return network.IPAddress
|
||||
}
|
||||
|
||||
// Should never happen.
|
||||
c.Error("No network found")
|
||||
return ""
|
||||
}
|
||||
|
||||
func withConfigFile(file string) string {
|
||||
return "--configFile=" + file
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ type K8sSuite struct{ BaseSuite }
|
||||
|
||||
func (s *K8sSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "k8s")
|
||||
s.composeProject.Start(c)
|
||||
s.composeUp(c)
|
||||
|
||||
abs, err := filepath.Abs("./fixtures/k8s/config.skip/kubeconfig.yaml")
|
||||
c.Assert(err, checker.IsNil)
|
||||
@@ -44,7 +44,7 @@ func (s *K8sSuite) SetUpSuite(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *K8sSuite) TearDownSuite(c *check.C) {
|
||||
s.composeProject.Stop(c)
|
||||
s.composeDown(c)
|
||||
|
||||
generatedFiles := []string{
|
||||
"./fixtures/k8s/config.skip/kubeconfig.yaml",
|
||||
@@ -56,8 +56,7 @@ func (s *K8sSuite) TearDownSuite(c *check.C) {
|
||||
}
|
||||
|
||||
for _, filename := range generatedFiles {
|
||||
err := os.Remove(filename)
|
||||
if err != nil {
|
||||
if err := os.Remove(filename); err != nil {
|
||||
log.WithoutContext().Warning(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,17 +13,38 @@ import (
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
const (
|
||||
traefikTestLogFileRotated = traefikTestLogFile + ".rotated"
|
||||
traefikTestAccessLogFileRotated = traefikTestAccessLogFile + ".rotated"
|
||||
)
|
||||
|
||||
// Log rotation integration test suite.
|
||||
type LogRotationSuite struct{ BaseSuite }
|
||||
|
||||
func (s *LogRotationSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "access_log")
|
||||
s.composeProject.Start(c)
|
||||
s.composeUp(c)
|
||||
}
|
||||
|
||||
s.composeProject.Container(c, "server1")
|
||||
func (s *LogRotationSuite) TearDownSuite(c *check.C) {
|
||||
s.composeDown(c)
|
||||
|
||||
generatedFiles := []string{
|
||||
traefikTestLogFile,
|
||||
traefikTestLogFileRotated,
|
||||
traefikTestAccessLogFile,
|
||||
traefikTestAccessLogFileRotated,
|
||||
}
|
||||
|
||||
for _, filename := range generatedFiles {
|
||||
if err := os.Remove(filename); err != nil {
|
||||
log.WithoutContext().Warning(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *LogRotationSuite) TestAccessLogRotation(c *check.C) {
|
||||
@@ -36,8 +57,6 @@ func (s *LogRotationSuite) TestAccessLogRotation(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
defer os.Remove(traefikTestAccessLogFile)
|
||||
|
||||
// Verify Traefik started ok
|
||||
verifyEmptyErrorLog(c, "traefik.log")
|
||||
|
||||
@@ -52,7 +71,7 @@ func (s *LogRotationSuite) TestAccessLogRotation(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Rename access log
|
||||
err = os.Rename(traefikTestAccessLogFile, traefikTestAccessLogFile+".rotated")
|
||||
err = os.Rename(traefikTestAccessLogFile, traefikTestAccessLogFileRotated)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// in the midst of the requests, issue SIGUSR1 signal to server process
|
||||
@@ -66,8 +85,8 @@ func (s *LogRotationSuite) TestAccessLogRotation(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Verify access.log.rotated output as expected
|
||||
logAccessLogFile(c, traefikTestAccessLogFile+".rotated")
|
||||
lineCount := verifyLogLines(c, traefikTestAccessLogFile+".rotated", 0, true)
|
||||
logAccessLogFile(c, traefikTestAccessLogFileRotated)
|
||||
lineCount := verifyLogLines(c, traefikTestAccessLogFileRotated, 0, true)
|
||||
c.Assert(lineCount, checker.GreaterOrEqualThan, 1)
|
||||
|
||||
// make sure that the access log file is at least created before we do assertions on it
|
||||
@@ -95,12 +114,10 @@ func (s *LogRotationSuite) TestTraefikLogRotation(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
defer os.Remove(traefikTestAccessLogFile)
|
||||
|
||||
waitForTraefik(c, "server1")
|
||||
|
||||
// Rename traefik log
|
||||
err = os.Rename(traefikTestLogFile, traefikTestLogFile+".rotated")
|
||||
err = os.Rename(traefikTestLogFile, traefikTestLogFileRotated)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// issue SIGUSR1 signal to server process
|
||||
@@ -118,7 +135,7 @@ func (s *LogRotationSuite) TestTraefikLogRotation(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// we have at least 6 lines in traefik.log.rotated
|
||||
lineCount := verifyLogLines(c, traefikTestLogFile+".rotated", 0, false)
|
||||
lineCount := verifyLogLines(c, traefikTestLogFileRotated, 0, false)
|
||||
|
||||
// GreaterOrEqualThan used to ensure test doesn't break
|
||||
// If more log entries are output on startup
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
@@ -12,7 +11,7 @@ import (
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Marathon test suites (using libcompose).
|
||||
// Marathon test suites.
|
||||
type MarathonSuite15 struct {
|
||||
BaseSuite
|
||||
marathonURL string
|
||||
@@ -20,53 +19,15 @@ type MarathonSuite15 struct {
|
||||
|
||||
func (s *MarathonSuite15) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "marathon15")
|
||||
s.composeProject.Start(c)
|
||||
s.composeUp(c)
|
||||
|
||||
marathonIPAddr := s.composeProject.Container(c, containerNameMarathon).NetworkSettings.IPAddress
|
||||
c.Assert(marathonIPAddr, checker.Not(checker.HasLen), 0)
|
||||
s.marathonURL = "http://" + marathonIPAddr + ":8080"
|
||||
s.marathonURL = "http://" + containerNameMarathon + ":8080"
|
||||
|
||||
// Wait for Marathon readiness prior to creating the client so that we
|
||||
// don't run into the "all cluster members down" state right from the
|
||||
// start.
|
||||
err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Add entry for Mesos slave container IP address in the hosts file so
|
||||
// that Traefik can properly forward traffic.
|
||||
// This is necessary as long as we are still using the docker-compose v1
|
||||
// spec. Once we switch to v2 or higher, we can have both the test/builder
|
||||
// container and the Mesos slave container join the same custom network and
|
||||
// enjoy DNS-discoverable container host names.
|
||||
mesosSlaveIPAddr := s.composeProject.Container(c, containerNameMesosSlave).NetworkSettings.IPAddress
|
||||
c.Assert(mesosSlaveIPAddr, checker.Not(checker.HasLen), 0)
|
||||
err = s.extendDockerHostsFile(containerNameMesosSlave, mesosSlaveIPAddr)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
// extendDockerHostsFile extends the hosts file (/etc/hosts) by the given
|
||||
// host/IP address mapping if we are running inside a container.
|
||||
func (s *MarathonSuite15) extendDockerHostsFile(host, ipAddr string) error {
|
||||
const hostsFile = "/etc/hosts"
|
||||
|
||||
// Determine if the run inside a container. The most reliable way to
|
||||
// do this is to inject an indicator, which we do in terms of an
|
||||
// environment variable.
|
||||
// (See also https://groups.google.com/d/topic/docker-user/JOGE7AnJ3Gw/discussion.)
|
||||
if os.Getenv("CONTAINER") == "DOCKER" {
|
||||
// We are running inside a container -- extend the hosts file.
|
||||
file, err := os.OpenFile(hostsFile, os.O_APPEND|os.O_WRONLY, 0o600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if _, err = file.WriteString(fmt.Sprintf("%s\t%s\n", ipAddr, host)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MarathonSuite15) TestConfigurationUpdate(c *check.C) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
@@ -12,12 +11,9 @@ import (
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
const (
|
||||
containerNameMesosSlave = "mesos-slave"
|
||||
containerNameMarathon = "marathon"
|
||||
)
|
||||
const containerNameMarathon = "marathon"
|
||||
|
||||
// Marathon test suites (using libcompose).
|
||||
// Marathon test suites.
|
||||
type MarathonSuite struct {
|
||||
BaseSuite
|
||||
marathonURL string
|
||||
@@ -25,53 +21,15 @@ type MarathonSuite struct {
|
||||
|
||||
func (s *MarathonSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "marathon")
|
||||
s.composeProject.Start(c)
|
||||
s.composeUp(c)
|
||||
|
||||
marathonIPAddr := s.composeProject.Container(c, containerNameMarathon).NetworkSettings.IPAddress
|
||||
c.Assert(marathonIPAddr, checker.Not(checker.HasLen), 0)
|
||||
s.marathonURL = "http://" + marathonIPAddr + ":8080"
|
||||
s.marathonURL = "http://" + containerNameMarathon + ":8080"
|
||||
|
||||
// Wait for Marathon readiness prior to creating the client so that we
|
||||
// don't run into the "all cluster members down" state right from the
|
||||
// start.
|
||||
err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Add entry for Mesos slave container IP address in the hosts file so
|
||||
// that Traefik can properly forward traffic.
|
||||
// This is necessary as long as we are still using the docker-compose v1
|
||||
// spec. Once we switch to v2 or higher, we can have both the test/builder
|
||||
// container and the Mesos slave container join the same custom network and
|
||||
// enjoy DNS-discoverable container host names.
|
||||
mesosSlaveIPAddr := s.composeProject.Container(c, containerNameMesosSlave).NetworkSettings.IPAddress
|
||||
c.Assert(mesosSlaveIPAddr, checker.Not(checker.HasLen), 0)
|
||||
err = s.extendDockerHostsFile(containerNameMesosSlave, mesosSlaveIPAddr)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
// extendDockerHostsFile extends the hosts file (/etc/hosts) by the given
|
||||
// host/IP address mapping if we are running inside a container.
|
||||
func (s *MarathonSuite) extendDockerHostsFile(host, ipAddr string) error {
|
||||
const hostsFile = "/etc/hosts"
|
||||
|
||||
// Determine if the run inside a container. The most reliable way to
|
||||
// do this is to inject an indicator, which we do in terms of an
|
||||
// environment variable.
|
||||
// (See also https://groups.google.com/d/topic/docker-user/JOGE7AnJ3Gw/discussion.)
|
||||
if os.Getenv("CONTAINER") == "DOCKER" {
|
||||
// We are running inside a container -- extend the hosts file.
|
||||
file, err := os.OpenFile(hostsFile, os.O_APPEND|os.O_WRONLY, 0o600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if _, err = file.WriteString(fmt.Sprintf("%s\t%s\n", ipAddr, host)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deployApplication(c *check.C, client marathon.Marathon, application *marathon.Application) {
|
||||
|
||||
@@ -10,22 +10,27 @@ import (
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type ProxyProtocolSuite struct{ BaseSuite }
|
||||
type ProxyProtocolSuite struct {
|
||||
BaseSuite
|
||||
gatewayIP string
|
||||
haproxyIP string
|
||||
whoamiIP string
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "proxy-protocol")
|
||||
s.composeProject.Start(c)
|
||||
s.composeUp(c)
|
||||
|
||||
s.gatewayIP = s.getContainerIP(c, "traefik")
|
||||
s.haproxyIP = s.getComposeServiceIP(c, "haproxy")
|
||||
s.whoamiIP = s.getComposeServiceIP(c, "whoami")
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolTrusted(c *check.C) {
|
||||
gatewayIP := s.composeProject.Container(c, "haproxy").NetworkSettings.Gateway
|
||||
haproxyIP := s.composeProject.Container(c, "haproxy").NetworkSettings.IPAddress
|
||||
whoamiIP := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress
|
||||
|
||||
file := s.adaptFile(c, "fixtures/proxy-protocol/with.toml", struct {
|
||||
HaproxyIP string
|
||||
WhoamiIP string
|
||||
}{HaproxyIP: haproxyIP, WhoamiIP: whoamiIP})
|
||||
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
@@ -34,21 +39,17 @@ func (s *ProxyProtocolSuite) TestProxyProtocolTrusted(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://"+haproxyIP+"/whoami", 1*time.Second,
|
||||
err = try.GetRequest("http://"+s.haproxyIP+"/whoami", 1*time.Second,
|
||||
try.StatusCodeIs(http.StatusOK),
|
||||
try.BodyContains("X-Forwarded-For: "+gatewayIP))
|
||||
try.BodyContains("X-Forwarded-For: "+s.gatewayIP))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolV2Trusted(c *check.C) {
|
||||
gatewayIP := s.composeProject.Container(c, "haproxy").NetworkSettings.Gateway
|
||||
haproxyIP := s.composeProject.Container(c, "haproxy").NetworkSettings.IPAddress
|
||||
whoamiIP := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress
|
||||
|
||||
file := s.adaptFile(c, "fixtures/proxy-protocol/with.toml", struct {
|
||||
HaproxyIP string
|
||||
WhoamiIP string
|
||||
}{HaproxyIP: haproxyIP, WhoamiIP: whoamiIP})
|
||||
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
@@ -57,20 +58,17 @@ func (s *ProxyProtocolSuite) TestProxyProtocolV2Trusted(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://"+haproxyIP+":81/whoami", 1*time.Second,
|
||||
err = try.GetRequest("http://"+s.haproxyIP+":81/whoami", 1*time.Second,
|
||||
try.StatusCodeIs(http.StatusOK),
|
||||
try.BodyContains("X-Forwarded-For: "+gatewayIP))
|
||||
try.BodyContains("X-Forwarded-For: "+s.gatewayIP))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolNotTrusted(c *check.C) {
|
||||
haproxyIP := s.composeProject.Container(c, "haproxy").NetworkSettings.IPAddress
|
||||
whoamiIP := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress
|
||||
|
||||
file := s.adaptFile(c, "fixtures/proxy-protocol/without.toml", struct {
|
||||
HaproxyIP string
|
||||
WhoamiIP string
|
||||
}{HaproxyIP: haproxyIP, WhoamiIP: whoamiIP})
|
||||
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
@@ -79,20 +77,17 @@ func (s *ProxyProtocolSuite) TestProxyProtocolNotTrusted(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://"+haproxyIP+"/whoami", 1*time.Second,
|
||||
err = try.GetRequest("http://"+s.haproxyIP+"/whoami", 1*time.Second,
|
||||
try.StatusCodeIs(http.StatusOK),
|
||||
try.BodyContains("X-Forwarded-For: "+haproxyIP))
|
||||
try.BodyContains("X-Forwarded-For: "+s.haproxyIP))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolV2NotTrusted(c *check.C) {
|
||||
haproxyIP := s.composeProject.Container(c, "haproxy").NetworkSettings.IPAddress
|
||||
whoamiIP := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress
|
||||
|
||||
file := s.adaptFile(c, "fixtures/proxy-protocol/without.toml", struct {
|
||||
HaproxyIP string
|
||||
WhoamiIP string
|
||||
}{HaproxyIP: haproxyIP, WhoamiIP: whoamiIP})
|
||||
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
@@ -101,8 +96,8 @@ func (s *ProxyProtocolSuite) TestProxyProtocolV2NotTrusted(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://"+haproxyIP+":81/whoami", 1*time.Second,
|
||||
err = try.GetRequest("http://"+s.haproxyIP+":81/whoami", 1*time.Second,
|
||||
try.StatusCodeIs(http.StatusOK),
|
||||
try.BodyContains("X-Forwarded-For: "+haproxyIP))
|
||||
try.BodyContains("X-Forwarded-For: "+s.haproxyIP))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ type RateLimitSuite struct {
|
||||
|
||||
func (s *RateLimitSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "ratelimit")
|
||||
s.composeProject.Start(c)
|
||||
s.composeUp(c)
|
||||
|
||||
s.ServerIP = s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
|
||||
s.ServerIP = s.getComposeServiceIP(c, "whoami1")
|
||||
}
|
||||
|
||||
func (s *RateLimitSuite) TestSimpleConfiguration(c *check.C) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package integration
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -18,20 +19,22 @@ import (
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Redis test suites (using libcompose).
|
||||
// Redis test suites.
|
||||
type RedisSuite struct {
|
||||
BaseSuite
|
||||
kvClient store.Store
|
||||
kvClient store.Store
|
||||
redisAddr string
|
||||
}
|
||||
|
||||
func (s *RedisSuite) setupStore(c *check.C) {
|
||||
s.createComposeProject(c, "redis")
|
||||
s.composeProject.Start(c)
|
||||
s.composeUp(c)
|
||||
|
||||
s.redisAddr = net.JoinHostPort(s.getComposeServiceIP(c, "redis"), "6379")
|
||||
redis.Register()
|
||||
kv, err := valkeyrie.NewStore(
|
||||
store.REDIS,
|
||||
[]string{s.composeProject.Container(c, "redis").NetworkSettings.IPAddress + ":6379"},
|
||||
[]string{s.redisAddr},
|
||||
&store.Config{
|
||||
ConnectionTimeout: 10 * time.Second,
|
||||
},
|
||||
@@ -46,20 +49,10 @@ func (s *RedisSuite) setupStore(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *RedisSuite) TearDownTest(c *check.C) {
|
||||
// shutdown and delete compose project
|
||||
if s.composeProject != nil {
|
||||
s.composeProject.Stop(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RedisSuite) TearDownSuite(c *check.C) {}
|
||||
|
||||
func (s *RedisSuite) TestSimpleConfiguration(c *check.C) {
|
||||
s.setupStore(c)
|
||||
|
||||
address := s.composeProject.Container(c, "redis").NetworkSettings.IPAddress + ":6379"
|
||||
file := s.adaptFile(c, "fixtures/redis/simple.toml", struct{ RedisAddress string }{address})
|
||||
file := s.adaptFile(c, "fixtures/redis/simple.toml", struct{ RedisAddress string }{s.redisAddr})
|
||||
defer os.Remove(file)
|
||||
|
||||
data := map[string]string{
|
||||
|
||||
@@ -1,77 +1,91 @@
|
||||
server0:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.rt-server0.entryPoints=web
|
||||
- traefik.http.routers.rt-server0.rule=Path("/test")
|
||||
- traefik.http.services.service1.loadbalancer.server.port=80
|
||||
server1:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.rt-server1.entryPoints=web
|
||||
- traefik.http.routers.rt-server1.rule=Host("frontend1.docker.local")
|
||||
- traefik.http.routers.rt-server1.service=service1
|
||||
- traefik.http.services.service1.loadbalancer.server.port=80
|
||||
server2:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.rt-server2.entryPoints=web
|
||||
- traefik.http.routers.rt-server2.rule=Host("frontend2.docker.local")
|
||||
- traefik.http.services.service2.loadbalancer.server.port=80
|
||||
server3:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.rt-server3.entryPoints=web
|
||||
- traefik.http.routers.rt-server3.rule=Host("frontend2.docker.local")
|
||||
- traefik.http.services.service2.loadbalancer.server.port=80
|
||||
authFrontend:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.rt-authFrontend.entryPoints=httpFrontendAuth
|
||||
- traefik.http.routers.rt-authFrontend.rule=Host("frontend.auth.docker.local")
|
||||
- traefik.http.routers.rt-authFrontend.middlewares=basicauth
|
||||
- traefik.http.middlewares.basicauth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/
|
||||
- traefik.http.services.service3.loadbalancer.server.port=80
|
||||
digestAuthMiddleware:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.rt-digestAuthMiddleware.entryPoints=digestAuth
|
||||
- traefik.http.routers.rt-digestAuthMiddleware.rule=Host("entrypoint.digest.auth.docker.local")
|
||||
- traefik.http.routers.rt-digestAuthMiddleware.middlewares=digestauth
|
||||
- traefik.http.middlewares.digestauth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05, test2:traefik:518845800f9e2bfb1f1f740ec24f074e
|
||||
- traefik.http.services.service3.loadbalancer.server.port=80
|
||||
frontendRedirect:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.rt-frontendRedirect.entryPoints=frontendRedirect
|
||||
- traefik.http.routers.rt-frontendRedirect.rule=Path("/test")
|
||||
- traefik.http.routers.rt-frontendRedirect.middlewares=redirecthttp
|
||||
- traefik.http.middlewares.redirecthttp.redirectScheme.scheme=http
|
||||
- traefik.http.middlewares.redirecthttp.redirectScheme.port=8000
|
||||
- traefik.http.services.service3.loadbalancer.server.port=80
|
||||
rateLimit:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.rt-rateLimit.entryPoints=httpRateLimit
|
||||
- traefik.http.routers.rt-rateLimit.rule=Host("ratelimit.docker.local")
|
||||
- traefik.http.routers.rt-rateLimit.middlewares=rate
|
||||
- traefik.http.middlewares.rate.ratelimit
|
||||
- traefik.http.middlewares.rate.ratelimit.average=1
|
||||
- traefik.http.middlewares.rate.ratelimit.burst=2
|
||||
- traefik.http.services.service3.loadbalancer.server.port=80
|
||||
frontendWhitelist:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.rt-frontendWhitelist.entryPoints=web
|
||||
- traefik.http.routers.rt-frontendWhitelist.rule=Host("frontend.whitelist.docker.local")
|
||||
- traefik.http.routers.rt-frontendWhitelist.middlewares=wl
|
||||
- traefik.http.middlewares.wl.ipwhitelist.sourcerange=8.8.8.8/32
|
||||
- traefik.http.services.service3.loadbalancer.server.port=80
|
||||
version: "3.8"
|
||||
services:
|
||||
server0:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.rt-server0.entryPoints: web
|
||||
traefik.http.routers.rt-server0.rule: Path(`/test`)
|
||||
traefik.http.services.service1.loadbalancer.server.port: 80
|
||||
|
||||
server1:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.rt-server1.entryPoints: web
|
||||
traefik.http.routers.rt-server1.rule: Host(`frontend1.docker.local`)
|
||||
traefik.http.routers.rt-server1.service: service1
|
||||
traefik.http.services.service1.loadbalancer.server.port: 80
|
||||
|
||||
server2:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.rt-server2.entryPoints: web
|
||||
traefik.http.routers.rt-server2.rule: Host(`frontend2.docker.local`)
|
||||
traefik.http.services.service2.loadbalancer.server.port: 80
|
||||
|
||||
server3:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.rt-server3.entryPoints: web
|
||||
traefik.http.routers.rt-server3.rule: Host(`frontend2.docker.local`)
|
||||
traefik.http.services.service2.loadbalancer.server.port: 80
|
||||
|
||||
authFrontend:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.rt-authFrontend.entryPoints: httpFrontendAuth
|
||||
traefik.http.routers.rt-authFrontend.rule: Host(`frontend.auth.docker.local`)
|
||||
traefik.http.routers.rt-authFrontend.middlewares: basicauth
|
||||
traefik.http.middlewares.basicauth.basicauth.users: test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/
|
||||
traefik.http.services.service3.loadbalancer.server.port: 80
|
||||
|
||||
digestAuthMiddleware:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.rt-digestAuthMiddleware.entryPoints: digestAuth
|
||||
traefik.http.routers.rt-digestAuthMiddleware.rule: Host(`entrypoint.digest.auth.docker.local`)
|
||||
traefik.http.routers.rt-digestAuthMiddleware.middlewares: digestauth
|
||||
traefik.http.middlewares.digestauth.digestauth.users: test:traefik:a2688e031edb4be6a3797f3882655c05, test2:traefik:518845800f9e2bfb1f1f740ec24f074e
|
||||
traefik.http.services.service3.loadbalancer.server.port: 80
|
||||
|
||||
frontendRedirect:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.rt-frontendRedirect.entryPoints: frontendRedirect
|
||||
traefik.http.routers.rt-frontendRedirect.rule: Path(`/test`)
|
||||
traefik.http.routers.rt-frontendRedirect.middlewares: redirecthttp
|
||||
traefik.http.middlewares.redirecthttp.redirectScheme.scheme: http
|
||||
traefik.http.middlewares.redirecthttp.redirectScheme.port: 8000
|
||||
traefik.http.services.service3.loadbalancer.server.port: 80
|
||||
|
||||
rateLimit:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.rt-rateLimit.entryPoints: httpRateLimit
|
||||
traefik.http.routers.rt-rateLimit.rule: Host(`ratelimit.docker.local`)
|
||||
traefik.http.routers.rt-rateLimit.middlewares: rate
|
||||
traefik.http.middlewares.rate.ratelimit.average: 1
|
||||
traefik.http.middlewares.rate.ratelimit.burst: 2
|
||||
traefik.http.services.service3.loadbalancer.server.port: 80
|
||||
|
||||
frontendWhitelist:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.rt-frontendWhitelist.entryPoints: web
|
||||
traefik.http.routers.rt-frontendWhitelist.rule: Host(`frontend.whitelist.docker.local`)
|
||||
traefik.http.routers.rt-frontendWhitelist.middlewares: wl
|
||||
traefik.http.middlewares.wl.ipwhitelist.sourcerange: 8.8.8.8/32
|
||||
traefik.http.services.service3.loadbalancer.server.port: 80
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.router1.rule=PathPrefix("/whoami")
|
||||
- traefik.http.routers.router2.rule=PathPrefix("/whoami2")
|
||||
version: "3.8"
|
||||
services:
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.router1.rule: PathPrefix(`/whoami`)
|
||||
traefik.http.routers.router2.rule: PathPrefix(`/whoami2`)
|
||||
|
||||
whoami2:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=false
|
||||
whoami2:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: false
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
consul:
|
||||
image: consul:1.6
|
||||
ports:
|
||||
- "8500:8500"
|
||||
version: "3.8"
|
||||
services:
|
||||
consul:
|
||||
image: consul:1.6
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,32 +1,37 @@
|
||||
consul:
|
||||
image: consul:1.6.2
|
||||
ports:
|
||||
- 8500:8500
|
||||
command: "agent -server -bootstrap -ui -client 0.0.0.0 -hcl 'connect { enabled = true }'"
|
||||
consul-agent:
|
||||
image: consul:1.6.2
|
||||
ports:
|
||||
- 8501:8500
|
||||
command: "agent -retry-join consul -client 0.0.0.0"
|
||||
links:
|
||||
- consul
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
hostname: whoami1
|
||||
whoami2:
|
||||
image: traefik/whoami
|
||||
hostname: whoami2
|
||||
whoami3:
|
||||
image: traefik/whoami
|
||||
hostname: whoami3
|
||||
whoamitcp:
|
||||
image: traefik/whoamitcp
|
||||
hostname: whoamitcp
|
||||
connect:
|
||||
image: hashicorpnomad/uuid-api:v5
|
||||
links:
|
||||
- consul
|
||||
environment:
|
||||
PORT: 443
|
||||
BIND: 0.0.0.0
|
||||
CONSUL_HTTP_ADDR: http://consul:8500
|
||||
version: "3.8"
|
||||
services:
|
||||
consul:
|
||||
image: consul:1.6.2
|
||||
command: agent -server -bootstrap -ui -client 0.0.0.0 -hcl 'connect { enabled = true }'
|
||||
|
||||
consul-agent:
|
||||
image: consul:1.6.2
|
||||
command: agent -retry-join consul -client 0.0.0.0
|
||||
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
hostname: whoami1
|
||||
|
||||
whoami2:
|
||||
image: traefik/whoami
|
||||
hostname: whoami2
|
||||
|
||||
whoami3:
|
||||
image: traefik/whoami
|
||||
hostname: whoami3
|
||||
|
||||
whoamitcp:
|
||||
image: traefik/whoamitcp
|
||||
hostname: whoamitcp
|
||||
|
||||
connect:
|
||||
image: hashicorpnomad/uuid-api:v5
|
||||
environment:
|
||||
PORT: 443
|
||||
BIND: 0.0.0.0
|
||||
CONSUL_HTTP_ADDR: http://consul:8500
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
43
integration/resources/compose/docker.yml
Normal file
43
integration/resources/compose/docker.yml
Normal 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
|
||||
@@ -1,4 +1,12 @@
|
||||
nginx1:
|
||||
image: nginx:1.13.8-alpine
|
||||
nginx2:
|
||||
image: nginx:1.13.8-alpine
|
||||
version: "3.8"
|
||||
services:
|
||||
nginx1:
|
||||
image: nginx:1.13.8-alpine
|
||||
|
||||
nginx2:
|
||||
image: nginx:1.13.8-alpine
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
etcd:
|
||||
image: quay.io/coreos/etcd:v3.3.18
|
||||
command: etcd --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://0.0.0.0:2380
|
||||
ports:
|
||||
- "2379:2379"
|
||||
version: "3.8"
|
||||
services:
|
||||
etcd:
|
||||
image: quay.io/coreos/etcd:v3.3.18
|
||||
command: etcd --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://0.0.0.0:2380
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
ports:
|
||||
- "8881:80"
|
||||
whoami2:
|
||||
image: traefik/whoami
|
||||
ports:
|
||||
- "8882:80"
|
||||
whoami3:
|
||||
image: traefik/whoami
|
||||
ports:
|
||||
- "8883:80"
|
||||
whoami4:
|
||||
image: traefik/whoami
|
||||
ports:
|
||||
- "8884:80"
|
||||
whoami5:
|
||||
image: traefik/whoami
|
||||
ports:
|
||||
- "8885:80"
|
||||
version: "3.8"
|
||||
services:
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
|
||||
whoami2:
|
||||
image: traefik/whoami
|
||||
|
||||
whoami3:
|
||||
image: traefik/whoami
|
||||
|
||||
whoami4:
|
||||
image: traefik/whoami
|
||||
|
||||
whoami5:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
version: "3.8"
|
||||
services:
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
|
||||
whoami2:
|
||||
image: traefik/whoami
|
||||
whoami2:
|
||||
image: traefik/whoami
|
||||
|
||||
whoami3:
|
||||
image: traefik/whoami
|
||||
whoami3:
|
||||
image: traefik/whoami
|
||||
|
||||
whoami4:
|
||||
image: traefik/whoami
|
||||
whoami4:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
server1:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.services.service1.loadbalancer.server.port=80
|
||||
- traefik.http.routers.router1.rule=Host("github.com")
|
||||
version: "3.8"
|
||||
services:
|
||||
server1:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.services.service1.loadbalancer.server.port: 80
|
||||
traefik.http.routers.router1.rule: Host(`github.com`)
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
server:
|
||||
image: rancher/k3s:v1.18.20-k3s1
|
||||
command: server --disable-agent --no-deploy coredns --no-deploy servicelb --no-deploy traefik --no-deploy local-storage --no-deploy metrics-server --log /output/k3s.log
|
||||
environment:
|
||||
- K3S_CLUSTER_SECRET=somethingtotallyrandom
|
||||
- K3S_KUBECONFIG_OUTPUT=/output/kubeconfig.yaml
|
||||
- K3S_KUBECONFIG_MODE=666
|
||||
volumes:
|
||||
- ../../fixtures/k8s/config.skip:/output
|
||||
- ../../fixtures/k8s:/var/lib/rancher/k3s/server/manifests
|
||||
ports:
|
||||
- 6443:6443
|
||||
version: "3.8"
|
||||
services:
|
||||
server:
|
||||
image: rancher/k3s:v1.18.20-k3s1
|
||||
command: server --disable-agent --no-deploy coredns --no-deploy servicelb --no-deploy traefik --no-deploy local-storage --no-deploy metrics-server --log /output/k3s.log --bind-address=server --tls-san=server
|
||||
environment:
|
||||
K3S_CLUSTER_SECRET: somethingtotallyrandom
|
||||
K3S_KUBECONFIG_OUTPUT: /output/kubeconfig.yaml
|
||||
K3S_KUBECONFIG_MODE: 666
|
||||
volumes:
|
||||
- ./fixtures/k8s/config.skip:/output
|
||||
- ./fixtures/k8s:/var/lib/rancher/k3s/server/manifests
|
||||
|
||||
node:
|
||||
image: rancher/k3s:v1.18.20-k3s1
|
||||
privileged: true
|
||||
links:
|
||||
- server
|
||||
environment:
|
||||
- K3S_URL=https://server:6443
|
||||
- K3S_CLUSTER_SECRET=somethingtotallyrandom
|
||||
node:
|
||||
image: rancher/k3s:v1.18.20-k3s1
|
||||
privileged: true
|
||||
environment:
|
||||
K3S_URL: https://server:6443
|
||||
K3S_CLUSTER_SECRET: somethingtotallyrandom
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,54 +1,60 @@
|
||||
zookeeper:
|
||||
image: zookeeper:3.4.10
|
||||
version: "3.8"
|
||||
services:
|
||||
zookeeper:
|
||||
image: zookeeper:3.4.10
|
||||
|
||||
mesos-master:
|
||||
links:
|
||||
- zookeeper
|
||||
image: mesosphere/mesos-master:1.0.1-2.0.93.ubuntu1404
|
||||
# Uncomment published ports for interactive debugging.
|
||||
# ports:
|
||||
# - "5050:5050"
|
||||
environment:
|
||||
- MESOS_HOSTNAME=mesos-master
|
||||
- MESOS_CLUSTER=local
|
||||
- MESOS_REGISTRY=in_memory
|
||||
- MESOS_LOG_DIR=/var/log
|
||||
- MESOS_WORK_DIR=/var/lib/mesos
|
||||
- MESOS_ZK=zk://zookeeper:2181/mesos
|
||||
mesos-master:
|
||||
image: mesosphere/mesos-master:1.0.1-2.0.93.ubuntu1404
|
||||
# Uncomment published ports for interactive debugging.
|
||||
# ports:
|
||||
# - "5050:5050"
|
||||
environment:
|
||||
MESOS_HOSTNAME: mesos-master
|
||||
MESOS_CLUSTER: local
|
||||
MESOS_REGISTRY: in_memory
|
||||
MESOS_LOG_DIR: /var/log
|
||||
MESOS_WORK_DIR: /var/lib/mesos
|
||||
MESOS_ZK: zk://zookeeper:2181/mesos
|
||||
|
||||
mesos-slave:
|
||||
links:
|
||||
- zookeeper
|
||||
- mesos-master
|
||||
image: mesosphere/mesos-slave-dind:0.3.0_mesos-1.0.1_docker-1.10.3_ubuntu-14.04.5
|
||||
privileged: true
|
||||
# Uncomment published ports for interactive debugging.
|
||||
# ports:
|
||||
# - "5051:5051"
|
||||
environment:
|
||||
- MESOS_HOSTNAME=mesos-slave
|
||||
- MESOS_CONTAINERIZERS=docker,mesos
|
||||
- MESOS_ISOLATOR=cgroups/cpu,cgroups/mem
|
||||
- MESOS_LOG_DIR=/var/log
|
||||
- MESOS_MASTER=zk://zookeeper:2181/mesos
|
||||
- MESOS_PORT=5051
|
||||
- MESOS_WORK_DIR=/var/lib/mesos
|
||||
- MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins
|
||||
- MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs
|
||||
- MESOS_DOCKER_STOP_TIMEOUT=60secs
|
||||
- MESOS_RESOURCES=cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]
|
||||
mesos-slave:
|
||||
image: docker:dind
|
||||
privileged: true
|
||||
# Uncomment published ports for interactive debugging.
|
||||
# ports:
|
||||
# - "5051:5051"
|
||||
# docker version in mesosphere/mesos-slave-dind:0.3.0_mesos-1.0.1_docker-1.10.3_ubuntu-14.04.5 is too old and can't
|
||||
# pull images on new kernels.
|
||||
command:
|
||||
- "/bin/sh"
|
||||
- "-c"
|
||||
- "(/usr/local/bin/dockerd-entrypoint.sh &); sleep 10; set -x; \
|
||||
docker -H unix:///var/run/docker.sock run -d --net=host --privileged \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v /cgroup:/cgroup -v /sys:/sys \
|
||||
-v /usr/local/bin/docker:/usr/local/bin/docker \
|
||||
-e MESOS_HOSTNAME=mesos-slave \
|
||||
-e MESOS_CONTAINERIZERS=docker,mesos \
|
||||
-e MESOS_ISOLATOR=cgroups/cpu,cgroups/mem \
|
||||
-e MESOS_LOG_DIR=/var/log \
|
||||
-e MESOS_MASTER=zk://zookeeper:2181/mesos \
|
||||
-e MESOS_PORT=5051 \
|
||||
-e MESOS_WORK_DIR=/var/lib/mesos \
|
||||
-e MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins \
|
||||
-e MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs \
|
||||
-e MESOS_DOCKER_STOP_TIMEOUT=60secs \
|
||||
-e MESOS_RESOURCES='cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]' \
|
||||
mesosphere/mesos-slave:1.0.3; sleep 600"
|
||||
|
||||
marathon:
|
||||
links:
|
||||
- zookeeper
|
||||
- mesos-master
|
||||
- mesos-slave
|
||||
image: mesosphere/marathon:v1.3.12
|
||||
# Uncomment published ports for interactive debugging.
|
||||
# ports:
|
||||
# - "8080:8080"
|
||||
extra_hosts:
|
||||
- "mesos-slave:172.17.0.1"
|
||||
environment:
|
||||
- MARATHON_ZK=zk://zookeeper:2181/marathon
|
||||
- MARATHON_MASTER=zk://zookeeper:2181/mesos
|
||||
marathon:
|
||||
image: mesosphere/marathon:v1.3.12
|
||||
# Uncomment published ports for interactive debugging.
|
||||
# ports:
|
||||
# - "8080:8080"
|
||||
environment:
|
||||
MARATHON_ZK: zk://zookeeper:2181/marathon
|
||||
MARATHON_MASTER: zk://zookeeper:2181/mesos
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,55 +1,51 @@
|
||||
zookeeper:
|
||||
image: zookeeper:3.4.10
|
||||
version: "3.8"
|
||||
services:
|
||||
zookeeper:
|
||||
image: zookeeper:3.4.10
|
||||
|
||||
mesos-master:
|
||||
links:
|
||||
- zookeeper
|
||||
image: mesosphere/mesos-master:1.4.1
|
||||
# Uncomment published ports for interactive debugging.
|
||||
# ports:
|
||||
# - "5050:5050"
|
||||
environment:
|
||||
- MESOS_HOSTNAME=mesos-master
|
||||
- MESOS_CLUSTER=local
|
||||
- MESOS_REGISTRY=in_memory
|
||||
- MESOS_LOG_DIR=/var/log
|
||||
- MESOS_WORK_DIR=/var/lib/mesos
|
||||
- MESOS_ZK=zk://zookeeper:2181/mesos
|
||||
mesos-master:
|
||||
image: mesosphere/mesos-master:1.4.1
|
||||
# Uncomment published ports for interactive debugging.
|
||||
# ports:
|
||||
# - "5050:5050"
|
||||
environment:
|
||||
MESOS_HOSTNAME: mesos-master
|
||||
MESOS_CLUSTER: local
|
||||
MESOS_REGISTRY: in_memory
|
||||
MESOS_LOG_DIR: /var/log
|
||||
MESOS_WORK_DIR: /var/lib/mesos
|
||||
MESOS_ZK: zk://zookeeper:2181/mesos
|
||||
|
||||
mesos-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
|
||||
privileged: true
|
||||
# Uncomment published ports for interactive debugging.
|
||||
# ports:
|
||||
# - "5051:5051"
|
||||
environment:
|
||||
- MESOS_HOSTNAME=mesos-slave
|
||||
- MESOS_CONTAINERIZERS=docker,mesos
|
||||
- MESOS_ISOLATOR=cgroups/cpu,cgroups/mem
|
||||
- MESOS_LOG_DIR=/var/log
|
||||
- MESOS_MASTER=zk://zookeeper:2181/mesos
|
||||
- MESOS_PORT=5051
|
||||
- MESOS_WORK_DIR=/var/lib/mesos
|
||||
- MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins
|
||||
- MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs
|
||||
- MESOS_DOCKER_STOP_TIMEOUT=60secs
|
||||
- MESOS_RESOURCES=cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]
|
||||
- MESOS_SYSTEMD_ENABLE_SUPPORT=false
|
||||
mesos-slave:
|
||||
image: mesosphere/mesos-slave-dind:0.4.0_mesos-1.4.1_docker-17.05.0_ubuntu-16.04.3
|
||||
privileged: true
|
||||
# Uncomment published ports for interactive debugging.
|
||||
# ports:
|
||||
# - "5051:5051"
|
||||
environment:
|
||||
MESOS_HOSTNAME: mesos-slave
|
||||
MESOS_CONTAINERIZERS: docker,mesos
|
||||
MESOS_ISOLATOR: cgroups/cpu,cgroups/mem
|
||||
MESOS_LOG_DIR: /var/log
|
||||
MESOS_MASTER: zk://zookeeper:2181/mesos
|
||||
MESOS_PORT: 5051
|
||||
MESOS_WORK_DIR: /var/lib/mesos
|
||||
MESOS_EXECUTOR_REGISTRATION_TIMEOUT: 5mins
|
||||
MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD: 90secs
|
||||
MESOS_DOCKER_STOP_TIMEOUT: 60secs
|
||||
MESOS_RESOURCES: cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]
|
||||
MESOS_SYSTEMD_ENABLE_SUPPORT: false
|
||||
|
||||
marathon:
|
||||
links:
|
||||
- zookeeper
|
||||
- mesos-master
|
||||
- mesos-slave
|
||||
image: mesosphere/marathon:v1.5.9
|
||||
# Uncomment published ports for interactive debugging.
|
||||
# ports:
|
||||
# - "8080:8080"
|
||||
extra_hosts:
|
||||
- "mesos-slave:172.17.0.1"
|
||||
environment:
|
||||
- MARATHON_ZK=zk://zookeeper:2181/marathon
|
||||
- MARATHON_MASTER=zk://zookeeper:2181/mesos
|
||||
marathon:
|
||||
image: mesosphere/marathon:v1.5.9
|
||||
# Uncomment published ports for interactive debugging.
|
||||
# ports:
|
||||
# - "8080:8080"
|
||||
environment:
|
||||
MARATHON_ZK: zk://zookeeper:2181/marathon
|
||||
MARATHON_MASTER: zk://zookeeper:2181/mesos
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.http.Routers.RouterMini.Rule=PathPrefix("/whoami")
|
||||
- traefik.enable=true
|
||||
|
||||
version: "3.8"
|
||||
services:
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.http.Routers.RouterMini.Rule: PathPrefix(`/whoami`)
|
||||
traefik.enable: true
|
||||
deploy:
|
||||
replicas: 2
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
pebble:
|
||||
image: letsencrypt/pebble:v2.3.1
|
||||
command: pebble --dnsserver ${DOCKER_HOST_IP}:5053
|
||||
ports:
|
||||
- 14000:14000
|
||||
environment:
|
||||
# https://github.com/letsencrypt/pebble#testing-at-full-speed
|
||||
- PEBBLE_VA_NOSLEEP=1
|
||||
# https://github.com/letsencrypt/pebble#invalid-anti-replay-nonce-errors
|
||||
- PEBBLE_WFE_NONCEREJECT=0
|
||||
version: "3.8"
|
||||
services:
|
||||
pebble:
|
||||
image: letsencrypt/pebble:v2.3.1
|
||||
command: pebble --dnsserver traefik:5053
|
||||
environment:
|
||||
# https://github.com/letsencrypt/pebble#testing-at-full-speed
|
||||
PEBBLE_VA_NOSLEEP: 1
|
||||
# https://github.com/letsencrypt/pebble#invalid-anti-replay-nonce-errors
|
||||
PEBBLE_WFE_NONCEREJECT: 0
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
haproxy:
|
||||
image: haproxy:2.2
|
||||
volumes:
|
||||
- ../haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
|
||||
version: "3.8"
|
||||
services:
|
||||
haproxy:
|
||||
image: haproxy:2.2
|
||||
volumes:
|
||||
- ./resources/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
|
||||
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,2 +1,9 @@
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
version: "3.8"
|
||||
services:
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
redis:
|
||||
image: redis:5.0
|
||||
ports:
|
||||
- "6379:6379"
|
||||
version: "3.8"
|
||||
services:
|
||||
redis:
|
||||
image: redis:5.0
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,2 +1,9 @@
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
version: "3.8"
|
||||
services:
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
ports:
|
||||
- "8881:80"
|
||||
version: "3.8"
|
||||
services:
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,2 +1,9 @@
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
version: "3.8"
|
||||
services:
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
whoami2:
|
||||
image: traefik/whoami
|
||||
version: "3.8"
|
||||
services:
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
|
||||
whoami2:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,38 +1,39 @@
|
||||
whoami-a:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-a -certFile /certs/whoami-a.crt -keyFile /certs/whoami-a.key
|
||||
volumes:
|
||||
- ../../fixtures/tcp:/certs
|
||||
ports:
|
||||
- "8081:8080"
|
||||
version: "3.8"
|
||||
services:
|
||||
whoami-a:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-a -certFile /certs/whoami-a.crt -keyFile /certs/whoami-a.key
|
||||
volumes:
|
||||
- ./fixtures/tcp:/certs
|
||||
|
||||
whoami-b:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-b -certFile /certs/whoami-b.crt -keyFile /certs/whoami-b.key
|
||||
volumes:
|
||||
- ../../fixtures/tcp:/certs
|
||||
ports:
|
||||
- "8082:8080"
|
||||
whoami-b:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-b -certFile /certs/whoami-b.crt -keyFile /certs/whoami-b.key
|
||||
volumes:
|
||||
- ./fixtures/tcp:/certs
|
||||
|
||||
whoami-no-cert:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-no-cert
|
||||
ports:
|
||||
- "8083:8080"
|
||||
whoami-ab:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-ab -certFile /certs/whoami-b.crt -keyFile /certs/whoami-b.key
|
||||
volumes:
|
||||
- ./fixtures/tcp:/certs
|
||||
|
||||
whoami-no-tls:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-no-tls
|
||||
ports:
|
||||
- "8084:8080"
|
||||
whoami-no-cert:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-no-cert
|
||||
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
ports:
|
||||
- "8085:80"
|
||||
whoami-no-tls:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-no-tls
|
||||
|
||||
whoami-banner:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-banner --banner
|
||||
ports:
|
||||
- "8086:8080"
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
whoami-banner:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-banner --banner
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
timeoutEndpoint:
|
||||
image: yaman/timeout
|
||||
environment:
|
||||
- PROTO=http
|
||||
- PORT=9000
|
||||
ports:
|
||||
- "9000:9000"
|
||||
version: "3.8"
|
||||
services:
|
||||
timeoutEndpoint:
|
||||
image: yaman/timeout
|
||||
environment:
|
||||
PROTO: http
|
||||
PORT: 9000
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
whoami:
|
||||
version: "3.8"
|
||||
services:
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.http.routers.route1.rule=PathPrefix(`/foo`)
|
||||
- traefik.http.routers.route1.middlewares=passtls
|
||||
- traefik.http.routers.route1.tls=true
|
||||
- traefik.http.middlewares.passtls.passtlsclientcert.pem=true
|
||||
traefik.http.routers.route1.rule: PathPrefix(`/foo`)
|
||||
traefik.http.routers.route1.middlewares: passtls
|
||||
traefik.http.routers.route1.tls: true
|
||||
traefik.http.middlewares.passtls.passtlsclientcert.pem: true
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
zipkin:
|
||||
image: openzipkin/zipkin:2.16.2
|
||||
environment:
|
||||
STORAGE_TYPE: mem
|
||||
JAVA_OPTS: -Dlogging.level.zipkin=DEBUG
|
||||
ports:
|
||||
- 9411:9411
|
||||
jaeger:
|
||||
image: jaegertracing/all-in-one:1.14
|
||||
environment:
|
||||
COLLECTOR_ZIPKIN_HTTP_PORT: 9411
|
||||
ports:
|
||||
- "5775:5775/udp"
|
||||
- "6831:6831/udp"
|
||||
- "6832:6832/udp"
|
||||
- "5778:5778"
|
||||
- "16686:16686"
|
||||
- "14268:14268"
|
||||
- "9411:9411"
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
version: "3.8"
|
||||
services:
|
||||
zipkin:
|
||||
image: openzipkin/zipkin:2.16.2
|
||||
environment:
|
||||
STORAGE_TYPE: mem
|
||||
JAVA_OPTS: -Dlogging.level.zipkin=DEBUG
|
||||
|
||||
jaeger:
|
||||
image: jaegertracing/all-in-one:1.14
|
||||
environment:
|
||||
COLLECTOR_ZIPKIN_HTTP_PORT: 9411
|
||||
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
whoami-a:
|
||||
image: traefik/whoamiudp:latest
|
||||
command: -name whoami-a
|
||||
version: "3.8"
|
||||
services:
|
||||
whoami-a:
|
||||
image: traefik/whoamiudp:latest
|
||||
command: -name whoami-a
|
||||
|
||||
whoami-b:
|
||||
image: traefik/whoamiudp:latest
|
||||
command: -name whoami-b
|
||||
whoami-b:
|
||||
image: traefik/whoamiudp:latest
|
||||
command: -name whoami-b
|
||||
|
||||
whoami-c:
|
||||
image: traefik/whoamiudp:latest
|
||||
command: -name whoami-c
|
||||
whoami-c:
|
||||
image: traefik/whoamiudp:latest
|
||||
command: -name whoami-c
|
||||
|
||||
whoami-d:
|
||||
image: traefik/whoami
|
||||
whoami-d:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,34 +1,41 @@
|
||||
noOverrideWhitelist:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.rt1.rule=Host("no.override.whitelist.docker.local")
|
||||
- traefik.http.routers.rt1.middlewares=wl1
|
||||
- traefik.http.middlewares.wl1.ipwhiteList.sourceRange=8.8.8.8
|
||||
version: "3.8"
|
||||
services:
|
||||
noOverrideWhitelist:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.rt1.rule: Host(`no.override.whitelist.docker.local`)
|
||||
traefik.http.routers.rt1.middlewares: wl1
|
||||
traefik.http.middlewares.wl1.ipwhiteList.sourceRange: 8.8.8.8
|
||||
|
||||
overrideIPStrategyRemoteAddrWhitelist:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.rt2.rule=Host("override.remoteaddr.whitelist.docker.local")
|
||||
- traefik.http.routers.rt2.middlewares=wl2
|
||||
- traefik.http.middlewares.wl2.ipwhitelist.sourceRange=8.8.8.8
|
||||
- traefik.http.middlewares.wl2.ipwhitelist.ipStrategy=true
|
||||
overrideIPStrategyRemoteAddrWhitelist:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.rt2.rule: Host(`override.remoteaddr.whitelist.docker.local`)
|
||||
traefik.http.routers.rt2.middlewares: wl2
|
||||
traefik.http.middlewares.wl2.ipwhitelist.sourceRange: 8.8.8.8
|
||||
traefik.http.middlewares.wl2.ipwhitelist.ipStrategy: true
|
||||
|
||||
overrideIPStrategyDepthWhitelist:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.rt3.rule=Host("override.depth.whitelist.docker.local")
|
||||
- traefik.http.routers.rt3.middlewares=wl3
|
||||
- traefik.http.middlewares.wl3.ipwhitelist.sourceRange=8.8.8.8
|
||||
- traefik.http.middlewares.wl3.ipwhitelist.ipStrategy.depth=3
|
||||
overrideIPStrategyDepthWhitelist:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.rt3.rule: Host(`override.depth.whitelist.docker.local`)
|
||||
traefik.http.routers.rt3.middlewares: wl3
|
||||
traefik.http.middlewares.wl3.ipwhitelist.sourceRange: 8.8.8.8
|
||||
traefik.http.middlewares.wl3.ipwhitelist.ipStrategy.depth: 3
|
||||
|
||||
overrideIPStrategyExcludedIPsWhitelist:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.rt4.rule=Host("override.excludedips.whitelist.docker.local")
|
||||
- traefik.http.routers.rt4.middlewares=wl4
|
||||
- traefik.http.middlewares.wl4.ipwhitelist.sourceRange=8.8.8.8
|
||||
- traefik.http.middlewares.wl4.ipwhitelist.ipStrategy.excludedIPs=10.0.0.1,10.0.0.2
|
||||
overrideIPStrategyExcludedIPsWhitelist:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.rt4.rule: Host(`override.excludedips.whitelist.docker.local`)
|
||||
traefik.http.routers.rt4.middlewares: wl4
|
||||
traefik.http.middlewares.wl4.ipwhitelist.sourceRange: 8.8.8.8
|
||||
traefik.http.middlewares.wl4.ipwhitelist.ipStrategy.excludedIPs: 10.0.0.1,10.0.0.2
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
zookeeper:
|
||||
image: zookeeper:3.5
|
||||
ports:
|
||||
- "2181:2181"
|
||||
version: "3.8"
|
||||
services:
|
||||
zookeeper:
|
||||
image: zookeeper:3.5
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
||||
@@ -23,8 +23,8 @@ frontend TestServerTestV2
|
||||
|
||||
backend TestServerNodes
|
||||
mode tcp
|
||||
server TestServer01 172.17.0.1:8000 send-proxy
|
||||
server TestServer01 traefik:8000 send-proxy
|
||||
|
||||
backend TestServerNodesV2
|
||||
mode tcp
|
||||
server TestServer01 172.17.0.1:8000 send-proxy-v2
|
||||
server TestServer01 traefik:8000 send-proxy-v2
|
||||
|
||||
@@ -3,6 +3,7 @@ package integration
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
@@ -14,12 +15,16 @@ import (
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type RestSuite struct{ BaseSuite }
|
||||
type RestSuite struct {
|
||||
BaseSuite
|
||||
whoamiAddr string
|
||||
}
|
||||
|
||||
func (s *RestSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "rest")
|
||||
s.composeUp(c)
|
||||
|
||||
s.composeProject.Start(c)
|
||||
s.whoamiAddr = net.JoinHostPort(s.getComposeServiceIP(c, "whoami1"), "80")
|
||||
}
|
||||
|
||||
func (s *RestSuite) TestSimpleConfigurationInsecure(c *check.C) {
|
||||
@@ -60,7 +65,7 @@ func (s *RestSuite) TestSimpleConfigurationInsecure(c *check.C) {
|
||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "http://" + s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80",
|
||||
URL: "http://" + s.whoamiAddr,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -86,7 +91,7 @@ func (s *RestSuite) TestSimpleConfigurationInsecure(c *check.C) {
|
||||
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||
Servers: []dynamic.TCPServer{
|
||||
{
|
||||
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80",
|
||||
Address: s.whoamiAddr,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -164,7 +169,7 @@ func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
|
||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "http://" + s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80",
|
||||
URL: "http://" + s.whoamiAddr,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -190,7 +195,7 @@ func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
|
||||
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||
Servers: []dynamic.TCPServer{
|
||||
{
|
||||
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80",
|
||||
Address: s.whoamiAddr,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -213,10 +218,10 @@ func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1000*time.Millisecond, try.BodyContains(test.ruleMatch))
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains(test.ruleMatch))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,18 +11,20 @@ import (
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type RetrySuite struct{ BaseSuite }
|
||||
type RetrySuite struct {
|
||||
BaseSuite
|
||||
whoamiIP string
|
||||
}
|
||||
|
||||
func (s *RetrySuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "retry")
|
||||
s.composeProject.Start(c)
|
||||
s.composeUp(c)
|
||||
|
||||
s.whoamiIP = s.getComposeServiceIP(c, "whoami")
|
||||
}
|
||||
|
||||
func (s *RetrySuite) TestRetry(c *check.C) {
|
||||
whoamiEndpoint := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress
|
||||
file := s.adaptFile(c, "fixtures/retry/simple.toml", struct {
|
||||
WhoamiEndpoint string
|
||||
}{whoamiEndpoint})
|
||||
file := s.adaptFile(c, "fixtures/retry/simple.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
@@ -44,10 +46,7 @@ func (s *RetrySuite) TestRetry(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *RetrySuite) TestRetryBackoff(c *check.C) {
|
||||
whoamiEndpoint := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress
|
||||
file := s.adaptFile(c, "fixtures/retry/backoff.toml", struct {
|
||||
WhoamiEndpoint string
|
||||
}{whoamiEndpoint})
|
||||
file := s.adaptFile(c, "fixtures/retry/backoff.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
@@ -72,10 +71,7 @@ func (s *RetrySuite) TestRetryBackoff(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *RetrySuite) TestRetryWebsocket(c *check.C) {
|
||||
whoamiEndpoint := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress
|
||||
file := s.adaptFile(c, "fixtures/retry/simple.toml", struct {
|
||||
WhoamiEndpoint string
|
||||
}{whoamiEndpoint})
|
||||
file := s.adaptFile(c, "fixtures/retry/simple.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user