1
0
mirror of https://github.com/containous/traefik.git synced 2025-09-08 13:44:22 +03:00

Compare commits

...

951 Commits

Author SHA1 Message Date
Emile Vauge
5a57515c6b Merge pull request #1318 from containous/prepare-release-v1.2.0
Prepare release v1.2.0
2017-03-21 10:37:24 +01:00
Emile Vauge
3490b9d35d Prepare release v1.2.0
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-03-20 23:26:52 +01:00
Emile Vauge
dd0a20a668 Merge pull request #1304 from Yshayy/filter-non-running-tasks
Add filter on task status in addition to desired status (Docker Provider - swarm)
2017-03-20 19:28:10 +01:00
Emile Vauge
d13cef6ff6 sub-tests + Fatalf/Errorf
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-03-20 17:54:09 +01:00
Emile Vauge
9f149977d6 Add Docker task list test
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-03-20 12:36:49 +01:00
yshay
e65544f414 Add check on task status in addition to desired status 2017-03-20 12:12:53 +01:00
Sebastian
8010758b29 Docker: Added warning if network could not be found (#1310)
* Added warning if network could not be found

* Removed regex import from master

* Corrected wrong function call
2017-03-19 18:40:09 +01:00
Regner Blok-Andersen
75d92c6967 Abort Kubernetes Ingress update if Kubernetes API call fails (#1295)
* Abort Kubernetes Ingress update if Kubernetes API call fails

Currently if a Kubernetes API call fails we potentially remove a working service from Traefik. This changes it so if a Kubernetes API call fails we abort out of the ingress update and use the current working config. Github issue: #1240

Also added a test to cover when requested resources (services and endpoints) that the user has specified don’t exist.

* Specifically capturing the tc range as documented here: https://blog.golang.org/subtests

* Updating service names in the mock data to be more clear

* Updated expected data to match what currently happens in the loadIngress

* Adding a blank Servers to the expected output so we compare against that instead of nil.

* Replacing the JSON test output with spew for the TestMissingResources test to help ensure we have useful output incase of failures

* Adding a temporary fix to the GetEndoints mocked function so we can override the return value for if the endpoints exist.

After the 1.2 release the use of properExists should be removed and the GetEndpoints function should return false for the second value indicating the endpoint doesn’t exist. However at this time that would break a lot of the tests.

* Adding quick TODO line about removing the properExists property

* Link to issue 1307 re: properExists flag.
2017-03-17 16:34:34 +01:00
Emile Vauge
0f67cc7818 Merge pull request #1291 from containous/small-fixes
Small fixes
2017-03-15 18:04:41 +01:00
Emile Vauge
f428a752a5 Refactor k8s client config
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-03-15 15:24:01 +01:00
Emile Vauge
3fe3784b6c Removed unused log
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-03-15 15:24:01 +01:00
Emile Vauge
e4d63331cf Fix default config in generic Mesos provider
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-03-15 15:24:01 +01:00
Vincent Demeester
8ae521db64 Merge pull request #1278 from akanto/update-oxy
Update Oxy, fix for #1199
2017-03-15 15:22:35 +01:00
Timo Reimann
24fde36b20 Revert "Pass context to ListReleases when checking for new versions."
This reverts commit 07db6a2df1.
2017-03-15 11:01:47 +01:00
Timo Reimann
7c55a4fd0c Update github.com/containous/oxy only. 2017-03-15 11:01:43 +01:00
Timo Reimann
7b1c0a97f7 Reset glide files to versions from upstream/v1.2. 2017-03-15 10:41:10 +01:00
Attila Kanto
8392846bd4 Update vulcand and pin deps in glide.yaml 2017-03-15 06:59:34 +01:00
Timo Reimann
07db6a2df1 Pass context to ListReleases when checking for new versions.
Required by go-github update.
2017-03-15 06:59:34 +01:00
Emile Vauge
cc9bb4b1f8 Merge pull request #1285 from timoreimann/rename-healthcheck-url-to-path
Rename health check URL parameter to path.
2017-03-14 23:39:24 +01:00
Timo Reimann
de91b99639 Rename health check URL parameter to path.
Also improve documentation.
2017-03-14 01:53:24 +01:00
Timo Reimann
c582ea5ff0 Merge pull request #1258 from matevzmihalic/fix/metrics
Fix metrics registering
2017-03-11 07:37:24 +01:00
Matevz Mihalic
b5de37e722 Fix metrics registering 2017-03-10 21:26:34 +01:00
Emile Vauge
ee9032f0bf Merge pull request #1209 from owen/ecs-chunk-taskarns
Chunk taskArns into groups of 100
2017-03-09 15:55:42 +01:00
Owen Marshall
11a68ce7f9 Chunk taskArns into groups of 100
If the ECS cluster has > 100 tasks, passing them to
ecs.DescribeTasksRequest() will result in the AWS API returning
errors.

This patch breaks them into chunks of at most 100, and calls
DescribeTasks for each chunk.

We also return early in case ListTasks returns no values; this
prevents DescribeTasks from throwing HTTP errors.
2017-03-07 20:52:33 -05:00
Emile Vauge
0dbac0af0d Merge pull request #1239 from timoreimann/update-maxidleconnsperhost-default-in-docs
Update DefaultMaxIdleConnsPerHost default in docs.
2017-03-07 15:20:07 +01:00
Timo Reimann
9541ee4cf6 Docs: Update default value for DefaultMaxIdleConnsPerHost. 2017-03-06 21:26:33 +01:00
Emile Vauge
2958a67ce5 Merge pull request #1225 from dtomcej/fix-670
Update WSS/WS Proto [Fixes #670]
2017-03-02 23:51:48 +01:00
dtomcej
eebbf6ebbb update oxy hash 2017-03-02 14:59:19 -07:00
Vincent Demeester
0133178b84 Merge pull request #1219 from SantoDE/feature-bump-gorancher
Bump go-rancher version
2017-03-02 13:13:44 +01:00
Manuel Laufenberg
9af5ba34ae Bump go-rancher version 2017-03-02 09:39:43 +01:00
Emile Vauge
9b24e13418 Merge pull request #1204 from containous/prepare-release-v1.2.0-rc2
Prepare release v1.2.0 rc2
2017-03-01 13:54:55 +01:00
Emile Vauge
8fd880a3f1 Prepare release v1.2.0-rc2
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-03-01 13:19:08 +01:00
Emile Vauge
89700666b9 Merge pull request #1198 from jangie/revert-1080
Revert "Ensure that we don't add balancees with no health check runs …
2017-02-27 21:59:47 +01:00
Bruce Lee
343e0547df Revert "Ensure that we don't add balancees with no health check runs if there is a health check defined on it"
This reverts commit ad12a7264e.
2017-02-27 13:56:53 -05:00
Emile Vauge
a7d5e6ce4f Merge pull request #1167 from christopherobin/bugfix-docker
Fix docker issues with global and dead tasks
2017-02-23 10:30:20 +01:00
Christophe Robin
d342ae68d8 Add task parser unit test for docker provider 2017-02-22 23:16:33 +01:00
Christophe Robin
a87cd3fc2c Fix docker issues with global and dead tasks 2017-02-22 23:16:33 +01:00
Emile Vauge
28a4d65b38 Merge pull request #1173 from SantoDE/feature-rancher-improvements-1125
Small fixes and improvments
2017-02-22 23:15:23 +01:00
Manuel Laufenberg
253dbfab94 Small fixes and improvments 2017-02-22 16:30:54 +01:00
Emile Vauge
727f79f432 Merge pull request #1141 from containous/fix-stats-race
Fix stats race condition
2017-02-22 16:29:48 +01:00
Emile Vauge
6a56eb480b Fix stats race condition
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-22 15:02:26 +01:00
Emile Vauge
155d0900bb Merge pull request #1143 from lpetre/ecs_nil_checks
Better ECS error checking
2017-02-22 15:01:42 +01:00
Luke Petre
a59a165cd7 Try harder to query all the possible ec2 instances, and filter on instance state / lack of IP address 2017-02-22 13:38:11 +01:00
Emile Vauge
5d540be81b Merge pull request #1132 from Juliens/healthcheck
Healthcheck tests and doc
2017-02-21 14:03:13 +01:00
Julien Salleyron
05f2449d84 Wrong tests docker images 2017-02-21 11:09:19 +01:00
Julien Salleyron
44fa364cdd Add doc 2017-02-21 11:09:19 +01:00
Julien Salleyron
04a25b841f Add some integration test 2017-02-21 11:09:19 +01:00
Julien Salleyron
efbbff671c Add healthcheck interval 2017-02-21 11:09:19 +01:00
Emile Vauge
27c2c721ed Merge pull request #1137 from rickard-von-essen/ecs-docs
ECS: Docs - info about cred. resolution and required access policies
2017-02-09 12:08:26 +01:00
Rickard von Essen
abe16d4480 ECS: Docs - info about cred. resolution and required access policies
Added information about how AWS credentials are resolved and which
access rights is needed the Traefik ECS provider.
2017-02-08 20:19:39 +01:00
Emile Vauge
445bb8189b Merge pull request #1128 from containous/fix-travis-deploy
Fix travis deploy
2017-02-06 21:36:30 +01:00
Emile Vauge
ff7dfdcd43 Fix travis deploy
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-06 21:32:57 +01:00
Emile Vauge
5e662c9dbd Merge pull request #1126 from containous/prepare-release-v1.2.0-rc1
Prepare release v1.2.0 rc1
2017-02-06 20:52:30 +01:00
Emile Vauge
78d60b3651 Changelog for v1.2.0-rc1
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-06 19:54:28 +01:00
Emile Vauge
7a7992a639 Add v1.2 codename
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-06 18:51:56 +01:00
Emile Vauge
39f8f6868a Merge pull request #1124 from containous/fix-git-rmpr
Fix checkout initial before calling rmpr
2017-02-06 18:49:24 +01:00
Emile Vauge
556915cab6 Fix checkout initial before calling rmpr
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-06 17:50:11 +01:00
Emile Vauge
bff654b843 Merge pull request #1120 from SantoDE/feature-rancher-integration
Feature rancher integration
2017-02-06 17:49:38 +01:00
Manuel Laufenberg
3a875e2954 add default config
lint files
2017-02-06 17:03:43 +01:00
Manuel Laufenberg
bdb63ac785 add watch function 2017-02-06 17:03:43 +01:00
Manuel Laufenberg
9a5dc54f85 add some unit tests
fmt & lint
2017-02-06 17:03:41 +01:00
Manuel Laufenberg
48524a58ff fix all containers - no matter of pagination
fmt & lint
2017-02-06 17:03:38 +01:00
Manuel Laufenberg
38bd49b97e add dependency, start provider and fetch data
add tons of labels

Provide - WIP

add rancher data over rancher types

first version of direct fetch - pagination still an issue
2017-02-06 17:02:53 +01:00
Emile Vauge
28054a0be3 Merge pull request #1061 from WTFKr0/replace_underscores_in_url
Replace underscores to dash in autogenerated urls (docker provider)
2017-02-06 16:32:28 +01:00
WTFKr0
250a0863f6 Tab Lint
Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
2017-02-06 15:38:18 +01:00
WTFKr0
b1764a6864 Adapt test to new urls
Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
2017-02-06 15:38:18 +01:00
WTFKr0
41f8f0113b Replace underscores to dash in autogenerated urls (docker provider)
Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
2017-02-06 15:38:18 +01:00
Emile Vauge
db63e84a9f Merge pull request #1033 from foleymic/feature-1024
Support sticky sessions under SWARM Mode. #1024
2017-02-06 15:23:47 +01:00
Mike Foley
e0a4c58081 Added service name to dockerData struct.
In Swarm mode with with Docker Swarm’s Load Balancer disabled (traefik.backend.loadbalancer.swarm=false)
service name will be the name of the docker service and name will be the container task name
(e.g. whoami0.1).  When generating backend and fronted rules, we will use service name instead of name if a
rule is not provided.

Initialize dockerData.ServiceName to dockerData.Name to support non-swarm mode.
2017-02-06 14:44:25 +01:00
Mike Foley
d2b47a5681 Support sticky sessions under SWARM Mode.
SWARM Mode has it's own built in Load balancer, so if we want to leverage sticky sessions,
 or if we would just prefer to bypass it and go directly to the containers (aka tasks), via
	--label traefik.backend.disable.swarm.loadbalancer=true
 then we need to let Traefik know about the underlying tasks and register them as
 services within it's backend.
2017-02-06 14:44:25 +01:00
Emile Vauge
106e5c1f92 Merge pull request #1109 from containous/fix-git-rpr-upstream
Fix git rpr
2017-02-06 14:40:45 +01:00
Emile Vauge
c00a9fae0c Add rmpr command
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-06 14:02:23 +01:00
Emile Vauge
087bbd2e3e Add cpr command
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-06 14:02:23 +01:00
Emile Vauge
e16f2bb23d Fix git rpr
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-06 14:02:23 +01:00
Emile Vauge
8d0bacf146 Merge pull request #1098 from ddunkin/fix-k8s-example-ui
Fix k8s example UI port.
2017-02-06 11:06:32 +01:00
Dave Dunkin
354f69b2f6 Fix k8s example UI port.
Port was out of sync from 495cba591f.
2017-02-06 10:18:16 +01:00
Emile Vauge
39e6b16069 Merge pull request #918 from Juliens/httpchk
(WIP) feat: HealthCheck
2017-02-06 10:15:37 +01:00
Julien Salleyron
b30272d896 fix lint 2017-02-06 09:36:30 +01:00
Julien Salleyron
755822bf14 fix after review 2017-02-06 09:36:30 +01:00
Julien Salleyron
99ffc26d40 One goroutine for each backend + fix typo 2017-02-06 09:36:30 +01:00
Julien Salleyron
4a8f032304 feat: timeout on check 2017-02-06 09:36:30 +01:00
Julien Salleyron
a0b775a7c0 Lint on healthcheck 2017-02-06 09:36:30 +01:00
Julien Salleyron
0ab0bdf818 feat: HealthCheck 2017-02-06 09:36:30 +01:00
Emile Vauge
fce32ea5c7 Merge pull request #1088 from lpetre/amazon_ecs_provider
Add an ECS provider
2017-02-05 21:01:17 +01:00
Luke Petre
8d3c77a0b9 Add an ECS provider 2017-02-05 18:09:30 +00:00
Emile Vauge
00de73bdfc Merge pull request #1119 from containous/fix-glide-go-units
Fix glide go units
2017-02-05 18:59:32 +01:00
Emile Vauge
96197af3f1 Add glide hash validation
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-05 17:24:14 +01:00
Emile Vauge
dacde21c27 Fix glide.yml go-units
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-05 17:24:13 +01:00
Emile Vauge
0d3b2ed230 Merge pull request #1115 from StefanScherer/check-file-permission-unix-only
Skip file permission check on Windows
2017-02-05 13:49:00 +01:00
Stefan Scherer
fa4226c742 Skip file permission check on Windows 2017-02-05 10:30:56 +01:00
Vincent Demeester
7cb4c42772 Merge pull request #1116 from vdemeester/carry-watchdog
Carry #818 —  Add systemd watchdog feature
2017-02-05 10:29:50 +01:00
Guilhem Lettron
99f251451e Update glide
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2017-02-05 10:05:32 +01:00
Guilhem Lettron
d5f9a80b6c Remove web watchdog 2017-02-04 19:06:56 +01:00
Guilhem Lettron
d324040adc Add systemd watchdog feature 2017-02-04 19:06:24 +01:00
Emile Vauge
da5eba17d8 Merge pull request #1113 from StefanScherer/fix-docker-api-version-for-windows
Fix Docker API version for Windows
2017-02-04 17:26:05 +01:00
Stefan Scherer
434596b103 Fix Docker API version for Windows
Signed-off-by: Stefan Scherer <scherer_stefan@icloud.com>
2017-02-04 16:44:10 +01:00
Emile Vauge
71a185c70e Merge pull request #1090 from diegooliveira/IP-Per-Task-Fix
Fix marathon provider
2017-02-04 16:41:49 +01:00
Diego de Oliveira
cbbb5f4ccb Fix marathon provider
The IP-Per-Task PR introduced a bug using the marathon application
port mapping. This port should be used only in the proxy server, the
downstream connection should be always made with the task port.

    This commit fix the regression and adds a unit test to prevent new
problems in this setup.
2017-02-04 16:05:35 +01:00
Vincent Demeester
89ec25f718 Merge pull request #1084 from JamesKyburz/feature/fix-gzip-for-websockets
update NYTimes/gziphandler fixes #1059
2017-02-04 16:02:39 +01:00
Emile Vauge
e5b688214c Merge branch 'master' into feature/fix-gzip-for-websockets 2017-02-04 15:18:22 +01:00
Brian Akins
225dbcce0a Allow setting circuitbreaker expression via Kubernetes annotation (#1056) 2017-02-03 17:47:48 +01:00
Vincent Demeester
b22dc213e8 Merge pull request #1080 from jangie/only-add-marathon-balancees-if-any-healthcheck-results
Ensure that we don't add balancees with no health check runs if there is a health check defined on it
2017-02-03 15:55:23 +01:00
Bruce Lee
ad12a7264e Ensure that we don't add balancees with no health check runs if there is a health check defined on it
Change test behavior
2017-02-03 08:45:15 -05:00
Vincent Demeester
29059b77a8 Merge pull request #1078 from geoffgarside/release-build-bsd
Add FreeBSD & OpenBSD to crossbinary
2017-02-03 13:50:39 +01:00
Geoff Garside
cdaa64a4b2 Add OpenBSD to script/crossbinary 2017-02-03 12:02:20 +01:00
Geoff Garside
bc4296729f Add FreeBSD to script/crossbinary 2017-02-03 12:02:20 +01:00
Vincent Demeester
3a3630f3ef Merge pull request #1102 from bamarni/patch-3
[doc] typo fixes for kubernetes user guide
2017-02-03 12:01:49 +01:00
Bilal Amarni
93ce747205 [doc] typo fixes for kubernetes user guide 2017-02-03 11:08:38 +01:00
Vincent Demeester
1493a4c815 Merge pull request #1105 from containous/merge-v1.1.2-master
Merge v1.1.2 master
2017-02-03 10:44:28 +01:00
Emile Vauge
54be6beaab Lint files
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-03 09:55:47 +01:00
Emile Vauge
e9fc9fdf12 Prepare release v1.1.2 2017-02-03 09:47:23 +01:00
Emile Vauge
ba4670eddc Fix duplicate acme certificates 2017-02-03 09:47:23 +01:00
Emile Vauge
5a67d0ac84 Fix panic in k8s loadIngresses
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-03 09:46:27 +01:00
Emile Vauge
be362f0d9f Add Operation with recover 2017-02-03 09:46:27 +01:00
Emile Vauge
a394e6a3e3 Manage acme cert in infinit channels
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-03 09:45:39 +01:00
Emile Vauge
1a5f1977c4 Fix safe panic 2017-02-03 09:41:41 +01:00
Emile Vauge
feee8ad72e Fix redirect regex
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-03 09:41:41 +01:00
Timo Reimann
c9e78c4f4a Fix docker version specifier (#1108)
* Fix Docker version specifier.

- The download URL[1] does not contain a leading 'v'.
- The major version is 1.

[1] https://github.com/docker/docker/releases/tag/v1.10.3

* Drop -S and and -f in build.Dockerfile curl commands.

- `-f` (`--fail`) turns HTTP error response codes into a non-zero exit
  code, making curl fail early and properly. While the documentation
  mentions that there is supposed to be no output, we do see an error
  message.
- `-S` (`--show-error`) is only meaningful when used together with `-s`
  (`--silent`). We do not want to go silent but see the progress bar
  though.
2017-02-03 09:15:56 +01:00
Emile Vauge
d0e2349dfd Merge pull request #1016 from bamarni/issue-1008
Set a NopCloser request body with retry middleware
2017-02-02 19:13:43 +01:00
James Kyburz
d516cbfe6c update NYTimes/gziphandler fixes #1059 2017-02-02 17:56:07 +01:00
Bilal Amarni
86fd5b4c97 Set a NopCloser request body with retry middleware
As the http client always closes the request body,
this makes sure the request can be retried if needed.

Fixes #1008
2017-02-02 17:24:49 +01:00
Emile Vauge
1131a972cd Merge pull request #1103 from containous/fix-travis-script-again-again
add sh before script in deploy...
2017-02-02 17:24:01 +01:00
Emile Vauge
2048f77178 add sh before script in deploy...
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-02 16:19:09 +01:00
Emile Vauge
a70c6f25ea Merge pull request #1068 from bakins/kubernetes-loadbalancer-annotations
Allow setting load balancer method and sticky using service annotations
2017-02-02 16:15:50 +01:00
Brian Akins
490427f94d Allow setting load balancer method and sticky using service annotations 2017-02-02 14:03:39 +00:00
Emile Vauge
7cc91a8244 Merge pull request #1101 from containous/fix-travis-script-again
add skip_cleanup in deploy
2017-02-02 14:35:27 +01:00
Emile Vauge
4f951a242b add skip_cleanup in deploy
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-02 13:59:28 +01:00
Matevz Mihalic
c095fc1eab Fix metrics for multiple entry points (#1071) 2017-02-02 12:34:00 +01:00
Emile Vauge
c1182377db Fix travis script (#1067)
* Fix travis script

Signed-off-by: Emile Vauge <emile@vauge.com>

* how do i pronounce this damn project

Signed-off-by: Emile Vauge <emile@vauge.com>

* Remove unstable Docker 1.13 tests

Signed-off-by: Emile Vauge <emile@vauge.com>
2017-02-02 10:58:42 +01:00
Nicolas Pouillard
02473328e7 Update comment to reflect the code (#1087) 2017-01-31 15:28:40 +01:00
Emile Vauge
2b00cdf330 Fix k8s example (#1062)
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-01-30 13:04:32 +01:00
Emile Vauge
18cf49755e Merge pull request #1066 from timoreimann/patch-1
Add missing fmt verb specifier in k8s provider.
2017-01-26 14:50:50 +01:00
Timo Reimann
3a7de0be5c Add missing fmt verb specifier in k8s provider. 2017-01-26 11:05:13 +01:00
Emile Vauge
a1b610ee03 Merge pull request #1063 from containous/add-git-rpr
Add git rpr command
2017-01-24 21:30:27 +01:00
Emile Vauge
4d99b84e5b Add git rpr command
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-01-24 18:38:53 +01:00
Emile Vauge
e20d13c44e Merge pull request #1041 from twelvelabs/patch-1
Update user guide for upcoming `docker stack deploy`
2017-01-24 16:45:11 +01:00
Skip Baney
18e9064d25 Add link to GH issue for docker stack deploy 2017-01-24 14:49:28 +01:00
Emile Vauge
fad3038df2 Merge pull request #843 from guilhem/travis_deploy
Use deployment primitives from travis
2017-01-24 13:01:19 +01:00
Guilhem Lettron
8e4c4f8407 Use deployment primitives from travis 2017-01-23 15:52:28 +01:00
Vincent Demeester
68bd24d065 Don't run go test on .glide cache folder
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2017-01-23 15:43:24 +01:00
Adam Stankiewicz
d15a17b634 Allow for wildcards in k8s ingress host, fixes #792 (#1029) 2017-01-20 14:16:05 +01:00
Alberto
fa1090b6eb Improving instrumentation. (#1042) 2017-01-17 18:14:13 +01:00
Manuel Laufenberg
483ef486af Merge pull request #1022 from enxebre/prometheus
Add commit prometheus middleware v1.
2017-01-16 15:40:06 +01:00
enxebre
175659a3dd Support for Metrics and Prometheus. 2017-01-16 15:00:16 +01:00
Emile Vauge
dd85cbca39 Merge pull request #1009 from bamarni/acme-perms
check permissions on acme.json during startup
2017-01-12 15:41:56 +01:00
Bilal Amarni
22b97b7214 check permissions on acme.json during startup
Follow-up from #639. At the moment people that were affected
by this security issue would still be vulnerable even after upgrading.

This patch makes sure permissions are also checked for already existing
files.

Signed-off-by: Bilal Amarni <bilal.amarni@gmail.com>
2017-01-12 12:14:35 +01:00
Csaba Palfi
db68dd3bc1 Fix docs build and add missing benchmarks page (#1017)
* fix mkdocs theme dependency - mkdocs/mkdocs#201

* add missing benchmarks page
2017-01-09 15:12:11 +01:00
Vincent Demeester
85b9c19871 Merge pull request #1023 from syfonseq/fix-acme-http-only-entrypoint
Don't fetch ACME certificates for frontends using non-TLS entrypoints (#989)
2017-01-06 21:16:25 +01:00
Matthieu Martin
2bfc237e53 Don't fetch ACME certificates for frontends using non-TLS entrypoints 2017-01-06 17:06:48 +01:00
Diego de Oliveira
d74ea22d7d IP-per-task: (#841)
Support IP per task with marathon/mesos
2017-01-06 16:26:50 +01:00
Thomas Recloux
8004132a3a Merge pull request #1018 from dtomcej/fix-672
Return Proper Non-ACME certificate - Fixes Issue 672
2017-01-05 09:37:02 +01:00
Daniel Tomcej
a6f4183cde Add regex for wildcard certs
fix spacing
2017-01-04 14:32:44 -07:00
Bilal Amarni
51e9f3ede2 instruct to flatten dependencies with glide 2017-01-01 19:23:35 +01:00
j0hnsmith
bfc7b3d183 Add multiple values for one rule to docs 2016-12-30 22:29:37 +01:00
Vincent Demeester
8a348423ae Import order as goimports does
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-12-30 19:04:02 +01:00
Bilal Amarni
e4952cd145 [doc] few tweaks on the basics page 2016-12-30 16:49:13 +01:00
Guilhem Lettron
5b0bf5d150 See the right go report badge
look like a copypasta error
2016-12-30 15:20:15 +01:00
Thomas Recloux
79180dc021 Merge pull request #975 from trecloux/integration-test-acme
Add ACME/Let’s Encrypt integration tests
2016-12-22 10:46:15 +01:00
Thomas Recloux
599c95e5f6 Add ACME/Let’s Encrypt integration tests
Thx @gwallet for the help.
2016-12-22 10:11:37 +01:00
Vincent Demeester
e1ed8b71f6 Merge pull request #931 from Juliens/addprefix
Add Rule AddPrefix
2016-12-21 21:45:09 +01:00
Emile Vauge
6ca142bf20 Merge branch 'master' into addprefix 2016-12-20 22:26:04 +01:00
Rodrigo Menezes
6b20d2a5f3 toml zookeeper doc fix (#948)
Having that slash there causes traefik to be able to get keys from ZK
2016-12-20 22:25:50 +01:00
Emile Vauge
bef55db120 Merge branch 'master' into addprefix 2016-12-20 12:18:37 +01:00
Emile Vauge
3bb3658d7d Merge pull request #921 from containous/add-github-issue
Add bug command
2016-12-20 11:36:06 +01:00
Julien Salleyron
a4034ce1e2 Add some docs 2016-12-19 17:17:24 +01:00
Julien Salleyron
d9fc66fdbc Add Rule AddPrefix 2016-12-19 17:12:52 +01:00
Emile Vauge
3ebfd729cf Refactor StatsRecorder
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-12-19 15:24:00 +01:00
Emile Vauge
6adb346cee Add bug command
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-12-19 15:23:59 +01:00
Manuel Laufenberg
318ff52ff3 Merge pull request #969 from Mic92/patch-1
deploy.sh: upload release source tarball
2016-12-19 11:13:37 +01:00
Jörg Thalheim
b7b0f8f68d deploy.sh: upload release source tarball
Having a release tarball including all vendor source makes life of maintainers a lot easier to create downstream packages.
It also ensures that as long as the go release is available the software can be build reproducible.
2016-12-17 12:17:05 +01:00
Ian
94bb7a1435 Add ability to set authenticated user in request header (#889)
* Add ability to set authenticated user in request header

Some web applications provide the ability to authorize users based on
the authenticated from Basic Auth. This patch provides a way to set a
key to which the authenticated user can be set in the Header.

For example, if I set `HeaderValue = "X-WebAuth-User"` and authenticate,
my application will be able to read my user name from that header and
provide me with the proper access.

This fixes #802
2016-12-16 16:42:51 +01:00
Emile Vauge
913a297e8d Merge pull request #930 from Juliens/defaultFuncMap
feat: Add defaultFuncMap to template
2016-12-14 18:41:47 +01:00
Julien Salleyron
d469d426f8 Remove useless func in FuncMaps 2016-12-08 20:44:13 +01:00
Julien Salleyron
ec05fbcf19 feat: Add defaultFuncMap to template 2016-12-08 20:44:13 +01:00
Vincent Demeester
686faf0556 Merge pull request #936 from funkyfuture/getting-started
Updates index.md 'Test it!' section
2016-12-08 18:39:04 +01:00
Frank Sachsenheim
fe2d4e0d38 Updates index.md 'Test it!' section
adapted to current schema for compose files
uses networks as necessary in a real world usage
2016-12-08 17:01:49 +01:00
Vincent Demeester
c500873586 Merge pull request #932 from yvespp/master
Kubernetes: cleanup channel handling
2016-12-08 11:23:20 +01:00
Yves Peter
fc788eb426 Kubernetes: cleanup channel handling
Only use one channel for all watches
Re-use stop channel from the provider
Skip events that have already been handled by the provider, builds on 007f8cc48e
2016-12-07 20:12:14 +01:00
Phil Kates
87eac1dc1a Fix deadlock in k8s provider
On a reasonably sized cluster:
63 nodes
87 services
90 endpoints

The initialization of the k8s provider would hang.

I tracked this down to the ResourceEventHandlerFuncs. Once you reach the
channel buffer size (10) the k8s Informer gets stuck. You can't read or
write messages to the channel anymore. I think this is probably a lock
issue somewhere in k8s but the more reasonable solution for the traefik
usecase is to just drop events when the queue is full since we only use
the events for signalling, not their content, thus dropping an event
doesn't matter.
2016-12-07 20:12:14 +01:00
Emile Vauge
91d9b9811f Merge pull request #738 from tyrken/lego-dns
Support Lets Encrypt DNS Challenges
2016-12-07 09:31:49 +01:00
Tristan Keen
71beb4b08f Support Lets Encrypt DNS Challenges
* Add exoscale support for Let’s encrypt DNS challenge
* Use name->DNS provider mapping from lego lib
2016-12-07 01:04:33 +00:00
Emile Vauge
d26f06e2d1 Merge pull request #938 from containous/merge-v1.1.1-master
Merge v1.1.1 master
2016-12-06 09:14:39 +01:00
Emile Vauge
dca08af003 Merge v1.1.1 into master
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-12-06 08:44:23 +01:00
Darius Karel
4c740e26d7 Clarify exposedbydefault behaviour (#904)
* docs: clarify exposedbydefault behaviour

* docs: sentence clarity
2016-12-05 11:40:06 +01:00
Vincent Demeester
131f581f77 Merge pull request #836 from yvespp/master
Migrate k8s to kubernetes/client-go
2016-12-01 12:00:05 +01:00
Yves Peter
9236a43a4d kubernetes: moved doc of client to the interface 2016-11-30 19:25:22 +01:00
yvespp
7f4eddf6d6 k8s: changed debug log, removed unneeded stop channels, increased watch channel buffer 2016-11-30 19:16:48 +01:00
Ed Robinson
d1e631a487 Flatten dependencies
Deps for the integration suite are handled seperately, and not
flattend, as glide can't read the version info from docker/docker
2016-11-30 19:16:48 +01:00
Yves Peter
0b78375211 Kubernetes client: set resync period to 5 minutes for more robustness 2016-11-30 19:16:48 +01:00
Yves Peter
15540764a0 Switched Kubernetes provider to new client implementation: https://github.com/kubernetes/client-go 2016-11-30 19:16:48 +01:00
Vincent Demeester
82234cbbb2 Merge pull request #862 from Juliens/eureka
test-integration(eureka): Add some integration tests
2016-11-29 23:00:50 +01:00
Emile Vauge
22392daef7 Merge branch 'master' into eureka 2016-11-29 19:04:43 +01:00
Emile Vauge
7f3ae6edb0 Merge pull request #915 from containous/prepare-release-v1.1.1
Prepare release v1.1.1
2016-11-29 16:25:52 +01:00
Emile Vauge
1a993f5dfb Prepare release v1.1.1
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-11-29 14:52:55 +01:00
Emile Vauge
4e527304d0 Merge pull request #908 from containous/fix-swarm-panic
Fix Swarm panic
2016-11-29 14:47:51 +01:00
Emile Vauge
841be8d806 Fix Swarm panic 2016-11-28 16:46:37 +01:00
Ryan Leary
055cd01bb7 Fix GroupsAsSubDomains option for Mesos and Marathon (#868)
* Fix GroupsAsSubDomains option for Mesos and Marathon
* Refactor reverseStringSlice function
2016-11-28 14:59:08 +01:00
Emile Vauge
e34c364d5e Merge pull request #900 from containous/fix-k8s-panic
Fix k8s panic
2016-11-28 12:19:52 +01:00
Emile Vauge
926eb099f1 Fix k8s client panic
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-11-24 19:19:10 +01:00
Emile Vauge
710508dc40 Fix digest auth doc 2016-11-24 18:17:57 +01:00
Alexander Block
b4ea68b88a Fix missing value for k8s watch request parameter (#874)
Fixes: 732
2016-11-23 23:21:09 +01:00
WTFKr0
2bf9acd95e Normalize backend even if is user-defined (#865)
Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
2016-11-23 21:31:37 +01:00
Kristian Klausen
a8cb905255 consul/kv.tmpl: weight default value should be a int (#826)
* consul/kv.tmpl: weight default value should be a int

Fix #821

* Use 0 as default weight in all backends
2016-11-23 14:49:55 +01:00
Lewis Headden
567387aee0 Enable TCP Keep Alive for Marathon Client and make value configurable (#784)
* Resolve rebase conflicts

* Fix imports that VSCode messed up
2016-11-22 16:11:28 +01:00
Julien Salleyron
5b71e3184a fix: lint 2016-11-20 18:34:42 +01:00
Julien Salleyron
e1724444ac test(integration-test): Integration test for eureka 2016-11-20 18:25:48 +01:00
Julien Salleyron
cf8940e80e fix(eureka): Wrong host in rule 2016-11-20 18:25:48 +01:00
Emile Vauge
fe1b982d13 Merge pull request #856 from containous/prepare-release-v1.1.0
Changelog v1.1.0
2016-11-17 22:41:11 +01:00
Emile Vauge
221ae2427b changelog v1.1.0 2016-11-17 22:07:15 +01:00
Emile Vauge
29f780863b Merge pull request #845 from containous/fix-kubernetes-watch-leak
Fix Kubernetes watch leak
2016-11-17 18:54:12 +01:00
Emile Vauge
8aaca8e55c Update docs with errm talk 2016-11-17 17:37:06 +01:00
Emile Vauge
2dda3d2feb Fix Kubernetes watch leak
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-11-17 17:37:06 +01:00
Emile Vauge
22ebaedb45 Merge pull request #855 from containous/fix-path-case-sensitive-v1.1
Fix path case sensitive v1.1
2016-11-17 17:36:40 +01:00
Steven Bower
7065f00443 Fixes #851 (#852) 2016-11-17 15:40:25 +01:00
Steven Bower
15732269da Fixes #851 (#852) 2016-11-17 15:36:10 +01:00
Emile Vauge
7b06be8f5e Merge pull request #636 from Juliens/eureka
Add Eureka provider
2016-11-17 09:32:27 +01:00
Julien Salleyron
d2dcec40e1 test(integration-test): First test for eureka 2016-11-16 23:21:47 +01:00
Julien Salleyron
2af6cc4d1b feat(provider): Add Eureka Provider 2016-11-16 22:00:24 +01:00
Ed Robinson
56c6174d61 Merge pull request #622 from errm/use-stdlib-context
Context is part of the stdlib in go 1.7
2016-11-16 14:26:38 +00:00
Ed Robinson
66e914a8ab Adds Cleanup method to safe.Pool 2016-11-16 14:03:23 +00:00
Ed Robinson
8ae9607d9b Update dev documentation to require go 1.7 2016-11-16 14:03:23 +00:00
Ed Robinson
5c0297fb61 Context is part of the stdlib on 1.7 2016-11-16 14:03:23 +00:00
Vincent Demeester
f5bf9a2cda Merge pull request #846 from errm/yarn
Use the yarn package manager for javascript
2016-11-16 13:29:21 +01:00
Ed Robinson
987ab7612d Use the yarn pacakge manager for javascript
[Yarn](https://yarnpkg.com/) is a drop in replacement for npm.

We should use it because:

* It's faster
* It uses a lockfile, making the builds more deterministic.
2016-11-16 12:02:30 +00:00
Vincent Demeester
a186d5f87a Merge pull request #847 from errm/typo
Fixes a spelling error
2016-11-16 12:37:34 +01:00
Emile Vauge
801e0f9ef7 Merge pull request #849 from containous/fix-golint-1.1
Fix golint in v1.1
2016-11-16 12:26:56 +01:00
Ed Robinson
874ea62dd5 Adds misspell to validate target 2016-11-16 11:04:26 +00:00
Ed Robinson
ac20ddfc6c Fix golint
recent additions to golint mean that a number of files cause the
build to start failing if they are edited (we only run against changed
files)

This fixes all the errors in the repo so things don't unexpectedly start
failing for people making PRs
2016-11-16 11:52:15 +01:00
Ed Robinson
f0b991e1a8 Validate misspellings in documentation 2016-11-16 09:50:20 +00:00
Ed Robinson
adf385fdf3 Fix docs misspelling 2016-11-16 09:42:10 +00:00
Ed Robinson
7af6bc093d Adds misspell validation 2016-11-16 09:29:36 +00:00
Ed Robinson
3708fa864b Fixes a spelling error 2016-11-16 09:28:16 +00:00
Emile Vauge
28276e1b37 Merge pull request #848 from errm/golint
Fix golint
2016-11-16 10:23:02 +01:00
Ed Robinson
b0efd685a9 Fix golint
recent additions to golint mean that a number of files cause the
build to start failing if they are edited (we only run against changed
files)

This fixes all the errors in the repo so things don't unexpectedly start
failing for people making PRs
2016-11-16 08:56:52 +00:00
Ed Robinson
422aacf8e6 Merge pull request #716 from jangie/allow-connection-timeout-configuration
Allow specification of dialertimeout
2016-11-15 21:38:53 +00:00
Vincent Demeester
f6576cce27 Merge pull request #842 from guilhem/version-cross-binary
Pass Version, Codename and Date to crosscompiled
2016-11-14 17:35:58 +01:00
Bruce Lee
e068ee09ca Allow specification of dialertimeout
Address documentation comments
2016-11-14 10:57:46 -05:00
Guilhem Lettron
d3b48cdd22 Pass Version, Codename and Date to crosscompiled
Copy variables from ./script/binary
2016-11-14 16:41:30 +01:00
Manuel Laufenberg
91e3bdff48 Merge pull request #827 from errm/remove-versions-from-examples
Remove version numbers from examples
2016-11-14 11:45:27 +01:00
Ed Robinson
4299d1526b Remove version numbers from examples
Fixes #808
2016-11-14 09:13:09 +00:00
Emile Vauge
c26b36cf4f Merge pull request #820 from trecloux/check_http2
Check that we serve HTTP/2
2016-11-14 09:38:31 +01:00
Thomas Recloux
3095da64d7 Check that we provide HTTP/2 2016-11-14 09:10:47 +01:00
Vincent Demeester
07f961ecba Merge pull request #829 from SantoDE/fix-webui-dashboard
Add Nvd3 Dependency to fix UI / Dashboard
2016-11-13 11:47:22 +01:00
Manuel Laufenberg
8d9caaec71 Merge pull request #789 from wallies/master
Add marathon tls options to documentation
2016-11-13 11:35:00 +01:00
Cam Parry
91634d5c1c Add marathon tls options to documentation 2016-11-13 19:11:36 +10:00
Vincent Demeester
f5463c3d38 Merge pull request #788 from TerraTech/fix_makefile
Makefile: Strip 'heads/' from git rev-parse --abbrev-ref HEAD
2016-11-12 13:29:47 +01:00
TerraTech
73b70393d4 Makefile: Strip 'heads/' from git rev-parse --abbrev-ref HEAD
git rev-parse --abbrev-ref HEAD can return results in a couple different ways:
  1) tag v1.1.0-rc3 exists and branch==v1.1.0-rc3
     result: heads/v1.1.0-rc3
  2) tag v1.1.0-rc3 doesn't exist and branch==v1.1.0-rc3
     result: v1.1.0-rc3

  Strip it off GIT_BRANCH regardless as it will break the build.  e.g.

  $ make binary
  docker build  -t "traefik-dev:heads/v1.1.0-rc3" -f build.Dockerfile .
  invalid value "traefik-dev:heads/v1.1.0-rc3" for flag -t: Error parsing reference: "traefik-dev:heads/v1.1.0-rc3" is not a valid repository/tag
  See 'docker build --help'.
  Makefile:51: recipe for target 'build' failed
  make: *** [build] Error 125
2016-11-11 16:22:51 -05:00
Manuel Laufenberg
3db6e185e0 Add Nvd3 Dependency to fix UI / Dashboard 2016-11-11 21:50:59 +01:00
Manuel Laufenberg
d174ed75c7 Merge pull request #787 from SirCAS/contribute-guide
Added note for how to avoid running vendor tests
2016-11-10 19:34:28 +01:00
Christoffer Illum Søndergaard
513d261f10 Added note for how to avoid running vendor tests 2016-11-10 19:05:52 +01:00
Emile Vauge
4430befe90 Merge pull request #823 from containous/fix-mkdoc-theme
Fix mkdoc theme
2016-11-10 12:20:46 +01:00
Emile Vauge
acf425b6cf Merge pull request #817 from gomes/master
Marathon ExposedByDefault is true by default
2016-11-10 11:34:00 +01:00
Emile Vauge
1c4eb4322b Fix changelog 2016-11-10 11:15:42 +01:00
Emile Vauge
3f3fa61a51 Fix mkdocs theme 2016-11-10 11:12:54 +01:00
Emile Vauge
ddf24039e8 Merge pull request #822 from containous/prepare-release-v1.1.0-rc4
Prepare release v1.1.0 rc4
2016-11-10 10:40:36 +01:00
Diogo Gomes
98b35affd5 Merge branch 'master' into master 2016-11-09 22:04:56 -02:00
Manuel Laufenberg
b3cc1e1af1 Merge pull request #806 from djalal/patch-2
fix typos
2016-11-09 23:09:29 +01:00
Emile Vauge
5b6a5f8aa9 Changelog v1.1.0-rc4 2016-11-09 22:00:10 +01:00
Emile Vauge
3e6d2391f7 Add dtomcej, SantoDE remove samber from maintainers 2016-11-09 21:59:58 +01:00
Emile Vauge
664ee9d82f Merge pull request #814 from containous/fix-acme-renew
Fix multiple issues
2016-11-09 21:47:13 +01:00
Emile Vauge
c9cc3c9895 Fix contraint store/read from KV
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-11-09 21:08:37 +01:00
Emile Vauge
00c7e5c72b Ensure HTTP/2 enabled 2016-11-09 17:56:41 +01:00
Diogo Gomes
2b770ae2f8 Actually the current Marathon default for exposedByDefault is true, as
…
we can see in
https://github.com/containous/traefik/blob/master/configuration.go
“defaultMarathon.ExposedByDefault = true”
2016-11-08 11:20:50 -02:00
Emile Vauge
558b31f4d9 Fix oxy version 2016-11-08 10:34:39 +01:00
Emile Vauge
174a5e7f13 Fix ACME renew 2016-11-07 21:51:23 +01:00
djalal
952fcf5d09 fix typos 2016-11-05 23:02:43 +01:00
Emile Vauge
c821f191b0 Merge pull request #783 from containous/add-version-check
Fix ACME renew & add version check
2016-11-03 14:14:06 +01:00
Emile Vauge
3322e564fd Add version check
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-11-03 11:30:00 +01:00
Emile Vauge
7bf5d557c1 Fix acme renew 2016-11-03 11:30:00 +01:00
Vincent Demeester
0c1e06199c Merge pull request #782 from guilhem/defaultToIndex1
Use first port by default
2016-11-02 14:34:42 -07:00
Guilhem Lettron
85a20b9a39 Use first index for ports 2016-11-02 17:31:27 +01:00
Vincent Demeester
931a124349 Merge pull request #786 from guybrush/doc-basics-frontends
Fix typo in docs
2016-11-02 07:39:20 +01:00
Patrick Pfeiffer
ab52f4d91d Fix typo in docs 2016-10-30 13:21:43 +01:00
Vincent Demeester
f3182ef29b Merge pull request #761 from nathan-osman/errors-in-health
Errors in health
2016-10-28 17:52:52 +02:00
Guilhem Lettron
5641af437e Use first port by default
If no information is given, use first index of ports
2016-10-28 11:59:24 +02:00
Guilhem Lettron
1c8d3ded3d Add name to some case to help debug 2016-10-28 11:59:24 +02:00
Emile Vauge
c2a445370e Merge pull request #779 from containous/prepare-release-v1.1.0-rc3
Prepare release v1.1.0-rc3
2016-10-26 17:59:09 +02:00
Emile Vauge
8e5355f2d9 Prepare release v1.1.0-rc3
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-10-26 17:38:18 +02:00
Emile Vauge
2492157833 Merge pull request #776 from containous/fix-response-recorder-flush
Fix ResponseRecorder Flush
2016-10-26 17:00:49 +02:00
Emile Vauge
7c375e8fd9 Fix ResponseRecorder Flush
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-10-26 16:26:19 +02:00
Emile Vauge
53b5d8ac33 Merge pull request #758 from containous/fix-multiple-certs-flag
Fix multiple certificates using flag
2016-10-26 16:23:06 +02:00
Emile Vauge
e5a8fb390e Fix multiple certificates using flags
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-10-26 15:40:27 +02:00
Emile Vauge
79cbae0c73 Merge pull request #759 from containous/fix-mapstructure-slice
Fix mapstructure issue with anonymous slice
2016-10-26 15:39:45 +02:00
Emile Vauge
22b0b8b750 Fix mapstructure issue with anonymous slice
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-10-26 15:17:54 +02:00
Emile Vauge
ddbddf6edf Merge pull request #760 from containous/fix-ProvidersThrottleDuration-doc
Fix providers throttle duration doc
2016-10-26 14:20:10 +02:00
Emile Vauge
adcf58da68 Fix ProvidersThrottleDuration doc 2016-10-26 12:47:19 +02:00
Nathan Osman
05f6b79e29 Add optional statistics to API and web UI.
A new option (--web.statistics) enables the collection of some basic
information about requests and responses. This currently consists of
the most recent 10 requests that resulted in HTTP 4xx or 5xx errors.
2016-10-25 15:36:23 -07:00
Guilhem Lettron
649cb548d0 Use sdnotify for systemd (#768)
* Use sdnotify for systemd

This is useful if a configuration is long to load.
Systemd will continue dependency chain only when server have finish to start.

https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=

* Extract the waiting behavior from Start()
2016-10-25 08:59:39 -07:00
Emile Vauge
14db2343c9 Merge pull request #773 from containous/merge-v1.1.0-rc2
Merge v1.1.0 rc2
2016-10-25 09:04:07 +02:00
Emile Vauge
67eb0c8de0 Merge tag 'v1.1.0-rc2' into master 2016-10-24 21:38:42 +02:00
Vincent Demeester
870f378782 Merge pull request #748 from containous/really-fix-deploy-ghr
Really fix deploy ghr...
2016-10-19 12:14:54 +02:00
Emile Vauge
82a58010f5 Really fix deploy ghr... 2016-10-19 11:49:24 +02:00
Emile Vauge
f652c58367 Merge pull request #742 from containous/fix-deploy-ghr
Fixes deploy ghr
2016-10-19 10:56:54 +02:00
Emile Vauge
468d138be7 Fixes deploy ghr 2016-10-17 23:42:22 +02:00
Emile Vauge
f409d2f435 Merge pull request #740 from containous/prepare-v1.1.0-rc2
prepare v1.1.0-rc2
2016-10-17 19:38:23 +02:00
Emile Vauge
5780a17794 prepare v1.1.0-rc2 2016-10-17 19:14:49 +02:00
Hans Kristian Flaatten
9b765d23fa Update Kubernetes examples (#731)
* Set `hostNetwork` to `true` in Kubernetes deployment example

* Remove duplicate Kubernetes examples

* Update Kubernetes Træfik Docker Image to 1.1.0
2016-10-17 18:36:32 +02:00
Vincent Demeester
4476861d9f Merge pull request #733 from containous/fix-case-sensitive-hosts
Fix case sensitive host
2016-10-17 15:44:09 +02:00
Emile Vauge
e12ddca1a5 Fix case sensitive host 2016-10-17 13:52:29 +02:00
Emile Vauge
084d00a156 Merge pull request #728 from containous/fix-marathon-dots-ID
fIx marathon template with dots in ID
2016-10-13 16:23:00 +02:00
Emile Vauge
404a73a712 fIx marathon template with dots in ID 2016-10-13 15:33:23 +02:00
Vincent Demeester
3b2410d904 Merge pull request #720 from guilhem/marathon-lb
Add basic compatibility with marathon-lb
2016-10-12 20:47:38 +02:00
Guilhem Lettron
bd5009058b Merge branch 'v1.1' into marathon-lb 2016-10-12 15:51:41 +02:00
Emile Vauge
d3f79c7ad3 Merge pull request #724 from vincentlepot/fix_network_label_service
Fix networkMap construction in ListServices
2016-10-10 17:16:09 +02:00
Guilhem Lettron
3f65503a79 Add basic compatibility with marathon-lb
Add compatibility with labels: `HAPROXY_GROUP` and `HAPROXY_0_VHOST`.
* `HAPROXY_GROUP` become a new tag
* `HAPROXY_0_VHOST` become a rule `Host:`

https://github.com/mesosphere/marathon-lb
2016-10-07 19:30:16 +02:00
Vincent Lepot
6ac1216f8c Fix networkMap construction (pointer always reference the last network found) 2016-10-07 16:44:33 +02:00
Vincent Demeester
1cae35f96b Merge pull request #713 from oscerd/readme-fix
Remove duplicated link to Kubernetes.io in README.md
2016-10-07 11:20:16 +02:00
Andrea Cosentino
0d13e91a62 Remove duplicated link to Kubernetes.io in README.md 2016-10-07 08:13:06 +02:00
Emile Vauge
b1b600e09e Merge pull request #715 from vdemeester/update-docs-for-swarmmode
Add documentation for Træfik on docker swarm mode
2016-10-06 16:34:24 +02:00
Vincent Demeester
3692e1c4bd Add documentation for Træfik on docker swarm mode
Also small update on the swarm one.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-10-06 15:48:23 +02:00
Emile Vauge
dcbd82ac3b Merge pull request #717 from containous/update-README
Add Ed's video at ContainerCamp
2016-10-06 15:18:26 +02:00
Emile Vauge
d4f0541027 Fix mailgun/manners push force...
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-10-06 14:58:49 +02:00
Emile Vauge
a30d8e7819 Add Ed's video at ContainerCamp
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-10-06 12:24:52 +02:00
Emile Vauge
8ee6bf044a Merge pull request #708 from vdemeester/docker-support-healthcheck
Add support for docker healthcheck 👼
2016-10-03 12:44:38 +02:00
Emile Vauge
6632247c9c Merge pull request #709 from vhf/webui-show-version
Show current version in web UI
2016-10-03 11:37:20 +02:00
Vincent Demeester
d68389dc52 Add support for docker healthcheck
- React to health_status events
- Filter container that have a health status *and* that are not healthy

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-10-03 11:01:37 +02:00
Victor Felder
4a43273ee5 Show current version in web UI 2016-10-02 20:46:10 +02:00
Vincent Demeester
66f52a6e21 Merge pull request #707 from billglover/master
Fix syntax in Swarm example. Resolves #528
2016-10-02 14:00:34 +02:00
Bill Glover
640bfc4eff Fix syntax in Swarm example. Resolves #528
Prior to this fix the documentation for the swarm example included
syntax that would fail with the following error.

`Error : flag needs an argument: --docker.domain`

This fix specifies flags using the `=` between the flag name and value.

Tested on: Docker version 1.12.2-rc1, build 45bed2c, experimental
2016-10-01 22:37:15 +01:00
Emile Vauge
408ef0f5b7 Merge pull request #705 from containous/prepare-release-v1.1.0-rc1
Prepare release v1.1.0 rc1
2016-09-30 15:57:09 +02:00
Emile Vauge
b9f76394aa Update Mesos documentation 2016-09-30 15:37:52 +02:00
Emile Vauge
a96f483d56 Fix regression in acme.json secure mode 2016-09-30 15:06:12 +02:00
Emile Vauge
84cb9f15a4 Prepare release v1.1.0-rc1 2016-09-30 15:04:57 +02:00
Emile Vauge
d4da14cf18 Merge pull request #625 from containous/add-ha-acme-support
HA acme support
2016-09-30 13:34:59 +02:00
Emile Vauge
4ad4b8e0b8 Add ACME account to storeconfig command
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-09-30 12:29:39 +02:00
Emile Vauge
bb29d9c8ca Add documentation
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-09-30 12:29:39 +02:00
Emile Vauge
e72e65858f Challenge certs PEM encoding
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-09-30 11:26:25 +02:00
Emile Vauge
a42845502e Add ACME store
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-09-30 11:26:17 +02:00
Emile Vauge
bea5ad3f13 Add leadership election
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-09-30 11:26:05 +02:00
Emile Vauge
5a0440d6f8 Add KV datastore
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-09-30 11:26:05 +02:00
Emile Vauge
38b62d4ae3 Merge pull request #701 from containous/carry-pr-446
Carry PR 446 - Add sticky session support (round two!)
2016-09-30 11:25:26 +02:00
Emile Vauge
462d8b3e74 Fix Docker & KV templates for sticky
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-09-30 10:57:55 +02:00
Emile Vauge
291c3b6dbc Fix sticky sessions Docker/Marathon labels 2016-09-30 10:56:47 +02:00
Owen Marshall
df225d9170 Change cookie name to match documentation 2016-09-30 10:56:36 +02:00
Owen Marshall
592e981bd2 glide up 2016-09-30 10:56:36 +02:00
Owen Marshall
3d7c44735a Reorder sticky session definitions 2016-09-30 10:56:17 +02:00
Owen Marshall
81fddb4ccf missed a cherry pick, good start :=/ 2016-09-30 10:56:17 +02:00
Owen Marshall
c9d4c5ae3e Fix Docker integration problems 2016-09-30 10:56:17 +02:00
Owen Marshall
be5b1fd92b docs, sticky session for Docker 2016-09-30 10:56:17 +02:00
Owen Marshall
d78c419627 Add sticky support to DRR lb 2016-09-30 10:56:17 +02:00
Owen Marshall
dc52abf4ce Add sticky session support to Traefik.
This change adds sticky session support, by using the new
oxy/rr/StickySession feature.

To use it, set traefik.backend.sticky to true.

This is currently only implemented in the wrr load balancer, and against
the Marathon backend, but lifting it should be very doable.

In the wrr load balancer, a cookie called _TRAEFIK_SERVERNAME will be
set with the backend to use.  If the cookie is altered to an invalid
backend server, or the server is removed from the load balancer, the
next server will be used instead.

Otherwise, the cookie will be checked in Oxy's rr on access and if valid
the connection will be wired through to it.
2016-09-30 10:56:17 +02:00
Vincent Demeester
a13549cc28 Merge pull request #702 from tuier/http_compression
Add HTTP compression
2016-09-29 18:25:49 +02:00
tuier
baf4c474e3 Documentation 2016-09-28 23:05:01 +01:00
tuier
a58750992d lint 2016-09-28 23:04:18 +01:00
tuier
17546c3a08 Add HTTP compression 2016-09-28 23:04:18 +01:00
Emile Vauge
067f13b61c Merge pull request #690 from dtomcej/disable-tls10
Selectable TLS Versions
2016-09-28 23:52:34 +02:00
Daniel Tomcej
e249983c77 add TLS Min Version
silly copy paste
Add cipher selection

add TLS Min Version

silly copy paste

silly copy paste

add TLS Min Version

silly copy paste

fix formatting

Add cipher selection

linted

arg

update cipher map
2016-09-27 14:29:36 -06:00
Emile Vauge
454b191370 Merge pull request #687 from containous/some-fixes
Some fixes
2016-09-27 22:21:59 +02:00
Emile Vauge
a882a9d79f Fix constraints and add doc 2016-09-27 21:45:29 +02:00
Emile Vauge
89fc835bb2 Add Katacoda in docs 2016-09-27 21:45:29 +02:00
Emile Vauge
364958cbaf Move jobs backoff back into traefik
https://github.com/cenk/backoff/pull/27#issuecomment-245842725
2016-09-27 21:45:29 +02:00
Emile Vauge
1b6af2045e Clean web authentication 2016-09-27 21:45:29 +02:00
Emile Vauge
be09ff8e43 Merge pull request #602 from diegofernandes/master
#504 Initial support for Docker 1.12 Swarm Mode
2016-09-27 21:45:07 +02:00
Diego Osse Fernandes
99c8bffcbf Initial support for Docker 1.12 Swarm Mode 2016-09-27 14:21:38 -03:00
Emile Vauge
03d16d12d5 Merge pull request #697 from tuier/remove_unused_endpoint_marathon
Remove unused endpoint when using constraints with Marathon provider
2016-09-27 15:18:48 +02:00
tuier
1624c51cb5 remove unused endpoint when using constraints in marathon 2016-09-23 22:05:11 +01:00
Vincent Demeester
83aabefcc5 Merge pull request #696 from solidnerd/patch-1
Replace imagelayers.io with microbadger
2016-09-23 14:01:48 +02:00
Niclas Mietz
dfece708e1 Replace imagelayers.io with microbadger
This replace the badge of imagelayers.io with a badge microbadger.com because imagelayers.io doesn't work anymore through the registry v2 specification and docker hub supports only the v2 spec.
2016-09-23 13:03:44 +02:00
Emile Vauge
5d0f82ffbd Merge pull request #686 from tuier/marathon_constraints
feat(constraints): Supports constraints for Marathon provider
2016-09-23 09:58:17 +02:00
tuier
361dc94002 fmt 2016-09-21 17:27:48 +02:00
tuier
cc0fdf15ef test for task and application constraint 2016-09-21 17:27:47 +02:00
tuier
928675a847 feat(constraints): Support constraint for Marathon provider 2016-09-21 17:27:47 +02:00
Emile Vauge
12c1131b0c Merge pull request #689 from containous/carry-pr-439
Carry pr 439
2016-09-21 15:51:43 +02:00
Emile Vauge
bb1dde0469 Fix kv
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-09-21 14:33:45 +02:00
Samuel BERTHE
ced69b8397 refacto(constraint-kv): Move constraint checking out of template 2016-09-21 14:33:45 +02:00
Samuel BERTHE
013808956c feat(constraints): Supports kv stores backends 2016-09-21 14:33:45 +02:00
Emile Vauge
009057cb87 Merge pull request #688 from ydubreuil/fix-clean-url
Disable gorilla/mux URL cleaning to prevent sending redirect
2016-09-20 21:14:39 +02:00
Yoann Dubreuil
82cb21fca3 Disable gorilla/mux URL cleaning to prevent sending redirect
This fixes #167 and #651. By default, gorilla/mux cleans URL paths
such that adjacent slashes are collapsed into one single slash. This
behavior is pretty common in application stacks and it is fine, but
for Traefik, this can lead to incorrect URL paths forwarded to backend
servers.

See https://github.com/gorilla/mux/issues/94 for background.
2016-09-20 20:31:11 +02:00
Vincent Demeester
7e8937a332 Merge pull request #685 from dtomcej/update-docs
Update docs to improve contribution setup
2016-09-20 18:04:56 +02:00
dtomcej
e5dcfa0a2e Update docs for current install
silly spelling mistake

Document accepted values for logLevel.

Add possibility to use BindPort IPAddress 👼

Signed-off-by: Vincent Demeester <vincent@sbr.pm>

Update marathon

Signed-off-by: Emile Vauge <emile@vauge.com>
2016-09-20 09:13:52 -06:00
Emile Vauge
f4520a011a Merge pull request #648 from containous/update-marathon
Update marathon
2016-09-20 16:57:44 +02:00
Emile Vauge
98dd6ca460 Update marathon
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-09-20 16:01:45 +02:00
Emile Vauge
c3d9312240 Merge pull request #657 from vdemeester/use-port-ip-address
Add possibility to use BindPort IPAddress 👼
2016-09-20 15:20:48 +02:00
Vincent Demeester
5ea761e19f Add possibility to use BindPort IPAddress 👼
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-09-20 14:52:35 +02:00
Vincent Demeester
46a7860427 Merge pull request #676 from InQuicker/docs-log-levels
Document accepted values for logLevel.
2016-09-20 09:45:20 +02:00
Jimmy Cuadra
af9b63eaed Document accepted values for logLevel. 2016-09-19 16:07:53 -07:00
Emile Vauge
9a26e0db16 Merge pull request #610 from containous/merge-v1.0.2-master
Merge v1.0.2 master
2016-09-19 20:29:37 +02:00
Emile Vauge
efe6989fd3 Merge acme from v1.0.2
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-09-19 19:58:34 +02:00
Emile Vauge
aa1c9b80e3 Prepare release v1.0.2
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-09-19 16:49:21 +02:00
Emile Vauge
6981df3b9a Fix ACME TOS
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-09-19 16:49:21 +02:00
Emile Vauge
0d1ed625a8 Bump oxy version, fix streaming
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-09-19 16:49:21 +02:00
Emile Vauge
710fc56c6a Merge pull request #677 from SantoDE/master
Add basic auth support for web backend
2016-09-19 16:48:05 +02:00
Manuel Laufenberg
d5a15d6756 add basic auth support
implemented requested changes

fix docs

remove struct tag
2016-09-19 09:40:43 +02:00
Emile Vauge
b376da1829 Merge pull request #645 from jangie/add-backend-features-to-consul-catalog
enable consul catalog to use maxconn
2016-09-15 18:46:30 +02:00
Bruce Lee
f7f17f0057 enable consul catalog to use maxconn 2016-09-15 12:11:37 -04:00
Emile Vauge
d06b9c2992 Merge pull request #616 from jangie/master
Add ability for marathon provider to set maxconn values, loadbalancer algorithm, and circuit breaker expression
2016-09-15 17:19:12 +02:00
Bruce Lee
99ca5d0a03 Add ability for marathon provider to set maxconn values
Initial implementation: Force both to be present to trigger behavior.

add ability to see rendered template in debug

add support for loadbalancer and circuit breaker specification

add documentation for new configuration
2016-09-14 16:52:02 -04:00
Vincent Demeester
4783c7f70a Merge pull request #646 from jangie/add-backend-features-to-docker
Add backend features to docker
2016-09-14 22:48:59 +02:00
Bruce Lee
d89bdfbd27 Add backend features to docker 2016-09-14 14:51:31 -04:00
Diogo Gomes
1e324ad3bc If Marathon doesn't have healthcheck, assume it's ok (#665)
Healthcheck are not mandatory, so if a result is not present, assume it
is ok to continue. Fixes the case when a new leader is elected and
don't have any healthcheck result's, returning 404 to all requests.
https://github.com/containous/traefik/issues/653
2016-09-14 17:44:37 +02:00
Emile Vauge
52737e91e5 Merge pull request #660 from JayH5/acme-renew-30-days
ACME: renew certificates 30 days before expiry
2016-09-14 08:01:07 +02:00
Jamie Hewland
1872e2b63d ACME: renew certificates 30 days before expiry, like the official certbot client 2016-09-13 16:15:58 +02:00
Martijn Heemels
3c5605b793 Update broken link in sample config file. (#658) 2016-09-13 15:17:34 +02:00
Vincent Demeester
9a2b7cf5be Merge pull request #668 from yvespp/master
Kubernetes provider: traefik.frontend.rule.type logging
2016-09-13 10:56:20 +02:00
Yves Peter
1a20e9f9b4 Kubernetes provider: don't log a warning if traefik.frontend.rule.type is empty, log namespace and ingress if invalide. 2016-09-12 21:06:21 +02:00
Vincent Demeester
14d79e4eef Merge pull request #641 from errm/code-of-conduct
Adopt the Code Of Coduct from http://contributor-covenant.org
2016-08-30 22:26:29 +02:00
Ed Robinson
71f48d2aef Adopt the Code Of Coduct from http://contributor-covenant.org 2016-08-26 10:26:41 +01:00
Emile Vauge
312adca226 Merge pull request #630 from jangie/add-ping-handler
add PING handler to dashboard API
2016-08-25 23:10:26 +02:00
Bruce Lee
d35c6e77d7 add PING handler to dashboard API 2016-08-24 21:37:12 -04:00
Emile Vauge
1de21c86ae Merge pull request #639 from discordianfish/fish/fix-acme-perm
Use secure mode 600 instead of 644 for acme.json
2016-08-24 20:06:33 +02:00
Johannes 'fish' Ziemke
c709a592eb Use secure mode 600 instead of 644 for acme.json 2016-08-22 13:33:49 +02:00
Vincent Demeester
a54c544eb4 Merge pull request #637 from djalal/patch-1
docker clarification, fix dead urls, misc typos
2016-08-22 13:06:35 +02:00
djalal
7d936ec6aa docker clarification, fix dead urls, misc typos 2016-08-22 11:03:34 +02:00
Emile Vauge
f63ec1332f Merge pull request #628 from containous/mirgate-to-JobBackOff
Migrate to JobBackOff
2016-08-19 22:24:39 +02:00
Emile Vauge
d340ccd601 Migrate to JobBackOff 2016-08-19 14:24:09 +02:00
Vincent Demeester
95e8f0a31e Merge pull request #627 from containous/add-long-job-exponential-backoff
Add long job exponential backoff
2016-08-19 11:40:16 +02:00
Emile Vauge
97ddfcb17a Use long job RetryBackoff in providers 2016-08-19 11:09:54 +02:00
Emile Vauge
7bb5f9a1e4 Add long job RetryBackoff 2016-08-19 11:09:34 +02:00
Emile Vauge
11297b38c5 Remove misused Fatal* 2016-08-19 10:36:54 +02:00
Emile Vauge
fc19ab2868 Merge pull request #601 from containous/add-host-cert-acme-generation
Add Host cert ACME generation
2016-08-18 15:01:41 +02:00
Emile Vauge
5e01c0a7db Add Host cert ACME generation
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-08-18 14:20:55 +02:00
Vincent Demeester
f1c3d820f7 Merge pull request #617 from jangie/fix-nil-client-tls
fix for nil clientTLS causing issue
2016-08-17 09:46:17 +02:00
Bruce Lee
0757a75732 fix for nil clientTLS causing issue 2016-08-16 17:50:22 -04:00
Emile Vauge
f0ea45a0f8 Merge pull request #613 from keis/installable-systemd-unit
Make systemd unit installable
2016-08-16 15:11:59 +02:00
David Keijser
45f2335a60 Make systemd unit installable
Having a install section makes it possible to enable/disable traefik
using the standard systemd commands

`systemctl enable traefik`
`systemctl disable traefk`
2016-08-16 14:50:20 +02:00
Vincent Demeester
d629939cf3 Merge pull request #620 from containous/bump-go-1.7
Bump go v1.7
2016-08-16 12:58:11 +02:00
Emile Vauge
404f76dcb9 Bump go v1.7
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-08-16 11:11:47 +02:00
Vincent Demeester
498ce6b00c Merge pull request #573 from errm/fix-k8s-watch
Fix k8s watch
2016-08-16 09:32:50 +02:00
Ed Robinson
e3a8fd116d Don't filter the endpoint and service watches
We added the ability to filter the ingresses used by traefik based
on a label selector, but we shouldn't need to have matching
labels on every other resource, Ingress allready has a way
to explicty choose which pods end up in the load ballancer
(by refering to the membership of a particular service)
2016-08-16 06:50:50 +01:00
Ed Robinson
d33e09bcf3 Ignore .DS_Store (Mac junk) 2016-08-16 06:50:50 +01:00
Vincent Demeester
fb3bad3887 Merge pull request #619 from jangie/consistent-duration-logging
Make duration logging consistent
2016-08-15 18:30:25 +02:00
Bruce Lee
3a736ad4a8 Make duration logging consistent
GH #559 points out that the logging of the elapsed time is inconsistent
depending on the scale of the measured time; this is due to Duration’s
String handling.

With this PR, I propose that traefik logs millis, and not fractions of
millis.
2016-08-15 08:43:20 -04:00
Vincent Demeester
c1b0c41769 Merge pull request #609 from cocap10/update-staert-toml-default-pointer-behaviour
update staert and flaeg
2016-08-15 13:19:24 +02:00
Martin
c03274703e update staert and flaeg 2016-08-11 14:34:33 +02:00
Christian Winther
4cd08e88f6 Fix Consul prefix (#589)
Seemed to have been the cause of #587
2016-08-08 11:53:00 +02:00
Vincent Demeester
e2c4872030 Merge pull request #596 from errm/k8s-server-naming
Name servers after thier pods
2016-08-07 09:21:44 +02:00
Ed Robinson
d4f190e995 Name servers after thier pods
The TargetRef contains information from the object referenced
by the pod, unless the service has been set up with bare
endpoints - i.e. not pointing at pods this information
will be present.

It just makes the information that we show in the web-ui
a little more constent with that shown in kubectl
and the kuberntes dashboard.
2016-08-06 20:40:40 +01:00
Vincent Demeester
039107e837 Merge pull request #598 from keiths-osc/version_fix
Fixed binary script so traefik version command doesn't just print default values
2016-08-05 16:05:25 +02:00
Keith Shook
ef6c211275 Fixed binary script so traefik version command doesn't just print default values 2016-08-05 09:19:45 -04:00
Vincent Demeester
1f3accc0d7 Merge pull request #580 from cocap10/beautify-help
beautify help
2016-08-05 15:13:28 +02:00
Martin
2815f80063 beautify help
and fixes
2016-08-05 14:26:36 +02:00
Emile Vauge
fa645abee3 Add requirements.txt for netlify (#567)
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-08-05 12:32:49 +02:00
Micaël Mbagira
a86649def3 Upgrade directives name since we use angular-ui-bootstrap (#578) 2016-08-05 11:49:34 +02:00
Vincent Demeester
1fc4c56bc4 Merge pull request #588 from philk/kubernetes-priorities
Prioritize kubernetes routes by path length
2016-08-05 11:08:07 +02:00
Phil Kates
79dd72f53d Prioritize kubernetes routes by path length
The Kubernetes provider wasn't setting priorities which was causing
shorter paths to get chosen before longer ones. This now matches the
[documentation](https://github.com/containous/traefik/blob/master/docs/basics.md#priorities)
2016-08-03 11:37:22 -07:00
Andreas Jägle
ffa060ce56 Fix basic docs for configuration of multiple rules (#576) 2016-08-03 18:50:13 +02:00
Emile Vauge
5ce9719951 Merge pull request #557 from stuart-c/insecure_skip_verify
Add global InsecureSkipVerify option to disable certificate checking
2016-08-01 15:42:33 +02:00
Stuart Clark
914aa7d372 Add some documentation 2016-07-31 17:08:33 +01:00
Stuart Clark
4a88cbde3a Adjust formatting 2016-07-31 16:59:48 +01:00
Stuart Clark
4882519c0f Add global InsecureSkipVerify option to disable certificate checking
Signed-off-by: Stuart Clark <stuart.clark@Jahingo.com>
2016-07-31 16:59:48 +01:00
Vincent Demeester
7abe68fac1 Merge pull request #565 from containous/merge-v1.0.1-master
Merge v1.0.1 master
2016-07-28 21:00:13 +02:00
Emile Vauge
e62cca1e7c Merge v1.0.1
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-28 20:15:09 +02:00
Emile Vauge
a016741918 Merge pull request #547 from containous/add-basic-authentication
Add basic/digest auth
2016-07-28 19:01:46 +02:00
Emile Vauge
2f95810fa3 Add experimental Docker push
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-28 18:32:26 +02:00
Emile Vauge
16e2c3b1e0 Add basic/digest auth doc
Signed-off-by: Emile Vauge <emile@vauge.com>

Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-28 18:32:21 +02:00
Emile Vauge
bc8a92caa9 Add basic/digest auth tests
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-28 18:19:47 +02:00
Emile Vauge
3a5b67a3e1 Add basic/digest auth
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-28 18:19:47 +02:00
Emile Vauge
2a596b8162 Merge pull request #558 from micaelmbagira/webui-webpack-fountainjs
Move webui to FountainJS with Webpack
2016-07-27 22:29:17 +02:00
Micaël
e059239bc3 Move webui to FountainJS with Webpack 2016-07-27 16:16:02 +02:00
Vincent Demeester
986ad9fc57 Merge pull request #551 from cocap10/upload-config-kv
Add command storeconfig
2016-07-22 16:52:00 +02:00
Martin
1bb3d9be73 add command storeconfig
add test integration command storeconfig

update doc
2016-07-22 15:20:47 +02:00
Emile Vauge
ae31f19ef6 Merge pull request #552 from vdemeester/update-libkermit
Upgrade libkermit and dependencies
2016-07-21 19:13:27 +02:00
Vincent Demeester
c170ddc7ae Upgrade libkermit and dependencies
And use ContainerAPIClient where needed 👼

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-07-21 17:43:05 +02:00
Emile Vauge
58b6d92ce2 Merge pull request #553 from vdemeester/move-version-in-package
Move version.go in its own package…
2016-07-21 17:35:52 +02:00
Vincent Demeester
87a4d73556 Move version.go in its own package…
… making it possible to use in other packages ; and thus in the
User-Agent header for the docker client.

Also removing the dockerverion hack as it's not required anymore.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-07-21 16:33:49 +02:00
Emile Vauge
4c54a003fa Merge pull request #546 from vdemeester/bump-webui-node
Bump node to 6 for webui
2016-07-21 10:46:59 +02:00
Vincent Demeester
a5f3eabf8b Bump node to version 6 for webui
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-07-21 10:21:04 +02:00
Emile Vauge
3bf6c59d23 Merge pull request #545 from vdemeester/bump-go-1.6.3
Bump golang to 1.6.3
2016-07-21 10:20:33 +02:00
Vincent Demeester
ef83dea95c Bump golang to 1.6.3
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-07-21 09:50:17 +02:00
Vincent Demeester
686c23d25b Merge pull request #481 from cocap10/global-config-kv
Use KvStores as global config sources
2016-07-21 09:49:58 +02:00
Martin
b153e90ec5 add createStore() funcs and skip consul TLS test 2016-07-21 09:22:35 +02:00
Martin
38cc36980f update doc 2016-07-21 09:22:35 +02:00
Martin
b83fb525a8 Add TLS support for etcd and consul 2016-07-21 09:22:35 +02:00
Martin
e26e0955b3 add struct ClientTLS : supports either a paths to a file or directly the certificate 2016-07-21 09:22:35 +02:00
Martin
7ada80b619 Certificate can contain path or file contents
Signed-off-by: Martin <martin.piegay@zenika.com>
2016-07-21 09:22:35 +02:00
Martin
056e0fe2d9 Use KvStores as global config source 2016-07-21 09:22:35 +02:00
Vincent Demeester
9be0c67d5c Merge pull request #461 from andersbetner/client_tls_auth
Add endpoint option to authenticate by client tls cert.
2016-07-21 09:06:34 +02:00
Anders Betnér
664bc9cae0 Added tests for client certificate authentication 2016-07-20 14:41:38 +02:00
Anders Betnér
959c7dc783 Support for client certificate authentication 2016-07-20 14:41:38 +02:00
Emile Vauge
8e333d0a03 Merge pull request #353 from saagie/feature/mesos
add mesos provider inspired by mesos-dns & marathon provider
2016-07-20 12:49:09 +02:00
julien
5afcf17706 add mesos provider inspired by mesos-dns & marathon provider 2016-07-20 11:56:14 +02:00
Emile Vauge
a8d05294bc Merge pull request #542 from containous/prepare-release-1.0.1
Prepare release v1.0.1
2016-07-19 16:54:16 +02:00
Emile Vauge
1b25e492c7 Prepare release v1.0.1
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-19 16:05:03 +02:00
Vincent Demeester
61b22316d6 Merge pull request #538 from jimt/docs
Fix typos
2016-07-19 15:34:08 +02:00
Emile Vauge
be8ebdba46 Merge pull request #527 from containous/add-sse-support
Add sse support
2016-07-19 11:51:21 +02:00
Emile Vauge
2d759df47a Fix basics doc
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-19 10:29:48 +02:00
Emile Vauge
d1b5cf99d0 Add GraceTimeOut support
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-18 18:01:59 +02:00
Emile Vauge
516608d883 Bump containous/oxy version with SSE support
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-18 17:59:50 +02:00
Emile Vauge
bf95e6def9 Add deploy-pr on non master branch
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-18 17:59:50 +02:00
Emile Vauge
3c5cb31775 default values logs from WARN to DEBUG
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-18 17:59:50 +02:00
Jim Tittsler
d2f51fccb9 Fix typos 2016-07-18 14:55:45 +09:00
Emile Vauge
c13db04f6d Merge pull request #519 from errm/k8s-docs
Kubernetes user-guide
2016-07-17 15:46:45 +02:00
Ed Robinson
d3aa056151 Kubernetes user-guide 2016-07-15 09:49:08 +01:00
Ed Robinson
1c60f0b53b Fix the name of Traefik in the documentation 2016-07-15 09:49:08 +01:00
Emile Vauge
ca2b85f453 Merge pull request #514 from vdemeester/carry-pr-358
Carry #358 : Option to disable expose of all docker containers
2016-07-14 11:57:31 +02:00
Vincent Demeester
b80479f9ef Option to disable expose of all docker containers
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-07-14 11:32:15 +02:00
Vincent Demeester
0a9070c394 Merge pull request #531 from Jsewill/patch-2
Update server.go
2016-07-14 11:28:29 +02:00
Jsewill
bd29bac716 Update server.go
Fixed a bug that caused a panic when sending multiple signals: signals are no longer sent on the server.signals channel after it has closed.
2016-07-14 03:22:18 -05:00
Emile Vauge
d42a22f446 Merge pull request #512 from containous/fix-acme-ondemand
Fix acme checkOnDemandDomain
2016-07-14 10:13:24 +02:00
Emile Vauge
d1112a0feb Merge pull request #510 from vdemeester/remove-frontend-value-docker
Remove traefik.frontend.value support in docker…
2016-07-13 21:53:38 +02:00
Vincent Demeester
a73baded88 Remove traefik.frontend.value support in docker…
… provider 👼. Was deprecated in 1.0, removing it for 1.1.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-07-13 19:28:08 +02:00
Emile Vauge
24d3a698a0 Fix acme checkOnDemandDomain
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-13 19:25:47 +02:00
Emile Vauge
1eeba34806 Merge pull request #511 from errm/etcd-endpoint-default
Fix default etcd port
2016-07-13 19:23:58 +02:00
Emile Vauge
94fa95d747 Merge pull request #516 from pnegahdar/selector
Implement Kubernetes Selectors, minor kube endpoint fix
2016-07-13 19:22:40 +02:00
Emile Vauge
c98a561722 Fix GraceTimeOut flag description
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-13 17:49:00 +02:00
Parham Negahdar
9f6484a328 Fixes #363: Allow for kubernetes label selectors 2016-07-12 17:50:01 -04:00
Parham Negahdar
40c0ed092e Fixes #501: prioritize kube.endpoint passed via cli 2016-07-11 15:39:20 -04:00
Ed Robinson
c719aa3db8 Fix default etcd port
Fixes #508
2016-07-11 13:14:43 +01:00
Emile Vauge
8f8f72fa76 Merge pull request #496 from containous/prepare-release-1.0.0
Prepare release 1.0.0
2016-07-06 01:09:33 +02:00
Emile Vauge
4ae6d42871 Add Changelog
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-05 21:17:30 +02:00
Emile Vauge
64243382cf Add codename
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-05 21:03:37 +02:00
Emile Vauge
c7acb2d2c4 Update doc on combining multiple rules and priorities
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-05 21:03:06 +02:00
Emile Vauge
20795cf884 Add Russell-IO and errm in maintainers
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-05 21:02:14 +02:00
Vincent Demeester
6b9f64a273 Merge pull request #495 from containous/fix-windows-build
Fix windows builds
2016-07-05 16:40:07 +02:00
Emile Vauge
9e270c951a Fix windows builds
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-05 16:02:36 +02:00
Vincent Demeester
20308dc804 Merge pull request #494 from containous/fix-docker-network-host
Fix host Docker network
2016-07-05 14:41:48 +02:00
Emile Vauge
b1ecb1f61f Use of container.HostConfig.NetworkMode to detect host mode
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-05 14:11:33 +02:00
Emile Vauge
6fd8979754 Remove deprecated traefik.domain label
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-05 11:29:13 +02:00
Emile Vauge
050416224d Fix host Docker network
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-05 11:29:13 +02:00
Vincent Demeester
6e5a221180 Merge pull request #493 from containous/fix-empty-tls-flag
Fix empty tls flag
2016-07-05 11:27:53 +02:00
Emile Vauge
a1ab252303 Fix empty tls flag
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-05 10:56:48 +02:00
Emile Vauge
3c89fd51ee Merge pull request #491 from containous/fix-default-weight-in-loadConfig
Fix default weight in server.LoadConfig
2016-07-05 10:56:26 +02:00
Emile Vauge
018b8a6315 Fix default weight in server.LoadConfig
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-05 10:26:28 +02:00
Emile Vauge
ecaa146d5b Merge pull request #492 from containous/fix-webui-proxy
Fix webui proxying
2016-07-05 10:17:49 +02:00
Emile Vauge
f50a4d8c2a Fix webui proxying
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-05 09:34:17 +02:00
Emile Vauge
68b0e44fbd Merge pull request #490 from containous/fix-retry-headers
Fix retry headers, simplify ResponseRecorder
2016-07-05 09:18:36 +02:00
Emile Vauge
ac9946c697 Fix retry headers, simplify ResponseRecorder
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-07-04 19:32:19 +02:00
Vincent Demeester
a0a8bc24e8 Merge pull request #479 from containous/disable-constraints-temporarily
Disable constraints in doc until 1.1
2016-06-23 17:46:05 +02:00
Emile Vauge
06ab802bc6 Disable constraints in doc until 1.1
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-23 17:25:12 +02:00
Vincent Demeester
04ec757083 Merge pull request #477 from containous/fix-spamming-events
Fix spamming events in listenProviders
2016-06-23 17:09:59 +02:00
Emile Vauge
15e04bb55d Fix consul catalog issue with dot in serviceName
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-23 16:33:54 +02:00
Emile Vauge
e4ed7fd8f7 Fix bad circuit breaker expression
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-23 16:33:54 +02:00
Emile Vauge
fd5352b0c6 Fix empty rule
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-23 16:33:54 +02:00
Emile Vauge
606e667b88 Fix spamming events in listenProviders
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-23 16:33:54 +02:00
Vincent Demeester
2a209c23c4 Merge pull request #478 from keis/consul-stable-ordering-of-nodes
Sort nodes before creating consul catalog config
2016-06-23 16:33:22 +02:00
David Keijser
70305266dc Sort nodes before creating consul catalog config
The watch of consul can return for various reasons and not of all of
them require a reload of the config. The order of nodes provided by
consul is not stable so to ensure a identical config is generated for an
identical server set the nodes needs to be sorted before creating the
config.
2016-06-23 13:08:12 +02:00
Vincent Demeester
8e561d9f95 Merge pull request #441 from NicolasGeraud/patch-1
mount acme folder instead of file
2016-06-23 10:00:09 +02:00
Nicolas Géraud
f446cac43c mount acme folder instead of file
I you use traefik in Docker and use Let's Encrypt, you have to mount the folder containing the acme.json file instead of the file itself.
2016-06-23 00:02:01 +02:00
Vincent Demeester
7e1ceb9a3e Merge pull request #476 from containous/fix-empty-response
Fix empty responses
2016-06-22 16:39:40 +02:00
Emile Vauge
1b5e35461d Bump oxy to b57d6706e9ff606343c596940b60df7f90012d29
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-22 15:33:39 +02:00
Vincent Demeester
df75700015 Merge pull request #468 from containous/fix-marathon-tls-auth
Fix marathon TLS/basic auth
2016-06-22 14:23:16 +02:00
Emile Vauge
b586df6689 Fix marathon tests
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-22 13:56:28 +02:00
Emile Vauge
4ca2ff0495 Bump go-marathon a558128c87724cd7430060ef5aedf39f83937f55, add DCOS support
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-20 17:11:32 +02:00
Emile Vauge
93494c7e35 Fix errors load config (#470)
* Trim spaces in rules

Signed-off-by: Emile Vauge <emile@vauge.com>

* dont break the whole config while only one part is wrong

Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-20 15:19:52 +02:00
Emile Vauge
11874bc4ae Fix acme renew, add test (#472)
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-20 13:55:50 +02:00
Kevin Busse
dcf98d13c8 Fix typo in error message. (#471) 2016-06-20 12:15:31 +02:00
Vincent Demeester
2a735e815a Merge pull request #469 from kumy/patch-1
Typo: Replace French words by English ones
2016-06-18 16:24:54 +02:00
kumy
52de16b4c9 Merge branch 'master' into patch-1 2016-06-18 16:06:49 +02:00
Vincent Demeester
7133a28fdb Merge pull request #460 from containous/fix-websocket-hijack
Fix websocket connection Hijack
2016-06-18 15:50:30 +02:00
kumy
ade2ff97e0 Typo: Replace French words by English ones 2016-06-18 15:43:35 +02:00
Emile Vauge
450d86be7d Fix websocket connection Hijack
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-18 13:37:21 +02:00
Vincent Demeester
c9caf612eb Merge pull request #464 from containous/fix-memory-leak
Fix memory leak in listenProviders
2016-06-17 00:52:21 +02:00
Emile Vauge
56ef678c09 Fix memory leak in listenProviders
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-16 22:49:57 +02:00
Emile Vauge
29e647763a Merge pull request #438 from samber/TRAEFIK-311--support-docker-backend
feat(constraints): Supports constraints for docker backend
2016-06-13 00:29:28 +02:00
Samuel BERTHE
357150bcab fix(constainrs,docker): Syntax 2016-06-11 19:06:39 +02:00
Samuel BERTHE
f7224ff403 feat(constraints): Supports constraints for docker backend 2016-06-11 19:06:39 +02:00
Vincent Demeester
01ffad2e6e Merge pull request #450 from containous/fix-default-kv-configuration
Fix default KV configuration
2016-06-11 15:03:57 +02:00
Emile Vauge
223e8cafac Fix default KV configuration
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-09 23:44:49 +02:00
Emile Vauge
d1ffbd8a03 Merge pull request #443 from vdemeester/442-and-share-context
Fix panic if listContainers fails…
2016-06-09 09:37:48 +02:00
Vincent Demeester
f286cb9a34 Fix panic if listContainers fails…
… and also share context accross API call, as this is how it's meant to
be used (and it allows to skip some calls if `cancel` is called).

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-06-08 19:39:38 +02:00
Emile Vauge
5c63855cc0 Merge branch 'AlmogBaku-master' 2016-06-07 20:19:51 +02:00
Emile Vauge
2a96ae9ec2 Merge branch 'master' of https://github.com/AlmogBaku/traefik into AlmogBaku-master 2016-06-07 20:19:21 +02:00
Samuel BERTHE
36a2da0659 Merge pull request #440 from containous/emilevauge-add-samber-to-maintainers
Add @samber to maintainers
2016-06-07 20:15:08 +02:00
Emile Vauge
38abec520c Add @samber to maintainers 2016-06-07 19:45:12 +02:00
Almog Baku
1274d26b4c Merge branch 'master' into master 2016-06-07 19:45:53 +03:00
Vincent Demeester
6556c79207 Merge pull request #433 from containous/add-routes-priorities
Add routes priorities
2016-06-07 10:10:19 +02:00
Emile Vauge
7e6c580130 Add routes priorities in documentation
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-07 09:54:12 +02:00
Emile Vauge
cc4fb64b34 Add routes priorities in integration tests
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-07 09:18:37 +02:00
Emile Vauge
f4cb4bb1b8 Add routes priorities in providers
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-07 09:18:37 +02:00
Emile Vauge
287b3ba1f4 Add routes priorities test
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-07 09:18:37 +02:00
Emile Vauge
208998972a Add routes priorities
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-07 09:17:39 +02:00
Vincent Demeester
7cdd062432 Merge pull request #435 from fclaeys/multiRules
Allow multiple rules
2016-06-07 09:12:39 +02:00
Fabrice CLAEYS
eccb529605 update docs 2016-06-07 08:52:43 +02:00
Fabrice CLAEYS
78dc28cce8 test rules parsing 2016-06-06 17:20:01 +02:00
Fabrice CLAEYS
84076db78e allow multiple rules 2016-06-06 09:22:23 +02:00
Almog Baku
c3779f0e94 Merge branch 'master' into master 2016-06-04 18:49:26 +03:00
Emile Vauge
c5ac563e74 Merge pull request #426 from containous/fix-marathon-directory-subdomain
Fix marathon groups subdomain
2016-06-03 11:39:40 +02:00
Emile Vauge
92ca220890 Add groupsAsSubDomains option
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-03 09:10:59 +02:00
Emile Vauge
72f88e5c0f Add marathon directory subdomain
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-03 09:10:59 +02:00
Vincent Demeester
1a75a71ad6 Merge pull request #428 from containous/fix-default-configuration
Fix default configuration
2016-06-02 17:43:01 +02:00
Emile Vauge
3c3b179c29 Deploy PR Docker image
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-02 17:22:45 +02:00
Emile Vauge
3f08bb4cdf Fix panic on help, Better version
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-02 15:17:04 +02:00
Emile Vauge
423268f485 Fix default configuration
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-06-02 11:51:36 +02:00
Vincent Demeester
d3f003a15f Merge pull request #415 from download13/docker_network
Added getIPAddress helper for docker template
2016-06-02 10:57:32 +02:00
Erin Dachtler
7386378cc0 Merge branch 'master' into docker_network 2016-06-01 08:38:23 -07:00
Vincent Demeester
d6547462e5 Merge pull request #342 from samber/TRAEFIK-311--adding-constraint-filtering
feat(constraints): Implementation of constraint filtering (cmd + toml + matching functions), implementation proposal with consul
2016-06-01 16:01:00 +02:00
Samuel BERTHE
d297a220ce fix(constraints): Syntax 2016-06-01 10:30:34 +02:00
Samuel BERTHE
1de5434e1a refacto(constraints): Migration to Flaeg cli library 2016-06-01 10:30:34 +02:00
Samuel BERTHE
f46accc74d test(constraint): unit tests + integration tests + make validate 2016-06-01 10:30:34 +02:00
Samuel BERTHE
cd2100ed84 doc(constraints): Added in ConsulCatalog backend + new 'Constraint' section 2016-06-01 10:30:34 +02:00
Samuel BERTHE
ac087921d8 feat(constraints): Implementation of constraint filtering (cmd + toml + matching functions), implementation proposal with consul 2016-06-01 10:30:34 +02:00
Erin Dachtler
82b1f14e2b Merge branch 'master' into docker_network 2016-05-31 22:19:45 -07:00
Erin Dachtler
df7e1cf078 Squashed commit of the following:
commit 468cdf5c74b8df80fe6cc093feda84d124d47460
Author: Erin Dachtler <download333@gmail.com>
Date:   Mon May 30 17:21:50 2016 -0700

    Documentation update

commit bcbe622141fc333579177e056b49d418997c511d
Author: Erin Dachtler <download333@gmail.com>
Date:   Sat May 28 15:32:34 2016 -0700

    Whoops, forgot to fmt

commit 1ad5f1052541372722adc372069da094b422c793
Author: Erin Dachtler <download333@gmail.com>
Date:   Sat May 28 14:56:04 2016 -0700

    Added getIPAddress helper for docker template, and tests
2016-05-31 22:11:17 -07:00
Emile Vauge
39fa8f7be4 Merge pull request #418 from samber/doc--tooling--integration-test-filtering
Doc about skipping some integration tests with '-check.f ConsulCatalogSuite'
2016-05-31 21:40:57 +02:00
Samuel BERTHE
46c2184de4 doc(tooling): Doc about selecting some tests with argument '-check.f' of gochecker library 2016-05-31 12:07:54 +02:00
Emile Vauge
a9f9894f29 Merge pull request #422 from containous/fix-travis-tag
Fix travis tag check
2016-05-31 00:15:58 +02:00
Emile Vauge
a6c360eeda Fix travis hangs on docker version
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-30 23:59:27 +02:00
Emile Vauge
01a4002169 Fix travis tag check
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-30 23:44:53 +02:00
Emile Vauge
8caaf317ae Merge pull request #412 from containous/prepare-release-candidate
Prepare release candidate
2016-05-30 18:27:48 +02:00
Emile Vauge
0e3c2ef10f Fix log config file
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-30 17:57:57 +02:00
Emile Vauge
db6c85d3d7 Prepare release candidate
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-30 17:48:50 +02:00
Vincent Demeester
2bd95620a5 Merge pull request #420 from cocap10/fixes-log
log info about TOML configuration file using
2016-05-30 17:48:00 +02:00
Martin
d8ad30f38a log info about TOML configuration file using
+glide update flaeg & staert
+fix README.md
+fix configFile flag description

Signed-off-by: Martin <martin.piegay@zenika.com>
2016-05-30 17:04:26 +02:00
Vincent Demeester
aad5f52968 Merge pull request #416 from download13/no_require_expose
Don't filter out containers with no exposed port if they have a traefik.port label set
2016-05-30 11:21:49 +02:00
Erin Dachtler
f5d49f6657 Merge branch 'master' into no_require_expose 2016-05-28 16:36:59 -07:00
Erin Dachtler
53ae64e578 Filter containers with no exposed ports unless they have a traefik.port label 2016-05-28 15:16:57 -07:00
Vincent Demeester
1a936b6aca Merge pull request #403 from cocap10/migrate-to-staert
Migrate to staert
2016-05-27 16:41:44 +02:00
Martin
4776fa1361 add parsers tests
Signed-off-by: Martin <martin.piegay@zenika.com>
2016-05-27 13:23:38 +02:00
Martin
c5084fd025 update staert + glide pin version 2016-05-27 10:06:19 +02:00
Martin
cc2735f733 add Debug StructTag
Signed-off-by: Martin <martin.piegay@zenika.com>
2016-05-27 10:06:19 +02:00
Martin
7f6b2b80f8 rm useless TestNoOrInexistentConfigShouldNotFail
Signed-off-by: Martin <martin.piegay@zenika.com>
2016-05-27 10:06:19 +02:00
Martin
f64c2bc065 add flag on ACME
add flag on Retry

set Retry.MaxMem to 2 by default

rm useless import

rm useless structtag

add custom parser on []acme.Domain type

add commants + refactor
2016-05-27 10:06:19 +02:00
Martin
6752b49536 rm useless StrucTag 2016-05-27 10:06:19 +02:00
Martin
ab138e7df1 update to new version go-bindata-assetfs 2016-05-27 10:06:19 +02:00
Martin
059da90a96 clean glide dependancies 2016-05-27 10:06:19 +02:00
Martin
0821c7bdd9 Add version in logs 2016-05-27 10:06:19 +02:00
Martin
89e00eb5a4 add staert & fleag 2016-05-27 10:06:19 +02:00
Martin
1a0f347023 update default value 2016-05-27 10:06:19 +02:00
Martin
1e27c2dabe fix TestNoOrInexistentConfigShouldNotFail 2016-05-27 10:06:19 +02:00
Martin
629be45c4a fix DisablePassHostHeaders 2016-05-27 10:06:19 +02:00
Martin
e115e3c4e7 fix default value 2016-05-27 10:06:19 +02:00
Martin
414fb1f406 add kubernetes.Namespaces parser 2016-05-27 10:06:19 +02:00
Martin
fe0a8f3363 Flaeg integration 2016-05-27 10:06:19 +02:00
Erin Dachtler
45589d5133 Reminder 2016-05-26 11:03:40 -07:00
Vincent Demeester
7804787e9e Merge pull request #408 from errm/k8s-endpoints
Build backend config using the K8S endpoint resource.
2016-05-26 17:12:23 +02:00
Ed Robinson
2e735f622f Adds some more coverage of the endpoint port selection logic. 2016-05-26 12:09:36 +01:00
Ed Robinson
6accb90c47 Simplify Service Lookup
Since we already know the name and namespace
of the service(s) we want we can just get the
correct one back from the API without filtering
the results.
2016-05-26 11:17:38 +01:00
Ed Robinson
e948a013cd Build backend config using the K8S endpoint resource.
* Potentialy saves a network hop
* Ability to configure LB algothim (given some work to expose an
anotation etc...)
* K8s config Watch is triggered far less often
2016-05-26 10:52:30 +01:00
Ed Robinson
b79535f369 Support ingresses without a host (#406)
fixes #370
2016-05-25 14:16:19 +02:00
Vincent Demeester
ed3bcc6d9a Merge pull request #387 from containous/fix-k8s-memory-leak
Fix k8s memory leak
2016-05-25 09:57:42 +02:00
Emile Vauge
0f23581f64 Fix k8s memory leak
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-24 23:37:17 +02:00
Emile Vauge
2af1e4b192 Fix k8s compose file
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-24 23:31:35 +02:00
Emile Vauge
dc404b365f Add expvar endpoint
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-24 23:31:35 +02:00
Emile Vauge
86f3891a2b Add debug flag
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-24 23:31:35 +02:00
Vincent Demeester
86053ea54b Update Makefile to fix local builds (#397)
Use --build-arg only if DOCKER_VERSION is specified

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-05-23 16:07:35 +02:00
Vincent Demeester
938600ba95 Merge pull request #398 from containous/fix-safari-http2
Fix safari http2
2016-05-23 14:37:19 +02:00
Emile Vauge
80ab967d39 Fix benchmarks doc
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-23 14:02:25 +02:00
Emile Vauge
43acbaa702 Fix safari error with http2
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-23 14:00:14 +02:00
Vincent Demeester
5d6492e6f5 Merge pull request #395 from vdemeester/carry-pr-382
Carry: http protocol should not use TLS
2016-05-23 13:11:56 +02:00
Jonas Falck
aeb9cc1732 http protocol should not use TLS
I need this in order to run kubectl proxy and then
make traefik use http://localhost to get to my cluster
when developing
2016-05-23 09:51:05 +02:00
Vincent Demeester
fa25c8ef22 Merge pull request #394 from vdemeester/carry-pr-312
Carry: Updating Toml to sure PathPrefix instead of Path
2016-05-23 09:50:38 +02:00
Russell Clare
77a9613c3a Updating Toml to sure PathPrefix instead of Path 2016-05-23 09:35:18 +02:00
Almog Baku
ba62a1f630 Merge branch 'master' into master 2016-05-20 21:13:59 +03:00
Vincent Demeester
153ab8f0fa Update engine-api to fix versions issues (#383)
Updating an engine-api that has fixed some versioning issues (filters
json marshalling)

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-05-19 21:11:30 +02:00
Vincent Demeester
f6c860afc0 Merge pull request #380 from errm/k8s-ref-ports-by-name
Allow k8s ports to be referenced by name as well as number
2016-05-19 15:00:12 +02:00
Ed Robinson
d13b755df2 Allow k8s ports to be referenced by name as well as number 2016-05-19 13:36:19 +01:00
Vincent Demeester
6bacbf6cac Merge pull request #379 from errm/k8s-services-from-same-namespace
The referenced k8s service(s) must be in namespace
2016-05-19 14:08:53 +02:00
AlmogBaku
0d5baa2219 Merge branch 'master' of https://github.com/containous/traefik 2016-05-19 01:10:44 +03:00
AlmogBaku
97c8a1d7ab fixes wrong "default" for k8s annotation in document... 2016-05-19 01:09:32 +03:00
Ed Robinson
5923d22379 The referenced k8s service(s) must be in namespace
By design k8s ingress is only designed to ballance services from within
the namespace of the ingress.

This is disscuessed a little in
https://github.com/kubernetes/kubernetes/issues/17088.

For now traefik should only reference the services in the current
namespace. For me this was a confusing change of behaviour
from the reference implimentations, as I have services
with the same name in each namespace.
2016-05-18 17:38:47 +01:00
Vincent Demeester
70494117d1 Merge pull request #373 from AlmogBaku/master
K8s: add an option to configure "PathPrefixStrip" for the ingress-resource using annotation
2016-05-18 17:19:11 +02:00
AlmogBaku
8210743dad change log error of "ruleType" to warning 2016-05-17 16:54:40 +03:00
AlmogBaku
895f3cc109 fixes golint error 2016-05-17 16:22:37 +03:00
AlmogBaku
71f160dddc Following up to the conversation on Slack & GitHub:
- Change the annotation to define the rule type in `traefik.frontend.rule.type`
 - Update tests
 - Add documentation
 - Add example
2016-05-17 13:50:06 +03:00
AlmogBaku
92abaa0d47 fixes wrong actual on unit-test 2016-05-16 01:24:23 +03:00
AlmogBaku
47710c1385 fixes wrong names on tests - make it pass 2016-05-16 01:06:30 +03:00
AlmogBaku
df3abcbc9a gofmt to tests.. 2016-05-15 20:01:26 +03:00
AlmogBaku
dbb7ad41e5 Add tests for k8s PathPrefixStrip annotation 2016-05-15 12:16:27 +03:00
AlmogBaku
9773d4e409 K8s: add an option to configure "PathPrefixStrip" for the ingress-resource using annotation 2016-05-15 12:00:20 +03:00
Emile Vauge
993165fa66 Added Devoxx Video & support (#371)
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-13 17:32:39 +02:00
Emile Vauge
c49f5dad05 Merge pull request #368 from vdemeester/update-docker-deps
Update docker dependencies to fix issues
2016-05-13 08:21:09 +02:00
Vincent Demeester
c0bdedfed3 Add travis matrix for 1.9.1 and 1.10.1
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-05-12 17:18:58 +02:00
Vincent Demeester
061107b65f Update docker dependencies to fix issues
Update engine-api, libcompose and related dependencies (including
libkermit), to fix issues with docker v1.9.1 and lower.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-05-12 17:10:42 +02:00
Vincent Demeester
7bf421f847 Merge pull request #369 from containous/fix-hijack-logger
fix hijack logger middleware
2016-05-12 17:06:15 +02:00
Emile Vauge
cb0c1d34a2 fix hijack logger middleware
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-12 16:32:12 +02:00
Vincent Demeester
749b381f26 Merge pull request #355 from containous/change-PathPrefixStrip-k8s
Replace PathPrefixStrip by PathPrefix in k8s
2016-05-12 13:56:43 +02:00
Emile Vauge
d89279d708 Replace PathPrefixStrip by PathPrefix in k8s
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-12 12:44:26 +02:00
Marcus Stong
be209ed30c #216: sets passHostHeader to true by default (#351) 2016-05-10 13:43:24 +02:00
Emile Vauge
4a4ba2791d Merge pull request #357 from s7anley/generate-fix
Create static folder on first generate
2016-05-09 23:47:23 +02:00
Ján Koščo
c61d9776e7 Create static folder on first generate 2016-05-09 23:13:22 +02:00
Vincent Demeester
b5716abd3e Merge pull request #347 from keis/consul-catalog-replace-space-in-tags
Replace whitespace in tags in consul_catalog
2016-05-07 17:26:17 +02:00
David Keijser
b9bb78d04b Normalise tags in backend name of consul_catalog
Another fun thing consul lets you do is use spaces in your tags. This
means when including tags in backend name it's possible to generate
invalid names.
2016-05-07 16:30:38 +02:00
Vincent Demeester
8a39ee65cd Merge pull request #341 from errm/k8s-namespacing
Adds option to namespace k8s ingresses
2016-05-07 13:30:35 +02:00
Ed Robinson
301a463aeb Adds option to namespace k8s ingresses
If the flag kubernetes.namespaces is set...
Then we only select ingresses from that/those namespace(s)

This allows multiple instances of traefik to
independently load balance for each namespace.
This could be for logical or security reasons.

Addresses #336
2016-05-06 11:36:53 +01:00
Vincent Demeester
d1b0bece47 Merge pull request #356 from errm/documentation-documentation
Adds some documentation about adding documentation
2016-05-05 23:33:35 +02:00
Ed Robinson
63fd7d1d63 Adds some documentation about adding documentation 2016-05-05 21:45:57 +01:00
Vincent Demeester
f4fb2518a1 Merge pull request #352 from containous/remove-alpine-from-build
Go back to standard golang image
2016-05-05 19:45:12 +02:00
Emile Vauge
ee486de947 Go back to standard golang image
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-05 18:31:55 +02:00
Vincent Demeester
c1a12a58eb Merge pull request #340 from containous/fix-etcd-backend
Fix etcd backend with prefix /
2016-05-03 16:16:10 +02:00
Emile Vauge
c3aadab615 Add Consul integration tests
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-03 15:41:09 +02:00
Emile Vauge
26774d2317 Add Etcd integration tests
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-03 15:41:09 +02:00
Emile Vauge
61def880db Fix etcd backend with prefix /
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-05-03 15:41:09 +02:00
Vincent Demeester
11a6331185 Merge pull request #349 from stongo/acme-bundle
#345: bundle intermediate certificates
2016-05-03 11:49:35 +02:00
Marcus Stong
378509cef4 #345: bundle intermediate certificates
fixes warnings and gives generated certs an A rating on ssl labs
2016-05-02 20:01:10 -04:00
Vincent Demeester
4a1fa03b2d Merge pull request #318 from stongo/master
#304: enhance acme documentation
2016-05-02 18:21:48 +02:00
Marcus Stong
52bff85dda Merge remote-tracking branch 'upstream/master' 2016-05-02 11:44:07 -04:00
Vincent Demeester
e5b0b34604 Merge pull request #325 from CiscoCloud/master
Add frontend, backend, and timing to access log
2016-04-28 23:19:27 +02:00
David Tootill
0a0063fa27 Tweak comments to satisfy golint 2016-04-28 04:00:38 -07:00
David Tootill
bf1f6f663a Minor refactor as requested in PR comments 2016-04-28 10:53:02 +00:00
David Tootill
8bac454792 Merge branch 'master' of https://github.com/CiscoCloud/traefik 2016-04-28 10:20:24 +00:00
Vincent Demeester
7eaf09b3da Merge pull request #310 from samber/TRAEFIK-294--consul--use-service-addess-or-node-if-nil
feat(consul-provider): If service ip is nil then use node ip
2016-04-27 22:34:06 +02:00
Poney baker
378a261e64 feat(consul-provider): If Service.Address is nil then use Node.Address
test(consul-catalog): Test on backend-name and backend-address
2016-04-27 21:09:42 +02:00
David Tootill
53c99f7469 Add moul/http2curl to glide.yaml 2016-04-27 10:24:00 -07:00
David Tootill
f93e618f67 Merge remote-tracking branch 'refs/remotes/containous/master'
# Conflicts:
#	glide.lock
#	glide.yaml
2016-04-27 09:41:51 -07:00
David Tootill
64b78461f6 Remove some debug logs (requested in review) 2016-04-27 09:25:13 -07:00
Vincent Demeester
2f5c9273ee Merge pull request #334 from containous/fix-k8s-watch-ssl
Fix Kubernetes watch SSL & empty schema
2016-04-27 10:20:26 +02:00
Emile Vauge
38371234a2 Add logo credits
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-27 10:05:04 +02:00
Emile Vauge
10cb606578 Add Kubernetes URL
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-27 10:05:04 +02:00
Emile Vauge
87caf458df Fix Kubernetes schema
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-27 10:05:04 +02:00
Emile Vauge
4ff4e4e626 Fix Kubernetes watch SSL
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-27 10:05:04 +02:00
Vincent Demeester
9053f9bb98 Merge pull request #335 from tboerger/feature/libkv-update
Updated libkv dependency
2016-04-27 09:57:38 +02:00
Thomas Boerger
b6b72c861f Replaced etcd-go with etcd/client
In order to meet the requirements of the updated libkv library I have
also replaced etcd-go with the up2date etcd client.

Signed-off-by: Thomas Boerger <thomas@webhippie.de>
2016-04-26 23:18:53 +02:00
Thomas Boerger
478eed6603 Updated libkv dependency
In order to fix the TLS client authentication I have updated the libkv
dependency. Now the connection to secured etcd and consuld should work
properly.

Signed-off-by: Thomas Boerger <thomas@webhippie.de>
2016-04-26 22:37:19 +02:00
Vincent Demeester
6b76f64b48 Merge pull request #186 from containous/add-kubernetes-ingress-support
Add kubernetes Ingress backend
2016-04-25 18:40:29 +02:00
Emile Vauge
53a2787626 Fix watch pods/services/rc/ingresses
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-25 17:13:26 +02:00
Emile Vauge
cac9927395 Fix namespace, fix PathPrefixStrip
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-22 13:57:00 +02:00
Emile Vauge
9e14619a0b Add doc
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-22 13:57:00 +02:00
Emile Vauge
c0dd4c3209 Add unit test
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-22 13:57:00 +02:00
Emile Vauge
d82e1342fb Fix integration test
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-22 13:57:00 +02:00
emile
720912e880 Add kubernetes Ingress backend
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-22 13:57:00 +02:00
Vincent Demeester
6f47434833 Merge pull request #328 from samber/consul-catalog--remove-disable-frontend
feat(consul-catalog): Remove frontend when backends disabled
2016-04-22 12:09:14 +02:00
Poney baker
6f13a2c0c7 feat(consul-catalog): Remove frontend when backends disabled 2016-04-22 11:55:31 +02:00
Vincent Demeester
b7a150bc64 Merge pull request #327 from pborreli/typos
Fixed typos
2016-04-22 11:38:02 +02:00
Pascal Borreli
4d22c45b76 Fixed typos 2016-04-21 23:38:44 +01:00
David Tootill
2a76a717e6 Add access log integration test 2016-04-20 11:54:57 -07:00
Vincent Demeester
b3b658a955 Merge pull request #324 from containous/fix-kv-backend
Fix KV backend
2016-04-20 08:01:32 +02:00
David Tootill
c8c0d208be Update glide files for mattn/shellwords 2016-04-20 01:36:51 +00:00
David Tootill
04dd41ac3b Minor corrections 2016-04-20 01:25:22 +00:00
David Tootill
10815eca8e Initial update - manage access log 2016-04-19 16:45:59 -07:00
Emile Vauge
06d2f343dd Fix KV backend
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-19 23:49:26 +02:00
Vincent Demeester
a6c5e85ae7 Merge pull request #320 from samber/consul-provider-compare-tag-lowercase
fix(consul-provider): Compare consul catalog tag keys with lowered case
2016-04-19 18:23:47 +02:00
Samuel BERTHE
45d6a326cd fix(consul-provider): Compare consul catalog tag keys with lowered case 2016-04-19 17:27:19 +02:00
Vincent Demeester
0332e32293 Merge pull request #322 from containous/fix-marathon-backend
Fix Marathon backend
2016-04-19 12:32:56 +02:00
Emile Vauge
2a3a34a80c Fix Marathon backend
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-19 12:05:28 +02:00
Emile Vauge
68da47b59a Merge pull request #321 from samber/minor-doc-fix
fix(doc)
2016-04-19 12:04:13 +02:00
Samuel BERTHE
b1f0f048cd fix(doc) 2016-04-19 10:00:33 +02:00
Marcus Stong
a7b4463f86 #304: enhance acme documentation 2016-04-18 12:31:45 -04:00
Vincent Demeester
ee60adc45a Merge pull request #315 from containous/add-backoff-marathon
Add backoff to marathon provider
2016-04-16 17:32:01 +02:00
Emile Vauge
36338b4928 add backoff to marathon provider
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-16 17:21:24 +02:00
Emile Vauge
23d3c512c2 Merge pull request #316 from vdemeester/docker-provider-stop-support
Support stop chan on docker provider
2016-04-16 17:20:55 +02:00
Vincent Demeester
4144638be4 Support stop chan on docker provider
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-04-16 14:46:35 +02:00
Emile Vauge
f2320ee648 Merge pull request #313 from containous/add-user-guide
Add doc user guide with swarm
2016-04-15 19:13:53 +02:00
Emile Vauge
17afa3e672 Add doc user guide with swarm
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-15 19:00:08 +02:00
Vincent Demeester
5b2c355c38 Merge pull request #305 from containous/fix-races
Fix races
2016-04-15 18:09:50 +02:00
Emile Vauge
61d54903e3 Fix doc
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-14 15:27:42 +02:00
Emile Vauge
c1078c4374 Fix races
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-14 15:27:42 +02:00
Emile Vauge
4e427b5a9e remove error oxy log
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-14 15:27:42 +02:00
Vincent Demeester
227ec71db3 Merge pull request #306 from kevioke/oxy-glide-update
Update glide files to use most recent version of containous/oxy
2016-04-14 15:08:31 +02:00
kevin
d047b8daa1 Update glide files to use most recent version of containous/oxy 2016-04-13 14:51:14 -07:00
Emile Vauge
c2009b71b1 Merge pull request #303 from containous/emilevauge-bump-go1.6.1
Bump to go v1.6.1
2016-04-13 21:28:53 +02:00
Emile Vauge
ba8629e2ac Bump to go v1.6.1 2016-04-13 21:09:39 +02:00
Vincent Demeester
6aba453afb Merge pull request #301 from kevioke/maxconns
Add support for maximum connections for backends.
2016-04-13 18:50:29 +02:00
kevin
a15578a8f6 Add support for maximum connections for backends. 2016-04-13 09:37:11 -07:00
Vincent Demeester
5c8d9f4eb9 Merge pull request #274 from samber/consul-catalog-with-tags-settings
feat(traefik,consul-catalog): Set attributes from consul catalog tags (loadbalancer,circuitbreaker,weight)
2016-04-13 17:17:10 +02:00
Emile Vauge
a9e615b3c7 Fix period in frontend name in KV store 2016-04-13 14:56:51 +02:00
Emile Vauge
94ad21020c Merge pull request #297 from containous/emilevauge-fix-period-frontend-kvstore
Fix period in frontend name in KV store
2016-04-13 13:25:52 +02:00
Emile Vauge
4b76cb4318 Fix period in frontend name in KV store 2016-04-13 13:00:20 +02:00
Vincent Demeester
fad7ec6b7f Merge pull request #299 from containous/add-better-benchmarks
add better benchmarks
2016-04-13 12:56:17 +02:00
Emile Vauge
82a49a8e89 add better benchmarks
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-13 12:17:53 +02:00
Vincent Demeester
2bcc5a2ac7 Merge pull request #294 from samber/TRAEFIK-275-consul-catalog-backend-using-container-internal-ip
feat(consul-catalog-provider): + setting unique backend name + backendd redirecting to internal container ip
2016-04-13 09:38:09 +02:00
Samuel BERTHE
4f044cf2f9 feat(consul-catalog-provider): + setting unique backend name + backend redirecting to internal container ip 2016-04-13 08:05:44 +02:00
Emile Vauge
9a407f79ff Merge pull request #291 from vdemeester/kewl-makefile
Add a make help target
2016-04-12 10:35:48 +02:00
Vincent Demeester
affec30c64 Add a make help target
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-04-12 10:09:16 +02:00
Emile Vauge
d050e60da2 Merge pull request #278 from vdemeester/migrate-to-engine-api
Migrate docker provider traefik to engine-api
2016-04-08 15:21:26 +02:00
Vincent Demeester
866b9835a6 Migrate traefik to engine-api
The docker provider now uses docker/engine-api and
vdemeester/docker-events instead of fsouza-dockerclient.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-04-08 14:21:02 +02:00
Emile Vauge
f6564909aa Merge pull request #279 from vdemeester/update-dockerignore
Add **/*.test to .dockerignore
2016-04-07 17:22:53 +02:00
Vincent Demeester
315e8b64b8 Add **/*.test to .dockerignore
`*.test` files are generated by `go test`, do not include them into the
build context. It will lighter a bit the build context..

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-04-07 16:48:35 +02:00
Emile Vauge
f99f634816 Merge pull request #290 from containous/fix-issues
Fix issues
2016-04-07 16:36:13 +02:00
Emile Vauge
5292a5b9d4 Migrate to official docker image
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-07 16:24:11 +02:00
Emile Vauge
cf22d62a74 Fix mkdoc deploy
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-07 16:24:11 +02:00
Emile Vauge
9363e2ab83 Fix broken table in webUI
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-07 16:24:11 +02:00
Emile Vauge
e5ddd92677 Fix port support in host rule
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-07 16:23:57 +02:00
Vincent Demeester
04628056af Merge pull request #287 from containous/fix-doc-deploy
Fix doc deploy...
2016-04-06 19:17:50 +02:00
Emile Vauge
dada86c0b0 Fix doc deploy...
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-06 18:50:35 +02:00
Vincent Demeester
92c269c972 Merge pull request #286 from containous/fix-CI-env-variable
Fix CI env variable...
2016-04-06 17:45:34 +02:00
Emile Vauge
6991e3c99b Fix CI env variable...
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-06 17:31:43 +02:00
Vincent Demeester
3ee3daee00 Merge pull request #285 from containous/add-multiple-rules
Add multiple rules
2016-04-06 16:24:16 +02:00
Emile Vauge
85fcff4cf7 Multiple rules docs
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-06 16:10:20 +02:00
Emile Vauge
30db47d9b6 Fix SSH key, I hope...
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-06 15:28:25 +02:00
Emile Vauge
4d2c85ffdc Fix multiple response.WriteHeader calls
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-06 14:30:29 +02:00
Emile Vauge
e36433c23a Fix retry attempts
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-06 14:07:51 +02:00
Emile Vauge
8486766a60 Add multiple rules
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-06 13:27:54 +02:00
Vincent Demeester
ef72d355d6 Merge pull request #283 from containous/fix-openssl-travis
Fix SSH key
2016-04-06 00:46:30 +02:00
Emile Vauge
7d013ad5e8 Fix SSH key
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-05 22:40:42 +02:00
Vincent Demeester
5fcce6567e Merge pull request #282 from containous/fix-openssl-travis
Fix openssl travis
2016-04-05 22:24:25 +02:00
Emile Vauge
00af537b0d Fix link in README
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-05 22:07:16 +02:00
Emile Vauge
78449fa62f Fix openssl load key in CI
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-05 20:47:23 +02:00
Vincent Demeester
ab0d648a03 Merge pull request #280 from containous/add-doc-site
Add docs.traefik.io
2016-04-05 17:26:26 +02:00
Emile Vauge
43d2107493 Add mkdoc in CI
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-05 17:13:08 +02:00
Emile Vauge
fd8b4a3305 add documentation website
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-05 17:13:08 +02:00
Emile Vauge
79dc4f9a70 Merge pull request #277 from vdemeester/micro-libkermit-update
Update libkermit again for compose enhancements
2016-04-04 10:34:43 +02:00
Vincent Demeester
b0fa11b8b8 Update libkermit again for compose enhancements
Using `.Container(…)`, it's way easier to get the container from a
project's service.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-04-02 15:33:12 +02:00
Emile Vauge
6e7bb93fd6 Merge pull request #276 from vdemeester/mini-kermit-update
A small update of libkermit
2016-04-02 13:26:16 +02:00
Vincent Demeester
e1448eb238 A small update of libkermit
Using compose/check package (and less code)

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-04-02 12:40:21 +02:00
Emile Vauge
585aeb8f0b Merge pull request #272 from wallies/patch-1
Add Go Report Card badge
2016-04-01 14:41:18 +02:00
Cameron
563823189a Merge branch 'master' into patch-1 2016-04-01 13:28:51 +01:00
Vincent Demeester
e9bf916a74 Merge pull request #270 from containous/fix-acme-renew
Fix acme renew panic
2016-04-01 14:12:18 +02:00
Emile Vauge
bcc5f24c0f Add GoSafe goroutine launch
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-04-01 14:01:31 +02:00
Cameron
9462c2e476 Add Go Report Card badge 2016-04-01 12:43:55 +01:00
Emile Vauge
af41c79798 Fix acme renew panic
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-31 17:21:05 +02:00
Vincent Demeester
733cbb5304 Merge pull request #266 from containous/refactor-frontend-rules
Refactor frontends rules
2016-03-31 16:29:51 +02:00
Emile Vauge
d5e1d2efd5 Fix documentation
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-31 16:17:59 +02:00
Emile Vauge
bb072a1f8f Add backwards compatibility
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-31 13:11:18 +02:00
Emile Vauge
8737530a7d Refactor frontends rules
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-31 13:11:07 +02:00
Vincent Demeester
dd160dc342 Merge pull request #267 from containous/add-retries
add retries request
2016-03-30 19:04:39 +02:00
Emile Vauge
4a9e82903e add retries request
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-29 22:25:32 +02:00
Vincent Demeester
1d040dbdd2 Merge pull request #265 from antoinecarton/master
Fix typo
2016-03-29 11:12:18 +02:00
Antoine Carton
e4db9c72dd Fix typo 2016-03-28 20:54:06 +02:00
Emile Vauge
6308ce2740 Merge pull request #264 from vdemeester/libkermit-integration
Libkermit integration 😇
2016-03-28 19:16:37 +02:00
Vincent Demeester
87bad71bec Use libkermit for integration test
Using the compose package for starting and stopping project.
2016-03-27 19:58:08 +02:00
Vincent Demeester
50f09c8e4d Move Suite definition to their respective file 2016-03-27 16:27:56 +02:00
Emile Vauge
bb1ecdd3c9 Merge pull request #262 from containous/fix-marathon-exposedByDefault
Add exposedByDefault doc
2016-03-25 11:14:19 +01:00
Emile Vauge
a2c3e6e405 Add exposedByDefault doc
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-25 10:38:41 +01:00
Emile Vauge
cddbb44c75 Merge pull request #259 from vdemeester/few-build-adjustements
Add a verbose mode to builds
2016-03-24 00:50:09 +01:00
Vincent Demeester
7aa0c91401 Add a verbose mode to builds
Using the VERBOSE environment variable, tests and binary compilation are
ran in verbose mode (using -v), but by default there are more quiet O:).

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-03-23 23:06:22 +01:00
Vincent Demeester
6bfc849a24 Merge pull request #224 from containous/add-lets-encrypt-suppport
Add let's encrypt support
2016-03-23 16:52:21 +01:00
Emile Vauge
ac4aa0d182 add errcheck validation
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-23 16:39:09 +01:00
Emile Vauge
d9ffc39075 add acme package, refactor acme as resuable API
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-22 00:12:43 +01:00
Emile Vauge
87e8393b07 Fix tests with lets encrypt
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-21 20:15:28 +01:00
Emile Vauge
1ab9c82dfb Let's Encrypt Doc
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-21 20:15:28 +01:00
Emile Vauge
6e484e5c2d add let's encrypt support
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-21 20:15:28 +01:00
Emile Vauge
087b68e14d Merge pull request #251 from sample/master
Add defaultExpose option to marathon section
2016-03-21 14:01:57 +01:00
Nikita Borzykh
c313950891 Add exposedByDefault option to marathon section 2016-03-21 12:37:02 +03:00
Vincent Demeester
7716d3377a Merge pull request #256 from containous/move-to-containous-oxy
Move to containous/oxy
2016-03-16 11:41:20 +01:00
Emile Vauge
0cbe34eef3 Move to containous/oxy, remove websocket specific support
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-15 23:42:52 +01:00
Vincent Demeester
08d8c334a3 Merge pull request #255 from containous/Fix-remove-travis-build-tag
Avoid travis building on tags
2016-03-14 18:28:51 +01:00
Emile Vauge
d75a151df3 Avoid travis building on tags
due to https://github.com/travis-ci/travis-ci/issues/1532
2016-03-14 17:36:12 +01:00
Emile Vauge
10e223ede2 Merge pull request #246 from keis/new-style-argument-systemd
Update systemd service file with new cli flags
2016-03-14 16:53:05 +01:00
David Keijser
6a8bacf01c Update systemd service file with new cli flags 2016-03-14 16:34:31 +01:00
Emile Vauge
d4cc3900bd Merge pull request #250 from containous/bump-beta-semver
Bump to beta, using semver
2016-03-09 23:55:26 +01:00
Emile Vauge
ab619a4a3f Bump to beta, using semver
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-09 23:40:01 +01:00
Emile Vauge
4c447985b6 Merge pull request #247 from containous/fix-redirect-bug
fixes redirect bug en port 80
2016-03-09 19:54:16 +01:00
Emile Vauge
eaadd2d0cd fixes redirect bug en port 80 2016-03-09 18:59:08 +01:00
Emile Vauge
9830086790 Merge pull request #242 from containous/fix-old-docker-repo
Fix push to old docker repo emilevauge/traefik
2016-03-08 17:24:26 +01:00
Emile Vauge
8393746e02 Fix benchmarks 2016-03-08 16:27:12 +01:00
Emile Vauge
2314ad9bf9 Fix push to old docker repo emilevauge/traefik 2016-03-08 13:16:58 +01:00
Vincent Demeester
3af21612b6 Merge pull request #239 from goguardian/kv-watch-tree
Support libkv.WatchTree chan errors:
2016-03-05 21:58:48 +01:00
Advait Shinde
7674a82801 Fatalf for timeout cases. 2016-03-05 20:43:44 +00:00
Advait Shinde
d63d2a8a26 Support libkv.WatchTree chan errors:
- libkv.WatchTree returns a channel whose messages represent changes
    to the watched tree. In situations where libkv cannot read from the
    underlying store, libkv will close the provided channel.
  - This PR handles this edge case and fixes #238.
2016-03-05 20:38:33 +00:00
Vincent Demeester
a458018aa2 Merge pull request #240 from containous/update-benchmarks
update benchmarks with haproxy and latest results
2016-03-05 18:39:00 +01:00
Emile Vauge
33cde6aacd update benchmarks with haproxy and latest results
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-05 13:34:18 +01:00
Vincent Demeester
4ded2682d2 Merge pull request #235 from containous/refactor-hot-reload
Refactor hot reload
2016-03-04 16:41:45 +01:00
Emile Vauge
4042938556 add handler switcher instead of Manners
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-04 15:55:28 +01:00
Vincent Demeester
0e683cc535 Merge pull request #234 from thermeon/feature/quick_typo
Fix typo Unkown -> unknown in error
2016-03-04 09:01:49 +01:00
Gareth Kirwan
4923da7f4d Fix typo Unkown -> unknown in error 2016-03-03 20:29:52 +00:00
Vincent Demeester
11781087ca Merge pull request #230 from tayzlor/marathon-event-stream
Use event stream API instead of event subscriptions
2016-03-02 15:24:43 +01:00
Graham Taylor
3063251d43 Use event stream API instead of event subscriptions 2016-03-02 09:22:14 +00:00
Vincent Demeester
b42b170ad2 Merge pull request #227 from containous/fix-docker-network
Fix docker network
2016-03-01 13:12:08 +01:00
Emile Vauge
defbb44b35 Fix docker network
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-03-01 11:52:30 +00:00
Emile Vauge
a00eb81f03 Merge pull request #228 from ProPheT777/patch-1
My $0.02 - Center gopher
2016-02-29 19:35:47 +01:00
Johann Saunier
a63d989a35 My $0.02 - Center gopher 2016-02-29 18:27:09 +01:00
Vincent Demeester
6c3c5578c6 Merge pull request #225 from containous/add-path-prefix
Add PathPrefixStrip and PathStrip rules
2016-02-26 16:52:12 +01:00
Emile Vauge
122783e36b Add PathPrefixStrip and PathStrip rules
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-02-26 15:58:55 +01:00
Emile Vauge
b84b95fe97 Merge pull request #223 from goguardian/kv-multi
Support multiple endpoints for KV stores:
2016-02-26 11:41:18 +01:00
Advait Shinde
a99010b8c2 Create an integration test for Etcd:
- Integration test specifically spins up an Etcd cluster with three
    nodes.
2016-02-25 23:34:51 +00:00
Advait Shinde
8954aa7118 Update docs to mention commas. 2016-02-25 23:34:51 +00:00
Advait Shinde
3cf848958f Support multiple endpoints for KV stores:
- Fixes #222
2016-02-25 23:34:51 +00:00
Vincent Demeester
1a5668377c Merge pull request #209 from tboerger/feature/tls-auth
Integrated TLS auth for etcd and consul
2016-02-25 10:58:23 +01:00
Thomas Boerger
dc10c56b35 Integrated TLS auth for etcd and consul 2016-02-24 23:32:34 +01:00
Vincent Demeester
331cd173ce Merge pull request #220 from containous/transfer-repo-to-containous-org
Transfer emilevauge/traefik to containous/traefik
2016-02-24 22:22:57 +01:00
Emile Vauge
1881d5eeed Transfer emilevauge/traefik to containous/traefik
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-02-24 17:38:36 +01:00
Vincent Demeester
e0872b6157 Merge pull request #219 from emilevauge/add-traefik-library-image
Add publish to traefik-library-image
2016-02-24 16:11:15 +01:00
Emile Vauge
63fb9c7135 publish binary to traefik-library-image repo
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-02-24 15:48:03 +01:00
Vincent Demeester
9964654495 Merge pull request #183 from keis/consul-catalog
WIP consul catalog provider
2016-02-24 09:35:26 +01:00
David Keijser
ae275c9e60 Consul catalog provider
Fixes #176
2016-02-24 09:23:27 +01:00
David Keijser
4277fe2fdb Bump libcompose 2016-02-24 09:23:27 +01:00
Vincent Demeester
7acc2beae0 Merge pull request #214 from octoblu/add-frontend-determinism
Deterministic frontend registration
2016-02-24 00:05:03 +01:00
Roy van de Water
847deeac79 Deterministic frontend registration
Conflicts:
	server.go
2016-02-22 13:37:54 -07:00
Emile Vauge
ac56c1310c Merge pull request #206 from emilevauge/add-partners
Add partners
2016-02-22 17:33:28 +01:00
emile
7460b343fe Cleanup configuration management 2016-02-22 17:15:45 +01:00
emile
ec16011e31 Add partners, move contributing 2016-02-22 16:26:20 +01:00
emile
71b0e27517 bash instead? 2016-02-22 16:03:57 +01:00
emile
60e9282f0a fixes typo ghr 2016-02-22 15:35:51 +01:00
emile
6cd35a50ce after succes make deploy 2016-02-22 15:17:14 +01:00
emile
b35ad76ec6 rewrite deploy tests 2016-02-22 15:01:00 +01:00
emile
54208f6fc3 travis after_success instead of deploy
Signed-off-by: emile <emile@vauge.com>
2016-02-22 14:33:46 +01:00
emile
6282bf33a0 travis skip_cleanup
Signed-off-by: emile <emile@vauge.com>
2016-02-22 14:11:17 +01:00
Emile Vauge
a1c1958235 Merge pull request #208 from emilevauge/migrate-on-travisci
Migrate on travisci
2016-02-22 13:35:00 +01:00
emile
91b699fbe0 Migrate CI to travis
- Add travis build file
- Use golang alpine image
- Clean scripts a little bit
- Disable CGO for test-integration >_<
2016-02-22 12:20:56 +01:00
Vincent Demeester
3a08655b06 Merge pull request #188 from emilevauge/add-marathon-tls-client-config
Add Marathon TLS client config
2016-02-18 14:23:38 +01:00
emile
9a9c8e5709 Add Marathon TLS client config
Signed-off-by: emile <emile@vauge.com>
2016-02-18 12:42:59 +00:00
Vincent Demeester
c7d34b54aa Merge pull request #205 from emilevauge/bump-go-1.6
Bump go 1.6
2016-02-18 11:07:18 +01:00
emile
8d860c84c8 Add HTTP2 support
Signed-off-by: emile <emile@vauge.com>
2016-02-18 10:31:56 +01:00
emile
1dc086730e Bump golang 1.6 2016-02-18 10:30:41 +01:00
Emile Vauge
5d79e56d30 Merge pull request #193 from dontrebootme/fix192
fix mantl url typo
2016-02-17 23:05:26 +01:00
Vincent Demeester
6e7677de79 Merge pull request #203 from goguardian/alias
Implement `/traefik/alias` for KV stores.
2016-02-17 09:56:43 +01:00
Patrick O'Connor
fab6b8be3c fix mantl url typo 2016-02-16 12:30:33 -08:00
Advait Shinde
f1c1eed437 Fix typo in documentation 2016-02-16 11:55:42 -05:00
Advait Shinde
348ab794c9 Add documentation for /traefik/alias. 2016-02-15 18:46:03 -05:00
Advait Shinde
aacedcc4b3 Implement /traefik/alias for KV stores. 2016-02-15 18:14:57 -05:00
Emile Vauge
786acc961a Merge pull request #200 from vdemeester/some-fixes
Do some build / test-integration fixes
2016-02-13 16:33:42 +01:00
Vincent Demeester
7adffdbd78 Run npm in quiet mode O:)
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-02-13 16:14:26 +01:00
Vincent Demeester
e3b519cdd8 Do some build / test-integration fixes
- target generate-webui depends on build-webui
- generate-webui will run only if the folder static does not exists
- create compose project before starting it >_<'', otherwise it does
  nothing :'D

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-02-13 16:04:08 +01:00
Vincent Demeester
e9c23195a0 Merge pull request #195 from emilevauge/fix-regression-marathon-backends
Fix regression on marathon backend
2016-02-12 15:31:59 +01:00
emile
c6c3af8099 Fix regression on marathon backend
Signed-off-by: emile <emile@vauge.com>
2016-02-12 15:03:28 +01:00
Emile Vauge
07c077cf94 Merge pull request #189 from vdemeester/fix-make-all
Fix make all
2016-02-10 14:10:26 +01:00
Vincent Demeester
4ac18f1989 Fix make all
Add build-ui as dependent target for all. Otherwise it does not build >_<

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-02-10 13:55:47 +01:00
Vincent Demeester
4ecb919787 Merge pull request #178 from emilevauge/add-multiple-entrypoints-support
Add multiple entry points support
2016-02-10 13:54:30 +01:00
emile
4152bd5e26 Update doc with entrypoints 2016-02-10 12:18:50 +01:00
emile
a8cc26fd91 Add entrypoints to providers 2016-02-10 12:14:16 +01:00
emile
81cb00573f Fix tests to accept entrypoints 2016-02-10 12:14:16 +01:00
emile
c22598c8ff Add multiple entry points support, add entry point redirection 2016-02-10 12:14:16 +01:00
Vincent Demeester
bb3b9f61cd Merge pull request #187 from emilevauge/add-max-idle-conns-per-host
Add MaxIdleConnsPerHost. Fixes too many open files error.
2016-02-09 22:49:03 +01:00
emile
49cd7f799e Add MaxIdleConnsPerHost. Fixes too many open files error. 2016-02-09 22:29:01 +01:00
Vincent Demeester
8b334551d8 Merge pull request #185 from ReadmeCritic/master
Update README URLs based on HTTP redirects
2016-02-08 19:15:41 +01:00
ReadmeCritic
5ef6d53d00 Update README URLs based on HTTP redirects 2016-02-08 07:43:43 -08:00
Vincent Demeester
901c9b29bc Merge pull request #171 from tayzlor/fix-170-marathon-getbackend
Fix #170 - getBackend for marathon plugin
2016-02-06 14:06:42 +01:00
Graham Taylor
2d79c500df Fix #170 - lookup backend for marathon plugin so we can specify traefik.backend via labels on the container 2016-02-05 18:01:47 +00:00
Vincent Demeester
d3598021b7 Merge pull request #184 from dontrebootme/master
Updated getEscapedName with slash to dash instead of space
2016-02-03 22:09:52 +01:00
Patrick O'Connor
31e0340959 Updated getEscapedName with slash to dash instead of space
Remove only the first slash, convert the rest to dash
2016-02-03 12:07:08 -08:00
Emile Vauge
cb46e8751b Merge pull request #177 from Hugues-Antoine/master
Updating documentation to make a more explicit usage of the traefik.frontend.rule rule when combined with traefik.frontend.value
2016-01-29 19:46:12 +01:00
Hugues-Antoine
739a836c52 Updating documentation to make a more explicit usage of the traefik.frontend.rule rule when combined with traefik.frontend.value 2016-01-29 18:59:31 +01:00
Vincent Demeester
1cbe00d613 Merge pull request #161 from emilevauge/add-env-args
Add environnement variables and arguments configuration
2016-01-29 11:49:33 +01:00
Vincent Demeester
10d92ca176 Merge branch 'master' into add-env-args 2016-01-29 11:34:15 +01:00
Vincent Demeester
257dbd188f Merge pull request #174 from ldez/feature/clean-static
refactor(webui): better build command
2016-01-27 22:55:22 +01:00
Fernandez Ludovic
38cc0579a6 refactor: add static to gitignore 2016-01-27 22:38:48 +01:00
Fernandez Ludovic
a9c8cda5ec refactor: remove static folder 2016-01-27 22:38:47 +01:00
Fernandez Ludovic
06654ff3a6 chore(webui): better build command
- clean before build (mode force)
- update documentation
- update `Makefile`
- ordering build
2016-01-27 22:38:10 +01:00
emile
f1b62b45f4 Fixes following review 2016-01-27 19:47:20 +01:00
emile
8adadaa5d4 Add launch configuration documentation 2016-01-27 13:56:46 +01:00
emile
35070f7c1c Use of Viper and cobra 2016-01-27 13:56:46 +01:00
emile
a0b15a0efd Main file refactoring, extract a Server object 2016-01-27 13:55:40 +01:00
Emile Vauge
b906e9361f Merge pull request #175 from emilevauge/glide-quick
Glide up quick
2016-01-27 11:18:09 +01:00
emile
ec2d7efe0e Add --quick to glide up 2016-01-27 11:00:13 +01:00
Emile Vauge
81e9fdfe75 Merge pull request #172 from keis/sysd-service
Add minimal systemd service file
2016-01-22 18:33:43 +01:00
David Keijser
465bb133c7 Add minimal systemd service file 2016-01-22 14:46:38 +01:00
Vincent Demeester
c15d7e03b4 Merge pull request #149 from ldez/feature/webui-reload
New build system for Web UI
2016-01-21 10:17:17 +01:00
Fernandez Ludovic
5bfcfeb779 feat: build static file in global process
- Create a webui DockerFile
- add task `generate-webui`
- use task `generate-webui` in build process
2016-01-20 23:24:19 +01:00
Fernandez Ludovic
faa7fd0f05 docs(webui): add more documentation 2016-01-20 20:06:07 +01:00
Fernandez Ludovic
ab50b10d1b feat: generate new static files
- use new build system for generate static files
2016-01-20 20:06:07 +01:00
Fernandez Ludovic
b7a71edfcb feat: new Web UI build system
- use generator-gulp-angular by @swiip
- remove old static file
2016-01-20 20:06:07 +01:00
Vincent Demeester
587b17c120 Merge pull request #168 from emilevauge/add-marathon-basic-authentication
Add basic authentication support in Marathon
2016-01-19 09:17:01 +01:00
emile
c46ffed846 Add basic authentication support in Marathon 2016-01-18 13:23:38 +01:00
Vincent Demeester
707b6f9a95 Merge pull request #166 from danzel/patch-1
Consul config doesn't need "http://"
2016-01-15 09:04:12 +01:00
Dave Leaver
4bdc704a25 http here doesn't work 2016-01-15 11:53:13 +13:00
Emile Vauge
c0fd700904 Merge pull request #164 from vdemeester/bump-go
Bump Go 1.5.3
2016-01-14 16:00:51 +01:00
Vincent Demeester
72177c676e Bump Go 1.5.3
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-01-14 15:45:23 +01:00
Vincent Demeester
784fd74d3f Merge pull request #138 from dylanmei/marathon_uses_port_from_label
Marathon provider uses port from label.
2016-01-13 08:30:00 +01:00
Dylan Meissner
cfbd43d1ee Marathon provider uses port or portIndex from label. 2016-01-12 06:46:29 -08:00
Vincent Demeester
f10bbd8c69 Merge pull request #153 from PierreZ/master
Fix Issue #150: Add possibility to have REST API in read-only mode
2016-01-09 00:32:53 +01:00
Pierre Zemb
6bcb6f92f5 Update Doc about read-only mode 2016-01-03 20:45:53 +01:00
PierreZ
f6b5684a5b adding read only mode 2016-01-03 20:42:09 +01:00
Vincent Demeester
866e8db5f7 Merge pull request #137 from dylanmei/marathon_route_names_with_slashes
Marathon tmpl converts slashes in Marathon app names to dashes
2015-12-07 22:12:45 +01:00
Dylan Meissner
a9925c7521 The included Marathon tmpl converts multiple slashes in Marathon app names to dashes. 2015-12-05 10:02:39 -08:00
Vincent Demeester
f955cc33c5 Merge pull request #134 from emilevauge/add-getBool-kvprovider-or-not
Removes getBool from kv provider
2015-12-04 09:41:36 +01:00
emile
e728f32a15 Removes getBool from kv provider, fixes https://github.com/emilevauge/traefik/issues/117 2015-12-04 09:28:43 +01:00
Vincent Demeester
4abb4c6489 Merge pull request #135 from ViBiOh/master
Adding expose for default port
2015-12-03 17:45:22 +01:00
Vincent Boutour
66998e60b8 Adding expose for default port 2015-12-03 17:15:01 +01:00
Vincent Demeester
71288e5799 Merge pull request #123 from emilevauge/alltasks-status-marathon
Add filter task by running status in marathon
2015-12-02 09:49:28 +01:00
emile
8fdd0b20d1 Add filter task by running status in marathon 2015-12-01 22:53:31 +01:00
Emile Vauge
4e9ff45747 Merge pull request #121 from janeczku/sni-support
Add TLS SNI support
2015-12-01 22:52:27 +01:00
Jan Broer
d6e28a923c Adds TLS SNI support for the frontends 2015-12-01 22:26:17 +01:00
Vincent Demeester
1604786285 Merge pull request #126 from emilevauge/lock-prepareserver
Add mutex around prepareserver
2015-11-24 10:20:44 +01:00
emile
35cb9100cd Add mutex around prepareserver 2015-11-24 09:12:20 +01:00
Vincent Demeester
4729e3e999 Merge pull request #124 from emilevauge/panic-bad-configuration
Add check in invoked method
2015-11-23 20:54:16 +01:00
emile
b0e66a4aa6 Add check invoked method 2015-11-23 16:06:47 +01:00
Vincent Demeester
4218467ab3 Merge pull request #122 from emilevauge/add-getBool-kvprovider
Add GetBool function in KV provider, used by passHostHeader
2015-11-23 08:38:35 +01:00
emile
6e62625ebf Add GetBool function in KV provider, used by passHostHeader 2015-11-22 23:39:43 +01:00
Vincent Demeester
c8a0a83e2b Merge pull request #120 from starpost/docker-tls
Docker TLS support
2015-11-20 18:51:36 +01:00
KM Tong
76bd04e349 Merge branch 'master' into docker-tls 2015-11-20 23:13:26 +08:00
唐家文
a8a78b8ea3 docker TLS support 2015-11-20 23:05:06 +08:00
Emile Vauge
3435ebfe42 Merge pull request #108 from vdemeester/refactor-providers-with-test
Refactor providers and add unit tests
2015-11-19 19:42:03 +01:00
Vincent Demeester
4d485e1b6b Refactor providers and add tests
- Add a `baseProvider` struct with common
- Refactor docker, kv(s) and marathon providers (spliting into small pieces)
- Add unit tests

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2015-11-19 17:22:17 +01:00
Vincent Demeester
3f905ee7d0 Merge pull request #112 from bennyhansson/master
Add passHostHeader to kv frontend definition.
2015-11-17 16:28:59 +01:00
Benny Hansson
e90cb6b53b Add passHostHeader to frontend definition. 2015-11-16 22:51:52 +01:00
Vincent Demeester
400655f212 Merge pull request #109 from polds/docker/clean-frontend
Replace [ and ] in frontend names
2015-11-13 09:35:14 +01:00
Peter Olds
481a4b2096 Replace [ and ] in frontend names
Signed-off-by: Peter Olds <polds@kyanicorp.com>
2015-11-12 17:04:19 -07:00
Emile Vauge
85bbd49798 Merge pull request #96 from vdemeester/validate-golint
Add validate-golint target and script …
2015-11-08 20:05:01 +01:00
Vincent Demeester
40391c57c2 Add validate-golint target and script …
… and *lint* the latest piece of code.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2015-11-06 18:11:57 +01:00
Emile Vauge
7607eb173b Merge pull request #94 from vdemeester/fix-labels-docker
Fix docker labels (frontend.*) non-presence
2015-11-05 15:50:30 +01:00
Vincent Demeester
15318c4631 Fix docker labels (frontend.*)
Using Docker provider, you can specify `traefik.frontend.rule` and
`traefik.frontend.value` labels. If they are not both provided, there is
a default behavior. On the current master, if they are not defined, the
container is filtered (and thus the default behavior is broken).

Fixes that.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2015-11-05 15:14:25 +01:00
344 changed files with 47066 additions and 4092 deletions

View File

@@ -1,3 +1,5 @@
dist/
vendor/
!dist/traefik
site/
**/*.test

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
glide.lock binary

146
.github/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,146 @@
# Contributing
### Building
You need either [Docker](https://github.com/docker/docker) and `make` (Method 1), or `go` and `glide` (Method 2) in order to build traefik.
#### Method 1: Using `Docker` and `Makefile`
You need to run the `binary` target. This will create binaries for Linux platform in the `dist` folder.
```bash
$ make binary
docker build -t "traefik-dev:no-more-godep-ever" -f build.Dockerfile .
Sending build context to Docker daemon 295.3 MB
Step 0 : FROM golang:1.7
---> 8c6473912976
Step 1 : RUN go get github.com/Masterminds/glide
[...]
docker run --rm -v "/var/run/docker.sock:/var/run/docker.sock" -it -e OS_ARCH_ARG -e OS_PLATFORM_ARG -e TESTFLAGS -v "/home/emile/dev/go/src/github.com/containous/traefik/"dist":/go/src/github.com/containous/traefik/"dist"" "traefik-dev:no-more-godep-ever" ./script/make.sh generate binary
---> Making bundle: generate (in .)
removed 'gen.go'
---> Making bundle: binary (in .)
$ ls dist/
traefik*
```
#### Method 2: Using `go` and `glide`
###### Setting up your `go` environment
- You need `go` v1.7+
- It is recommended you clone Træfɪk into a directory like `~/go/src/github.com/containous/traefik` (This is the official golang workspace hierarchy, and will allow dependencies to resolve properly)
- This will allow your `GOPATH` and `PATH` variable to be set to `~/go` via:
```
$ export GOPATH=~/go
$ export PATH=$PATH:$GOPATH/bin
```
This can be verified via `$ go env`
- You will want to add those 2 export lines to your `.bashrc` or `.bash_profile`
- You need `go-bindata` to be able to use `go generate` command (needed to build) : `$ go get github.com/jteeuwen/go-bindata/...` (Please note, the ellipses are required)
###### Setting up your `glide` environment
- Glide can be installed either via homebrew: `$ brew install glide` or via the official glide script: `$ curl https://glide.sh/get | sh`
The idea behind `glide` is the following :
- when checkout(ing) a project, run `$ glide install -v` from the cloned directory to install
(`go get …`) the dependencies in your `GOPATH`.
- if you need another dependency, import and use it in
the source, and run `$ glide get github.com/Masterminds/cookoo` to save it in
`vendor` and add it to your `glide.yaml`.
```bash
$ glide install --strip-vendor
# generate (Only required to integrate other components such as web dashboard)
$ go generate
# Standard go build
$ go build
# Using gox to build multiple platform
$ gox "linux darwin" "386 amd64 arm" \
-output="dist/traefik_{{.OS}}-{{.Arch}}"
# run other commands like tests
```
### Tests
##### Method 1: `Docker` and `make`
You can run unit tests using the `test-unit` target and the
integration test using the `test-integration` target.
```bash
$ make test-unit
docker build -t "traefik-dev:your-feature-branch" -f build.Dockerfile .
# […]
docker run --rm -it -e OS_ARCH_ARG -e OS_PLATFORM_ARG -e TESTFLAGS -v "/home/vincent/src/github/vdemeester/traefik/dist:/go/src/github.com/containous/traefik/dist" "traefik-dev:your-feature-branch" ./script/make.sh generate test-unit
---> Making bundle: generate (in .)
removed 'gen.go'
---> Making bundle: test-unit (in .)
+ go test -cover -coverprofile=cover.out .
ok github.com/containous/traefik 0.005s coverage: 4.1% of statements
Test success
```
For development purposes, you can specify which tests to run by using:
```
# Run every tests in the MyTest suite
TESTFLAGS="-check.f MyTestSuite" make test-integration
# Run the test "MyTest" in the MyTest suite
TESTFLAGS="-check.f MyTestSuite.MyTest" make test-integration
# Run every tests starting with "My", in the MyTest suite
TESTFLAGS="-check.f MyTestSuite.My" make test-integration
# Run every tests ending with "Test", in the MyTest suite
TESTFLAGS="-check.f MyTestSuite.*Test" make test-integration
```
More: https://labix.org/gocheck
##### Method 2: `go` and `glide`
- Tests can be run from the cloned directory, by `$ go test ./...` which should return `ok` similar to:
```
ok _/home/vincent/src/github/vdemeester/traefik 0.004s
```
- Note that `$ go test ./...` will run all tests (including the ones in the vendor directory for the dependencies that glide have fetched). If you only want to run the tests for traefik use `$ go test $(glide novendor)` instead.
### Documentation
The [documentation site](http://docs.traefik.io/) is built with [mkdocs](http://mkdocs.org/)
First make sure you have python and pip installed
```
$ python --version
Python 2.7.2
$ pip --version
pip 1.5.2
```
Then install mkdocs with pip
```
$ pip install mkdocs
```
To test documentation locally run `mkdocs serve` in the root directory, this should start a server locally to preview your changes.
```
$ mkdocs serve
INFO - Building documentation...
WARNING - Config value: 'theme'. Warning: The theme 'united' will be removed in an upcoming MkDocs release. See http://www.mkdocs.org/about/release-notes/ for more details
INFO - Cleaning site directory
[I 160505 22:31:24 server:281] Serving on http://127.0.0.1:8000
[I 160505 22:31:24 handlers:59] Start watching changes
[I 160505 22:31:24 handlers:61] Start detecting changes
```

13
.github/ISSUE_TEMPLATE vendored Normal file
View File

@@ -0,0 +1,13 @@
### What version of Traefik are you using (`traefik version`)?
### What is your environment & configuration (arguments, toml...)?
### What did you do?
### What did you expect to see?
### What did you see instead?

26
.github/cpr.sh vendored Executable file
View File

@@ -0,0 +1,26 @@
#!/bin/sh
#
# git config --global alias.cpr '!sh .github/cpr.sh'
set -e # stop on error
usage="$(basename "$0") pr -- Checkout a Pull Request locally"
if [ "$#" -ne 1 ]; then
echo "Illegal number of parameters"
echo "$usage" >&2
exit 1
fi
command -v jq >/dev/null 2>&1 || { echo "I require jq but it's not installed. Aborting." >&2; exit 1; }
set -x # echo on
initial=$(git rev-parse --abbrev-ref HEAD)
pr=$1
remote=$(curl -s https://api.github.com/repos/containous/traefik/pulls/$pr | jq -r .head.repo.owner.login)
branch=$(curl -s https://api.github.com/repos/containous/traefik/pulls/$pr | jq -r .head.ref)
git remote add $remote git@github.com:$remote/traefik.git
git fetch $remote $branch
git checkout -t $remote/$branch

27
.github/rmpr.sh vendored Executable file
View File

@@ -0,0 +1,27 @@
#!/bin/sh
#
# git config --global alias.rmpr '!sh .github/rmpr.sh'
set -e # stop on error
usage="$(basename "$0") pr -- remove a Pull Request local branch & remote"
if [ "$#" -ne 1 ]; then
echo "Illegal number of parameters"
echo "$usage" >&2
exit 1
fi
command -v jq >/dev/null 2>&1 || { echo "I require jq but it's not installed. Aborting." >&2; exit 1; }
set -x # echo on
initial=$(git rev-parse --abbrev-ref HEAD)
pr=$1
remote=$(curl -s https://api.github.com/repos/containous/traefik/pulls/$pr | jq -r .head.repo.owner.login)
branch=$(curl -s https://api.github.com/repos/containous/traefik/pulls/$pr | jq -r .head.ref)
# clean
git checkout $initial
git branch -D $branch
git remote remove $remote

36
.github/rpr.sh vendored Executable file
View File

@@ -0,0 +1,36 @@
#!/bin/sh
#
# git config --global alias.rpr '!sh .github/rpr.sh'
set -e # stop on error
usage="$(basename "$0") pr remote/branch -- rebase a Pull Request against a remote branch"
if [ "$#" -ne 2 ]; then
echo "Illegal number of parameters"
echo "$usage" >&2
exit 1
fi
command -v jq >/dev/null 2>&1 || { echo "I require jq but it's not installed. Aborting." >&2; exit 1; }
set -x # echo on
initial=$(git rev-parse --abbrev-ref HEAD)
pr=$1
base=$2
remote=$(curl -s https://api.github.com/repos/containous/traefik/pulls/$pr | jq -r .head.repo.owner.login)
branch=$(curl -s https://api.github.com/repos/containous/traefik/pulls/$pr | jq -r .head.ref)
clean ()
{
git checkout $initial
.github/rmpr.sh $pr
}
trap clean EXIT
.github/cpr.sh $pr
git rebase $base
git push -f $remote $branch

8
.gitignore vendored
View File

@@ -1,9 +1,15 @@
/dist
gen.go
.idea
log
.intellij
*.iml
traefik
traefik.toml
*.test
vendor/
static/
.vscode/
site/
*.log
*.exe
.DS_Store

10
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,10 @@
- repo: git://github.com/pre-commit/pre-commit-hooks
sha: 44e1753f98b0da305332abe26856c3e621c5c439
hooks:
- id: detect-private-key
- repo: git://github.com/containous/pre-commit-hooks
sha: 35e641b5107671e94102b0ce909648559e568d61
hooks:
- id: goFmt
- id: goLint
- id: goErrcheck

67
.travis.yml Normal file
View File

@@ -0,0 +1,67 @@
sudo: required
dist: trusty
services:
- docker
env:
global:
- secure: btt4r13t09gQlHb6gYrvGC2yGCMMHfnp1Mz1RQedc4Mpf/FfT8aE6xmK2a2i9CCvskjrP0t/BFaS4yxIURjnFRn+ugQIEa0pLspB9UJArW/vgOSpIWM9/OQ/fg8z5XuMxN6Md4DL1/iLypMNSageA1x0TRdt89+D1N1dALpg5XRCXLFbC84TLi0gjlFuib9ibPKzEhLT+anCRJ6iZMzeupDSoaCVbAtJMoDvXw4+4AcRZ1+k4MybBLyCib5boaEOt4pTT88mz4Kk0YaMwPVJyg9Qv36VqyUcPS09Yd95LuyVQ4+tZt8Y1ccbIzULsK+sLM3hLCzxlmlpN3dQBlZJiiRtQde0mgGAKyC0P0A1XjuDTywcsa5edB+fTk1Dsewz9xZ9V0NmMz8t+UNZnaSsAPga9i86jULbXUUwMVSzVRc+Xgx02liB/8qI1xYC9FM6ilStt7rn7mF0k3KbiWhcptgeXjO6Lah9FjEKd5w4MXsdUSTi/86rQaLo+kj+XdaTrXCTulKHyRyQEUj+8V1w0oVz7pcGjePHd7y5oU9ByifVQy6sytuFBfRZvugM5bKHo+i0pcWvixrZS42DrzwxZJsspANOvqSe5ifVbvOkfUppQdCBIwptxV5N1b49XPKU3W/w34QJ8xGmKp3TFA7WwVCztriFHjPgiRpB3EG99Bg=
- REPO: $TRAVIS_REPO_SLUG
- VERSION: $TRAVIS_TAG
- CODENAME: morbier
matrix:
fast_finish: true
include:
- env: DOCKER_VERSION=1.10.3
- env: DOCKER_VERSION=1.12.6
before_install:
- sudo -E apt-get -yq update
- sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install docker-engine=${DOCKER_VERSION}*
install:
- docker version
- pip install --user -r requirements.txt
before_script:
- make validate
- make binary
script:
- travis_retry make test-unit
- travis_retry make test-integration
after_failure:
- docker ps
after_success:
- make crossbinary
- make image
before_deploy:
- mkdocs build --clean
- tar cfz dist/traefik-${VERSION}.src.tar.gz --exclude-vcs --exclude dist .
deploy:
- provider: pages
edge: true
github_token: ${GITHUB_TOKEN}
local_dir: site
skip_cleanup: true
on:
repo: containous/traefik
tags: true
- provider: releases
api_key: ${GITHUB_TOKEN}
file: dist/traefik*
skip_cleanup: true
file_glob: true
on:
repo: containous/traefik
tags: true
- provider: script
script: sh script/deploy.sh
skip_cleanup: true
on:
repo: containous/traefik
tags: true
- provider: script
script: sh script/deploy-docker.sh
skip_cleanup: true
on:
repo: containous/traefik

BIN
.travis/traefik.id_rsa.enc Normal file

Binary file not shown.

880
CHANGELOG.md Normal file
View File

@@ -0,0 +1,880 @@
# Change Log
## [v1.2.0](https://github.com/containous/traefik/tree/v1.2.0) (2017-03-20)
[Full Changelog](https://github.com/containous/traefik/compare/v1.1.2...v1.2.0)
**Merged pull requests:**
- Docker: Added warning if network could not be found [\#1310](https://github.com/containous/traefik/pull/1310) ([zweizeichen](https://github.com/zweizeichen))
- Add filter on task status in addition to desired status \(Docker Provider - swarm\) [\#1304](https://github.com/containous/traefik/pull/1304) ([Yshayy](https://github.com/Yshayy))
- Abort Kubernetes Ingress update if Kubernetes API call fails [\#1295](https://github.com/containous/traefik/pull/1295) ([Regner](https://github.com/Regner))
- Small fixes [\#1291](https://github.com/containous/traefik/pull/1291) ([emilevauge](https://github.com/emilevauge))
- Rename health check URL parameter to path. [\#1285](https://github.com/containous/traefik/pull/1285) ([timoreimann](https://github.com/timoreimann))
- Update Oxy, fix for \#1199 [\#1278](https://github.com/containous/traefik/pull/1278) ([akanto](https://github.com/akanto))
- Fix metrics registering [\#1258](https://github.com/containous/traefik/pull/1258) ([matevzmihalic](https://github.com/matevzmihalic))
- Update DefaultMaxIdleConnsPerHost default in docs. [\#1239](https://github.com/containous/traefik/pull/1239) ([timoreimann](https://github.com/timoreimann))
- Update WSS/WS Proto \[Fixes \#670\] [\#1225](https://github.com/containous/traefik/pull/1225) ([dtomcej](https://github.com/dtomcej))
- Bump go-rancher version [\#1219](https://github.com/containous/traefik/pull/1219) ([SantoDE](https://github.com/SantoDE))
- Chunk taskArns into groups of 100 [\#1209](https://github.com/containous/traefik/pull/1209) ([owen](https://github.com/owen))
- Prepare release v1.2.0 rc2 [\#1204](https://github.com/containous/traefik/pull/1204) ([emilevauge](https://github.com/emilevauge))
- Revert "Ensure that we don't add balancees with no health check runs … [\#1198](https://github.com/containous/traefik/pull/1198) ([jangie](https://github.com/jangie))
- Small fixes and improvments [\#1173](https://github.com/containous/traefik/pull/1173) ([SantoDE](https://github.com/SantoDE))
- Fix docker issues with global and dead tasks [\#1167](https://github.com/containous/traefik/pull/1167) ([christopherobin](https://github.com/christopherobin))
- Better ECS error checking [\#1143](https://github.com/containous/traefik/pull/1143) ([lpetre](https://github.com/lpetre))
- Fix stats race condition [\#1141](https://github.com/containous/traefik/pull/1141) ([emilevauge](https://github.com/emilevauge))
- ECS: Docs - info about cred. resolution and required access policies [\#1137](https://github.com/containous/traefik/pull/1137) ([rickard-von-essen](https://github.com/rickard-von-essen))
- Healthcheck tests and doc [\#1132](https://github.com/containous/traefik/pull/1132) ([Juliens](https://github.com/Juliens))
- Fix travis deploy [\#1128](https://github.com/containous/traefik/pull/1128) ([emilevauge](https://github.com/emilevauge))
- Prepare release v1.2.0 rc1 [\#1126](https://github.com/containous/traefik/pull/1126) ([emilevauge](https://github.com/emilevauge))
- Fix checkout initial before calling rmpr [\#1124](https://github.com/containous/traefik/pull/1124) ([emilevauge](https://github.com/emilevauge))
- Feature rancher integration [\#1120](https://github.com/containous/traefik/pull/1120) ([SantoDE](https://github.com/SantoDE))
- Fix glide go units [\#1119](https://github.com/containous/traefik/pull/1119) ([emilevauge](https://github.com/emilevauge))
- Carry \#818 — Add systemd watchdog feature [\#1116](https://github.com/containous/traefik/pull/1116) ([vdemeester](https://github.com/vdemeester))
- Skip file permission check on Windows [\#1115](https://github.com/containous/traefik/pull/1115) ([StefanScherer](https://github.com/StefanScherer))
- Fix Docker API version for Windows [\#1113](https://github.com/containous/traefik/pull/1113) ([StefanScherer](https://github.com/StefanScherer))
- Fix git rpr [\#1109](https://github.com/containous/traefik/pull/1109) ([emilevauge](https://github.com/emilevauge))
- Fix docker version specifier [\#1108](https://github.com/containous/traefik/pull/1108) ([timoreimann](https://github.com/timoreimann))
- Merge v1.1.2 master [\#1105](https://github.com/containous/traefik/pull/1105) ([emilevauge](https://github.com/emilevauge))
- add sh before script in deploy... [\#1103](https://github.com/containous/traefik/pull/1103) ([emilevauge](https://github.com/emilevauge))
- \[doc\] typo fixes for kubernetes user guide [\#1102](https://github.com/containous/traefik/pull/1102) ([bamarni](https://github.com/bamarni))
- add skip\_cleanup in deploy [\#1101](https://github.com/containous/traefik/pull/1101) ([emilevauge](https://github.com/emilevauge))
- Fix k8s example UI port. [\#1098](https://github.com/containous/traefik/pull/1098) ([ddunkin](https://github.com/ddunkin))
- Fix marathon provider [\#1090](https://github.com/containous/traefik/pull/1090) ([diegooliveira](https://github.com/diegooliveira))
- Add an ECS provider [\#1088](https://github.com/containous/traefik/pull/1088) ([lpetre](https://github.com/lpetre))
- Update comment to reflect the code [\#1087](https://github.com/containous/traefik/pull/1087) ([np](https://github.com/np))
- update NYTimes/gziphandler fixes \#1059 [\#1084](https://github.com/containous/traefik/pull/1084) ([JamesKyburz](https://github.com/JamesKyburz))
- Ensure that we don't add balancees with no health check runs if there is a health check defined on it [\#1080](https://github.com/containous/traefik/pull/1080) ([jangie](https://github.com/jangie))
- Add FreeBSD & OpenBSD to crossbinary [\#1078](https://github.com/containous/traefik/pull/1078) ([geoffgarside](https://github.com/geoffgarside))
- Fix metrics for multiple entry points [\#1071](https://github.com/containous/traefik/pull/1071) ([matevzmihalic](https://github.com/matevzmihalic))
- Allow setting load balancer method and sticky using service annotations [\#1068](https://github.com/containous/traefik/pull/1068) ([bakins](https://github.com/bakins))
- Fix travis script [\#1067](https://github.com/containous/traefik/pull/1067) ([emilevauge](https://github.com/emilevauge))
- Add missing fmt verb specifier in k8s provider. [\#1066](https://github.com/containous/traefik/pull/1066) ([timoreimann](https://github.com/timoreimann))
- Add git rpr command [\#1063](https://github.com/containous/traefik/pull/1063) ([emilevauge](https://github.com/emilevauge))
- Fix k8s example [\#1062](https://github.com/containous/traefik/pull/1062) ([emilevauge](https://github.com/emilevauge))
- Replace underscores to dash in autogenerated urls \(docker provider\) [\#1061](https://github.com/containous/traefik/pull/1061) ([WTFKr0](https://github.com/WTFKr0))
- Don't run go test on .glide cache folder [\#1057](https://github.com/containous/traefik/pull/1057) ([vdemeester](https://github.com/vdemeester))
- Allow setting circuitbreaker expression via Kubernetes annotation [\#1056](https://github.com/containous/traefik/pull/1056) ([bakins](https://github.com/bakins))
- Improving instrumentation. [\#1042](https://github.com/containous/traefik/pull/1042) ([enxebre](https://github.com/enxebre))
- Update user guide for upcoming `docker stack deploy` [\#1041](https://github.com/containous/traefik/pull/1041) ([twelvelabs](https://github.com/twelvelabs))
- Support sticky sessions under SWARM Mode. \#1024 [\#1033](https://github.com/containous/traefik/pull/1033) ([foleymic](https://github.com/foleymic))
- Allow for wildcards in k8s ingress host, fixes \#792 [\#1029](https://github.com/containous/traefik/pull/1029) ([sheerun](https://github.com/sheerun))
- Don't fetch ACME certificates for frontends using non-TLS entrypoints \(\#989\) [\#1023](https://github.com/containous/traefik/pull/1023) ([syfonseq](https://github.com/syfonseq))
- Return Proper Non-ACME certificate - Fixes Issue 672 [\#1018](https://github.com/containous/traefik/pull/1018) ([dtomcej](https://github.com/dtomcej))
- Fix docs build and add missing benchmarks page [\#1017](https://github.com/containous/traefik/pull/1017) ([csabapalfi](https://github.com/csabapalfi))
- Set a NopCloser request body with retry middleware [\#1016](https://github.com/containous/traefik/pull/1016) ([bamarni](https://github.com/bamarni))
- instruct to flatten dependencies with glide [\#1010](https://github.com/containous/traefik/pull/1010) ([bamarni](https://github.com/bamarni))
- check permissions on acme.json during startup [\#1009](https://github.com/containous/traefik/pull/1009) ([bamarni](https://github.com/bamarni))
- \[doc\] few tweaks on the basics page [\#1005](https://github.com/containous/traefik/pull/1005) ([bamarni](https://github.com/bamarni))
- Import order as goimports does [\#1004](https://github.com/containous/traefik/pull/1004) ([vdemeester](https://github.com/vdemeester))
- See the right go report badge [\#991](https://github.com/containous/traefik/pull/991) ([guilhem](https://github.com/guilhem))
- Add multiple values for one rule to docs [\#978](https://github.com/containous/traefik/pull/978) ([j0hnsmith](https://github.com/j0hnsmith))
- Add ACME/Lets Encrypt integration tests [\#975](https://github.com/containous/traefik/pull/975) ([trecloux](https://github.com/trecloux))
- deploy.sh: upload release source tarball [\#969](https://github.com/containous/traefik/pull/969) ([Mic92](https://github.com/Mic92))
- toml zookeeper doc fix [\#948](https://github.com/containous/traefik/pull/948) ([brdude](https://github.com/brdude))
- Add Rule AddPrefix [\#931](https://github.com/containous/traefik/pull/931) ([Juliens](https://github.com/Juliens))
- Add bug command [\#921](https://github.com/containous/traefik/pull/921) ([emilevauge](https://github.com/emilevauge))
- \(WIP\) feat: HealthCheck [\#918](https://github.com/containous/traefik/pull/918) ([Juliens](https://github.com/Juliens))
- Add ability to set authenticated user in request header [\#889](https://github.com/containous/traefik/pull/889) ([ViViDboarder](https://github.com/ViViDboarder))
- IP-per-task: [\#841](https://github.com/containous/traefik/pull/841) ([diegooliveira](https://github.com/diegooliveira))
## [v1.2.0-rc2](https://github.com/containous/traefik/tree/v1.2.0-rc2) (2017-03-01)
[Full Changelog](https://github.com/containous/traefik/compare/v1.2.0-rc1...v1.2.0-rc2)
**Implemented enhancements:**
- Are there plans to support the service type ExternalName in Kubernetes? [\#1142](https://github.com/containous/traefik/issues/1142)
- Kubernetes Ingress and sticky support [\#911](https://github.com/containous/traefik/issues/911)
- kubernetes client does not support InsecureSkipVerify [\#876](https://github.com/containous/traefik/issues/876)
- Support active health checking like HAProxy [\#824](https://github.com/containous/traefik/issues/824)
- Allow k8s ingress controller serviceAccountToken and serviceAccountCACert to be changed [\#611](https://github.com/containous/traefik/issues/611)
**Fixed bugs:**
- \[rancher\] invalid memory address or nil pointer dereference [\#1134](https://github.com/containous/traefik/issues/1134)
- Kubernetes default backend should work [\#1073](https://github.com/containous/traefik/issues/1073)
**Closed issues:**
- Are release Download links broken? [\#1201](https://github.com/containous/traefik/issues/1201)
- Bind to specific ip address [\#1193](https://github.com/containous/traefik/issues/1193)
- DNS01 challenge use the wrong zone through route53 [\#1192](https://github.com/containous/traefik/issues/1192)
- Reverse proxy https to http backends fails [\#1180](https://github.com/containous/traefik/issues/1180)
- Swarm Mode + Letsecrypt + KV Store [\#1176](https://github.com/containous/traefik/issues/1176)
- docker deploy -c example.yml e [\#1169](https://github.com/containous/traefik/issues/1169)
- Traefik not finding dynamically added services \(Docker Swarm Mode\) [\#1168](https://github.com/containous/traefik/issues/1168)
- Traefik with Kubernetes backend - keep getting 401 on all GET requests to kube-apiserver [\#1166](https://github.com/containous/traefik/issues/1166)
- Near line 15 \(last key parsed 'backends.backend-monitor-viz.servers'\): Key 'backends.backend-monitor-viz.servers.server-monitor\_viz-1' has already been defined. [\#1154](https://github.com/containous/traefik/issues/1154)
- How to reuse SSL certificates automatically fetched from Let´s encrypt? [\#1152](https://github.com/containous/traefik/issues/1152)
- Dynamically ban ip when backend repeatedly returns specified status code. \( 403 \) [\#1136](https://github.com/containous/traefik/issues/1136)
- Always get 404 accessing my nginx backend service [\#1112](https://github.com/containous/traefik/issues/1112)
- Incomplete Docu [\#1091](https://github.com/containous/traefik/issues/1091)
- LoadCertificateForDomains: runtime error: invalid memory address [\#1069](https://github.com/containous/traefik/issues/1069)
- Traefik creating backends & mappings for ingress annotated with ingress.class: nginx [\#1058](https://github.com/containous/traefik/issues/1058)
- ACME file format description [\#1012](https://github.com/containous/traefik/issues/1012)
- SwarmMode - Not routing on worker node [\#838](https://github.com/containous/traefik/issues/838)
- Migrate k8s to kubernetes/client-go [\#678](https://github.com/containous/traefik/issues/678)
- Support for sticky session with kubernetes ingress as backend [\#674](https://github.com/containous/traefik/issues/674)
**Merged pull requests:**
- Revert "Ensure that we don't add balancees with no health check runs … [\#1198](https://github.com/containous/traefik/pull/1198) ([jangie](https://github.com/jangie))
- Small fixes and improvments [\#1173](https://github.com/containous/traefik/pull/1173) ([SantoDE](https://github.com/SantoDE))
- Fix docker issues with global and dead tasks [\#1167](https://github.com/containous/traefik/pull/1167) ([christopherobin](https://github.com/christopherobin))
- Better ECS error checking [\#1143](https://github.com/containous/traefik/pull/1143) ([lpetre](https://github.com/lpetre))
- Fix stats race condition [\#1141](https://github.com/containous/traefik/pull/1141) ([emilevauge](https://github.com/emilevauge))
- ECS: Docs - info about cred. resolution and required access policies [\#1137](https://github.com/containous/traefik/pull/1137) ([rickard-von-essen](https://github.com/rickard-von-essen))
- Healthcheck tests and doc [\#1132](https://github.com/containous/traefik/pull/1132) ([Juliens](https://github.com/Juliens))
## [v1.2.0-rc1](https://github.com/containous/traefik/tree/v1.2.0-rc1) (2017-02-06)
[Full Changelog](https://github.com/containous/traefik/compare/v1.1.2...v1.2.0-rc1)
**Implemented enhancements:**
- Add FreeBSD and OpenBSD to release builds [\#923](https://github.com/containous/traefik/issues/923)
- Write authenticated user to header key [\#802](https://github.com/containous/traefik/issues/802)
- Question: Wildcard Host for Kubernetes Ingress [\#792](https://github.com/containous/traefik/issues/792)
- First commit prometheus middleware. [\#1022](https://github.com/containous/traefik/pull/1022) ([enxebre](https://github.com/enxebre))
- Use deployment primitives from travis [\#843](https://github.com/containous/traefik/pull/843) ([guilhem](https://github.com/guilhem))
**Fixed bugs:**
- Increase Docker API version to work with Windows Containers [\#1094](https://github.com/containous/traefik/issues/1094)
**Closed issues:**
- How could I know whether forwarding path is correctly set? [\#1111](https://github.com/containous/traefik/issues/1111)
- ACME + Docker-compose labels [\#1099](https://github.com/containous/traefik/issues/1099)
- Loadbalance between 2 containers in Docker Swarm Mode [\#1095](https://github.com/containous/traefik/issues/1095)
- Add DNS01 letsencrypt challenge support through AWS. [\#1093](https://github.com/containous/traefik/issues/1093)
- New Release Cut [\#1092](https://github.com/containous/traefik/issues/1092)
- Marathon integration changed default backend server port from task-level to application-level [\#1072](https://github.com/containous/traefik/issues/1072)
- websockets not working when compress = true in toml config. [\#1059](https://github.com/containous/traefik/issues/1059)
- Proxying 403 http status into the application [\#1044](https://github.com/containous/traefik/issues/1044)
- Normalize auto generated frontend-rule \(docker\) [\#1043](https://github.com/containous/traefik/issues/1043)
- Traefik with Consul catalog backend + Registrator [\#1039](https://github.com/containous/traefik/issues/1039)
- \[Configuration help\] Can't connect to docker containers under a domain path [\#1032](https://github.com/containous/traefik/issues/1032)
- Kubernetes and etcd backend : `storeconfig` fails. [\#1031](https://github.com/containous/traefik/issues/1031)
- kubernetes: Undefined backend 'X/' for frontend X/" [\#1026](https://github.com/containous/traefik/issues/1026)
- TLS handshake error [\#1025](https://github.com/containous/traefik/issues/1025)
- Traefik failing on POST request [\#1008](https://github.com/containous/traefik/issues/1008)
- how config traffic.toml http 80 without basic auth, traefik WebUI 8080 with basic auth [\#1001](https://github.com/containous/traefik/issues/1001)
- Docs 404 [\#995](https://github.com/containous/traefik/issues/995)
- Disable acme for non https endpoints [\#989](https://github.com/containous/traefik/issues/989)
- Add parameter to configure TLS entrypoints with ca-bundle file [\#984](https://github.com/containous/traefik/issues/984)
- docker multiple networks routing [\#970](https://github.com/containous/traefik/issues/970)
- don't add Docker containers not on the same network as traefik [\#959](https://github.com/containous/traefik/issues/959)
- Multiple frontend routes [\#957](https://github.com/containous/traefik/issues/957)
- SNI based routing without TLS offloading [\#933](https://github.com/containous/traefik/issues/933)
- NEO4J + traefik proxy Issues [\#907](https://github.com/containous/traefik/issues/907)
- ACME OnDemand ignores entrypoint certificate [\#672](https://github.com/containous/traefik/issues/672)
- Ability to use self-signed certificates for local development [\#399](https://github.com/containous/traefik/issues/399)
**Merged pull requests:**
- Fix checkout initial before calling rmpr [\#1124](https://github.com/containous/traefik/pull/1124) ([emilevauge](https://github.com/emilevauge))
- Feature rancher integration [\#1120](https://github.com/containous/traefik/pull/1120) ([SantoDE](https://github.com/SantoDE))
- Fix glide go units [\#1119](https://github.com/containous/traefik/pull/1119) ([emilevauge](https://github.com/emilevauge))
- Carry \#818 — Add systemd watchdog feature [\#1116](https://github.com/containous/traefik/pull/1116) ([vdemeester](https://github.com/vdemeester))
- Skip file permission check on Windows [\#1115](https://github.com/containous/traefik/pull/1115) ([StefanScherer](https://github.com/StefanScherer))
- Fix Docker API version for Windows [\#1113](https://github.com/containous/traefik/pull/1113) ([StefanScherer](https://github.com/StefanScherer))
- Fix git rpr [\#1109](https://github.com/containous/traefik/pull/1109) ([emilevauge](https://github.com/emilevauge))
- Fix docker version specifier [\#1108](https://github.com/containous/traefik/pull/1108) ([timoreimann](https://github.com/timoreimann))
- Merge v1.1.2 master [\#1105](https://github.com/containous/traefik/pull/1105) ([emilevauge](https://github.com/emilevauge))
- add sh before script in deploy... [\#1103](https://github.com/containous/traefik/pull/1103) ([emilevauge](https://github.com/emilevauge))
- \[doc\] typo fixes for kubernetes user guide [\#1102](https://github.com/containous/traefik/pull/1102) ([bamarni](https://github.com/bamarni))
- add skip\_cleanup in deploy [\#1101](https://github.com/containous/traefik/pull/1101) ([emilevauge](https://github.com/emilevauge))
- Fix k8s example UI port. [\#1098](https://github.com/containous/traefik/pull/1098) ([ddunkin](https://github.com/ddunkin))
- Fix marathon provider [\#1090](https://github.com/containous/traefik/pull/1090) ([diegooliveira](https://github.com/diegooliveira))
- Add an ECS provider [\#1088](https://github.com/containous/traefik/pull/1088) ([lpetre](https://github.com/lpetre))
- Update comment to reflect the code [\#1087](https://github.com/containous/traefik/pull/1087) ([np](https://github.com/np))
- update NYTimes/gziphandler fixes \#1059 [\#1084](https://github.com/containous/traefik/pull/1084) ([JamesKyburz](https://github.com/JamesKyburz))
- Ensure that we don't add balancees with no health check runs if there is a health check defined on it [\#1080](https://github.com/containous/traefik/pull/1080) ([jangie](https://github.com/jangie))
- Add FreeBSD & OpenBSD to crossbinary [\#1078](https://github.com/containous/traefik/pull/1078) ([geoffgarside](https://github.com/geoffgarside))
- Fix metrics for multiple entry points [\#1071](https://github.com/containous/traefik/pull/1071) ([matevzmihalic](https://github.com/matevzmihalic))
- Allow setting load balancer method and sticky using service annotations [\#1068](https://github.com/containous/traefik/pull/1068) ([bakins](https://github.com/bakins))
- Fix travis script [\#1067](https://github.com/containous/traefik/pull/1067) ([emilevauge](https://github.com/emilevauge))
- Add missing fmt verb specifier in k8s provider. [\#1066](https://github.com/containous/traefik/pull/1066) ([timoreimann](https://github.com/timoreimann))
- Add git rpr command [\#1063](https://github.com/containous/traefik/pull/1063) ([emilevauge](https://github.com/emilevauge))
- Fix k8s example [\#1062](https://github.com/containous/traefik/pull/1062) ([emilevauge](https://github.com/emilevauge))
- Replace underscores to dash in autogenerated urls \(docker provider\) [\#1061](https://github.com/containous/traefik/pull/1061) ([WTFKr0](https://github.com/WTFKr0))
- Don't run go test on .glide cache folder [\#1057](https://github.com/containous/traefik/pull/1057) ([vdemeester](https://github.com/vdemeester))
- Allow setting circuitbreaker expression via Kubernetes annotation [\#1056](https://github.com/containous/traefik/pull/1056) ([bakins](https://github.com/bakins))
- Improving instrumentation. [\#1042](https://github.com/containous/traefik/pull/1042) ([enxebre](https://github.com/enxebre))
- Update user guide for upcoming `docker stack deploy` [\#1041](https://github.com/containous/traefik/pull/1041) ([twelvelabs](https://github.com/twelvelabs))
- Support sticky sessions under SWARM Mode. \#1024 [\#1033](https://github.com/containous/traefik/pull/1033) ([foleymic](https://github.com/foleymic))
- Allow for wildcards in k8s ingress host, fixes \#792 [\#1029](https://github.com/containous/traefik/pull/1029) ([sheerun](https://github.com/sheerun))
- Don't fetch ACME certificates for frontends using non-TLS entrypoints \(\#989\) [\#1023](https://github.com/containous/traefik/pull/1023) ([syfonseq](https://github.com/syfonseq))
- Return Proper Non-ACME certificate - Fixes Issue 672 [\#1018](https://github.com/containous/traefik/pull/1018) ([dtomcej](https://github.com/dtomcej))
- Fix docs build and add missing benchmarks page [\#1017](https://github.com/containous/traefik/pull/1017) ([csabapalfi](https://github.com/csabapalfi))
- Set a NopCloser request body with retry middleware [\#1016](https://github.com/containous/traefik/pull/1016) ([bamarni](https://github.com/bamarni))
- instruct to flatten dependencies with glide [\#1010](https://github.com/containous/traefik/pull/1010) ([bamarni](https://github.com/bamarni))
- check permissions on acme.json during startup [\#1009](https://github.com/containous/traefik/pull/1009) ([bamarni](https://github.com/bamarni))
- \[doc\] few tweaks on the basics page [\#1005](https://github.com/containous/traefik/pull/1005) ([bamarni](https://github.com/bamarni))
- Import order as goimports does [\#1004](https://github.com/containous/traefik/pull/1004) ([vdemeester](https://github.com/vdemeester))
- See the right go report badge [\#991](https://github.com/containous/traefik/pull/991) ([guilhem](https://github.com/guilhem))
- Add multiple values for one rule to docs [\#978](https://github.com/containous/traefik/pull/978) ([j0hnsmith](https://github.com/j0hnsmith))
- Add ACME/Lets Encrypt integration tests [\#975](https://github.com/containous/traefik/pull/975) ([trecloux](https://github.com/trecloux))
- deploy.sh: upload release source tarball [\#969](https://github.com/containous/traefik/pull/969) ([Mic92](https://github.com/Mic92))
- toml zookeeper doc fix [\#948](https://github.com/containous/traefik/pull/948) ([brdude](https://github.com/brdude))
- Add Rule AddPrefix [\#931](https://github.com/containous/traefik/pull/931) ([Juliens](https://github.com/Juliens))
- Add bug command [\#921](https://github.com/containous/traefik/pull/921) ([emilevauge](https://github.com/emilevauge))
- \(WIP\) feat: HealthCheck [\#918](https://github.com/containous/traefik/pull/918) ([Juliens](https://github.com/Juliens))
- Add ability to set authenticated user in request header [\#889](https://github.com/containous/traefik/pull/889) ([ViViDboarder](https://github.com/ViViDboarder))
- IP-per-task: [\#841](https://github.com/containous/traefik/pull/841) ([diegooliveira](https://github.com/diegooliveira))
## [v1.1.2](https://github.com/containous/traefik/tree/v1.1.2) (2016-12-15)
[Full Changelog](https://github.com/containous/traefik/compare/v1.1.1...v1.1.2)
**Fixed bugs:**
- Problem during HTTPS redirection [\#952](https://github.com/containous/traefik/issues/952)
- nil pointer with kubernetes ingress [\#934](https://github.com/containous/traefik/issues/934)
- ConsulCatalog and File not working [\#903](https://github.com/containous/traefik/issues/903)
- Traefik can not start [\#902](https://github.com/containous/traefik/issues/902)
- Cannot connect to Kubernetes server failed to decode watch event [\#532](https://github.com/containous/traefik/issues/532)
**Closed issues:**
- Updating certificates with configuration file. [\#968](https://github.com/containous/traefik/issues/968)
- Let's encrypt retrieving certificate from wrong IP [\#962](https://github.com/containous/traefik/issues/962)
- let's encrypt and dashboard? [\#961](https://github.com/containous/traefik/issues/961)
- Working HTTPS example for GKE? [\#960](https://github.com/containous/traefik/issues/960)
- GKE design pattern [\#958](https://github.com/containous/traefik/issues/958)
- Consul Catalog constraints does not seem to work [\#954](https://github.com/containous/traefik/issues/954)
- Issue in building traefik from master [\#949](https://github.com/containous/traefik/issues/949)
- Proxy http application to https doesn't seem to work correctly for all services [\#937](https://github.com/containous/traefik/issues/937)
- Excessive requests to kubernetes apiserver [\#922](https://github.com/containous/traefik/issues/922)
- I am getting a connection error while creating traefik with consul backend "dial tcp 127.0.0.1:8500: getsockopt: connection refused" [\#917](https://github.com/containous/traefik/issues/917)
- SwarmMode - 1.13 RC2 - DNS RR - Individual IPs not retrieved [\#913](https://github.com/containous/traefik/issues/913)
- Panic in kubernetes ingress \(traefik 1.1.0\) [\#910](https://github.com/containous/traefik/issues/910)
- Kubernetes updating deployment image requires Ingress to be remade [\#909](https://github.com/containous/traefik/issues/909)
- \[ACME\] Too many currently pending authorizations [\#905](https://github.com/containous/traefik/issues/905)
- WEB UI Authentication and Let's Encrypt : error 404 [\#754](https://github.com/containous/traefik/issues/754)
- Traefik as ingress controller for SNI based routing in kubernetes [\#745](https://github.com/containous/traefik/issues/745)
- Kubernetes Ingress backend: using self-signed certificates [\#486](https://github.com/containous/traefik/issues/486)
- Kubernetes Ingress backend: can't find token and ca.crt [\#484](https://github.com/containous/traefik/issues/484)
**Merged pull requests:**
- Fix duplicate acme certificates [\#972](https://github.com/containous/traefik/pull/972) ([emilevauge](https://github.com/emilevauge))
- Fix leadership panic [\#956](https://github.com/containous/traefik/pull/956) ([emilevauge](https://github.com/emilevauge))
- Fix redirect regex [\#947](https://github.com/containous/traefik/pull/947) ([emilevauge](https://github.com/emilevauge))
- Add operation recover [\#944](https://github.com/containous/traefik/pull/944) ([emilevauge](https://github.com/emilevauge))
## [v1.1.1](https://github.com/containous/traefik/tree/v1.1.1) (2016-11-29)
[Full Changelog](https://github.com/containous/traefik/compare/v1.1.0...v1.1.1)
**Implemented enhancements:**
- Getting "Kubernetes connection error failed to decode watch event : unexpected EOF" every minute in Traefik log [\#732](https://github.com/containous/traefik/issues/732)
**Fixed bugs:**
- 1.1.0 kubernetes panic: send on closed channel [\#877](https://github.com/containous/traefik/issues/877)
- digest auth example is incorrect [\#869](https://github.com/containous/traefik/issues/869)
- Marathon & Mesos providers' GroupsAsSubDomains option broken [\#867](https://github.com/containous/traefik/issues/867)
- 404 responses when a new Marathon leader is elected [\#653](https://github.com/containous/traefik/issues/653)
**Closed issues:**
- traefik:latest fails to auto-detect Docker containers [\#901](https://github.com/containous/traefik/issues/901)
- Panic error on bare metal Kubernetes \(installed with Kubeadm\) [\#897](https://github.com/containous/traefik/issues/897)
- api backend readOnly: what is the purpose of this setting [\#893](https://github.com/containous/traefik/issues/893)
- file backend: using external file - doesn't work [\#892](https://github.com/containous/traefik/issues/892)
- auth support for web backend [\#891](https://github.com/containous/traefik/issues/891)
- Basic auth with docker labels [\#890](https://github.com/containous/traefik/issues/890)
- file vs inline config [\#888](https://github.com/containous/traefik/issues/888)
- combine Host and HostRegexp rules [\#882](https://github.com/containous/traefik/issues/882)
- \[Question\] Traefik + Kubernetes + Let's Encrypt \(ssl not used\) [\#881](https://github.com/containous/traefik/issues/881)
- Traefik security for dashboard [\#880](https://github.com/containous/traefik/issues/880)
- Kubernetes Nginx Deployment Panic [\#879](https://github.com/containous/traefik/issues/879)
- Kubernetes Example Address already in use [\#872](https://github.com/containous/traefik/issues/872)
- ETCD Backend - frontend/backends missing [\#866](https://github.com/containous/traefik/issues/866)
- \[Swarm mode\] Dashboard does not work on RC4 [\#864](https://github.com/containous/traefik/issues/864)
- Docker v1.1.0 image does not exist [\#861](https://github.com/containous/traefik/issues/861)
- ConsulService catalog do not support multiple rules [\#859](https://github.com/containous/traefik/issues/859)
- Update official docker repo [\#858](https://github.com/containous/traefik/issues/858)
- Still a memory leak with k8s - 1.1 RC4 [\#844](https://github.com/containous/traefik/issues/844)
**Merged pull requests:**
- Fix Swarm panic [\#908](https://github.com/containous/traefik/pull/908) ([emilevauge](https://github.com/emilevauge))
- Fix k8s panic [\#900](https://github.com/containous/traefik/pull/900) ([emilevauge](https://github.com/emilevauge))
- Fix missing value for k8s watch request parameter [\#874](https://github.com/containous/traefik/pull/874) ([codablock](https://github.com/codablock))
- Fix GroupsAsSubDomains option for Mesos and Marathon [\#868](https://github.com/containous/traefik/pull/868) ([ryanleary](https://github.com/ryanleary))
- Normalize backend even if is user-defined [\#865](https://github.com/containous/traefik/pull/865) ([WTFKr0](https://github.com/WTFKr0))
- consul/kv.tmpl: weight default value should be a int [\#826](https://github.com/containous/traefik/pull/826) ([klausenbusk](https://github.com/klausenbusk))
## [v1.1.0](https://github.com/containous/traefik/tree/v1.1.0) (2016-11-17)
[Full Changelog](https://github.com/containous/traefik/compare/v1.0.0...v1.1.0)
**Implemented enhancements:**
- Support healthcheck if present for docker [\#666](https://github.com/containous/traefik/issues/666)
- Standard unit for traefik latency in access log [\#559](https://github.com/containous/traefik/issues/559)
- \[CI\] wiredep marked as unmaintained [\#550](https://github.com/containous/traefik/issues/550)
- Feature Request: Enable Health checks to containers. [\#540](https://github.com/containous/traefik/issues/540)
- Feature Request: SSL Cipher Selection [\#535](https://github.com/containous/traefik/issues/535)
- Error with -consulcatalog and missing load balance method on 1.0.0 [\#524](https://github.com/containous/traefik/issues/524)
- Running Traefik with Docker 1.12 Swarm Mode [\#504](https://github.com/containous/traefik/issues/504)
- Kubernetes provider: should allow the master url to be override [\#501](https://github.com/containous/traefik/issues/501)
- \[FRONTEND\]\[LE\] Pre-generate SSL certificates for "Host:" rules [\#483](https://github.com/containous/traefik/issues/483)
- Frontend Rule evolution [\#437](https://github.com/containous/traefik/issues/437)
- Add a Changelog [\#388](https://github.com/containous/traefik/issues/388)
- Add label matching for kubernetes ingests [\#363](https://github.com/containous/traefik/issues/363)
- Acme in HA Traefik Scenario [\#348](https://github.com/containous/traefik/issues/348)
- HTTP Basic Auth support [\#77](https://github.com/containous/traefik/issues/77)
- Session affinity / stickiness / persistence [\#5](https://github.com/containous/traefik/issues/5)
**Fixed bugs:**
- 1.1.0-rc4 dashboard UX not displaying [\#828](https://github.com/containous/traefik/issues/828)
- Traefik stopped serving on upgrade to v1.1.0-rc3 [\#807](https://github.com/containous/traefik/issues/807)
- cannot access webui/dashboard [\#796](https://github.com/containous/traefik/issues/796)
- Traefik cannot read constraints from KV [\#794](https://github.com/containous/traefik/issues/794)
- HTTP2 - configuration [\#790](https://github.com/containous/traefik/issues/790)
- Cannot provide multiple certificates using flag [\#757](https://github.com/containous/traefik/issues/757)
- Allow multiple certificates on a single entrypoint when trying to use TLS? [\#747](https://github.com/containous/traefik/issues/747)
- traefik \* Users: unsupported type: slice [\#743](https://github.com/containous/traefik/issues/743)
- \[Docker swarm mode\] The traefik.docker.network seems to have no effect [\#719](https://github.com/containous/traefik/issues/719)
- traefik hangs - stops handling requests [\#662](https://github.com/containous/traefik/issues/662)
- Add long jobs in exponential backoff providers [\#626](https://github.com/containous/traefik/issues/626)
- Tip of tree crashes on invalid pointer on Marathon provider [\#624](https://github.com/containous/traefik/issues/624)
- ACME: revoke certificate on agreement update [\#579](https://github.com/containous/traefik/issues/579)
- WebUI: Providers tabs disappeared [\#577](https://github.com/containous/traefik/issues/577)
- traefik version command contains incorrect information when building from master branch [\#569](https://github.com/containous/traefik/issues/569)
- Case sensitive domain names breaks routing [\#562](https://github.com/containous/traefik/issues/562)
- Flag --etcd.endpoint default [\#508](https://github.com/containous/traefik/issues/508)
- Conditional ACME on demand generation [\#505](https://github.com/containous/traefik/issues/505)
- Important delay with streams \(Mozilla EventSource\) [\#503](https://github.com/containous/traefik/issues/503)
- Traefik crashing [\#458](https://github.com/containous/traefik/issues/458)
- traefik.toml constraints error: `Expected map but found 'string'.` [\#451](https://github.com/containous/traefik/issues/451)
- Multiple path separators in the url path causing redirect [\#167](https://github.com/containous/traefik/issues/167)
**Closed issues:**
- All path rules require paths to be lowercase [\#851](https://github.com/containous/traefik/issues/851)
- The UI stops working after a time and have to restart the service. [\#840](https://github.com/containous/traefik/issues/840)
- Incorrect Dashboard page returned [\#831](https://github.com/containous/traefik/issues/831)
- LoadBalancing doesn't work in single node Swarm-mode [\#815](https://github.com/containous/traefik/issues/815)
- cannot connect to docker daemon [\#813](https://github.com/containous/traefik/issues/813)
- Let's encrypt configuration not working [\#805](https://github.com/containous/traefik/issues/805)
- Multiple subdomains for Marathon backend. [\#785](https://github.com/containous/traefik/issues/785)
- traefik-1.1.0-rc1: build error [\#781](https://github.com/containous/traefik/issues/781)
- dependencies installation error [\#755](https://github.com/containous/traefik/issues/755)
- k8s provider w/ acme? [\#752](https://github.com/containous/traefik/issues/752)
- Swarm Docs - How to use a FQDN [\#744](https://github.com/containous/traefik/issues/744)
- Documented ProvidersThrottleDuration value is invalid [\#741](https://github.com/containous/traefik/issues/741)
- Sensible configuration for consulCatalog [\#737](https://github.com/containous/traefik/issues/737)
- Traefik ignoring container listening in more than one TCP port [\#734](https://github.com/containous/traefik/issues/734)
- Loadbalaning issues with traefik and Docker Swarm cluster [\#730](https://github.com/containous/traefik/issues/730)
- issues with marathon app ids containing a dot [\#726](https://github.com/containous/traefik/issues/726)
- Error when using HA acme in kubernetes with etcd [\#725](https://github.com/containous/traefik/issues/725)
- \[Docker swarm mode\] No round robin when using service [\#718](https://github.com/containous/traefik/issues/718)
- Dose it support docker swarm mode [\#712](https://github.com/containous/traefik/issues/712)
- Kubernetes - Undefined backend [\#710](https://github.com/containous/traefik/issues/710)
- How Routing traffic depending on path not domain in docker [\#706](https://github.com/containous/traefik/issues/706)
- Constraints on Consul Catalogue not working as expected [\#703](https://github.com/containous/traefik/issues/703)
- Global InsecureSkipVerify does not work [\#700](https://github.com/containous/traefik/issues/700)
- Traefik crashes when using Consul catalog [\#699](https://github.com/containous/traefik/issues/699)
- \[documentation/feature\] Consul/etcd support atomic multiple key changes now [\#698](https://github.com/containous/traefik/issues/698)
- How to configure which network to use when starting traefik binary? [\#694](https://github.com/containous/traefik/issues/694)
- How to get multiple host headers working for docker labels? [\#692](https://github.com/containous/traefik/issues/692)
- Requests with URL-encoded characters are not forwarded correctly [\#684](https://github.com/containous/traefik/issues/684)
- File Watcher for rules does not work [\#683](https://github.com/containous/traefik/issues/683)
- Issue with global InsecureSkipVerify = true and self signed certificates [\#667](https://github.com/containous/traefik/issues/667)
- Docker exposedbydefault = false didn't work [\#663](https://github.com/containous/traefik/issues/663)
- swarm documentation needs update [\#656](https://github.com/containous/traefik/issues/656)
- \[ACME\] Auto SAN Detection [\#655](https://github.com/containous/traefik/issues/655)
- Fronting a domain with DNS A-record round-robin & ACME [\#654](https://github.com/containous/traefik/issues/654)
- Overriding toml configuration with environment variables [\#650](https://github.com/containous/traefik/issues/650)
- marathon provider exposedByDefault = false [\#647](https://github.com/containous/traefik/issues/647)
- Add status URL for service up checks [\#642](https://github.com/containous/traefik/issues/642)
- acme's storage file, containing private key, is word readable [\#638](https://github.com/containous/traefik/issues/638)
- wildcard domain with exclusions [\#633](https://github.com/containous/traefik/issues/633)
- Enable evenly distribution among backend [\#631](https://github.com/containous/traefik/issues/631)
- Traefik sporadically failing when proxying requests [\#615](https://github.com/containous/traefik/issues/615)
- TCP Proxy [\#608](https://github.com/containous/traefik/issues/608)
- How to use in Windows? [\#605](https://github.com/containous/traefik/issues/605)
- `ClientCAFiles` ignored [\#604](https://github.com/containous/traefik/issues/604)
- Let`s Encrypt enable in etcd [\#600](https://github.com/containous/traefik/issues/600)
- Support HTTP Basic Auth [\#599](https://github.com/containous/traefik/issues/599)
- Consul KV seem broken [\#587](https://github.com/containous/traefik/issues/587)
- HTTPS entryPoint not working [\#574](https://github.com/containous/traefik/issues/574)
- Traefik stuck when used as frontend for a streaming API [\#560](https://github.com/containous/traefik/issues/560)
- Exclude some frontends in consul catalog [\#555](https://github.com/containous/traefik/issues/555)
- Update docs with new Mesos provider [\#548](https://github.com/containous/traefik/issues/548)
- Can I use Traefik without a domain name? [\#539](https://github.com/containous/traefik/issues/539)
- docker run syntax in swarm example has changed [\#528](https://github.com/containous/traefik/issues/528)
- Priortities in 1.0.0 not behaving [\#506](https://github.com/containous/traefik/issues/506)
- Route by path [\#500](https://github.com/containous/traefik/issues/500)
- Secure WebSockets [\#467](https://github.com/containous/traefik/issues/467)
- Container IP Lost [\#375](https://github.com/containous/traefik/issues/375)
- Multiple routes support with Docker or Marathon labels [\#118](https://github.com/containous/traefik/issues/118)
**Merged pull requests:**
- Fix path case sensitive v1.1 [\#855](https://github.com/containous/traefik/pull/855) ([emilevauge](https://github.com/emilevauge))
- Fix golint in v1.1 [\#849](https://github.com/containous/traefik/pull/849) ([emilevauge](https://github.com/emilevauge))
- Fix Kubernetes watch leak [\#845](https://github.com/containous/traefik/pull/845) ([emilevauge](https://github.com/emilevauge))
- Pass Version, Codename and Date to crosscompiled [\#842](https://github.com/containous/traefik/pull/842) ([guilhem](https://github.com/guilhem))
- Add Nvd3 Dependency to fix UI / Dashboard [\#829](https://github.com/containous/traefik/pull/829) ([SantoDE](https://github.com/SantoDE))
- Fix mkdoc theme [\#823](https://github.com/containous/traefik/pull/823) ([emilevauge](https://github.com/emilevauge))
- Prepare release v1.1.0 rc4 [\#822](https://github.com/containous/traefik/pull/822) ([emilevauge](https://github.com/emilevauge))
- Check that we serve HTTP/2 [\#820](https://github.com/containous/traefik/pull/820) ([trecloux](https://github.com/trecloux))
- Fix multiple issues [\#814](https://github.com/containous/traefik/pull/814) ([emilevauge](https://github.com/emilevauge))
- Fix ACME renew & add version check [\#783](https://github.com/containous/traefik/pull/783) ([emilevauge](https://github.com/emilevauge))
- Use first port by default [\#782](https://github.com/containous/traefik/pull/782) ([guilhem](https://github.com/guilhem))
- Prepare release v1.1.0-rc3 [\#779](https://github.com/containous/traefik/pull/779) ([emilevauge](https://github.com/emilevauge))
- Fix ResponseRecorder Flush [\#776](https://github.com/containous/traefik/pull/776) ([emilevauge](https://github.com/emilevauge))
- Use sdnotify for systemd [\#768](https://github.com/containous/traefik/pull/768) ([guilhem](https://github.com/guilhem))
- Fix providers throttle duration doc [\#760](https://github.com/containous/traefik/pull/760) ([emilevauge](https://github.com/emilevauge))
- Fix mapstructure issue with anonymous slice [\#759](https://github.com/containous/traefik/pull/759) ([emilevauge](https://github.com/emilevauge))
- Fix multiple certificates using flag [\#758](https://github.com/containous/traefik/pull/758) ([emilevauge](https://github.com/emilevauge))
- Really fix deploy ghr... [\#748](https://github.com/containous/traefik/pull/748) ([emilevauge](https://github.com/emilevauge))
- Fixes deploy ghr [\#742](https://github.com/containous/traefik/pull/742) ([emilevauge](https://github.com/emilevauge))
- prepare v1.1.0-rc2 [\#740](https://github.com/containous/traefik/pull/740) ([emilevauge](https://github.com/emilevauge))
- Fix case sensitive host [\#733](https://github.com/containous/traefik/pull/733) ([emilevauge](https://github.com/emilevauge))
- Update Kubernetes examples [\#731](https://github.com/containous/traefik/pull/731) ([Starefossen](https://github.com/Starefossen))
- fIx marathon template with dots in ID [\#728](https://github.com/containous/traefik/pull/728) ([emilevauge](https://github.com/emilevauge))
- Fix networkMap construction in ListServices [\#724](https://github.com/containous/traefik/pull/724) ([vincentlepot](https://github.com/vincentlepot))
- Add basic compatibility with marathon-lb [\#720](https://github.com/containous/traefik/pull/720) ([guilhem](https://github.com/guilhem))
- Add Ed's video at ContainerCamp [\#717](https://github.com/containous/traefik/pull/717) ([emilevauge](https://github.com/emilevauge))
- Add documentation for Træfik on docker swarm mode [\#715](https://github.com/containous/traefik/pull/715) ([vdemeester](https://github.com/vdemeester))
- Remove duplicated link to Kubernetes.io in README.md [\#713](https://github.com/containous/traefik/pull/713) ([oscerd](https://github.com/oscerd))
- Show current version in web UI [\#709](https://github.com/containous/traefik/pull/709) ([vhf](https://github.com/vhf))
- Add support for docker healthcheck 👼 [\#708](https://github.com/containous/traefik/pull/708) ([vdemeester](https://github.com/vdemeester))
- Fix syntax in Swarm example. Resolves \#528 [\#707](https://github.com/containous/traefik/pull/707) ([billglover](https://github.com/billglover))
- Add HTTP compression [\#702](https://github.com/containous/traefik/pull/702) ([tuier](https://github.com/tuier))
- Carry PR 446 - Add sticky session support \(round two!\) [\#701](https://github.com/containous/traefik/pull/701) ([emilevauge](https://github.com/emilevauge))
- Remove unused endpoint when using constraints with Marathon provider [\#697](https://github.com/containous/traefik/pull/697) ([tuier](https://github.com/tuier))
- Replace imagelayers.io with microbadger [\#696](https://github.com/containous/traefik/pull/696) ([solidnerd](https://github.com/solidnerd))
- Selectable TLS Versions [\#690](https://github.com/containous/traefik/pull/690) ([dtomcej](https://github.com/dtomcej))
- Carry pr 439 [\#689](https://github.com/containous/traefik/pull/689) ([emilevauge](https://github.com/emilevauge))
- Disable gorilla/mux URL cleaning to prevent sending redirect [\#688](https://github.com/containous/traefik/pull/688) ([ydubreuil](https://github.com/ydubreuil))
- Some fixes [\#687](https://github.com/containous/traefik/pull/687) ([emilevauge](https://github.com/emilevauge))
- feat\(constraints\): Supports constraints for Marathon provider [\#686](https://github.com/containous/traefik/pull/686) ([tuier](https://github.com/tuier))
- Update docs to improve contribution setup [\#685](https://github.com/containous/traefik/pull/685) ([dtomcej](https://github.com/dtomcej))
- Add basic auth support for web backend [\#677](https://github.com/containous/traefik/pull/677) ([SantoDE](https://github.com/SantoDE))
- Document accepted values for logLevel. [\#676](https://github.com/containous/traefik/pull/676) ([jimmycuadra](https://github.com/jimmycuadra))
- If Marathon doesn't have healthcheck, assume it's ok [\#665](https://github.com/containous/traefik/pull/665) ([gomes](https://github.com/gomes))
- ACME: renew certificates 30 days before expiry [\#660](https://github.com/containous/traefik/pull/660) ([JayH5](https://github.com/JayH5))
- Update broken link and add a comment to sample config file [\#658](https://github.com/containous/traefik/pull/658) ([Yggdrasil](https://github.com/Yggdrasil))
- Add possibility to use BindPort IPAddress 👼 [\#657](https://github.com/containous/traefik/pull/657) ([vdemeester](https://github.com/vdemeester))
- Update marathon [\#648](https://github.com/containous/traefik/pull/648) ([emilevauge](https://github.com/emilevauge))
- Add backend features to docker [\#646](https://github.com/containous/traefik/pull/646) ([jangie](https://github.com/jangie))
- enable consul catalog to use maxconn [\#645](https://github.com/containous/traefik/pull/645) ([jangie](https://github.com/jangie))
- Adopt the Code Of Coduct from http://contributor-covenant.org [\#641](https://github.com/containous/traefik/pull/641) ([errm](https://github.com/errm))
- Use secure mode 600 instead of 644 for acme.json [\#639](https://github.com/containous/traefik/pull/639) ([discordianfish](https://github.com/discordianfish))
- docker clarification, fix dead urls, misc typos [\#637](https://github.com/containous/traefik/pull/637) ([djalal](https://github.com/djalal))
- add PING handler to dashboard API [\#630](https://github.com/containous/traefik/pull/630) ([jangie](https://github.com/jangie))
- Migrate to JobBackOff [\#628](https://github.com/containous/traefik/pull/628) ([emilevauge](https://github.com/emilevauge))
- Add long job exponential backoff [\#627](https://github.com/containous/traefik/pull/627) ([emilevauge](https://github.com/emilevauge))
- HA acme support [\#625](https://github.com/containous/traefik/pull/625) ([emilevauge](https://github.com/emilevauge))
- Bump go v1.7 [\#620](https://github.com/containous/traefik/pull/620) ([emilevauge](https://github.com/emilevauge))
- Make duration logging consistent [\#619](https://github.com/containous/traefik/pull/619) ([jangie](https://github.com/jangie))
- fix for nil clientTLS causing issue [\#617](https://github.com/containous/traefik/pull/617) ([jangie](https://github.com/jangie))
- Add ability for marathon provider to set maxconn values, loadbalancer algorithm, and circuit breaker expression [\#616](https://github.com/containous/traefik/pull/616) ([jangie](https://github.com/jangie))
- Make systemd unit installable [\#613](https://github.com/containous/traefik/pull/613) ([keis](https://github.com/keis))
- Merge v1.0.2 master [\#610](https://github.com/containous/traefik/pull/610) ([emilevauge](https://github.com/emilevauge))
- update staert and flaeg [\#609](https://github.com/containous/traefik/pull/609) ([cocap10](https://github.com/cocap10))
- \#504 Initial support for Docker 1.12 Swarm Mode [\#602](https://github.com/containous/traefik/pull/602) ([diegofernandes](https://github.com/diegofernandes))
- Add Host cert ACME generation [\#601](https://github.com/containous/traefik/pull/601) ([emilevauge](https://github.com/emilevauge))
- Fixed binary script so traefik version command doesn't just print default values [\#598](https://github.com/containous/traefik/pull/598) ([keiths-osc](https://github.com/keiths-osc))
- Name servers after thier pods [\#596](https://github.com/containous/traefik/pull/596) ([errm](https://github.com/errm))
- Fix Consul prefix [\#589](https://github.com/containous/traefik/pull/589) ([jippi](https://github.com/jippi))
- Prioritize kubernetes routes by path length [\#588](https://github.com/containous/traefik/pull/588) ([philk](https://github.com/philk))
- beautify help [\#580](https://github.com/containous/traefik/pull/580) ([cocap10](https://github.com/cocap10))
- Upgrade directives name since we use angular-ui-bootstrap [\#578](https://github.com/containous/traefik/pull/578) ([micaelmbagira](https://github.com/micaelmbagira))
- Fix basic docs for configuration of multiple rules [\#576](https://github.com/containous/traefik/pull/576) ([ajaegle](https://github.com/ajaegle))
- Fix k8s watch [\#573](https://github.com/containous/traefik/pull/573) ([errm](https://github.com/errm))
- Add requirements.txt for netlify [\#567](https://github.com/containous/traefik/pull/567) ([emilevauge](https://github.com/emilevauge))
- Merge v1.0.1 master [\#565](https://github.com/containous/traefik/pull/565) ([emilevauge](https://github.com/emilevauge))
- Move webui to FountainJS with Webpack [\#558](https://github.com/containous/traefik/pull/558) ([micaelmbagira](https://github.com/micaelmbagira))
- Add global InsecureSkipVerify option to disable certificate checking [\#557](https://github.com/containous/traefik/pull/557) ([stuart-c](https://github.com/stuart-c))
- Move version.go in its own package… [\#553](https://github.com/containous/traefik/pull/553) ([vdemeester](https://github.com/vdemeester))
- Upgrade libkermit and dependencies [\#552](https://github.com/containous/traefik/pull/552) ([vdemeester](https://github.com/vdemeester))
- Add command storeconfig [\#551](https://github.com/containous/traefik/pull/551) ([cocap10](https://github.com/cocap10))
- Add basic/digest auth [\#547](https://github.com/containous/traefik/pull/547) ([emilevauge](https://github.com/emilevauge))
- Bump node to 6 for webui [\#546](https://github.com/containous/traefik/pull/546) ([vdemeester](https://github.com/vdemeester))
- Bump golang to 1.6.3 [\#545](https://github.com/containous/traefik/pull/545) ([vdemeester](https://github.com/vdemeester))
- Fix typos [\#538](https://github.com/containous/traefik/pull/538) ([jimt](https://github.com/jimt))
- Kubernetes user-guide [\#519](https://github.com/containous/traefik/pull/519) ([errm](https://github.com/errm))
- Implement Kubernetes Selectors, minor kube endpoint fix [\#516](https://github.com/containous/traefik/pull/516) ([pnegahdar](https://github.com/pnegahdar))
- Carry \#358 : Option to disable expose of all docker containers [\#514](https://github.com/containous/traefik/pull/514) ([vdemeester](https://github.com/vdemeester))
- Remove traefik.frontend.value support in docker… [\#510](https://github.com/containous/traefik/pull/510) ([vdemeester](https://github.com/vdemeester))
- Use KvStores as global config sources [\#481](https://github.com/containous/traefik/pull/481) ([cocap10](https://github.com/cocap10))
- Add endpoint option to authenticate by client tls cert. [\#461](https://github.com/containous/traefik/pull/461) ([andersbetner](https://github.com/andersbetner))
- add mesos provider inspired by mesos-dns & marathon provider [\#353](https://github.com/containous/traefik/pull/353) ([skydjol](https://github.com/skydjol))
## [v1.1.0-rc4](https://github.com/containous/traefik/tree/v1.1.0-rc4) (2016-11-10)
[Full Changelog](https://github.com/containous/traefik/compare/v1.1.0-rc3...v1.1.0-rc4)
**Implemented enhancements:**
- Feature Request: Enable Health checks to containers. [\#540](https://github.com/containous/traefik/issues/540)
**Fixed bugs:**
- Traefik stopped serving on upgrade to v1.1.0-rc3 [\#807](https://github.com/containous/traefik/issues/807)
- Traefik cannot read constraints from KV [\#794](https://github.com/containous/traefik/issues/794)
- HTTP2 - configuration [\#790](https://github.com/containous/traefik/issues/790)
- Allow multiple certificates on a single entrypoint when trying to use TLS? [\#747](https://github.com/containous/traefik/issues/747)
**Closed issues:**
- LoadBalancing doesn't work in single node Swarm-mode [\#815](https://github.com/containous/traefik/issues/815)
- cannot connect to docker daemon [\#813](https://github.com/containous/traefik/issues/813)
- Let's encrypt configuration not working [\#805](https://github.com/containous/traefik/issues/805)
- Question: Wildcard Host for Kubernetes Ingress [\#792](https://github.com/containous/traefik/issues/792)
- Multiple subdomains for Marathon backend. [\#785](https://github.com/containous/traefik/issues/785)
- traefik-1.1.0-rc1: build error [\#781](https://github.com/containous/traefik/issues/781)
- Multiple routes support with Docker or Marathon labels [\#118](https://github.com/containous/traefik/issues/118)
**Merged pull requests:**
- Prepare release v1.1.0 rc4 [\#822](https://github.com/containous/traefik/pull/822) ([emilevauge](https://github.com/emilevauge))
- Fix multiple issues [\#814](https://github.com/containous/traefik/pull/814) ([emilevauge](https://github.com/emilevauge))
- Fix ACME renew & add version check [\#783](https://github.com/containous/traefik/pull/783) ([emilevauge](https://github.com/emilevauge))
- Use first port by default [\#782](https://github.com/containous/traefik/pull/782) ([guilhem](https://github.com/guilhem))
## [v1.1.0-rc3](https://github.com/containous/traefik/tree/v1.1.0-rc3) (2016-10-26)
[Full Changelog](https://github.com/containous/traefik/compare/v1.1.0-rc2...v1.1.0-rc3)
**Fixed bugs:**
- Cannot provide multiple certificates using flag [\#757](https://github.com/containous/traefik/issues/757)
- traefik \* Users: unsupported type: slice [\#743](https://github.com/containous/traefik/issues/743)
- \[Docker swarm mode\] The traefik.docker.network seems to have no effect [\#719](https://github.com/containous/traefik/issues/719)
- Case sensitive domain names breaks routing [\#562](https://github.com/containous/traefik/issues/562)
**Closed issues:**
- dependencies installation error [\#755](https://github.com/containous/traefik/issues/755)
- k8s provider w/ acme? [\#752](https://github.com/containous/traefik/issues/752)
- Documented ProvidersThrottleDuration value is invalid [\#741](https://github.com/containous/traefik/issues/741)
- Loadbalaning issues with traefik and Docker Swarm cluster [\#730](https://github.com/containous/traefik/issues/730)
- issues with marathon app ids containing a dot [\#726](https://github.com/containous/traefik/issues/726)
- How Routing traffic depending on path not domain in docker [\#706](https://github.com/containous/traefik/issues/706)
- Traefik crashes when using Consul catalog [\#699](https://github.com/containous/traefik/issues/699)
- File Watcher for rules does not work [\#683](https://github.com/containous/traefik/issues/683)
**Merged pull requests:**
- Fix ResponseRecorder Flush [\#776](https://github.com/containous/traefik/pull/776) ([emilevauge](https://github.com/emilevauge))
- Use sdnotify for systemd [\#768](https://github.com/containous/traefik/pull/768) ([guilhem](https://github.com/guilhem))
- Fix providers throttle duration doc [\#760](https://github.com/containous/traefik/pull/760) ([emilevauge](https://github.com/emilevauge))
- Fix mapstructure issue with anonymous slice [\#759](https://github.com/containous/traefik/pull/759) ([emilevauge](https://github.com/emilevauge))
- Fix multiple certificates using flag [\#758](https://github.com/containous/traefik/pull/758) ([emilevauge](https://github.com/emilevauge))
- Really fix deploy ghr... [\#748](https://github.com/containous/traefik/pull/748) ([emilevauge](https://github.com/emilevauge))
## [v1.1.0-rc2](https://github.com/containous/traefik/tree/v1.1.0-rc2) (2016-10-17)
[Full Changelog](https://github.com/containous/traefik/compare/v1.1.0-rc1...v1.1.0-rc2)
**Implemented enhancements:**
- Support healthcheck if present for docker [\#666](https://github.com/containous/traefik/issues/666)
**Closed issues:**
- Sensible configuration for consulCatalog [\#737](https://github.com/containous/traefik/issues/737)
- Traefik ignoring container listening in more than one TCP port [\#734](https://github.com/containous/traefik/issues/734)
- Error when using HA acme in kubernetes with etcd [\#725](https://github.com/containous/traefik/issues/725)
- \[Docker swarm mode\] No round robin when using service [\#718](https://github.com/containous/traefik/issues/718)
- Dose it support docker swarm mode [\#712](https://github.com/containous/traefik/issues/712)
- Kubernetes - Undefined backend [\#710](https://github.com/containous/traefik/issues/710)
- Constraints on Consul Catalogue not working as expected [\#703](https://github.com/containous/traefik/issues/703)
- docker run syntax in swarm example has changed [\#528](https://github.com/containous/traefik/issues/528)
- Secure WebSockets [\#467](https://github.com/containous/traefik/issues/467)
**Merged pull requests:**
- Fix case sensitive host [\#733](https://github.com/containous/traefik/pull/733) ([emilevauge](https://github.com/emilevauge))
- Update Kubernetes examples [\#731](https://github.com/containous/traefik/pull/731) ([Starefossen](https://github.com/Starefossen))
- fIx marathon template with dots in ID [\#728](https://github.com/containous/traefik/pull/728) ([emilevauge](https://github.com/emilevauge))
- Fix networkMap construction in ListServices [\#724](https://github.com/containous/traefik/pull/724) ([vincentlepot](https://github.com/vincentlepot))
- Add basic compatibility with marathon-lb [\#720](https://github.com/containous/traefik/pull/720) ([guilhem](https://github.com/guilhem))
- Add Ed's video at ContainerCamp [\#717](https://github.com/containous/traefik/pull/717) ([emilevauge](https://github.com/emilevauge))
- Add documentation for Træfik on docker swarm mode [\#715](https://github.com/containous/traefik/pull/715) ([vdemeester](https://github.com/vdemeester))
- Remove duplicated link to Kubernetes.io in README.md [\#713](https://github.com/containous/traefik/pull/713) ([oscerd](https://github.com/oscerd))
- Show current version in web UI [\#709](https://github.com/containous/traefik/pull/709) ([vhf](https://github.com/vhf))
- Add support for docker healthcheck 👼 [\#708](https://github.com/containous/traefik/pull/708) ([vdemeester](https://github.com/vdemeester))
- Fix syntax in Swarm example. Resolves \#528 [\#707](https://github.com/containous/traefik/pull/707) ([billglover](https://github.com/billglover))
## [v1.1.0-rc1](https://github.com/containous/traefik/tree/v1.1.0-rc1) (2016-09-30)
[Full Changelog](https://github.com/containous/traefik/compare/v1.0.0...v1.1.0-rc1)
**Implemented enhancements:**
- Feature Request: SSL Cipher Selection [\#535](https://github.com/containous/traefik/issues/535)
- Error with -consulcatalog and missing load balance method on 1.0.0 [\#524](https://github.com/containous/traefik/issues/524)
- Running Traefik with Docker 1.12 Swarm Mode [\#504](https://github.com/containous/traefik/issues/504)
- Kubernetes provider: should allow the master url to be override [\#501](https://github.com/containous/traefik/issues/501)
- \[FRONTEND\]\[LE\] Pre-generate SSL certificates for "Host:" rules [\#483](https://github.com/containous/traefik/issues/483)
- Frontend Rule evolution [\#437](https://github.com/containous/traefik/issues/437)
- Add a Changelog [\#388](https://github.com/containous/traefik/issues/388)
- Add label matching for kubernetes ingests [\#363](https://github.com/containous/traefik/issues/363)
- Acme in HA Traefik Scenario [\#348](https://github.com/containous/traefik/issues/348)
- HTTP Basic Auth support [\#77](https://github.com/containous/traefik/issues/77)
- Session affinity / stickiness / persistence [\#5](https://github.com/containous/traefik/issues/5)
- Kubernetes provider: traefik.frontend.rule.type logging [\#668](https://github.com/containous/traefik/pull/668) ([yvespp](https://github.com/yvespp))
**Fixed bugs:**
- traefik hangs - stops handling requests [\#662](https://github.com/containous/traefik/issues/662)
- Add long jobs in exponential backoff providers [\#626](https://github.com/containous/traefik/issues/626)
- Tip of tree crashes on invalid pointer on Marathon provider [\#624](https://github.com/containous/traefik/issues/624)
- ACME: revoke certificate on agreement update [\#579](https://github.com/containous/traefik/issues/579)
- WebUI: Providers tabs disappeared [\#577](https://github.com/containous/traefik/issues/577)
- traefik version command contains incorrect information when building from master branch [\#569](https://github.com/containous/traefik/issues/569)
- Flag --etcd.endpoint default [\#508](https://github.com/containous/traefik/issues/508)
- Conditional ACME on demand generation [\#505](https://github.com/containous/traefik/issues/505)
- Important delay with streams \(Mozilla EventSource\) [\#503](https://github.com/containous/traefik/issues/503)
- Traefik crashing [\#458](https://github.com/containous/traefik/issues/458)
- traefik.toml constraints error: `Expected map but found 'string'.` [\#451](https://github.com/containous/traefik/issues/451)
- Multiple path separators in the url path causing redirect [\#167](https://github.com/containous/traefik/issues/167)
**Closed issues:**
- Global InsecureSkipVerify does not work [\#700](https://github.com/containous/traefik/issues/700)
- \[documentation/feature\] Consul/etcd support atomic multiple key changes now [\#698](https://github.com/containous/traefik/issues/698)
- How to configure which network to use when starting traefik binary? [\#694](https://github.com/containous/traefik/issues/694)
- How to get multiple host headers working for docker labels? [\#692](https://github.com/containous/traefik/issues/692)
- Requests with URL-encoded characters are not forwarded correctly [\#684](https://github.com/containous/traefik/issues/684)
- Issue with global InsecureSkipVerify = true and self signed certificates [\#667](https://github.com/containous/traefik/issues/667)
- Docker exposedbydefault = false didn't work [\#663](https://github.com/containous/traefik/issues/663)
- \[ACME\] Auto SAN Detection [\#655](https://github.com/containous/traefik/issues/655)
- Fronting a domain with DNS A-record round-robin & ACME [\#654](https://github.com/containous/traefik/issues/654)
- Overriding toml configuration with environment variables [\#650](https://github.com/containous/traefik/issues/650)
- marathon provider exposedByDefault = false [\#647](https://github.com/containous/traefik/issues/647)
- Add status URL for service up checks [\#642](https://github.com/containous/traefik/issues/642)
- acme's storage file, containing private key, is word readable [\#638](https://github.com/containous/traefik/issues/638)
- wildcard domain with exclusions [\#633](https://github.com/containous/traefik/issues/633)
- Enable evenly distribution among backend [\#631](https://github.com/containous/traefik/issues/631)
- Traefik sporadically failing when proxying requests [\#615](https://github.com/containous/traefik/issues/615)
- TCP Proxy [\#608](https://github.com/containous/traefik/issues/608)
- How to use in Windows? [\#605](https://github.com/containous/traefik/issues/605)
- `ClientCAFiles` ignored [\#604](https://github.com/containous/traefik/issues/604)
- Let`s Encrypt enable in etcd [\#600](https://github.com/containous/traefik/issues/600)
- Support HTTP Basic Auth [\#599](https://github.com/containous/traefik/issues/599)
- Consul KV seem broken [\#587](https://github.com/containous/traefik/issues/587)
- HTTPS entryPoint not working [\#574](https://github.com/containous/traefik/issues/574)
- Traefik stuck when used as frontend for a streaming API [\#560](https://github.com/containous/traefik/issues/560)
- Exclude some frontends in consul catalog [\#555](https://github.com/containous/traefik/issues/555)
- Can I use Traefik without a domain name? [\#539](https://github.com/containous/traefik/issues/539)
- Priortities in 1.0.0 not behaving [\#506](https://github.com/containous/traefik/issues/506)
- Route by path [\#500](https://github.com/containous/traefik/issues/500)
- Container IP Lost [\#375](https://github.com/containous/traefik/issues/375)
**Merged pull requests:**
- Add HTTP compression [\#702](https://github.com/containous/traefik/pull/702) ([tuier](https://github.com/tuier))
- Carry PR 446 - Add sticky session support \(round two!\) [\#701](https://github.com/containous/traefik/pull/701) ([emilevauge](https://github.com/emilevauge))
- Remove unused endpoint when using constraints with Marathon provider [\#697](https://github.com/containous/traefik/pull/697) ([tuier](https://github.com/tuier))
- Replace imagelayers.io with microbadger [\#696](https://github.com/containous/traefik/pull/696) ([solidnerd](https://github.com/solidnerd))
- Selectable TLS Versions [\#690](https://github.com/containous/traefik/pull/690) ([dtomcej](https://github.com/dtomcej))
- Carry pr 439 [\#689](https://github.com/containous/traefik/pull/689) ([emilevauge](https://github.com/emilevauge))
- Disable gorilla/mux URL cleaning to prevent sending redirect [\#688](https://github.com/containous/traefik/pull/688) ([ydubreuil](https://github.com/ydubreuil))
- Some fixes [\#687](https://github.com/containous/traefik/pull/687) ([emilevauge](https://github.com/emilevauge))
- feat\(constraints\): Supports constraints for Marathon provider [\#686](https://github.com/containous/traefik/pull/686) ([tuier](https://github.com/tuier))
- Update docs to improve contribution setup [\#685](https://github.com/containous/traefik/pull/685) ([dtomcej](https://github.com/dtomcej))
- Add basic auth support for web backend [\#677](https://github.com/containous/traefik/pull/677) ([SantoDE](https://github.com/SantoDE))
- Document accepted values for logLevel. [\#676](https://github.com/containous/traefik/pull/676) ([jimmycuadra](https://github.com/jimmycuadra))
- If Marathon doesn't have healthcheck, assume it's ok [\#665](https://github.com/containous/traefik/pull/665) ([gomes](https://github.com/gomes))
- ACME: renew certificates 30 days before expiry [\#660](https://github.com/containous/traefik/pull/660) ([JayH5](https://github.com/JayH5))
- Update broken link and add a comment to sample config file [\#658](https://github.com/containous/traefik/pull/658) ([Yggdrasil](https://github.com/Yggdrasil))
- Add possibility to use BindPort IPAddress 👼 [\#657](https://github.com/containous/traefik/pull/657) ([vdemeester](https://github.com/vdemeester))
- Update marathon [\#648](https://github.com/containous/traefik/pull/648) ([emilevauge](https://github.com/emilevauge))
- Add backend features to docker [\#646](https://github.com/containous/traefik/pull/646) ([jangie](https://github.com/jangie))
- enable consul catalog to use maxconn [\#645](https://github.com/containous/traefik/pull/645) ([jangie](https://github.com/jangie))
- Adopt the Code Of Coduct from http://contributor-covenant.org [\#641](https://github.com/containous/traefik/pull/641) ([errm](https://github.com/errm))
- Use secure mode 600 instead of 644 for acme.json [\#639](https://github.com/containous/traefik/pull/639) ([discordianfish](https://github.com/discordianfish))
- docker clarification, fix dead urls, misc typos [\#637](https://github.com/containous/traefik/pull/637) ([djalal](https://github.com/djalal))
- add PING handler to dashboard API [\#630](https://github.com/containous/traefik/pull/630) ([jangie](https://github.com/jangie))
- Migrate to JobBackOff [\#628](https://github.com/containous/traefik/pull/628) ([emilevauge](https://github.com/emilevauge))
- Add long job exponential backoff [\#627](https://github.com/containous/traefik/pull/627) ([emilevauge](https://github.com/emilevauge))
- HA acme support [\#625](https://github.com/containous/traefik/pull/625) ([emilevauge](https://github.com/emilevauge))
- Bump go v1.7 [\#620](https://github.com/containous/traefik/pull/620) ([emilevauge](https://github.com/emilevauge))
- Make duration logging consistent [\#619](https://github.com/containous/traefik/pull/619) ([jangie](https://github.com/jangie))
- fix for nil clientTLS causing issue [\#617](https://github.com/containous/traefik/pull/617) ([jangie](https://github.com/jangie))
- Add ability for marathon provider to set maxconn values, loadbalancer algorithm, and circuit breaker expression [\#616](https://github.com/containous/traefik/pull/616) ([jangie](https://github.com/jangie))
- Make systemd unit installable [\#613](https://github.com/containous/traefik/pull/613) ([keis](https://github.com/keis))
- Merge v1.0.2 master [\#610](https://github.com/containous/traefik/pull/610) ([emilevauge](https://github.com/emilevauge))
- update staert and flaeg [\#609](https://github.com/containous/traefik/pull/609) ([cocap10](https://github.com/cocap10))
- \#504 Initial support for Docker 1.12 Swarm Mode [\#602](https://github.com/containous/traefik/pull/602) ([diegofernandes](https://github.com/diegofernandes))
- Add Host cert ACME generation [\#601](https://github.com/containous/traefik/pull/601) ([emilevauge](https://github.com/emilevauge))
- Fixed binary script so traefik version command doesn't just print default values [\#598](https://github.com/containous/traefik/pull/598) ([keiths-osc](https://github.com/keiths-osc))
- Name servers after thier pods [\#596](https://github.com/containous/traefik/pull/596) ([errm](https://github.com/errm))
- Fix Consul prefix [\#589](https://github.com/containous/traefik/pull/589) ([jippi](https://github.com/jippi))
- Prioritize kubernetes routes by path length [\#588](https://github.com/containous/traefik/pull/588) ([philk](https://github.com/philk))
- beautify help [\#580](https://github.com/containous/traefik/pull/580) ([cocap10](https://github.com/cocap10))
- Upgrade directives name since we use angular-ui-bootstrap [\#578](https://github.com/containous/traefik/pull/578) ([micaelmbagira](https://github.com/micaelmbagira))
- Fix basic docs for configuration of multiple rules [\#576](https://github.com/containous/traefik/pull/576) ([ajaegle](https://github.com/ajaegle))
- Fix k8s watch [\#573](https://github.com/containous/traefik/pull/573) ([errm](https://github.com/errm))
- Add requirements.txt for netlify [\#567](https://github.com/containous/traefik/pull/567) ([emilevauge](https://github.com/emilevauge))
- Merge v1.0.1 master [\#565](https://github.com/containous/traefik/pull/565) ([emilevauge](https://github.com/emilevauge))
- Move webui to FountainJS with Webpack [\#558](https://github.com/containous/traefik/pull/558) ([micaelmbagira](https://github.com/micaelmbagira))
- Add global InsecureSkipVerify option to disable certificate checking [\#557](https://github.com/containous/traefik/pull/557) ([stuart-c](https://github.com/stuart-c))
- Move version.go in its own package… [\#553](https://github.com/containous/traefik/pull/553) ([vdemeester](https://github.com/vdemeester))
- Upgrade libkermit and dependencies [\#552](https://github.com/containous/traefik/pull/552) ([vdemeester](https://github.com/vdemeester))
- Add command storeconfig [\#551](https://github.com/containous/traefik/pull/551) ([cocap10](https://github.com/cocap10))
- Add basic/digest auth [\#547](https://github.com/containous/traefik/pull/547) ([emilevauge](https://github.com/emilevauge))
- Bump node to 6 for webui [\#546](https://github.com/containous/traefik/pull/546) ([vdemeester](https://github.com/vdemeester))
- Bump golang to 1.6.3 [\#545](https://github.com/containous/traefik/pull/545) ([vdemeester](https://github.com/vdemeester))
- Fix typos [\#538](https://github.com/containous/traefik/pull/538) ([jimt](https://github.com/jimt))
- Kubernetes user-guide [\#519](https://github.com/containous/traefik/pull/519) ([errm](https://github.com/errm))
- Implement Kubernetes Selectors, minor kube endpoint fix [\#516](https://github.com/containous/traefik/pull/516) ([pnegahdar](https://github.com/pnegahdar))
- Carry \#358 : Option to disable expose of all docker containers [\#514](https://github.com/containous/traefik/pull/514) ([vdemeester](https://github.com/vdemeester))
- Remove traefik.frontend.value support in docker… [\#510](https://github.com/containous/traefik/pull/510) ([vdemeester](https://github.com/vdemeester))
- Use KvStores as global config sources [\#481](https://github.com/containous/traefik/pull/481) ([cocap10](https://github.com/cocap10))
- Add endpoint option to authenticate by client tls cert. [\#461](https://github.com/containous/traefik/pull/461) ([andersbetner](https://github.com/andersbetner))
- add mesos provider inspired by mesos-dns & marathon provider [\#353](https://github.com/containous/traefik/pull/353) ([skydjol](https://github.com/skydjol))
## [v1.0.2](https://github.com/containous/traefik/tree/v1.0.2) (2016-08-02)
[Full Changelog](https://github.com/containous/traefik/compare/v1.0.1...v1.0.2)
**Fixed bugs:**
- ACME: revoke certificate on agreement update [\#579](https://github.com/containous/traefik/issues/579)
**Closed issues:**
- Exclude some frontends in consul catalog [\#555](https://github.com/containous/traefik/issues/555)
**Merged pull requests:**
- Bump oxy version, fix streaming [\#584](https://github.com/containous/traefik/pull/584) ([emilevauge](https://github.com/emilevauge))
- Fix ACME TOS [\#582](https://github.com/containous/traefik/pull/582) ([emilevauge](https://github.com/emilevauge))
## [v1.0.1](https://github.com/containous/traefik/tree/v1.0.1) (2016-07-19)
[Full Changelog](https://github.com/containous/traefik/compare/v1.0.0...v1.0.1)
**Implemented enhancements:**
- Error with -consulcatalog and missing load balance method on 1.0.0 [\#524](https://github.com/containous/traefik/issues/524)
- Kubernetes provider: should allow the master url to be override [\#501](https://github.com/containous/traefik/issues/501)
**Fixed bugs:**
- Flag --etcd.endpoint default [\#508](https://github.com/containous/traefik/issues/508)
- Conditional ACME on demand generation [\#505](https://github.com/containous/traefik/issues/505)
- Important delay with streams \(Mozilla EventSource\) [\#503](https://github.com/containous/traefik/issues/503)
**Closed issues:**
- Can I use Traefik without a domain name? [\#539](https://github.com/containous/traefik/issues/539)
- Priortities in 1.0.0 not behaving [\#506](https://github.com/containous/traefik/issues/506)
- Route by path [\#500](https://github.com/containous/traefik/issues/500)
**Merged pull requests:**
- Update server.go [\#531](https://github.com/containous/traefik/pull/531) ([Jsewill](https://github.com/Jsewill))
- Add sse support [\#527](https://github.com/containous/traefik/pull/527) ([emilevauge](https://github.com/emilevauge))
- Fix acme checkOnDemandDomain [\#512](https://github.com/containous/traefik/pull/512) ([emilevauge](https://github.com/emilevauge))
- Fix default etcd port [\#511](https://github.com/containous/traefik/pull/511) ([errm](https://github.com/errm))
## [v1.0.0](https://github.com/containous/traefik/tree/v1.0.0) (2016-07-05)
[Full Changelog](https://github.com/containous/traefik/compare/v1.0.0-rc3...v1.0.0)
**Fixed bugs:**
- Enable to define empty TLS option by flag for Let's Encrypt [\#488](https://github.com/containous/traefik/issues/488)
- \[Docker\] No IP in backend in host networking mode [\#487](https://github.com/containous/traefik/issues/487)
- Response is compressed when not requested [\#485](https://github.com/containous/traefik/issues/485)
- loadConfig modifies configuration causing same config check to fail [\#480](https://github.com/containous/traefik/issues/480)
**Closed issues:**
- svg logo [\#482](https://github.com/containous/traefik/issues/482)
- etcd tries to connect with TLS even with --etcd.tls=false [\#456](https://github.com/containous/traefik/issues/456)
- Zookeeper - KV connection error: Failed to test KV store connection [\#455](https://github.com/containous/traefik/issues/455)
- "Not Found" api response needed instead of 404 [\#454](https://github.com/containous/traefik/issues/454)
- domain label doesn't work on docker [\#447](https://github.com/containous/traefik/issues/447)
- Any chance of a windows release? [\#425](https://github.com/containous/traefik/issues/425)
**Merged pull requests:**
- Fix windows builds [\#495](https://github.com/containous/traefik/pull/495) ([emilevauge](https://github.com/emilevauge))
- Fix host Docker network [\#494](https://github.com/containous/traefik/pull/494) ([emilevauge](https://github.com/emilevauge))
- Fix empty tls flag [\#493](https://github.com/containous/traefik/pull/493) ([emilevauge](https://github.com/emilevauge))
- Fix webui proxying [\#492](https://github.com/containous/traefik/pull/492) ([emilevauge](https://github.com/emilevauge))
- Fix default weight in server.LoadConfig [\#491](https://github.com/containous/traefik/pull/491) ([emilevauge](https://github.com/emilevauge))
- Fix retry headers, simplify ResponseRecorder [\#490](https://github.com/containous/traefik/pull/490) ([emilevauge](https://github.com/emilevauge))
## [v1.0.0-rc3](https://github.com/containous/traefik/tree/v1.0.0-rc3) (2016-06-23)
[Full Changelog](https://github.com/containous/traefik/compare/v1.0.0-rc2...v1.0.0-rc3)
**Implemented enhancements:**
- support more than one rule to Docker backend [\#419](https://github.com/containous/traefik/issues/419)
**Fixed bugs:**
- consulCatalog issue when serviceName contains a dot [\#475](https://github.com/containous/traefik/issues/475)
- Issue with empty responses [\#463](https://github.com/containous/traefik/issues/463)
- Severe memory leak in beta.470 and beyond crashes Traefik server [\#462](https://github.com/containous/traefik/issues/462)
- Marathon that starts with a space causes parsing errors. [\#459](https://github.com/containous/traefik/issues/459)
- A frontend route without a rule \(or empty rule\) causes a crash when traefik starts [\#453](https://github.com/containous/traefik/issues/453)
- container dropped out when connecting to Docker Swarm [\#442](https://github.com/containous/traefik/issues/442)
- Traefik setting Accept-Encoding: gzip on requests \(Traefik may also be broken with chunked responses\) [\#421](https://github.com/containous/traefik/issues/421)
**Closed issues:**
- HTTP headers case gets modified [\#466](https://github.com/containous/traefik/issues/466)
- File frontend \> Marathon Backend [\#465](https://github.com/containous/traefik/issues/465)
- Websocket: Unable to hijack the connection [\#452](https://github.com/containous/traefik/issues/452)
- kubernetes: Received event spamming? [\#449](https://github.com/containous/traefik/issues/449)
- kubernetes: backends not updated when i scale replication controller? [\#448](https://github.com/containous/traefik/issues/448)
- Add href link on frontend [\#436](https://github.com/containous/traefik/issues/436)
- Multiple Domains Rule [\#430](https://github.com/containous/traefik/issues/430)
**Merged pull requests:**
- Disable constraints in doc until 1.1 [\#479](https://github.com/containous/traefik/pull/479) ([emilevauge](https://github.com/emilevauge))
- Sort nodes before creating consul catalog config [\#478](https://github.com/containous/traefik/pull/478) ([keis](https://github.com/keis))
- Fix spamming events in listenProviders [\#477](https://github.com/containous/traefik/pull/477) ([emilevauge](https://github.com/emilevauge))
- Fix empty responses [\#476](https://github.com/containous/traefik/pull/476) ([emilevauge](https://github.com/emilevauge))
- Fix acme renew [\#472](https://github.com/containous/traefik/pull/472) ([emilevauge](https://github.com/emilevauge))
- Fix typo in error message. [\#471](https://github.com/containous/traefik/pull/471) ([KevinBusse](https://github.com/KevinBusse))
- Fix errors load config [\#470](https://github.com/containous/traefik/pull/470) ([emilevauge](https://github.com/emilevauge))
- Typo: Replace French words by English ones [\#469](https://github.com/containous/traefik/pull/469) ([kumy](https://github.com/kumy))
- Fix marathon TLS/basic auth [\#468](https://github.com/containous/traefik/pull/468) ([emilevauge](https://github.com/emilevauge))
- Fix memory leak in listenProviders [\#464](https://github.com/containous/traefik/pull/464) ([emilevauge](https://github.com/emilevauge))
- Fix websocket connection Hijack [\#460](https://github.com/containous/traefik/pull/460) ([emilevauge](https://github.com/emilevauge))
- Fix default KV configuration [\#450](https://github.com/containous/traefik/pull/450) ([emilevauge](https://github.com/emilevauge))
- Fix panic if listContainers fails… [\#443](https://github.com/containous/traefik/pull/443) ([vdemeester](https://github.com/vdemeester))
- mount acme folder instead of file [\#441](https://github.com/containous/traefik/pull/441) ([NicolasGeraud](https://github.com/NicolasGeraud))
- feat\(constraints\): Supports constraints for docker backend [\#438](https://github.com/containous/traefik/pull/438) ([samber](https://github.com/samber))
## [v1.0.0-rc2](https://github.com/containous/traefik/tree/v1.0.0-rc2) (2016-06-07)
[Full Changelog](https://github.com/containous/traefik/compare/v1.0.0-rc1...v1.0.0-rc2)
**Implemented enhancements:**
- Add @samber to maintainers [\#440](https://github.com/containous/traefik/pull/440) ([emilevauge](https://github.com/emilevauge))
**Fixed bugs:**
- Panic on help [\#429](https://github.com/containous/traefik/issues/429)
- Bad default values in configuration [\#427](https://github.com/containous/traefik/issues/427)
**Closed issues:**
- Traefik doesn't listen on IPv4 ports [\#434](https://github.com/containous/traefik/issues/434)
- Not listening on port 80 [\#432](https://github.com/containous/traefik/issues/432)
- docs need updating for new frontend rules format [\#423](https://github.com/containous/traefik/issues/423)
- Does traefik supports for Mac? \(For devlelopment\) [\#417](https://github.com/containous/traefik/issues/417)
**Merged pull requests:**
- Allow multiple rules [\#435](https://github.com/containous/traefik/pull/435) ([fclaeys](https://github.com/fclaeys))
- Add routes priorities [\#433](https://github.com/containous/traefik/pull/433) ([emilevauge](https://github.com/emilevauge))
- Fix default configuration [\#428](https://github.com/containous/traefik/pull/428) ([emilevauge](https://github.com/emilevauge))
- Fix marathon groups subdomain [\#426](https://github.com/containous/traefik/pull/426) ([emilevauge](https://github.com/emilevauge))
- Fix travis tag check [\#422](https://github.com/containous/traefik/pull/422) ([emilevauge](https://github.com/emilevauge))
- log info about TOML configuration file using [\#420](https://github.com/containous/traefik/pull/420) ([cocap10](https://github.com/cocap10))
- Doc about skipping some integration tests with '-check.f ConsulCatalogSuite' [\#418](https://github.com/containous/traefik/pull/418) ([samber](https://github.com/samber))
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*

74
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,74 @@
# Contributor Covenant Code of Conduct
## 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.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its 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@containo.us
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.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@@ -1,4 +1,5 @@
FROM scratch
COPY script/ca-certificates.crt /etc/ssl/certs/
COPY dist/traefik /
EXPOSE 80
ENTRYPOINT ["/traefik"]

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015 Emile Vauge, emile@vauge.com
Copyright (c) 2016 Containous SAS, Emile Vauge, emile@vauge.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE.

View File

@@ -3,60 +3,63 @@
TRAEFIK_ENVS := \
-e OS_ARCH_ARG \
-e OS_PLATFORM_ARG \
-e TESTFLAGS
-e TESTFLAGS \
-e VERBOSE \
-e VERSION \
-e CODENAME
SRCS = $(shell git ls-files '*.go' | grep -v '^external/')
BIND_DIR := "dist"
TRAEFIK_MOUNT := -v "$(CURDIR)/$(BIND_DIR):/go/src/github.com/emilevauge/traefik/$(BIND_DIR)"
TRAEFIK_MOUNT := -v "$(CURDIR)/$(BIND_DIR):/go/src/github.com/containous/traefik/$(BIND_DIR)"
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)
GIT_BRANCH := $(subst heads/,,$(shell git rev-parse --abbrev-ref HEAD 2>/dev/null))
TRAEFIK_DEV_IMAGE := traefik-dev$(if $(GIT_BRANCH),:$(GIT_BRANCH))
REPONAME := $(shell echo $(REPO) | tr '[:upper:]' '[:lower:]')
TRAEFIK_IMAGE := $(if $(REPONAME),$(REPONAME),"emilevauge/traefik")
TRAEFIK_IMAGE := $(if $(REPONAME),$(REPONAME),"containous/traefik")
INTEGRATION_OPTS := $(if $(MAKE_DOCKER_HOST),-e "DOCKER_HOST=$(MAKE_DOCKER_HOST)", -v "/var/run/docker.sock:/var/run/docker.sock")
DOCKER_RUN_TRAEFIK := docker run $(if $(CIRCLECI),,--rm) $(INTEGRATION_OPTS) -it $(TRAEFIK_ENVS) $(TRAEFIK_MOUNT) "$(TRAEFIK_DEV_IMAGE)"
DOCKER_BUILD_ARGS := $(if $(DOCKER_VERSION), "--build-arg=DOCKER_VERSION=$(DOCKER_VERSION)",)
DOCKER_RUN_TRAEFIK := docker run $(INTEGRATION_OPTS) -it $(TRAEFIK_ENVS) $(TRAEFIK_MOUNT) "$(TRAEFIK_DEV_IMAGE)"
print-%: ; @echo $*=$($*)
default: binary
all: build
all: generate-webui build ## validate all checks, build linux binary, run all tests\ncross non-linux binaries
$(DOCKER_RUN_TRAEFIK) ./script/make.sh
binary: build
binary: generate-webui build ## build the linux binary
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate binary
crossbinary: build
crossbinary: generate-webui build ## cross build the non-linux binaries
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate crossbinary
test: build
test: build ## run the unit and integration tests
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate test-unit binary test-integration
test-unit: build
test-unit: build ## run the unit tests
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate test-unit
test-integration: build
test-integration: build ## run the integration tests
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate test-integration
validate: build
$(DOCKER_RUN_TRAEFIK) ./script/make.sh validate-gofmt validate-govet
validate-gofmt: build
$(DOCKER_RUN_TRAEFIK) ./script/make.sh validate-gofmt
validate-govet: build
$(DOCKER_RUN_TRAEFIK) ./script/make.sh validate-govet
validate: build ## validate gofmt, golint and go vet
$(DOCKER_RUN_TRAEFIK) ./script/make.sh validate-glide validate-gofmt validate-govet validate-golint validate-misspell
build: dist
docker build -t "$(TRAEFIK_DEV_IMAGE)" -f build.Dockerfile .
docker build $(DOCKER_BUILD_ARGS) -t "$(TRAEFIK_DEV_IMAGE)" -f build.Dockerfile .
build-webui:
docker build -t traefik-webui -f webui/Dockerfile webui
build-no-cache: dist
docker build --no-cache -t "$(TRAEFIK_DEV_IMAGE)" -f build.Dockerfile .
shell: build
shell: build ## start a shell inside the build env
$(DOCKER_RUN_TRAEFIK) /bin/bash
image: build
image: build ## build a docker traefik image
docker build -t $(TRAEFIK_IMAGE) .
dist:
@@ -66,3 +69,18 @@ run-dev:
go generate
go build
./traefik
generate-webui: build-webui
if [ ! -d "static" ]; then \
mkdir -p static; \
docker run --rm -v "$$PWD/static":'/src/static' traefik-webui npm run build; \
echo 'For more informations show `webui/readme.md`' > $$PWD/static/DONT-EDIT-FILES-IN-THIS-DIRECTORY.md; \
fi
lint:
script/validate-golint
fmt:
gofmt -s -l -w $(SRCS)
help: ## this help
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {sub("\\\\n",sprintf("\n%22c"," "), $$2);printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)

187
README.md
View File

@@ -1,38 +1,80 @@
![Træfɪk](http://traefik.github.io/traefik.logo.svg "Træfɪk")
___
[![Circle CI](https://circleci.com/gh/emilevauge/traefik.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/emilevauge/traefik)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/EmileVauge/traefik/blob/master/LICENSE.md)
<p align="center">
<img src="docs/img/traefik.logo.png" alt="Træfɪk" title="Træfɪk" />
</p>
[![Build Status](https://travis-ci.org/containous/traefik.svg?branch=master)](https://travis-ci.org/containous/traefik)
[![Docs](https://img.shields.io/badge/docs-current-brightgreen.svg)](https://docs.traefik.io)
[![Go Report Card](https://goreportcard.com/badge/containous/traefik)](http://goreportcard.com/report/containous/traefik)
[![](https://images.microbadger.com/badges/image/traefik.svg)](https://microbadger.com/images/traefik)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/containous/traefik/blob/master/LICENSE.md)
[![Join the chat at https://traefik.herokuapp.com](https://img.shields.io/badge/style-register-green.svg?style=social&label=Slack)](https://traefik.herokuapp.com)
[![Twitter](https://img.shields.io/twitter/follow/traefikproxy.svg?style=social)](https://twitter.com/intent/follow?screen_name=traefikproxy)
Træfɪk is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease.
It supports several backends ([Docker :whale:](https://www.docker.com/), [Mesos/Marathon](https://mesosphere.github.io/marathon/), [Consul](https://consul.io/), [Etcd](https://coreos.com/etcd/), [Zookeeper](https://zookeeper.apache.org), [BoltDB](https://github.com/boltdb/bolt), Rest API, file...) to manage its configuration automatically and dynamically.
Træfɪk (pronounced like [traffic](https://speak-ipa.bearbin.net/speak.cgi?speak=%CB%88tr%C3%A6f%C9%AAk)) is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease.
It supports several backends ([Docker](https://www.docker.com/), [Swarm](https://docs.docker.com/swarm), [Kubernetes](http://kubernetes.io), [Marathon](https://mesosphere.github.io/marathon/), [Mesos](https://github.com/apache/mesos), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Zookeeper](https://zookeeper.apache.org), [BoltDB](https://github.com/boltdb/bolt), [Eureka](https://github.com/Netflix/eureka), Rest API, file...) to manage its configuration automatically and dynamically.
## Overview
Imagine that you have deployed a bunch of microservices on your infrastructure. You probably used a service registry (like etcd or consul) and/or an orchestrator (swarm, Mesos/Marathon) to manage all these services.
If you want your users to access some of your microservices from the Internet, you will have to use a reverse proxy and configure it using virtual hosts or prefix paths:
- domain `api.domain.com` will point the microservice `api` in your private network
- path `domain.com/web` will point the microservice `web` in your private network
- domain `backoffice.domain.com` will point the microservices `backoffice` in your private network, load-balancing between your multiple instances
But a microservices architecture is dynamic... Services are added, removed, killed or upgraded often, eventually several times a day.
Traditional reverse-proxies are not natively dynamic. You can't change their configuration and hot-reload easily.
Here enters Træfɪk.
![Architecture](docs/img/architecture.png)
Træfɪk can listen to your service registry/orchestrator API, and knows each time a microservice is added, removed, killed or upgraded, and can generate its configuration automatically.
Routes to your services will be created instantly.
Run it and forget it!
## Features
- [It's fast](http://docs.traefik.io/benchmarks)
- No dependency hell, single binary made with go
- Simple json Rest API
- Simple TOML file configuration
- Multiple backends supported: Docker, Mesos/Marathon, Consul, Etcd, and more to come
- Watchers for backends, can listen change in backends to apply a new configuration automatically
- Rest API
- Multiple backends supported: Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, and more to come
- Watchers for backends, can listen for changes in backends to apply a new configuration automatically
- Hot-reloading of configuration. No need to restart the process
- Graceful shutdown http connections during hot-reloads
- Graceful shutdown http connections
- Circuit breakers on backends
- Round Robin, rebalancer load-balancers
- Rest Metrics
- Tiny docker image included
- [Tiny](https://microbadger.com/images/traefik) [official](https://hub.docker.com/r/_/traefik/) docker image included
- SSL backends support
- SSL frontend support
- SSL frontend support (with SNI)
- Clean AngularJS Web UI
- Websocket support
- HTTP/2 support
- Retry request if network error
- [Let's Encrypt](https://letsencrypt.org) support (Automatic HTTPS with renewal)
- High Availability with cluster mode
## Demo
## Quickstart
Here is a demo of Træfɪk using Docker backend, showing a load-balancing between two servers, hot reloading of configuration, and graceful shutdown.
You can have a quick look at Træfɪk in this [Katacoda tutorial](https://www.katacoda.com/courses/traefik/deploy-load-balancer) that shows how to load balance requests between multiple Docker containers.
[![asciicast](https://asciinema.org/a/4tcyde7riou5vxulo6my3mtko.png)](https://asciinema.org/a/4tcyde7riou5vxulo6my3mtko)
Here is a talk given by [Ed Robinson](https://github.com/errm) at the [ContainerCamp UK](https://container.camp) conference.
You will learn fundamental Træfɪk features and see some demos with Kubernetes.
[![Traefik ContainerCamp UK](http://img.youtube.com/vi/aFtpIShV60I/0.jpg)](https://www.youtube.com/watch?v=aFtpIShV60I)
Here is a talk (in French) given by [Emile Vauge](https://github.com/emilevauge) at the [Devoxx France 2016](http://www.devoxx.fr) conference.
You will learn fundamental Træfɪk features and see some demos with Docker, Mesos/Marathon and Let's Encrypt.
[![Traefik Devoxx France](http://img.youtube.com/vi/QvAz9mVx5TI/0.jpg)](http://www.youtube.com/watch?v=QvAz9mVx5TI)
## Web UI
@@ -43,114 +85,85 @@ You can access to a simple HTML frontend of Træfik.
## Plumbing
- [Oxy](https://github.com/mailgun/oxy/): an awsome proxy library made by Mailgun guys
- [Oxy](https://github.com/vulcand/oxy): an awesome proxy library made by Mailgun guys
- [Gorilla mux](https://github.com/gorilla/mux): famous request router
- [Negroni](https://github.com/codegangsta/negroni): web middlewares made simple
- [Manners](https://github.com/mailgun/manners): graceful shutdown of http.Handler servers
- [Lego](https://github.com/xenolf/lego): the best [Let's Encrypt](https://letsencrypt.org) library in go
## Quick start
## Test it
- The simple way: grab the latest binary from the [releases](https://github.com/emilevauge/traefik/releases) page and just run it with the [sample configuration file](https://raw.githubusercontent.com/EmileVauge/traefik/master/traefik.sample.toml):
- The simple way: grab the latest binary from the [releases](https://github.com/containous/traefik/releases) page and just run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/master/traefik.sample.toml):
```shell
./traefik traefik.toml
./traefik --configFile=traefik.toml
```
- Use the tiny Docker image:
```shell
docker run -d -p 8080:8080 -p 80:80 -v $PWD/traefik.toml:/traefik.toml emilevauge/traefik
docker run -d -p 8080:8080 -p 80:80 -v $PWD/traefik.toml:/etc/traefik/traefik.toml traefik
```
- From sources:
```shell
git clone https://github.com/EmileVauge/traefik
git clone https://github.com/containous/traefik
```
## Documentation
You can find the complete documentation [here](docs/index.md).
## Benchmarks
Refer to the [benchmarks section](docs/index.md#benchmarks) in the documentation.
You can find the complete documentation [here](https://docs.traefik.io).
## Contributing
### Building
Please refer to [this section](.github/CONTRIBUTING.md).
You need either [Docker](https://github.com/docker/docker) and `make`, or `go` and `glide` in order to build traefik.
## Code Of Conduct
#### Setting up your `go` environment
- You need `go` v1.5
- You need to set `export GO15VENDOREXPERIMENT=1` environment variable
- You need `go-bindata` to be able to use `go generate` command (needed to build) : `go get github.com/jteeuwen/go-bindata/...`.
- If you clone Træfɪk into something like `~/go/src/github.com/traefik`, your `GOPATH` variable will have to be set to `~/go`: export `GOPATH=~/go`.
Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
#### Using `Docker` and `Makefile`
## Support
You need to run the `binary` target. This will create binaries for
linux platform in the `dist` folder.
You can join [![Join the chat at https://traefik.herokuapp.com](https://img.shields.io/badge/style-register-green.svg?style=social&label=Slack)](https://traefik.herokuapp.com) to get basic support.
If you prefer commercial support, please contact [containo.us](https://containo.us) by mail: <mailto:support@containo.us>.
```bash
$ make binary
docker build -t "traefik-dev:no-more-godep-ever" -f build.Dockerfile .
Sending build context to Docker daemon 295.3 MB
Step 0 : FROM golang:1.5
---> 8c6473912976
Step 1 : RUN go get github.com/Masterminds/glide
[...]
docker run --rm -v "/var/run/docker.sock:/var/run/docker.sock" -it -e OS_ARCH_ARG -e OS_PLATFORM_ARG -e TESTFLAGS -v "/home/emile/dev/go/src/github.com/emilevauge/traefik/"dist":/go/src/github.com/emilevauge/traefik/"dist"" "traefik-dev:no-more-godep-ever" ./script/make.sh generate binary
---> Making bundle: generate (in .)
removed 'gen.go'
## Træfɪk here and there
---> Making bundle: binary (in .)
These projects use Træfɪk internally. If your company uses Træfɪk, we would be glad to get your feedback :) Contact us on [![Join the chat at https://traefik.herokuapp.com](https://img.shields.io/badge/style-register-green.svg?style=social&label=Slack)](https://traefik.herokuapp.com)
$ ls dist/
traefik*
```
- Project [Mantl](https://mantl.io/) from Cisco
#### Using `glide`
![Web UI Providers](docs/img/mantl-logo.png)
> Mantl is a modern platform for rapidly deploying globally distributed services. A container orchestrator, docker, a network stack, something to pool your logs, something to monitor health, a sprinkle of service discovery and some automation.
The idea behind `glide` is the following :
- Project [Apollo](http://capgemini.github.io/devops/apollo/) from Cap Gemini
- when checkout(ing) a project, **run `glide up`** to install
(`go get …`) the dependencies in the `GOPATH`.
- if you need another dependency, import and use it in
the source, and **run `glide get github.com/Masterminds/cookoo`** to save it in
`vendor` and add it to your `glide.yaml`.
![Web UI Providers](docs/img/apollo-logo.png)
> Apollo is an open source project to aid with building and deploying IAAS and PAAS services. It is particularly geared towards managing containerized applications across multiple hosts, and big data type workloads. Apollo leverages other open source components to provide basic mechanisms for deployment, maintenance, and scaling of infrastructure and applications.
```bash
$ glide up --update-vendored
# generate
$ go generate
# Simple go build
$ go build
# Using gox to build multiple platform
$ gox "linux darwin" "386 amd64 arm" \
-output="dist/traefik_{{.OS}}-{{.Arch}}"
# run other commands like tests
$ go test ./...
ok _/home/vincent/src/github/vdemeester/traefik 0.004s
```
## Partners
### Tests
[![Zenika](docs/img/zenika.logo.png)](https://zenika.com)
You can run unit tests using the `test-unit` target and the
integration test using the `test-integration` target.
Zenika is one of the leading providers of professional Open Source services and agile methodologies in
Europe. We provide consulting, development, training and support for the worlds leading Open Source
software products.
```bash
$ make test-unit
docker build -t "traefik-dev:your-feature-branch" -f build.Dockerfile .
# […]
docker run --rm -it -e OS_ARCH_ARG -e OS_PLATFORM_ARG -e TESTFLAGS -v "/home/vincent/src/github/vdemeester/traefik/dist:/go/src/github.com/emilevauge/traefik/dist" "traefik-dev:your-feature-branch" ./script/make.sh generate test-unit
---> Making bundle: generate (in .)
removed 'gen.go'
---> Making bundle: test-unit (in .)
+ go test -cover -coverprofile=cover.out .
ok github.com/emilevauge/traefik 0.005s coverage: 4.1% of statements
[![Asteris](docs/img/asteris.logo.png)](https://aster.is)
Test success
```
Founded in 2014, Asteris creates next-generation infrastructure software for the modern datacenter. Asteris writes software that makes it easy for companies to implement continuous delivery and realtime data pipelines. We support the HashiCorp stack, along with Kubernetes, Apache Mesos, Spark and Kafka. We're core committers on mantl.io, consul-cli and mesos-consul.
## Maintainers
- Emile Vauge [@emilevauge](https://github.com/emilevauge)
- Vincent Demeester [@vdemeester](https://github.com/vdemeester)
- Russell Clare [@Russell-IO](https://github.com/Russell-IO)
- Ed Robinson [@errm](https://github.com/errm)
- Daniel Tomcej [@dtomcej](https://github.com/dtomcej)
- Manuel Laufenberg [@SantoDE](https://github.com/SantoDE)
## Credits
Kudos to [Peka](http://peka.byethost11.com/photoblog/) for his awesome work on the logo ![logo](docs/img/traefik.icon.png)

245
acme/account.go Normal file
View File

@@ -0,0 +1,245 @@
package acme
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"errors"
"reflect"
"sort"
"strings"
"sync"
"time"
"github.com/containous/traefik/log"
"github.com/xenolf/lego/acme"
)
// Account is used to store lets encrypt registration info
type Account struct {
Email string
Registration *acme.RegistrationResource
PrivateKey []byte
DomainsCertificate DomainsCertificates
ChallengeCerts map[string]*ChallengeCert
}
// ChallengeCert stores a challenge certificate
type ChallengeCert struct {
Certificate []byte
PrivateKey []byte
certificate *tls.Certificate
}
// Init inits acccount struct
func (a *Account) Init() error {
err := a.DomainsCertificate.Init()
if err != nil {
return err
}
for _, cert := range a.ChallengeCerts {
if cert.certificate == nil {
certificate, err := tls.X509KeyPair(cert.Certificate, cert.PrivateKey)
if err != nil {
return err
}
cert.certificate = &certificate
}
if cert.certificate.Leaf == nil {
leaf, err := x509.ParseCertificate(cert.certificate.Certificate[0])
if err != nil {
return err
}
cert.certificate.Leaf = leaf
}
}
return nil
}
// NewAccount creates an account
func NewAccount(email string) (*Account, error) {
// Create a user. New accounts need an email and private key to start
privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
return nil, err
}
domainsCerts := DomainsCertificates{Certs: []*DomainsCertificate{}}
domainsCerts.Init()
return &Account{
Email: email,
PrivateKey: x509.MarshalPKCS1PrivateKey(privateKey),
DomainsCertificate: DomainsCertificates{Certs: domainsCerts.Certs},
ChallengeCerts: map[string]*ChallengeCert{}}, nil
}
// GetEmail returns email
func (a *Account) GetEmail() string {
return a.Email
}
// GetRegistration returns lets encrypt registration resource
func (a *Account) GetRegistration() *acme.RegistrationResource {
return a.Registration
}
// GetPrivateKey returns private key
func (a *Account) GetPrivateKey() crypto.PrivateKey {
if privateKey, err := x509.ParsePKCS1PrivateKey(a.PrivateKey); err == nil {
return privateKey
}
log.Errorf("Cannot unmarshall private key %+v", a.PrivateKey)
return nil
}
// Certificate is used to store certificate info
type Certificate struct {
Domain string
CertURL string
CertStableURL string
PrivateKey []byte
Certificate []byte
}
// DomainsCertificates stores a certificate for multiple domains
type DomainsCertificates struct {
Certs []*DomainsCertificate
lock sync.RWMutex
}
func (dc *DomainsCertificates) Len() int {
return len(dc.Certs)
}
func (dc *DomainsCertificates) Swap(i, j int) {
dc.Certs[i], dc.Certs[j] = dc.Certs[j], dc.Certs[i]
}
func (dc *DomainsCertificates) Less(i, j int) bool {
if reflect.DeepEqual(dc.Certs[i].Domains, dc.Certs[j].Domains) {
return dc.Certs[i].tlsCert.Leaf.NotAfter.After(dc.Certs[j].tlsCert.Leaf.NotAfter)
}
if dc.Certs[i].Domains.Main == dc.Certs[j].Domains.Main {
return strings.Join(dc.Certs[i].Domains.SANs, ",") < strings.Join(dc.Certs[j].Domains.SANs, ",")
}
return dc.Certs[i].Domains.Main < dc.Certs[j].Domains.Main
}
func (dc *DomainsCertificates) removeDuplicates() {
sort.Sort(dc)
for i := 0; i < len(dc.Certs); i++ {
for i2 := i + 1; i2 < len(dc.Certs); i2++ {
if reflect.DeepEqual(dc.Certs[i].Domains, dc.Certs[i2].Domains) {
// delete
log.Warnf("Remove duplicate cert: %+v, expiration :%s", dc.Certs[i2].Domains, dc.Certs[i2].tlsCert.Leaf.NotAfter.String())
dc.Certs = append(dc.Certs[:i2], dc.Certs[i2+1:]...)
i2--
}
}
}
}
// Init inits DomainsCertificates
func (dc *DomainsCertificates) Init() error {
dc.lock.Lock()
defer dc.lock.Unlock()
for _, domainsCertificate := range dc.Certs {
tlsCert, err := tls.X509KeyPair(domainsCertificate.Certificate.Certificate, domainsCertificate.Certificate.PrivateKey)
if err != nil {
return err
}
domainsCertificate.tlsCert = &tlsCert
if domainsCertificate.tlsCert.Leaf == nil {
leaf, err := x509.ParseCertificate(domainsCertificate.tlsCert.Certificate[0])
if err != nil {
return err
}
domainsCertificate.tlsCert.Leaf = leaf
}
}
dc.removeDuplicates()
return nil
}
func (dc *DomainsCertificates) renewCertificates(acmeCert *Certificate, domain Domain) error {
dc.lock.Lock()
defer dc.lock.Unlock()
for _, domainsCertificate := range dc.Certs {
if reflect.DeepEqual(domain, domainsCertificate.Domains) {
tlsCert, err := tls.X509KeyPair(acmeCert.Certificate, acmeCert.PrivateKey)
if err != nil {
return err
}
domainsCertificate.Certificate = acmeCert
domainsCertificate.tlsCert = &tlsCert
return nil
}
}
return errors.New("Certificate to renew not found for domain " + domain.Main)
}
func (dc *DomainsCertificates) addCertificateForDomains(acmeCert *Certificate, domain Domain) (*DomainsCertificate, error) {
dc.lock.Lock()
defer dc.lock.Unlock()
tlsCert, err := tls.X509KeyPair(acmeCert.Certificate, acmeCert.PrivateKey)
if err != nil {
return nil, err
}
cert := DomainsCertificate{Domains: domain, Certificate: acmeCert, tlsCert: &tlsCert}
dc.Certs = append(dc.Certs, &cert)
return &cert, nil
}
func (dc *DomainsCertificates) getCertificateForDomain(domainToFind string) (*DomainsCertificate, bool) {
dc.lock.RLock()
defer dc.lock.RUnlock()
for _, domainsCertificate := range dc.Certs {
domains := []string{}
domains = append(domains, domainsCertificate.Domains.Main)
domains = append(domains, domainsCertificate.Domains.SANs...)
for _, domain := range domains {
if domain == domainToFind {
return domainsCertificate, true
}
}
}
return nil, false
}
func (dc *DomainsCertificates) exists(domainToFind Domain) (*DomainsCertificate, bool) {
dc.lock.RLock()
defer dc.lock.RUnlock()
for _, domainsCertificate := range dc.Certs {
if reflect.DeepEqual(domainToFind, domainsCertificate.Domains) {
return domainsCertificate, true
}
}
return nil, false
}
// DomainsCertificate contains a certificate for multiple domains
type DomainsCertificate struct {
Domains Domain
Certificate *Certificate
tlsCert *tls.Certificate
}
func (dc *DomainsCertificate) needRenew() bool {
for _, c := range dc.tlsCert.Certificate {
crt, err := x509.ParseCertificate(c)
if err != nil {
// If there's an error, we assume the cert is broken, and needs update
return true
}
// <= 30 days left, renew certificate
if crt.NotAfter.Before(time.Now().Add(time.Duration(24 * 30 * time.Hour))) {
return true
}
}
return false
}

607
acme/acme.go Normal file
View File

@@ -0,0 +1,607 @@
package acme
import (
"context"
"crypto/tls"
"errors"
"fmt"
"io/ioutil"
fmtlog "log"
"os"
"regexp"
"strings"
"time"
"github.com/BurntSushi/ty/fun"
"github.com/cenk/backoff"
"github.com/containous/staert"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/containous/traefik/types"
"github.com/eapache/channels"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/providers/dns"
)
var (
// OSCPMustStaple enables OSCP stapling as from https://github.com/xenolf/lego/issues/270
OSCPMustStaple = false
)
// ACME allows to connect to lets encrypt and retrieve certs
type ACME struct {
Email string `description:"Email address used for registration"`
Domains []Domain `description:"SANs (alternative domains) to each main domain using format: --acme.domains='main.com,san1.com,san2.com' --acme.domains='main.net,san1.net,san2.net'"`
Storage string `description:"File or key used for certificates storage."`
StorageFile string // deprecated
OnDemand bool `description:"Enable on demand certificate. This will request a certificate from Let's Encrypt during the first TLS handshake for a hostname that does not yet have a certificate."`
OnHostRule bool `description:"Enable certificate generation on frontends Host rules."`
CAServer string `description:"CA server to use."`
EntryPoint string `description:"Entrypoint to proxy acme challenge to."`
DNSProvider string `description:"Use a DNS based challenge provider rather than HTTPS."`
DelayDontCheckDNS int `description:"Assume DNS propagates after a delay in seconds rather than finding and querying nameservers."`
ACMELogging bool `description:"Enable debug logging of ACME actions."`
client *acme.Client
defaultCertificate *tls.Certificate
store cluster.Store
challengeProvider *challengeProvider
checkOnDemandDomain func(domain string) bool
jobs *channels.InfiniteChannel
TLSConfig *tls.Config `description:"TLS config in case wildcard certs are used"`
}
//Domains parse []Domain
type Domains []Domain
//Set []Domain
func (ds *Domains) Set(str string) error {
fargs := func(c rune) bool {
return c == ',' || c == ';'
}
// get function
slice := strings.FieldsFunc(str, fargs)
if len(slice) < 1 {
return fmt.Errorf("Parse error ACME.Domain. Imposible to parse %s", str)
}
d := Domain{
Main: slice[0],
SANs: []string{},
}
if len(slice) > 1 {
d.SANs = slice[1:]
}
*ds = append(*ds, d)
return nil
}
//Get []Domain
func (ds *Domains) Get() interface{} { return []Domain(*ds) }
//String returns []Domain in string
func (ds *Domains) String() string { return fmt.Sprintf("%+v", *ds) }
//SetValue sets []Domain into the parser
func (ds *Domains) SetValue(val interface{}) {
*ds = Domains(val.([]Domain))
}
// Domain holds a domain name with SANs
type Domain struct {
Main string
SANs []string
}
func (a *ACME) init() error {
if a.ACMELogging {
acme.Logger = fmtlog.New(os.Stderr, "legolog: ", fmtlog.LstdFlags)
} else {
acme.Logger = fmtlog.New(ioutil.Discard, "", 0)
}
// no certificates in TLS config, so we add a default one
cert, err := generateDefaultCertificate()
if err != nil {
return err
}
a.defaultCertificate = cert
// TODO: to remove in the futurs
if len(a.StorageFile) > 0 && len(a.Storage) == 0 {
log.Warnf("ACME.StorageFile is deprecated, use ACME.Storage instead")
a.Storage = a.StorageFile
}
a.jobs = channels.NewInfiniteChannel()
return nil
}
// CreateClusterConfig creates a tls.config using ACME configuration in cluster mode
func (a *ACME) CreateClusterConfig(leadership *cluster.Leadership, tlsConfig *tls.Config, checkOnDemandDomain func(domain string) bool) error {
err := a.init()
if err != nil {
return err
}
if len(a.Storage) == 0 {
return errors.New("Empty Store, please provide a key for certs storage")
}
a.checkOnDemandDomain = checkOnDemandDomain
tlsConfig.Certificates = append(tlsConfig.Certificates, *a.defaultCertificate)
tlsConfig.GetCertificate = a.getCertificate
a.TLSConfig = tlsConfig
listener := func(object cluster.Object) error {
account := object.(*Account)
account.Init()
if !leadership.IsLeader() {
a.client, err = a.buildACMEClient(account)
if err != nil {
log.Errorf("Error building ACME client %+v: %s", object, err.Error())
}
}
return nil
}
datastore, err := cluster.NewDataStore(
leadership.Pool.Ctx(),
staert.KvSource{
Store: leadership.Store,
Prefix: a.Storage,
},
&Account{},
listener)
if err != nil {
return err
}
a.store = datastore
a.challengeProvider = &challengeProvider{store: a.store}
ticker := time.NewTicker(24 * time.Hour)
leadership.Pool.AddGoCtx(func(ctx context.Context) {
log.Infof("Starting ACME renew job...")
defer log.Infof("Stopped ACME renew job...")
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
a.renewCertificates()
}
}
})
leadership.AddListener(func(elected bool) error {
if elected {
object, err := a.store.Load()
if err != nil {
return err
}
transaction, object, err := a.store.Begin()
if err != nil {
return err
}
account := object.(*Account)
account.Init()
var needRegister bool
if account == nil || len(account.Email) == 0 {
account, err = NewAccount(a.Email)
if err != nil {
return err
}
needRegister = true
}
if err != nil {
return err
}
a.client, err = a.buildACMEClient(account)
if err != nil {
return err
}
if needRegister {
// New users will need to register; be sure to save it
log.Debugf("Register...")
reg, err := a.client.Register()
if err != nil {
return err
}
account.Registration = reg
}
// The client has a URL to the current Let's Encrypt Subscriber
// Agreement. The user will need to agree to it.
log.Debugf("AgreeToTOS...")
err = a.client.AgreeToTOS()
if err != nil {
// Let's Encrypt Subscriber Agreement renew ?
reg, err := a.client.QueryRegistration()
if err != nil {
return err
}
account.Registration = reg
err = a.client.AgreeToTOS()
if err != nil {
log.Errorf("Error sending ACME agreement to TOS: %+v: %s", account, err.Error())
}
}
err = transaction.Commit(account)
if err != nil {
return err
}
a.retrieveCertificates()
a.renewCertificates()
a.runJobs()
}
return nil
})
return nil
}
// CreateLocalConfig creates a tls.config using local ACME configuration
func (a *ACME) CreateLocalConfig(tlsConfig *tls.Config, checkOnDemandDomain func(domain string) bool) error {
err := a.init()
if err != nil {
return err
}
if len(a.Storage) == 0 {
return errors.New("Empty Store, please provide a filename for certs storage")
}
a.checkOnDemandDomain = checkOnDemandDomain
tlsConfig.Certificates = append(tlsConfig.Certificates, *a.defaultCertificate)
tlsConfig.GetCertificate = a.getCertificate
a.TLSConfig = tlsConfig
localStore := NewLocalStore(a.Storage)
a.store = localStore
a.challengeProvider = &challengeProvider{store: a.store}
var needRegister bool
var account *Account
if fileInfo, fileErr := os.Stat(a.Storage); fileErr == nil && fileInfo.Size() != 0 {
log.Infof("Loading ACME Account...")
// load account
object, err := localStore.Load()
if err != nil {
return err
}
account = object.(*Account)
} else {
log.Infof("Generating ACME Account...")
account, err = NewAccount(a.Email)
if err != nil {
return err
}
needRegister = true
}
a.client, err = a.buildACMEClient(account)
if err != nil {
return err
}
if needRegister {
// New users will need to register; be sure to save it
log.Infof("Register...")
reg, err := a.client.Register()
if err != nil {
return err
}
account.Registration = reg
}
// The client has a URL to the current Let's Encrypt Subscriber
// Agreement. The user will need to agree to it.
log.Debugf("AgreeToTOS...")
err = a.client.AgreeToTOS()
if err != nil {
// Let's Encrypt Subscriber Agreement renew ?
reg, err := a.client.QueryRegistration()
if err != nil {
return err
}
account.Registration = reg
err = a.client.AgreeToTOS()
if err != nil {
log.Errorf("Error sending ACME agreement to TOS: %+v: %s", account, err.Error())
}
}
// save account
transaction, _, err := a.store.Begin()
if err != nil {
return err
}
err = transaction.Commit(account)
if err != nil {
return err
}
a.retrieveCertificates()
a.renewCertificates()
a.runJobs()
ticker := time.NewTicker(24 * time.Hour)
safe.Go(func() {
for range ticker.C {
a.renewCertificates()
}
})
return nil
}
func (a *ACME) getCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
domain := types.CanonicalDomain(clientHello.ServerName)
account := a.store.Get().(*Account)
//use regex to test for wildcard certs that might have been added into TLSConfig
for k := range a.TLSConfig.NameToCertificate {
selector := "^" + strings.Replace(k, "*.", ".*\\.?", -1) + "$"
match, _ := regexp.MatchString(selector, domain)
if match {
return a.TLSConfig.NameToCertificate[k], nil
}
}
if challengeCert, ok := a.challengeProvider.getCertificate(domain); ok {
log.Debugf("ACME got challenge %s", domain)
return challengeCert, nil
}
if domainCert, ok := account.DomainsCertificate.getCertificateForDomain(domain); ok {
log.Debugf("ACME got domain cert %s", domain)
return domainCert.tlsCert, nil
}
if a.OnDemand {
if a.checkOnDemandDomain != nil && !a.checkOnDemandDomain(domain) {
return nil, nil
}
return a.loadCertificateOnDemand(clientHello)
}
log.Debugf("ACME got nothing %s", domain)
return nil, nil
}
func (a *ACME) retrieveCertificates() {
a.jobs.In() <- func() {
log.Infof("Retrieving ACME certificates...")
for _, domain := range a.Domains {
// check if cert isn't already loaded
account := a.store.Get().(*Account)
if _, exists := account.DomainsCertificate.exists(domain); !exists {
domains := []string{}
domains = append(domains, domain.Main)
domains = append(domains, domain.SANs...)
certificateResource, err := a.getDomainsCertificates(domains)
if err != nil {
log.Errorf("Error getting ACME certificate for domain %s: %s", domains, err.Error())
continue
}
transaction, object, err := a.store.Begin()
if err != nil {
log.Errorf("Error creating ACME store transaction from domain %s: %s", domain, err.Error())
continue
}
account = object.(*Account)
_, err = account.DomainsCertificate.addCertificateForDomains(certificateResource, domain)
if err != nil {
log.Errorf("Error adding ACME certificate for domain %s: %s", domains, err.Error())
continue
}
if err = transaction.Commit(account); err != nil {
log.Errorf("Error Saving ACME account %+v: %s", account, err.Error())
continue
}
}
}
log.Infof("Retrieved ACME certificates")
}
}
func (a *ACME) renewCertificates() {
a.jobs.In() <- func() {
log.Debugf("Testing certificate renew...")
account := a.store.Get().(*Account)
for _, certificateResource := range account.DomainsCertificate.Certs {
if certificateResource.needRenew() {
log.Debugf("Renewing certificate %+v", certificateResource.Domains)
renewedCert, err := a.client.RenewCertificate(acme.CertificateResource{
Domain: certificateResource.Certificate.Domain,
CertURL: certificateResource.Certificate.CertURL,
CertStableURL: certificateResource.Certificate.CertStableURL,
PrivateKey: certificateResource.Certificate.PrivateKey,
Certificate: certificateResource.Certificate.Certificate,
}, true, OSCPMustStaple)
if err != nil {
log.Errorf("Error renewing certificate: %v", err)
continue
}
log.Debugf("Renewed certificate %+v", certificateResource.Domains)
renewedACMECert := &Certificate{
Domain: renewedCert.Domain,
CertURL: renewedCert.CertURL,
CertStableURL: renewedCert.CertStableURL,
PrivateKey: renewedCert.PrivateKey,
Certificate: renewedCert.Certificate,
}
transaction, object, err := a.store.Begin()
if err != nil {
log.Errorf("Error renewing certificate: %v", err)
continue
}
account = object.(*Account)
err = account.DomainsCertificate.renewCertificates(renewedACMECert, certificateResource.Domains)
if err != nil {
log.Errorf("Error renewing certificate: %v", err)
continue
}
if err = transaction.Commit(account); err != nil {
log.Errorf("Error Saving ACME account %+v: %s", account, err.Error())
continue
}
}
}
}
}
func dnsOverrideDelay(delay int) error {
var err error
if delay > 0 {
log.Debugf("Delaying %d seconds rather than validating DNS propagation", delay)
acme.PreCheckDNS = func(_, _ string) (bool, error) {
time.Sleep(time.Duration(delay) * time.Second)
return true, nil
}
} else if delay < 0 {
err = fmt.Errorf("Invalid negative DelayDontCheckDNS: %d", delay)
}
return err
}
func (a *ACME) buildACMEClient(account *Account) (*acme.Client, error) {
log.Debugf("Building ACME client...")
caServer := "https://acme-v01.api.letsencrypt.org/directory"
if len(a.CAServer) > 0 {
caServer = a.CAServer
}
client, err := acme.NewClient(caServer, account, acme.RSA4096)
if err != nil {
return nil, err
}
if len(a.DNSProvider) > 0 {
log.Debugf("Using DNS Challenge provider: %s", a.DNSProvider)
err = dnsOverrideDelay(a.DelayDontCheckDNS)
if err != nil {
return nil, err
}
var provider acme.ChallengeProvider
provider, err = dns.NewDNSChallengeProviderByName(a.DNSProvider)
if err != nil {
return nil, err
}
client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.TLSSNI01})
err = client.SetChallengeProvider(acme.DNS01, provider)
} else {
client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.DNS01})
err = client.SetChallengeProvider(acme.TLSSNI01, a.challengeProvider)
}
if err != nil {
return nil, err
}
return client, nil
}
func (a *ACME) loadCertificateOnDemand(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
domain := types.CanonicalDomain(clientHello.ServerName)
account := a.store.Get().(*Account)
if certificateResource, ok := account.DomainsCertificate.getCertificateForDomain(domain); ok {
return certificateResource.tlsCert, nil
}
certificate, err := a.getDomainsCertificates([]string{domain})
if err != nil {
return nil, err
}
log.Debugf("Got certificate on demand for domain %s", domain)
transaction, object, err := a.store.Begin()
if err != nil {
return nil, err
}
account = object.(*Account)
cert, err := account.DomainsCertificate.addCertificateForDomains(certificate, Domain{Main: domain})
if err != nil {
return nil, err
}
if err = transaction.Commit(account); err != nil {
return nil, err
}
return cert.tlsCert, nil
}
// LoadCertificateForDomains loads certificates from ACME for given domains
func (a *ACME) LoadCertificateForDomains(domains []string) {
a.jobs.In() <- func() {
log.Debugf("LoadCertificateForDomains %s...", domains)
domains = fun.Map(types.CanonicalDomain, domains).([]string)
operation := func() error {
if a.client == nil {
return fmt.Errorf("ACME client still not built")
}
return nil
}
notify := func(err error, time time.Duration) {
log.Errorf("Error getting ACME client: %v, retrying in %s", err, time)
}
ebo := backoff.NewExponentialBackOff()
ebo.MaxElapsedTime = 30 * time.Second
err := backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify)
if err != nil {
log.Errorf("Error getting ACME client: %v", err)
return
}
account := a.store.Get().(*Account)
var domain Domain
if len(domains) == 0 {
// no domain
return
} else if len(domains) > 1 {
domain = Domain{Main: domains[0], SANs: domains[1:]}
} else {
domain = Domain{Main: domains[0]}
}
if _, exists := account.DomainsCertificate.exists(domain); exists {
// domain already exists
return
}
certificate, err := a.getDomainsCertificates(domains)
if err != nil {
log.Errorf("Error getting ACME certificates %+v : %v", domains, err)
return
}
log.Debugf("Got certificate for domains %+v", domains)
transaction, object, err := a.store.Begin()
if err != nil {
log.Errorf("Error creating transaction %+v : %v", domains, err)
return
}
account = object.(*Account)
_, err = account.DomainsCertificate.addCertificateForDomains(certificate, domain)
if err != nil {
log.Errorf("Error adding ACME certificates %+v : %v", domains, err)
return
}
if err = transaction.Commit(account); err != nil {
log.Errorf("Error Saving ACME account %+v: %v", account, err)
return
}
}
}
func (a *ACME) getDomainsCertificates(domains []string) (*Certificate, error) {
domains = fun.Map(types.CanonicalDomain, domains).([]string)
log.Debugf("Loading ACME certificates %s...", domains)
bundle := true
certificate, failures := a.client.ObtainCertificate(domains, bundle, nil, OSCPMustStaple)
if len(failures) > 0 {
log.Error(failures)
return nil, fmt.Errorf("Cannot obtain certificates %s+v", failures)
}
log.Debugf("Loaded ACME certificates %s", domains)
return &Certificate{
Domain: certificate.Domain,
CertURL: certificate.CertURL,
CertStableURL: certificate.CertStableURL,
PrivateKey: certificate.PrivateKey,
Certificate: certificate.Certificate,
}, nil
}
func (a *ACME) runJobs() {
safe.Go(func() {
for job := range a.jobs.Out() {
function := job.(func())
function()
}
})
}

279
acme/acme_test.go Normal file
View File

@@ -0,0 +1,279 @@
package acme
import (
"encoding/base64"
"net/http"
"net/http/httptest"
"reflect"
"sync"
"testing"
"time"
"github.com/xenolf/lego/acme"
)
func TestDomainsSet(t *testing.T) {
checkMap := map[string]Domains{
"": {},
"foo.com": {Domain{Main: "foo.com", SANs: []string{}}},
"foo.com,bar.net": {Domain{Main: "foo.com", SANs: []string{"bar.net"}}},
"foo.com,bar1.net,bar2.net,bar3.net": {Domain{Main: "foo.com", SANs: []string{"bar1.net", "bar2.net", "bar3.net"}}},
}
for in, check := range checkMap {
ds := Domains{}
ds.Set(in)
if !reflect.DeepEqual(check, ds) {
t.Errorf("Expected %+v\nGot %+v", check, ds)
}
}
}
func TestDomainsSetAppend(t *testing.T) {
inSlice := []string{
"",
"foo1.com",
"foo2.com,bar.net",
"foo3.com,bar1.net,bar2.net,bar3.net",
}
checkSlice := []Domains{
{},
{
Domain{
Main: "foo1.com",
SANs: []string{}}},
{
Domain{
Main: "foo1.com",
SANs: []string{}},
Domain{
Main: "foo2.com",
SANs: []string{"bar.net"}}},
{
Domain{
Main: "foo1.com",
SANs: []string{}},
Domain{
Main: "foo2.com",
SANs: []string{"bar.net"}},
Domain{Main: "foo3.com",
SANs: []string{"bar1.net", "bar2.net", "bar3.net"}}},
}
ds := Domains{}
for i, in := range inSlice {
ds.Set(in)
if !reflect.DeepEqual(checkSlice[i], ds) {
t.Errorf("Expected %s %+v\nGot %+v", in, checkSlice[i], ds)
}
}
}
func TestCertificatesRenew(t *testing.T) {
foo1Cert, foo1Key, _ := generateKeyPair("foo1.com", time.Now())
foo2Cert, foo2Key, _ := generateKeyPair("foo2.com", time.Now())
domainsCertificates := DomainsCertificates{
lock: sync.RWMutex{},
Certs: []*DomainsCertificate{
{
Domains: Domain{
Main: "foo1.com",
SANs: []string{}},
Certificate: &Certificate{
Domain: "foo1.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: foo1Key,
Certificate: foo1Cert,
},
},
{
Domains: Domain{
Main: "foo2.com",
SANs: []string{}},
Certificate: &Certificate{
Domain: "foo2.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: foo2Key,
Certificate: foo2Cert,
},
},
},
}
foo1Cert, foo1Key, _ = generateKeyPair("foo1.com", time.Now())
newCertificate := &Certificate{
Domain: "foo1.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: foo1Key,
Certificate: foo1Cert,
}
err := domainsCertificates.renewCertificates(
newCertificate,
Domain{
Main: "foo1.com",
SANs: []string{}})
if err != nil {
t.Errorf("Error in renewCertificates :%v", err)
}
if len(domainsCertificates.Certs) != 2 {
t.Errorf("Expected domainsCertificates length %d %+v\nGot %+v", 2, domainsCertificates.Certs, len(domainsCertificates.Certs))
}
if !reflect.DeepEqual(domainsCertificates.Certs[0].Certificate, newCertificate) {
t.Errorf("Expected new certificate %+v \nGot %+v", newCertificate, domainsCertificates.Certs[0].Certificate)
}
}
func TestRemoveDuplicates(t *testing.T) {
now := time.Now()
fooCert, fooKey, _ := generateKeyPair("foo.com", now)
foo24Cert, foo24Key, _ := generateKeyPair("foo.com", now.Add(24*time.Hour))
foo48Cert, foo48Key, _ := generateKeyPair("foo.com", now.Add(48*time.Hour))
barCert, barKey, _ := generateKeyPair("bar.com", now)
domainsCertificates := DomainsCertificates{
lock: sync.RWMutex{},
Certs: []*DomainsCertificate{
{
Domains: Domain{
Main: "foo.com",
SANs: []string{}},
Certificate: &Certificate{
Domain: "foo.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: foo24Key,
Certificate: foo24Cert,
},
},
{
Domains: Domain{
Main: "foo.com",
SANs: []string{}},
Certificate: &Certificate{
Domain: "foo.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: foo48Key,
Certificate: foo48Cert,
},
},
{
Domains: Domain{
Main: "foo.com",
SANs: []string{}},
Certificate: &Certificate{
Domain: "foo.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: fooKey,
Certificate: fooCert,
},
},
{
Domains: Domain{
Main: "bar.com",
SANs: []string{}},
Certificate: &Certificate{
Domain: "bar.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: barKey,
Certificate: barCert,
},
},
{
Domains: Domain{
Main: "foo.com",
SANs: []string{}},
Certificate: &Certificate{
Domain: "foo.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: foo48Key,
Certificate: foo48Cert,
},
},
},
}
domainsCertificates.Init()
if len(domainsCertificates.Certs) != 2 {
t.Errorf("Expected domainsCertificates length %d %+v\nGot %+v", 2, domainsCertificates.Certs, len(domainsCertificates.Certs))
}
for _, cert := range domainsCertificates.Certs {
switch cert.Domains.Main {
case "bar.com":
continue
case "foo.com":
if !cert.tlsCert.Leaf.NotAfter.Equal(now.Add(48 * time.Hour).Truncate(1 * time.Second)) {
t.Errorf("Bad expiration %s date for domain %+v, now %s", cert.tlsCert.Leaf.NotAfter.String(), cert, now.Add(48*time.Hour).Truncate(1*time.Second).String())
}
default:
t.Errorf("Unknown domain %+v", cert)
}
}
}
func TestNoPreCheckOverride(t *testing.T) {
acme.PreCheckDNS = nil // Irreversable - but not expecting real calls into this during testing process
err := dnsOverrideDelay(0)
if err != nil {
t.Errorf("Error in dnsOverrideDelay :%v", err)
}
if acme.PreCheckDNS != nil {
t.Errorf("Unexpected change to acme.PreCheckDNS when leaving DNS verification as is.")
}
}
func TestSillyPreCheckOverride(t *testing.T) {
err := dnsOverrideDelay(-5)
if err == nil {
t.Errorf("Missing expected error in dnsOverrideDelay!")
}
}
func TestPreCheckOverride(t *testing.T) {
acme.PreCheckDNS = nil // Irreversable - but not expecting real calls into this during testing process
err := dnsOverrideDelay(5)
if err != nil {
t.Errorf("Error in dnsOverrideDelay :%v", err)
}
if acme.PreCheckDNS == nil {
t.Errorf("No change to acme.PreCheckDNS when meant to be adding enforcing override function.")
}
}
func TestAcmeClientCreation(t *testing.T) {
acme.PreCheckDNS = nil // Irreversable - but not expecting real calls into this during testing process
// Lengthy setup to avoid external web requests - oh for easier golang testing!
account := &Account{Email: "f@f"}
account.PrivateKey, _ = base64.StdEncoding.DecodeString(`
MIIBPAIBAAJBAMp2Ni92FfEur+CAvFkgC12LT4l9D53ApbBpDaXaJkzzks+KsLw9zyAxvlrfAyTCQ
7tDnEnIltAXyQ0uOFUUdcMCAwEAAQJAK1FbipATZcT9cGVa5x7KD7usytftLW14heQUPXYNV80r/3
lmnpvjL06dffRpwkYeN8DATQF/QOcy3NNNGDw/4QIhAPAKmiZFxA/qmRXsuU8Zhlzf16WrNZ68K64
asn/h3qZrAiEA1+wFR3WXCPIolOvd7AHjfgcTKQNkoMPywU4FYUNQ1AkCIQDv8yk0qPjckD6HVCPJ
llJh9MC0svjevGtNlxJoE3lmEQIhAKXy1wfZ32/XtcrnENPvi6lzxI0T94X7s5pP3aCoPPoJAiEAl
cijFkALeQp/qyeXdFld2v9gUN3eCgljgcl0QweRoIc=---`)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{
"new-authz": "https://foo/acme/new-authz",
"new-cert": "https://foo/acme/new-cert",
"new-reg": "https://foo/acme/new-reg",
"revoke-cert": "https://foo/acme/revoke-cert"
}`))
}))
defer ts.Close()
a := ACME{DNSProvider: "manual", DelayDontCheckDNS: 10, CAServer: ts.URL}
client, err := a.buildACMEClient(account)
if err != nil {
t.Errorf("Error in buildACMEClient: %v", err)
}
if client == nil {
t.Errorf("No client from buildACMEClient!")
}
if acme.PreCheckDNS == nil {
t.Errorf("No change to acme.PreCheckDNS when meant to be adding enforcing override function.")
}
}

97
acme/challengeProvider.go Normal file
View File

@@ -0,0 +1,97 @@
package acme
import (
"crypto/tls"
"fmt"
"strings"
"sync"
"time"
"github.com/cenk/backoff"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/xenolf/lego/acme"
)
var _ acme.ChallengeProviderTimeout = (*challengeProvider)(nil)
type challengeProvider struct {
store cluster.Store
lock sync.RWMutex
}
func (c *challengeProvider) getCertificate(domain string) (cert *tls.Certificate, exists bool) {
log.Debugf("Challenge GetCertificate %s", domain)
if !strings.HasSuffix(domain, ".acme.invalid") {
return nil, false
}
c.lock.RLock()
defer c.lock.RUnlock()
account := c.store.Get().(*Account)
if account.ChallengeCerts == nil {
return nil, false
}
account.Init()
var result *tls.Certificate
operation := func() error {
for _, cert := range account.ChallengeCerts {
for _, dns := range cert.certificate.Leaf.DNSNames {
if domain == dns {
result = cert.certificate
return nil
}
}
}
return fmt.Errorf("Cannot find challenge cert for domain %s", domain)
}
notify := func(err error, time time.Duration) {
log.Errorf("Error getting cert: %v, retrying in %s", err, time)
}
ebo := backoff.NewExponentialBackOff()
ebo.MaxElapsedTime = 60 * time.Second
err := backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify)
if err != nil {
log.Errorf("Error getting cert: %v", err)
return nil, false
}
return result, true
}
func (c *challengeProvider) Present(domain, token, keyAuth string) error {
log.Debugf("Challenge Present %s", domain)
cert, _, err := TLSSNI01ChallengeCert(keyAuth)
if err != nil {
return err
}
c.lock.Lock()
defer c.lock.Unlock()
transaction, object, err := c.store.Begin()
if err != nil {
return err
}
account := object.(*Account)
if account.ChallengeCerts == nil {
account.ChallengeCerts = map[string]*ChallengeCert{}
}
account.ChallengeCerts[domain] = &cert
return transaction.Commit(account)
}
func (c *challengeProvider) CleanUp(domain, token, keyAuth string) error {
log.Debugf("Challenge CleanUp %s", domain)
c.lock.Lock()
defer c.lock.Unlock()
transaction, object, err := c.store.Begin()
if err != nil {
return err
}
account := object.(*Account)
delete(account.ChallengeCerts, domain)
return transaction.Commit(account)
}
func (c *challengeProvider) Timeout() (timeout, interval time.Duration) {
return 60 * time.Second, 5 * time.Second
}

135
acme/crypto.go Normal file
View File

@@ -0,0 +1,135 @@
package acme
import (
"crypto"
"crypto/ecdsa"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/hex"
"encoding/pem"
"fmt"
"math/big"
"time"
)
func generateDefaultCertificate() (*tls.Certificate, error) {
randomBytes := make([]byte, 100)
_, err := rand.Read(randomBytes)
if err != nil {
return nil, err
}
zBytes := sha256.Sum256(randomBytes)
z := hex.EncodeToString(zBytes[:sha256.Size])
domain := fmt.Sprintf("%s.%s.traefik.default", z[:32], z[32:])
certPEM, keyPEM, err := generateKeyPair(domain, time.Time{})
if err != nil {
return nil, err
}
certificate, err := tls.X509KeyPair(certPEM, keyPEM)
if err != nil {
return nil, err
}
return &certificate, nil
}
func generateKeyPair(domain string, expiration time.Time) ([]byte, []byte, error) {
rsaPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, nil, err
}
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(rsaPrivKey)})
certPEM, err := generatePemCert(rsaPrivKey, domain, expiration)
if err != nil {
return nil, nil, err
}
return certPEM, keyPEM, nil
}
func generatePemCert(privKey *rsa.PrivateKey, domain string, expiration time.Time) ([]byte, error) {
derBytes, err := generateDerCert(privKey, expiration, domain)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}), nil
}
func generateDerCert(privKey *rsa.PrivateKey, expiration time.Time, domain string) ([]byte, error) {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return nil, err
}
if expiration.IsZero() {
expiration = time.Now().Add(365)
}
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
CommonName: "TRAEFIK DEFAULT CERT",
},
NotBefore: time.Now(),
NotAfter: expiration,
KeyUsage: x509.KeyUsageKeyEncipherment,
BasicConstraintsValid: true,
DNSNames: []string{domain},
}
return x509.CreateCertificate(rand.Reader, &template, &template, &privKey.PublicKey, privKey)
}
// TLSSNI01ChallengeCert returns a certificate and target domain for the `tls-sni-01` challenge
func TLSSNI01ChallengeCert(keyAuth string) (ChallengeCert, string, error) {
// generate a new RSA key for the certificates
var tempPrivKey crypto.PrivateKey
tempPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return ChallengeCert{}, "", err
}
rsaPrivKey := tempPrivKey.(*rsa.PrivateKey)
rsaPrivPEM := pemEncode(rsaPrivKey)
zBytes := sha256.Sum256([]byte(keyAuth))
z := hex.EncodeToString(zBytes[:sha256.Size])
domain := fmt.Sprintf("%s.%s.acme.invalid", z[:32], z[32:])
tempCertPEM, err := generatePemCert(rsaPrivKey, domain, time.Time{})
if err != nil {
return ChallengeCert{}, "", err
}
certificate, err := tls.X509KeyPair(tempCertPEM, rsaPrivPEM)
if err != nil {
return ChallengeCert{}, "", err
}
return ChallengeCert{Certificate: tempCertPEM, PrivateKey: rsaPrivPEM, certificate: &certificate}, domain, nil
}
func pemEncode(data interface{}) []byte {
var pemBlock *pem.Block
switch key := data.(type) {
case *ecdsa.PrivateKey:
keyBytes, _ := x509.MarshalECPrivateKey(key)
pemBlock = &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes}
case *rsa.PrivateKey:
pemBlock = &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}
break
case *x509.CertificateRequest:
pemBlock = &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: key.Raw}
break
case []byte:
pemBlock = &pem.Block{Type: "CERTIFICATE", Bytes: []byte(data.([]byte))}
}
return pem.EncodeToMemory(pemBlock)
}

97
acme/localStore.go Normal file
View File

@@ -0,0 +1,97 @@
package acme
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"sync"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/log"
)
var _ cluster.Store = (*LocalStore)(nil)
// LocalStore is a store using a file as storage
type LocalStore struct {
file string
storageLock sync.RWMutex
account *Account
}
// NewLocalStore create a LocalStore
func NewLocalStore(file string) *LocalStore {
return &LocalStore{
file: file,
}
}
// Get atomically a struct from the file storage
func (s *LocalStore) Get() cluster.Object {
s.storageLock.RLock()
defer s.storageLock.RUnlock()
return s.account
}
// Load loads file into store
func (s *LocalStore) Load() (cluster.Object, error) {
s.storageLock.Lock()
defer s.storageLock.Unlock()
account := &Account{}
err := checkPermissions(s.file)
if err != nil {
return nil, err
}
f, err := os.Open(s.file)
if err != nil {
return nil, err
}
defer f.Close()
file, err := ioutil.ReadAll(f)
if err != nil {
return nil, err
}
if err := json.Unmarshal(file, &account); err != nil {
return nil, err
}
account.Init()
s.account = account
log.Infof("Loaded ACME config from store %s", s.file)
return account, nil
}
// Begin creates a transaction with the KV store.
func (s *LocalStore) Begin() (cluster.Transaction, cluster.Object, error) {
s.storageLock.Lock()
return &localTransaction{LocalStore: s}, s.account, nil
}
var _ cluster.Transaction = (*localTransaction)(nil)
type localTransaction struct {
*LocalStore
dirty bool
}
// Commit allows to set an object in the file storage
func (t *localTransaction) Commit(object cluster.Object) error {
t.LocalStore.account = object.(*Account)
defer t.storageLock.Unlock()
if t.dirty {
return fmt.Errorf("transaction already used, please begin a new one")
}
// write account to file
data, err := json.MarshalIndent(object, "", " ")
if err != nil {
return err
}
err = ioutil.WriteFile(t.file, data, 0600)
if err != nil {
return err
}
t.dirty = true
return nil
}

25
acme/localStore_unix.go Normal file
View File

@@ -0,0 +1,25 @@
// +build !windows
package acme
import (
"fmt"
"os"
)
// Check file permissions
func checkPermissions(name string) error {
f, err := os.Open(name)
if err != nil {
return err
}
defer f.Close()
fi, err := f.Stat()
if err != nil {
return err
}
if fi.Mode().Perm()&0077 != 0 {
return fmt.Errorf("permissions %o for %s are too open, please use 600", fi.Mode().Perm(), name)
}
return nil
}

View File

@@ -0,0 +1,6 @@
package acme
// Do not check file permissions on Windows right now
func checkPermissions(name string) error {
return nil
}

View File

@@ -4,42 +4,31 @@ Copyright
package main
import (
log "github.com/Sirupsen/logrus"
"github.com/gorilla/mux"
"github.com/mailgun/oxy/utils"
"net/http"
"github.com/containous/traefik/log"
)
// OxyLogger implements oxy Logger interface with logrus.
type OxyLogger struct {
}
// Infof logs specified string as Debug level in logrus.
func (oxylogger *OxyLogger) Infof(format string, args ...interface{}) {
log.Debugf(format, args...)
}
// Warningf logs specified string as Warning level in logrus.
func (oxylogger *OxyLogger) Warningf(format string, args ...interface{}) {
log.Warningf(format, args...)
}
// Errorf logs specified string as Warningf level in logrus.
func (oxylogger *OxyLogger) Errorf(format string, args ...interface{}) {
log.Errorf(format, args...)
}
type ErrorHandler struct {
}
func (e *ErrorHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, err error) {
log.Error("server error ", err.Error())
utils.DefaultHandler.ServeHTTP(w, req, err)
log.Warningf(format, args...)
}
func notFoundHandler(w http.ResponseWriter, r *http.Request) {
http.NotFound(w, r)
//templatesRenderer.HTML(w, http.StatusNotFound, "notFound", nil)
}
func LoadDefaultConfig(globalConfiguration *GlobalConfiguration) *mux.Router {
router := mux.NewRouter()
router.NotFoundHandler = http.HandlerFunc(notFoundHandler)
return router
}

View File

@@ -1,27 +1,36 @@
FROM golang:1.5
FROM golang:1.7
RUN go get github.com/Masterminds/glide
RUN go get github.com/mitchellh/gox
RUN go get github.com/tcnksm/ghr
RUN go get github.com/jteeuwen/go-bindata/...
RUN go get github.com/jteeuwen/go-bindata/... \
&& go get github.com/golang/lint/golint \
&& go get github.com/kisielk/errcheck \
&& go get github.com/client9/misspell/cmd/misspell \
&& go get github.com/mattfarina/glide-hash
# Which docker version to test on
ENV DOCKER_VERSION 1.6.2
ARG DOCKER_VERSION=1.10.3
# enable GO15VENDOREXPERIMENT
ENV GO15VENDOREXPERIMENT 1
# Which glide version to test on
ARG GLIDE_VERSION=v0.12.3
# Download glide
RUN mkdir -p /usr/local/bin \
&& curl -fL https://github.com/Masterminds/glide/releases/download/${GLIDE_VERSION}/glide-${GLIDE_VERSION}-linux-amd64.tar.gz \
| tar -xzC /usr/local/bin --transform 's#^.+/##x'
# Download docker
RUN set -ex; \
curl https://get.docker.com/builds/Linux/x86_64/docker-${DOCKER_VERSION} -o /usr/local/bin/docker-${DOCKER_VERSION}; \
chmod +x /usr/local/bin/docker-${DOCKER_VERSION}
RUN mkdir -p /usr/local/bin \
&& curl -fL https://get.docker.com/builds/Linux/x86_64/docker-${DOCKER_VERSION}.tgz \
| tar -xzC /usr/local/bin --transform 's#^.+/##x'
# Set the default Docker to be run
RUN ln -s /usr/local/bin/docker-${DOCKER_VERSION} /usr/local/bin/docker
WORKDIR /go/src/github.com/emilevauge/traefik
WORKDIR /go/src/github.com/containous/traefik
COPY glide.yaml glide.yaml
RUN glide up
COPY glide.lock glide.lock
RUN glide install -v
COPY . /go/src/github.com/emilevauge/traefik
COPY integration/glide.yaml integration/glide.yaml
COPY integration/glide.lock integration/glide.lock
RUN cd integration && glide install
COPY . /go/src/github.com/containous/traefik

255
cluster/datastore.go Normal file
View File

@@ -0,0 +1,255 @@
package cluster
import (
"context"
"encoding/json"
"fmt"
"sync"
"time"
"github.com/cenk/backoff"
"github.com/containous/staert"
"github.com/containous/traefik/job"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/docker/libkv/store"
"github.com/satori/go.uuid"
)
// Metadata stores Object plus metadata
type Metadata struct {
object Object
Object []byte
Lock string
}
// NewMetadata returns new Metadata
func NewMetadata(object Object) *Metadata {
return &Metadata{object: object}
}
// Marshall marshalls object
func (m *Metadata) Marshall() error {
var err error
m.Object, err = json.Marshal(m.object)
return err
}
func (m *Metadata) unmarshall() error {
if len(m.Object) == 0 {
return nil
}
return json.Unmarshal(m.Object, m.object)
}
// Listener is called when Object has been changed in KV store
type Listener func(Object) error
var _ Store = (*Datastore)(nil)
// Datastore holds a struct synced in a KV store
type Datastore struct {
kv staert.KvSource
ctx context.Context
localLock *sync.RWMutex
meta *Metadata
lockKey string
listener Listener
}
// NewDataStore creates a Datastore
func NewDataStore(ctx context.Context, kvSource staert.KvSource, object Object, listener Listener) (*Datastore, error) {
datastore := Datastore{
kv: kvSource,
ctx: ctx,
meta: &Metadata{object: object},
lockKey: kvSource.Prefix + "/lock",
localLock: &sync.RWMutex{},
listener: listener,
}
err := datastore.watchChanges()
if err != nil {
return nil, err
}
return &datastore, nil
}
func (d *Datastore) watchChanges() error {
stopCh := make(chan struct{})
kvCh, err := d.kv.Watch(d.lockKey, stopCh)
if err != nil {
return err
}
go func() {
ctx, cancel := context.WithCancel(d.ctx)
operation := func() error {
for {
select {
case <-ctx.Done():
stopCh <- struct{}{}
return nil
case _, ok := <-kvCh:
if !ok {
cancel()
return err
}
err = d.reload()
if err != nil {
return err
}
// log.Debugf("Datastore object change received: %+v", d.meta)
if d.listener != nil {
err := d.listener(d.meta.object)
if err != nil {
log.Errorf("Error calling datastore listener: %s", err)
}
}
}
}
}
notify := func(err error, time time.Duration) {
log.Errorf("Error in watch datastore: %+v, retrying in %s", err, time)
}
err := backoff.RetryNotify(safe.OperationWithRecover(operation), job.NewBackOff(backoff.NewExponentialBackOff()), notify)
if err != nil {
log.Errorf("Error in watch datastore: %v", err)
}
}()
return nil
}
func (d *Datastore) reload() error {
log.Debugf("Datastore reload")
d.localLock.Lock()
err := d.kv.LoadConfig(d.meta)
if err != nil {
d.localLock.Unlock()
return err
}
err = d.meta.unmarshall()
if err != nil {
d.localLock.Unlock()
return err
}
d.localLock.Unlock()
return nil
}
// Begin creates a transaction with the KV store.
func (d *Datastore) Begin() (Transaction, Object, error) {
id := uuid.NewV4().String()
log.Debugf("Transaction %s begins", id)
remoteLock, err := d.kv.NewLock(d.lockKey, &store.LockOptions{TTL: 20 * time.Second, Value: []byte(id)})
if err != nil {
return nil, nil, err
}
stopCh := make(chan struct{})
ctx, cancel := context.WithCancel(d.ctx)
var errLock error
go func() {
_, errLock = remoteLock.Lock(stopCh)
cancel()
}()
select {
case <-ctx.Done():
if errLock != nil {
return nil, nil, errLock
}
case <-d.ctx.Done():
stopCh <- struct{}{}
return nil, nil, d.ctx.Err()
}
// we got the lock! Now make sure we are synced with KV store
operation := func() error {
meta := d.get()
if meta.Lock != id {
return fmt.Errorf("Object lock value: expected %s, got %s", id, meta.Lock)
}
return nil
}
notify := func(err error, time time.Duration) {
log.Errorf("Datastore sync error: %v, retrying in %s", err, time)
err = d.reload()
if err != nil {
log.Errorf("Error reloading: %+v", err)
}
}
ebo := backoff.NewExponentialBackOff()
ebo.MaxElapsedTime = 60 * time.Second
err = backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify)
if err != nil {
return nil, nil, fmt.Errorf("Datastore cannot sync: %v", err)
}
// we synced with KV store, we can now return Setter
return &datastoreTransaction{
Datastore: d,
remoteLock: remoteLock,
id: id,
}, d.meta.object, nil
}
func (d *Datastore) get() *Metadata {
d.localLock.RLock()
defer d.localLock.RUnlock()
return d.meta
}
// Load load atomically a struct from the KV store
func (d *Datastore) Load() (Object, error) {
d.localLock.Lock()
defer d.localLock.Unlock()
err := d.kv.LoadConfig(d.meta)
if err != nil {
return nil, err
}
err = d.meta.unmarshall()
if err != nil {
return nil, err
}
return d.meta.object, nil
}
// Get atomically a struct from the KV store
func (d *Datastore) Get() Object {
d.localLock.RLock()
defer d.localLock.RUnlock()
return d.meta.object
}
var _ Transaction = (*datastoreTransaction)(nil)
type datastoreTransaction struct {
*Datastore
remoteLock store.Locker
dirty bool
id string
}
// Commit allows to set an object in the KV store
func (s *datastoreTransaction) Commit(object Object) error {
s.localLock.Lock()
defer s.localLock.Unlock()
if s.dirty {
return fmt.Errorf("Transaction already used, please begin a new one")
}
s.Datastore.meta.object = object
err := s.Datastore.meta.Marshall()
if err != nil {
return fmt.Errorf("Marshall error: %s", err)
}
err = s.kv.StoreConfig(s.Datastore.meta)
if err != nil {
return fmt.Errorf("StoreConfig error: %s", err)
}
err = s.remoteLock.Unlock()
if err != nil {
return fmt.Errorf("Unlock error: %s", err)
}
s.dirty = true
log.Debugf("Transaction committed %s", s.id)
return nil
}

104
cluster/leadership.go Normal file
View File

@@ -0,0 +1,104 @@
package cluster
import (
"context"
"time"
"github.com/cenk/backoff"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/containous/traefik/types"
"github.com/docker/leadership"
)
// Leadership allows leadership election using a KV store
type Leadership struct {
*safe.Pool
*types.Cluster
candidate *leadership.Candidate
leader *safe.Safe
listeners []LeaderListener
}
// NewLeadership creates a leadership
func NewLeadership(ctx context.Context, cluster *types.Cluster) *Leadership {
return &Leadership{
Pool: safe.NewPool(ctx),
Cluster: cluster,
candidate: leadership.NewCandidate(cluster.Store, cluster.Store.Prefix+"/leader", cluster.Node, 20*time.Second),
listeners: []LeaderListener{},
leader: safe.New(false),
}
}
// LeaderListener is called when leadership has changed
type LeaderListener func(elected bool) error
// Participate tries to be a leader
func (l *Leadership) Participate(pool *safe.Pool) {
pool.GoCtx(func(ctx context.Context) {
log.Debugf("Node %s running for election", l.Cluster.Node)
defer log.Debugf("Node %s no more running for election", l.Cluster.Node)
backOff := backoff.NewExponentialBackOff()
operation := func() error {
return l.run(ctx, l.candidate)
}
notify := func(err error, time time.Duration) {
log.Errorf("Leadership election error %+v, retrying in %s", err, time)
}
err := backoff.RetryNotify(safe.OperationWithRecover(operation), backOff, notify)
if err != nil {
log.Errorf("Cannot elect leadership %+v", err)
}
})
}
// AddListener adds a leadership listerner
func (l *Leadership) AddListener(listener LeaderListener) {
l.listeners = append(l.listeners, listener)
}
// Resign resigns from being a leader
func (l *Leadership) Resign() {
l.candidate.Resign()
log.Infof("Node %s resigned", l.Cluster.Node)
}
func (l *Leadership) run(ctx context.Context, candidate *leadership.Candidate) error {
electedCh, errCh := candidate.RunForElection()
for {
select {
case elected := <-electedCh:
l.onElection(elected)
case err := <-errCh:
return err
case <-ctx.Done():
l.candidate.Resign()
return nil
}
}
}
func (l *Leadership) onElection(elected bool) {
if elected {
log.Infof("Node %s elected leader ♚", l.Cluster.Node)
l.leader.Set(true)
l.Start()
} else {
log.Infof("Node %s elected slave ♝", l.Cluster.Node)
l.leader.Set(false)
l.Stop()
}
for _, listener := range l.listeners {
err := listener(elected)
if err != nil {
log.Errorf("Error calling Leadership listener: %s", err)
}
}
}
// IsLeader returns true if current node is leader
func (l *Leadership) IsLeader() bool {
return l.leader.Get().(bool)
}

16
cluster/store.go Normal file
View File

@@ -0,0 +1,16 @@
package cluster
// Object is the struct to store
type Object interface{}
// Store is a generic interface to represents a storage
type Store interface {
Load() (Object, error)
Get() Object
Begin() (Transaction, Object, error)
}
// Transaction allows to set a struct in the KV store
type Transaction interface {
Commit(object Object) error
}

111
cmd/bug.go Normal file
View File

@@ -0,0 +1,111 @@
package cmd
import (
"bytes"
"encoding/json"
"fmt"
"net/url"
"os/exec"
"regexp"
"runtime"
"text/template"
"github.com/containous/flaeg"
"github.com/mvdan/xurls"
)
var (
bugtracker = "https://github.com/containous/traefik/issues/new"
bugTemplate = `### What version of Traefik are you using?
` + "```" + `
{{.Version}}
` + "```" + `
### What is your environment & configuration (arguments, toml...)?
` + "```" + `
{{.Configuration}}
` + "```" + `
### What did you do?
### What did you expect to see?
### What did you see instead?
`
)
// NewBugCmd builds a new Bug command
func NewBugCmd(traefikConfiguration interface{}, traefikPointersConfiguration interface{}) *flaeg.Command {
//version Command init
return &flaeg.Command{
Name: "bug",
Description: `Report an issue on Traefik bugtracker`,
Config: traefikConfiguration,
DefaultPointersConfig: traefikPointersConfiguration,
Run: func() error {
var version bytes.Buffer
if err := getVersionPrint(&version); err != nil {
return err
}
tmpl, err := template.New("").Parse(bugTemplate)
if err != nil {
return err
}
configJSON, err := json.MarshalIndent(traefikConfiguration, "", " ")
if err != nil {
return err
}
v := struct {
Version string
Configuration string
}{
Version: version.String(),
Configuration: anonymize(string(configJSON)),
}
var bug bytes.Buffer
if err := tmpl.Execute(&bug, v); err != nil {
return err
}
body := bug.String()
url := bugtracker + "?body=" + url.QueryEscape(body)
if err := openBrowser(url); err != nil {
fmt.Print("Please file a new issue at " + bugtracker + " using this template:\n\n")
fmt.Print(body)
}
return nil
},
Metadata: map[string]string{
"parseAllSources": "true",
},
}
}
func openBrowser(url string) error {
var err error
switch runtime.GOOS {
case "linux":
err = exec.Command("xdg-open", url).Start()
case "windows":
err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
case "darwin":
err = exec.Command("open", url).Start()
default:
err = fmt.Errorf("unsupported platform")
}
return err
}
func anonymize(input string) string {
replace := "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
mailExp := regexp.MustCompile(`\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3}"`)
return xurls.Relaxed.ReplaceAllString(mailExp.ReplaceAllString(input, replace), replace)
}

63
cmd/version.go Normal file
View File

@@ -0,0 +1,63 @@
package cmd
import (
"fmt"
"io"
"os"
"runtime"
"text/template"
"github.com/containous/flaeg"
"github.com/containous/traefik/version"
)
var versionTemplate = `Version: {{.Version}}
Codename: {{.Codename}}
Go version: {{.GoVersion}}
Built: {{.BuildTime}}
OS/Arch: {{.Os}}/{{.Arch}}`
// NewVersionCmd builds a new Version command
func NewVersionCmd() *flaeg.Command {
//version Command init
return &flaeg.Command{
Name: "version",
Description: `Print version`,
Config: struct{}{},
DefaultPointersConfig: struct{}{},
Run: func() error {
if err := getVersionPrint(os.Stdout); err != nil {
return err
}
fmt.Printf("\n")
return nil
},
}
}
func getVersionPrint(wr io.Writer) error {
tmpl, err := template.New("").Parse(versionTemplate)
if err != nil {
return err
}
v := struct {
Version string
Codename string
GoVersion string
BuildTime string
Os string
Arch string
}{
Version: version.Version,
Codename: version.Codename,
GoVersion: runtime.Version(),
BuildTime: version.BuildDate,
Os: runtime.GOOS,
Arch: runtime.GOARCH,
}
return tmpl.Execute(wr, v)
}

View File

@@ -1,39 +1,456 @@
package main
import (
"crypto/tls"
"errors"
"fmt"
"os"
"regexp"
"strings"
"time"
"github.com/emilevauge/traefik/provider"
"github.com/emilevauge/traefik/types"
"github.com/containous/traefik/acme"
"github.com/containous/traefik/provider"
"github.com/containous/traefik/types"
)
type GlobalConfiguration struct {
Port string
GraceTimeOut int64
AccessLogsFile string
TraefikLogsFile string
CertFile, KeyFile string
LogLevel string
ProvidersThrottleDuration time.Duration
Docker *provider.Docker
File *provider.File
Web *WebProvider
Marathon *provider.Marathon
Consul *provider.Consul
Etcd *provider.Etcd
Zookeeper *provider.Zookepper
Boltdb *provider.BoltDb
// TraefikConfiguration holds GlobalConfiguration and other stuff
type TraefikConfiguration struct {
GlobalConfiguration `mapstructure:",squash"`
ConfigFile string `short:"c" description:"Configuration file to use (TOML)."`
}
func NewGlobalConfiguration() *GlobalConfiguration {
globalConfiguration := new(GlobalConfiguration)
// default values
globalConfiguration.Port = ":80"
globalConfiguration.GraceTimeOut = 10
globalConfiguration.LogLevel = "ERROR"
globalConfiguration.ProvidersThrottleDuration = time.Duration(2 * time.Second)
// GlobalConfiguration holds global configuration (with providers, etc.).
// It's populated from the traefik configuration file passed as an argument to the binary.
type GlobalConfiguration struct {
GraceTimeOut int64 `short:"g" description:"Duration to give active requests a chance to finish during hot-reload"`
Debug bool `short:"d" description:"Enable debug mode"`
CheckNewVersion bool `description:"Periodically check if a new version has been released"`
AccessLogsFile string `description:"Access logs file"`
TraefikLogsFile string `description:"Traefik logs file"`
LogLevel string `short:"l" description:"Log level"`
EntryPoints EntryPoints `description:"Entrypoints definition using format: --entryPoints='Name:http Address::8000 Redirect.EntryPoint:https' --entryPoints='Name:https Address::4442 TLS:tests/traefik.crt,tests/traefik.key;prod/traefik.crt,prod/traefik.key'"`
Cluster *types.Cluster `description:"Enable clustering"`
Constraints types.Constraints `description:"Filter services by constraint, matching with service tags"`
ACME *acme.ACME `description:"Enable ACME (Let's Encrypt): automatic SSL"`
DefaultEntryPoints DefaultEntryPoints `description:"Entrypoints to be used by frontends that do not specify any entrypoint"`
ProvidersThrottleDuration time.Duration `description:"Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time."`
MaxIdleConnsPerHost int `description:"If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used"`
InsecureSkipVerify bool `description:"Disable SSL certificate verification"`
Retry *Retry `description:"Enable retry sending request if network error"`
Docker *provider.Docker `description:"Enable Docker backend"`
File *provider.File `description:"Enable File backend"`
Web *WebProvider `description:"Enable Web backend"`
Marathon *provider.Marathon `description:"Enable Marathon backend"`
Consul *provider.Consul `description:"Enable Consul backend"`
ConsulCatalog *provider.ConsulCatalog `description:"Enable Consul catalog backend"`
Etcd *provider.Etcd `description:"Enable Etcd backend"`
Zookeeper *provider.Zookepper `description:"Enable Zookeeper backend"`
Boltdb *provider.BoltDb `description:"Enable Boltdb backend"`
Kubernetes *provider.Kubernetes `description:"Enable Kubernetes backend"`
Mesos *provider.Mesos `description:"Enable Mesos backend"`
Eureka *provider.Eureka `description:"Enable Eureka backend"`
ECS *provider.ECS `description:"Enable ECS backend"`
Rancher *provider.Rancher `description:"Enable Rancher backend"`
}
return globalConfiguration
// DefaultEntryPoints holds default entry points
type DefaultEntryPoints []string
// String is the method to format the flag's value, part of the flag.Value interface.
// The String method's output will be used in diagnostics.
func (dep *DefaultEntryPoints) String() string {
return strings.Join(*dep, ",")
}
// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func (dep *DefaultEntryPoints) Set(value string) error {
entrypoints := strings.Split(value, ",")
if len(entrypoints) == 0 {
return errors.New("Bad DefaultEntryPoints format: " + value)
}
for _, entrypoint := range entrypoints {
*dep = append(*dep, entrypoint)
}
return nil
}
// Get return the EntryPoints map
func (dep *DefaultEntryPoints) Get() interface{} {
return DefaultEntryPoints(*dep)
}
// SetValue sets the EntryPoints map with val
func (dep *DefaultEntryPoints) SetValue(val interface{}) {
*dep = DefaultEntryPoints(val.(DefaultEntryPoints))
}
// Type is type of the struct
func (dep *DefaultEntryPoints) Type() string {
return fmt.Sprint("defaultentrypoints")
}
// EntryPoints holds entry points configuration of the reverse proxy (ip, port, TLS...)
type EntryPoints map[string]*EntryPoint
// String is the method to format the flag's value, part of the flag.Value interface.
// The String method's output will be used in diagnostics.
func (ep *EntryPoints) String() string {
return fmt.Sprintf("%+v", *ep)
}
// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func (ep *EntryPoints) Set(value string) error {
regex := regexp.MustCompile("(?:Name:(?P<Name>\\S*))\\s*(?:Address:(?P<Address>\\S*))?\\s*(?:TLS:(?P<TLS>\\S*))?\\s*((?P<TLSACME>TLS))?\\s*(?:CA:(?P<CA>\\S*))?\\s*(?:Redirect.EntryPoint:(?P<RedirectEntryPoint>\\S*))?\\s*(?:Redirect.Regex:(?P<RedirectRegex>\\S*))?\\s*(?:Redirect.Replacement:(?P<RedirectReplacement>\\S*))?\\s*(?:Compress:(?P<Compress>\\S*))?")
match := regex.FindAllStringSubmatch(value, -1)
if match == nil {
return errors.New("Bad EntryPoints format: " + value)
}
matchResult := match[0]
result := make(map[string]string)
for i, name := range regex.SubexpNames() {
if i != 0 {
result[name] = matchResult[i]
}
}
var tls *TLS
if len(result["TLS"]) > 0 {
certs := Certificates{}
if err := certs.Set(result["TLS"]); err != nil {
return err
}
tls = &TLS{
Certificates: certs,
}
} else if len(result["TLSACME"]) > 0 {
tls = &TLS{
Certificates: Certificates{},
}
}
if len(result["CA"]) > 0 {
files := strings.Split(result["CA"], ",")
tls.ClientCAFiles = files
}
var redirect *Redirect
if len(result["RedirectEntryPoint"]) > 0 || len(result["RedirectRegex"]) > 0 || len(result["RedirectReplacement"]) > 0 {
redirect = &Redirect{
EntryPoint: result["RedirectEntryPoint"],
Regex: result["RedirectRegex"],
Replacement: result["RedirectReplacement"],
}
}
compress := false
if len(result["Compress"]) > 0 {
compress = strings.EqualFold(result["Compress"], "enable") || strings.EqualFold(result["Compress"], "on")
}
(*ep)[result["Name"]] = &EntryPoint{
Address: result["Address"],
TLS: tls,
Redirect: redirect,
Compress: compress,
}
return nil
}
// Get return the EntryPoints map
func (ep *EntryPoints) Get() interface{} {
return EntryPoints(*ep)
}
// SetValue sets the EntryPoints map with val
func (ep *EntryPoints) SetValue(val interface{}) {
*ep = EntryPoints(val.(EntryPoints))
}
// Type is type of the struct
func (ep *EntryPoints) Type() string {
return fmt.Sprint("entrypoints")
}
// EntryPoint holds an entry point configuration of the reverse proxy (ip, port, TLS...)
type EntryPoint struct {
Network string
Address string
TLS *TLS
Redirect *Redirect
Auth *types.Auth
Compress bool
}
// Redirect configures a redirection of an entry point to another, or to an URL
type Redirect struct {
EntryPoint string
Regex string
Replacement string
}
// TLS configures TLS for an entry point
type TLS struct {
MinVersion string
CipherSuites []string
Certificates Certificates
ClientCAFiles []string
}
// Map of allowed TLS minimum versions
var minVersion = map[string]uint16{
`VersionTLS10`: tls.VersionTLS10,
`VersionTLS11`: tls.VersionTLS11,
`VersionTLS12`: tls.VersionTLS12,
}
// Map of TLS CipherSuites from crypto/tls
var cipherSuites = map[string]uint16{
`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`: tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`: tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
`TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA`: tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
`TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA`: tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
`TLS_RSA_WITH_AES_128_GCM_SHA256`: tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
`TLS_RSA_WITH_AES_256_GCM_SHA384`: tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
`TLS_RSA_WITH_AES_128_CBC_SHA`: tls.TLS_RSA_WITH_AES_128_CBC_SHA,
`TLS_RSA_WITH_AES_256_CBC_SHA`: tls.TLS_RSA_WITH_AES_256_CBC_SHA,
`TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA`: tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
`TLS_RSA_WITH_3DES_EDE_CBC_SHA`: tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
}
// Certificates defines traefik certificates type
// Certs and Keys could be either a file path, or the file content itself
type Certificates []Certificate
//CreateTLSConfig creates a TLS config from Certificate structures
func (certs *Certificates) CreateTLSConfig() (*tls.Config, error) {
config := &tls.Config{}
config.Certificates = []tls.Certificate{}
certsSlice := []Certificate(*certs)
for _, v := range certsSlice {
isAPath := false
_, errCert := os.Stat(v.CertFile)
_, errKey := os.Stat(v.KeyFile)
if errCert == nil {
if errKey == nil {
isAPath = true
} else {
return nil, fmt.Errorf("bad TLS Certificate KeyFile format, expected a path")
}
} else if errKey == nil {
return nil, fmt.Errorf("bad TLS Certificate KeyFile format, expected a path")
}
cert := tls.Certificate{}
var err error
if isAPath {
cert, err = tls.LoadX509KeyPair(v.CertFile, v.KeyFile)
if err != nil {
return nil, err
}
} else {
cert, err = tls.X509KeyPair([]byte(v.CertFile), []byte(v.KeyFile))
if err != nil {
return nil, err
}
}
config.Certificates = append(config.Certificates, cert)
}
return config, nil
}
// String is the method to format the flag's value, part of the flag.Value interface.
// The String method's output will be used in diagnostics.
func (certs *Certificates) String() string {
if len(*certs) == 0 {
return ""
}
var result []string
for _, certificate := range *certs {
result = append(result, certificate.CertFile+","+certificate.KeyFile)
}
return strings.Join(result, ";")
}
// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func (certs *Certificates) Set(value string) error {
certificates := strings.Split(value, ";")
for _, certificate := range certificates {
files := strings.Split(certificate, ",")
if len(files) != 2 {
return errors.New("Bad certificates format: " + value)
}
*certs = append(*certs, Certificate{
CertFile: files[0],
KeyFile: files[1],
})
}
return nil
}
// Type is type of the struct
func (certs *Certificates) Type() string {
return fmt.Sprint("certificates")
}
// Certificate holds a SSL cert/key pair
// Certs and Key could be either a file path, or the file content itself
type Certificate struct {
CertFile string
KeyFile string
}
// Retry contains request retry config
type Retry struct {
Attempts int `description:"Number of attempts"`
}
// NewTraefikDefaultPointersConfiguration creates a TraefikConfiguration with pointers default values
func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration {
//default Docker
var defaultDocker provider.Docker
defaultDocker.Watch = true
defaultDocker.ExposedByDefault = true
defaultDocker.Endpoint = "unix:///var/run/docker.sock"
defaultDocker.SwarmMode = false
// default File
var defaultFile provider.File
defaultFile.Watch = true
defaultFile.Filename = "" //needs equivalent to viper.ConfigFileUsed()
// default Web
var defaultWeb WebProvider
defaultWeb.Address = ":8080"
defaultWeb.Statistics = &types.Statistics{
RecentErrors: 10,
}
// default Metrics
defaultWeb.Metrics = &types.Metrics{
Prometheus: &types.Prometheus{
Buckets: types.Buckets{0.1, 0.3, 1.2, 5},
},
}
// default Marathon
var defaultMarathon provider.Marathon
defaultMarathon.Watch = true
defaultMarathon.Endpoint = "http://127.0.0.1:8080"
defaultMarathon.ExposedByDefault = true
defaultMarathon.Constraints = types.Constraints{}
defaultMarathon.DialerTimeout = 60
defaultMarathon.KeepAlive = 10
// default Consul
var defaultConsul provider.Consul
defaultConsul.Watch = true
defaultConsul.Endpoint = "127.0.0.1:8500"
defaultConsul.Prefix = "traefik"
defaultConsul.Constraints = types.Constraints{}
// default ConsulCatalog
var defaultConsulCatalog provider.ConsulCatalog
defaultConsulCatalog.Endpoint = "127.0.0.1:8500"
defaultConsulCatalog.Constraints = types.Constraints{}
// default Etcd
var defaultEtcd provider.Etcd
defaultEtcd.Watch = true
defaultEtcd.Endpoint = "127.0.0.1:2379"
defaultEtcd.Prefix = "/traefik"
defaultEtcd.Constraints = types.Constraints{}
//default Zookeeper
var defaultZookeeper provider.Zookepper
defaultZookeeper.Watch = true
defaultZookeeper.Endpoint = "127.0.0.1:2181"
defaultZookeeper.Prefix = "/traefik"
defaultZookeeper.Constraints = types.Constraints{}
//default Boltdb
var defaultBoltDb provider.BoltDb
defaultBoltDb.Watch = true
defaultBoltDb.Endpoint = "127.0.0.1:4001"
defaultBoltDb.Prefix = "/traefik"
defaultBoltDb.Constraints = types.Constraints{}
//default Kubernetes
var defaultKubernetes provider.Kubernetes
defaultKubernetes.Watch = true
defaultKubernetes.Endpoint = ""
defaultKubernetes.LabelSelector = ""
defaultKubernetes.Constraints = types.Constraints{}
// default Mesos
var defaultMesos provider.Mesos
defaultMesos.Watch = true
defaultMesos.Endpoint = "http://127.0.0.1:5050"
defaultMesos.ExposedByDefault = true
defaultMesos.Constraints = types.Constraints{}
defaultMesos.RefreshSeconds = 30
defaultMesos.ZkDetectionTimeout = 30
defaultMesos.StateTimeoutSecond = 30
//default ECS
var defaultECS provider.ECS
defaultECS.Watch = true
defaultECS.ExposedByDefault = true
defaultECS.RefreshSeconds = 15
defaultECS.Cluster = "default"
defaultECS.Constraints = types.Constraints{}
//default Rancher
var defaultRancher provider.Rancher
defaultRancher.Watch = true
defaultRancher.ExposedByDefault = true
defaultConfiguration := GlobalConfiguration{
Docker: &defaultDocker,
File: &defaultFile,
Web: &defaultWeb,
Marathon: &defaultMarathon,
Consul: &defaultConsul,
ConsulCatalog: &defaultConsulCatalog,
Etcd: &defaultEtcd,
Zookeeper: &defaultZookeeper,
Boltdb: &defaultBoltDb,
Kubernetes: &defaultKubernetes,
Mesos: &defaultMesos,
ECS: &defaultECS,
Rancher: &defaultRancher,
Retry: &Retry{},
}
//default Rancher
//@TODO: ADD
return &TraefikConfiguration{
GlobalConfiguration: defaultConfiguration,
}
}
// NewTraefikConfiguration creates a TraefikConfiguration with default values
func NewTraefikConfiguration() *TraefikConfiguration {
return &TraefikConfiguration{
GlobalConfiguration: GlobalConfiguration{
GraceTimeOut: 10,
AccessLogsFile: "",
TraefikLogsFile: "",
LogLevel: "ERROR",
EntryPoints: map[string]*EntryPoint{},
Constraints: types.Constraints{},
DefaultEntryPoints: []string{},
ProvidersThrottleDuration: time.Duration(2 * time.Second),
MaxIdleConnsPerHost: 200,
CheckNewVersion: true,
},
ConfigFile: "",
}
}
type configs map[string]*types.Configuration

View File

@@ -0,0 +1,11 @@
[Unit]
Description=Traefik
[Service]
Type=notify
ExecStart=/usr/bin/traefik --configFile=/etc/traefik.toml
Restart=always
WatchdogSec=1s
[Install]
WantedBy=multi-user.target

1
docs/CNAME Normal file
View File

@@ -0,0 +1 @@
docs.traefik.io

386
docs/basics.md Normal file
View File

@@ -0,0 +1,386 @@
# Concepts
Let's take our example from the [overview](https://docs.traefik.io/#overview) again:
> Imagine that you have deployed a bunch of microservices on your infrastructure. You probably used a service registry (like etcd or consul) and/or an orchestrator (swarm, Mesos/Marathon) to manage all these services.
> If you want your users to access some of your microservices from the Internet, you will have to use a reverse proxy and configure it using virtual hosts or prefix paths:
> - domain `api.domain.com` will point the microservice `api` in your private network
> - path `domain.com/web` will point the microservice `web` in your private network
> - domain `backoffice.domain.com` will point the microservices `backoffice` in your private network, load-balancing between your multiple instances
> ![Architecture](img/architecture.png)
Let's zoom on Træfɪk and have an overview of its internal architecture:
![Architecture](img/internal.png)
- Incoming requests end on [entrypoints](#entrypoints), as the name suggests, they are the network entry points into Træfɪk (listening port, SSL, traffic redirection...).
- Traffic is then forwarded to a matching [frontend](#frontends). A frontend defines routes from [entrypoints](#entrypoints) to [backends](#backends).
Routes are created using requests fields (`Host`, `Path`, `Headers`...) and can match or not a request.
- The [frontend](#frontends) will then send the request to a [backend](#backends). A backend can be composed by one or more [servers](#servers), and by a load-balancing strategy.
- Finally, the [server](#servers) will forward the request to the corresponding microservice in the private network.
## Entrypoints
Entrypoints are the network entry points into Træfɪk.
They can be defined using:
- a port (80, 443...)
- SSL (Certificates, Keys, authentication with a client certificate signed by a trusted CA...)
- redirection to another entrypoint (redirect `HTTP` to `HTTPS`)
Here is an example of entrypoints definition:
```toml
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
certFile = "tests/traefik.crt"
keyFile = "tests/traefik.key"
```
- Two entrypoints are defined `http` and `https`.
- `http` listens on port `80` and `https` on port `443`.
- We enable SSL on `https` by giving a certificate and a key.
- We also redirect all the traffic from entrypoint `http` to `https`.
And here is another example with client certificate authentication:
```toml
[entryPoints]
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
clientCAFiles = ["tests/clientca1.crt", "tests/clientca2.crt"]
[[entryPoints.https.tls.certificates]]
certFile = "tests/traefik.crt"
keyFile = "tests/traefik.key"
```
- We enable SSL on `https` by giving a certificate and a key.
- One or several files containing Certificate Authorities in PEM format are added.
- It is possible to have multiple CA:s in the same file or keep them in separate files.
## Frontends
A frontend is a set of rules that forwards the incoming traffic from an entrypoint to a backend.
Frontends can be defined using the following rules:
- `Headers: Content-Type, application/json`: Headers adds a matcher for request header values. It accepts a sequence of key/value pairs to be matched.
- `HeadersRegexp: Content-Type, application/(text|json)`: Regular expressions can be used with headers as well. It accepts a sequence of key/value pairs, where the value has regex support.
- `Host: traefik.io, www.traefik.io`: Match request host with given host list.
- `HostRegexp: traefik.io, {subdomain:[a-z]+}.traefik.io`: Adds a matcher for the URL hosts. It accepts templates with zero or more URL variables enclosed by `{}`. Variables can define an optional regexp pattern to be matched.
- `Method: GET, POST, PUT`: Method adds a matcher for HTTP methods. It accepts a sequence of one or more methods to be matched.
- `Path: /products/, /articles/{category}/{id:[0-9]+}`: Path adds a matcher for the URL paths. It accepts templates with zero or more URL variables enclosed by `{}`.
- `PathStrip`: Same as `Path` but strip the given prefix from the request URL's Path.
- `PathPrefix`: PathPrefix adds a matcher for the URL path prefixes. This matches if the given template is a prefix of the full URL path.
- `PathPrefixStrip`: Same as `PathPrefix` but strip the given prefix from the request URL's Path.
- `AddPrefix` : Add prefix from the request URL's Path.
You can use multlple values for a rule by separating them with `,`.
You can use multiple rules by separating them by `;`.
You can optionally enable `passHostHeader` to forward client `Host` header to the backend.
Here is an example of frontends definition:
```toml
[frontends]
[frontends.frontend1]
backend = "backend2"
[frontends.frontend1.routes.test_1]
rule = "Host:test.localhost,test2.localhost"
[frontends.frontend2]
backend = "backend1"
passHostHeader = true
priority = 10
entrypoints = ["https"] # overrides defaultEntryPoints
[frontends.frontend2.routes.test_1]
rule = "HostRegexp:localhost,{subdomain:[a-z]+}.localhost"
[frontends.frontend3]
backend = "backend2"
[frontends.frontend3.routes.test_1]
rule = "Host:test3.localhost;Path:/test"
```
- Three frontends are defined: `frontend1`, `frontend2` and `frontend3`
- `frontend1` will forward the traffic to the `backend2` if the rule `Host:test.localhost,test2.localhost` is matched
- `frontend2` will forward the traffic to the `backend1` if the rule `Host:localhost,{subdomain:[a-z]+}.localhost` is matched (forwarding client `Host` header to the backend)
- `frontend3` will forward the traffic to the `backend2` if the rules `Host:test3.localhost` **AND** `Path:/test` are matched
### Combining multiple rules
As seen in the previous example, you can combine multiple rules.
In TOML file, you can use multiple routes:
```toml
[frontends.frontend3]
backend = "backend2"
[frontends.frontend3.routes.test_1]
rule = "Host:test3.localhost"
[frontends.frontend3.routes.test_2]
rule = "Path:/test"
```
Here `frontend3` will forward the traffic to the `backend2` if the rules `Host:test3.localhost` **AND** `Path:/test` are matched.
You can also use the notation using a `;` separator, same result:
```toml
[frontends.frontend3]
backend = "backend2"
[frontends.frontend3.routes.test_1]
rule = "Host:test3.localhost;Path:/test"
```
Finally, you can create a rule to bind multiple domains or Path to a frontend, using the `,` separator:
```toml
[frontends.frontend2]
[frontends.frontend2.routes.test_1]
rule = "Host:test1.localhost,test2.localhost"
[frontends.frontend3]
backend = "backend2"
[frontends.frontend3.routes.test_1]
rule = "Path:/test1,/test2"
```
### Priorities
By default, routes will be sorted (in descending order) using rules length (to avoid path overlap):
`PathPrefix:/12345` will be matched before `PathPrefix:/1234` that will be matched before `PathPrefix:/1`.
You can customize priority by frontend:
```
[frontends]
[frontends.frontend1]
backend = "backend1"
priority = 10
passHostHeader = true
[frontends.frontend1.routes.test_1]
rule = "PathPrefix:/to"
[frontends.frontend2]
priority = 5
backend = "backend2"
passHostHeader = true
[frontends.frontend2.routes.test_1]
rule = "PathPrefix:/toto"
```
Here, `frontend1` will be matched before `frontend2` (`10 > 5`).
## Backends
A backend is responsible to load-balance the traffic coming from one or more frontends to a set of http servers.
Various methods of load-balancing are supported:
- `wrr`: Weighted Round Robin
- `drr`: Dynamic Round Robin: increases weights on servers that perform better than others. It also rolls back to original weights if the servers have changed.
A circuit breaker can also be applied to a backend, preventing high loads on failing servers.
Initial state is Standby. CB observes the statistics and does not modify the request.
In case the condition matches, CB enters Tripped state, where it responds with predefined code or redirects to another frontend.
Once Tripped timer expires, CB enters Recovering state and resets all stats.
In case the condition does not match and recovery timer expires, CB enters Standby state.
It can be configured using:
- Methods: `LatencyAtQuantileMS`, `NetworkErrorRatio`, `ResponseCodeRatio`
- Operators: `AND`, `OR`, `EQ`, `NEQ`, `LT`, `LE`, `GT`, `GE`
For example:
- `NetworkErrorRatio() > 0.5`: watch error ratio over 10 second sliding window for a frontend
- `LatencyAtQuantileMS(50.0) > 50`: watch latency at quantile in milliseconds.
- `ResponseCodeRatio(500, 600, 0, 600) > 0.5`: ratio of response codes in range [500-600) to [0-600)
To proactively prevent backends from being overwhelmed with high load, a maximum connection limit can
also be applied to each backend.
Maximum connections can be configured by specifying an integer value for `maxconn.amount` and
`maxconn.extractorfunc` which is a strategy used to determine how to categorize requests in order to
evaluate the maximum connections.
For example:
```toml
[backends]
[backends.backend1]
[backends.backend1.maxconn]
amount = 10
extractorfunc = "request.host"
```
- `backend1` will return `HTTP code 429 Too Many Requests` if there are already 10 requests in progress for the same Host header.
- Another possible value for `extractorfunc` is `client.ip` which will categorize requests based on client source ip.
- Lastly `extractorfunc` can take the value of `request.header.ANY_HEADER` which will categorize requests based on `ANY_HEADER` that you provide.
Sticky sessions are supported with both load balancers. When sticky sessions are enabled, a cookie called `_TRAEFIK_BACKEND` is set on the initial
request. On subsequent requests, the client will be directed to the backend stored in the cookie if it is still healthy. If not, a new backend
will be assigned.
For example:
```toml
[backends]
[backends.backend1]
[backends.backend1.loadbalancer]
sticky = true
```
A health check can be configured in order to remove a backend from LB rotation
as long as it keeps returning HTTP status codes other than 200 OK to HTTP GET
requests periodically carried out by Traefik. The check is defined by a path
appended to the backend URL and an interval (given in a format understood by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration)) specifying how
often the health check should be executed (the default being 30 seconds). Each
backend must respond to the health check within 5 seconds.
A recovering backend returning 200 OK responses again is being returned to the
LB rotation pool.
For example:
```toml
[backends]
[backends.backend1]
[backends.backend1.healthcheck]
path = "/health"
interval = "10s"
```
## Servers
Servers are simply defined using a `URL`. You can also apply a custom `weight` to each server (this will be used by load-balancing).
Here is an example of backends and servers definition:
```toml
[backends]
[backends.backend1]
[backends.backend1.circuitbreaker]
expression = "NetworkErrorRatio() > 0.5"
[backends.backend1.servers.server1]
url = "http://172.17.0.2:80"
weight = 10
[backends.backend1.servers.server2]
url = "http://172.17.0.3:80"
weight = 1
[backends.backend2]
[backends.backend2.LoadBalancer]
method = "drr"
[backends.backend2.servers.server1]
url = "http://172.17.0.4:80"
weight = 1
[backends.backend2.servers.server2]
url = "http://172.17.0.5:80"
weight = 2
```
- Two backends are defined: `backend1` and `backend2`
- `backend1` will forward the traffic to two servers: `http://172.17.0.2:80"` with weight `10` and `http://172.17.0.3:80` with weight `1` using default `wrr` load-balancing strategy.
- `backend2` will forward the traffic to two servers: `http://172.17.0.4:80"` with weight `1` and `http://172.17.0.5:80` with weight `2` using `drr` load-balancing strategy.
- a circuit breaker is added on `backend1` using the expression `NetworkErrorRatio() > 0.5`: watch error ratio over 10 second sliding window
# Configuration
Træfɪk's configuration has two parts:
- The [static Træfɪk configuration](/basics#static-trfk-configuration) which is loaded only at the beginning.
- The [dynamic Træfɪk configuration](/basics#dynamic-trfk-configuration) which can be hot-reloaded (no need to restart the process).
## Static Træfɪk configuration
The static configuration is the global configuration which is setting up connections to configuration backends and entrypoints.
Træfɪk can be configured using many configuration sources with the following precedence order.
Each item takes precedence over the item below it:
- [Key-value Store](/basics/#key-value-stores)
- [Arguments](/basics/#arguments)
- [Configuration file](/basics/#configuration-file)
- Default
It means that arguments override configuration file, and Key-value Store overrides arguments.
### Configuration file
By default, Træfɪk will try to find a `traefik.toml` in the following places:
- `/etc/traefik/`
- `$HOME/.traefik/`
- `.` *the working directory*
You can override this by setting a `configFile` argument:
```bash
$ traefik --configFile=foo/bar/myconfigfile.toml
```
Please refer to the [global configuration](/toml/#global-configuration) section to get documentation on it.
### Arguments
Each argument (and command) is described in the help section:
```bash
$ traefik --help
```
Note that all default values will be displayed as well.
### Key-value stores
Træfɪk supports several Key-value stores:
- [Consul](https://consul.io)
- [etcd](https://coreos.com/etcd/)
- [ZooKeeper](https://zookeeper.apache.org/)
- [boltdb](https://github.com/boltdb/bolt)
Please refer to the [User Guide Key-value store configuration](/user-guide/kv-config/) section to get documentation on it.
## Dynamic Træfɪk configuration
The dynamic configuration concerns :
- [Frontends](/basics/#frontends)
- [Backends](/basics/#backends)
- [Servers](/basics/#servers)
Træfɪk can hot-reload those rules which could be provided by [multiple configuration backends](/toml/#configuration-backends).
We only need to enable `watch` option to make Træfɪk watch configuration backend changes and generate its configuration automatically.
Routes to services will be created and updated instantly at any changes.
Please refer to the [configuration backends](/toml/#configuration-backends) section to get documentation on it.
# Commands
Usage: `traefik [command] [--flag=flag_argument]`
List of Træfɪk available commands with description :                                                             
- `version` : Print version 
- `storeconfig` : Store the static traefik configuration into a Key-value stores. Please refer to the [Store Træfɪk configuration](/user-guide/kv-config/#store-trfk-configuration) section to get documentation on it.
Each command may have related flags.
All those related flags will be displayed with :
```bash
$ traefik [command] --help
```
Note that each command is described at the beginning of the help section:
```bash
$ traefik --help
```

213
docs/benchmarks.md Normal file
View File

@@ -0,0 +1,213 @@
# Benchmarks
## Configuration
I would like to thanks [vincentbernat](https://github.com/vincentbernat) from [exoscale.ch](https://www.exoscale.ch) who kindly provided the infrastructure needed for the benchmarks.
I used 4 VMs for the tests with the following configuration:
- 32 GB RAM
- 8 CPU Cores
- 10 GB SSD
- Ubuntu 14.04 LTS 64-bit
## Setup
1. One VM used to launch the benchmarking tool [wrk](https://github.com/wg/wrk)
2. One VM for traefik (v1.0.0-beta.416) / nginx (v1.4.6)
3. Two VMs for 2 backend servers in go [whoami](https://github.com/emilevauge/whoamI/)
Each VM has been tuned using the following limits:
```bash
sysctl -w fs.file-max="9999999"
sysctl -w fs.nr_open="9999999"
sysctl -w net.core.netdev_max_backlog="4096"
sysctl -w net.core.rmem_max="16777216"
sysctl -w net.core.somaxconn="65535"
sysctl -w net.core.wmem_max="16777216"
sysctl -w net.ipv4.ip_local_port_range="1025 65535"
sysctl -w net.ipv4.tcp_fin_timeout="30"
sysctl -w net.ipv4.tcp_keepalive_time="30"
sysctl -w net.ipv4.tcp_max_syn_backlog="20480"
sysctl -w net.ipv4.tcp_max_tw_buckets="400000"
sysctl -w net.ipv4.tcp_no_metrics_save="1"
sysctl -w net.ipv4.tcp_syn_retries="2"
sysctl -w net.ipv4.tcp_synack_retries="2"
sysctl -w net.ipv4.tcp_tw_recycle="1"
sysctl -w net.ipv4.tcp_tw_reuse="1"
sysctl -w vm.min_free_kbytes="65536"
sysctl -w vm.overcommit_memory="1"
ulimit -n 9999999
```
### Nginx
Here is the config Nginx file use `/etc/nginx/nginx.conf`:
```
user www-data;
worker_processes auto;
worker_rlimit_nofile 200000;
pid /var/run/nginx.pid;
events {
worker_connections 10000;
use epoll;
multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 300;
keepalive_requests 10000;
types_hash_max_size 2048;
open_file_cache max=200000 inactive=300s;
open_file_cache_valid 300s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
server_tokens off;
dav_methods off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log combined;
error_log /var/log/nginx/error.log warn;
gzip off;
gzip_vary off;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*.conf;
}
```
Here is the Nginx vhost file used:
```
upstream whoami {
server IP-whoami1:80;
server IP-whoami2:80;
keepalive 300;
}
server {
listen 8001;
server_name test.traefik;
access_log off;
error_log /dev/null crit;
if ($host != "test.traefik") {
return 404;
}
location / {
proxy_pass http://whoami;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header X-Forwarded-Host $host;
}
}
```
### Traefik
Here is the `traefik.toml` file used:
```
MaxIdleConnsPerHost = 100000
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":8000"
[file]
[backends]
[backends.backend1]
[backends.backend1.servers.server1]
url = "http://IP-whoami1:80"
weight = 1
[backends.backend1.servers.server2]
url = "http://IP-whoami2:80"
weight = 1
[frontends]
[frontends.frontend1]
backend = "backend1"
[frontends.frontend1.routes.test_1]
rule = "Host: test.traefik"
```
## Results
### whoami:
```
wrk -t20 -c1000 -d60s -H "Host: test.traefik" --latency http://IP-whoami:80/bench
Running 1m test @ http://IP-whoami:80/bench
20 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 70.28ms 134.72ms 1.91s 89.94%
Req/Sec 2.92k 742.42 8.78k 68.80%
Latency Distribution
50% 10.63ms
75% 75.64ms
90% 205.65ms
99% 668.28ms
3476705 requests in 1.00m, 384.61MB read
Socket errors: connect 0, read 0, write 0, timeout 103
Requests/sec: 57894.35
Transfer/sec: 6.40MB
```
### nginx:
```
wrk -t20 -c1000 -d60s -H "Host: test.traefik" --latency http://IP-nginx:8001/bench
Running 1m test @ http://IP-nginx:8001/bench
20 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 101.25ms 180.09ms 1.99s 89.34%
Req/Sec 1.69k 567.69 9.39k 72.62%
Latency Distribution
50% 15.46ms
75% 129.11ms
90% 302.44ms
99% 846.59ms
2018427 requests in 1.00m, 298.36MB read
Socket errors: connect 0, read 0, write 0, timeout 90
Requests/sec: 33591.67
Transfer/sec: 4.97MB
```
### traefik:
```
wrk -t20 -c1000 -d60s -H "Host: test.traefik" --latency http://IP-traefik:8000/bench
Running 1m test @ http://IP-traefik:8000/bench
20 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 91.72ms 150.43ms 2.00s 90.50%
Req/Sec 1.43k 266.37 2.97k 69.77%
Latency Distribution
50% 19.74ms
75% 121.98ms
90% 237.39ms
99% 687.49ms
1705073 requests in 1.00m, 188.63MB read
Socket errors: connect 0, read 0, write 0, timeout 7
Requests/sec: 28392.44
Transfer/sec: 3.14MB
```
## Conclusion
Traefik is obviously slower than Nginx, but not so much: Traefik can serve 28392 requests/sec and Nginx 33591 requests/sec which gives a ratio of 85%.
Not bad for young project :) !
Some areas of possible improvements:
- Use [GO_REUSEPORT](https://github.com/kavu/go_reuseport) listener
- Run a separate server instance per CPU core with `GOMAXPROCS=1` (it appears during benchmarks that there is a lot more context switches with traefik than with nginx)

61
docs/css/traefik.css Normal file
View File

@@ -0,0 +1,61 @@
a {
color: #37ABC8;
text-decoration: none;
}
a:hover, a:focus {
color: #25606F;
text-decoration: underline;
}
h1, h2, h3, H4 {
color: #37ABC8;
}
.navbar-default {
background-color: #37ABC8;
border-color: #25606F;
}
.navbar-default .navbar-nav>.active>a, .navbar-default .navbar-nav>.active>a:hover, .navbar-default .navbar-nav>.active>a:focus {
color: #fff;
background-color: #25606F;
}
.navbar-default .navbar-nav>li>a:hover, .navbar-default .navbar-nav>li>a:focus {
color: #fff;
background-color: #25606F;
}
.navbar-default .navbar-toggle {
border-color: #25606F;
}
.navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus .navbar-toggle {
background-color: #25606F;
}
.navbar-default .navbar-collapse, .navbar-default .navbar-form {
border-color: #25606F;
}
blockquote p {
font-size: 14px;
}
.navbar-default .navbar-nav>.open>a, .navbar-default .navbar-nav>.open>a:hover, .navbar-default .navbar-nav>.open>a:focus {
color: #fff;
background-color: #25606F;
}
.dropdown-menu>li>a:hover, .dropdown-menu>li>a:focus {
color: #fff;
text-decoration: none;
background-color: #25606F;
}
.dropdown-menu>.active>a, .dropdown-menu>.active>a:hover, .dropdown-menu>.active>a:focus {
color: #fff;
text-decoration: none;
background-color: #25606F;
outline: 0;
}

BIN
docs/img/apollo-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
docs/img/architecture.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

2407
docs/img/architecture.svg Normal file

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 100 KiB

BIN
docs/img/asteris.logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/img/internal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

View File

@@ -0,0 +1,172 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="337.37802"
height="107.921"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="letsencrypt-logo-horizontal.svg">
<metadata
id="metadata37">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs35" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="640"
inkscape:window-height="480"
id="namedview33"
showgrid="false"
fit-margin-bottom="30"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
inkscape:zoom="0.72861357"
inkscape:cx="168.57"
inkscape:cy="69.027001"
inkscape:window-x="0"
inkscape:window-y="30"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<g
id="g4"
transform="translate(-0.930001,-1.606)">
<title
id="title6">Layer 1</title>
<g
id="svg_1">
<g
id="svg_2">
<g
id="svg_3">
<path
id="svg_4"
d="m 76.621002,68.878998 0,-31.406998 7.629997,0 0,24.796997 12.153999,0 0,6.609001 -19.783997,0 0,9.99e-4 z"
inkscape:connector-curvature="0"
style="fill:#2c3c69" />
<path
id="svg_5"
d="m 121.547,58.098999 c 0,0.295998 0,0.592003 0,0.888 0,0.295997 -0.015,0.576004 -0.044,0.843002 l -16.01301,0 c 0.059,0.620995 0.244,1.182999 0.555,1.685997 0.311,0.502998 0.71,0.938004 1.197,1.308998 0.488,0.370003 1.035,0.658005 1.642,0.864006 0.605,0.208 1.234,0.310997 1.885,0.310997 1.153,0 2.13,-0.213997 2.928,-0.642998 0.799,-0.429001 1.449,-0.983002 1.952,-1.664001 l 5.05699,3.194 c -1.03498,1.507996 -2.40199,2.668999 -4.10299,3.482002 -1.701,0.811996 -3.676,1.219994 -5.922,1.219994 -1.657,0 -3.224,-0.259995 -4.702,-0.775993 -1.479,-0.518005 -2.772,-1.271004 -3.882,-2.263 -1.108,-0.990005 -1.981,-2.210007 -2.616996,-3.659004 -0.635994,-1.448997 -0.953003,-3.104996 -0.953003,-4.969002 0,-1.802994 0.309998,-3.437996 0.931,-4.900997 0.620999,-1.463001 1.463999,-2.706001 2.528999,-3.726002 1.064,-1.021 2.32,-1.811996 3.771,-2.373997 1.448,-0.561001 3.016,-0.843002 4.701,-0.843002 1.626,0 3.12,0.274002 4.48,0.820999 1.36,0.546997 2.528,1.338001 3.505,2.373001 0.976,1.035 1.73599,2.292 2.284,3.771 0.546,1.478001 0.819,3.165001 0.819,5.056 z m -6.698,-2.794998 c 0,-1.153 -0.362,-2.144001 -1.087,-2.972 -0.725,-0.827 -1.812,-1.242001 -3.26,-1.242001 -0.71,0 -1.36,0.111 -1.952,0.333 -0.59199,0.222 -1.108,0.525002 -1.553,0.909 -0.443,0.384998 -0.798,0.835999 -1.064,1.354 -0.266,0.517998 -0.414,1.057999 -0.443,1.618 l 9.359,0 z"
inkscape:connector-curvature="0"
style="fill:#2c3c69" />
<path
id="svg_6"
d="m 133.168,52.200001 0,8.461002 c 0,1.038994 0.2,1.816994 0.60001,2.337997 0.39799,0.519997 1.11499,0.778 2.151,0.778 0.35399,0 0.73098,-0.028 1.13099,-0.089 0.39901,-0.05901 0.73101,-0.147003 0.998,-0.266006 l 0.089,5.323006 c -0.50299,0.176994 -1.13899,0.332001 -1.90699,0.465996 -0.76999,0.133003 -1.538,0.199005 -2.307,0.199005 -1.479,0 -2.722,-0.186005 -3.727,-0.556007 C 129.19,68.484002 128.384,67.949998 127.77901,67.252 127.172,66.556001 126.73599,65.725999 126.47,64.762002 126.203,63.799005 126.071,62.724 126.071,61.538003 l 0,-9.338001 -3.549,0 0,-5.412003 3.504,0 0,-5.810997 7.142,0 0,5.810997 5.19,0 0,5.412003 -5.19,0 z"
inkscape:connector-curvature="0"
style="fill:#2c3c69" />
<path
id="svg_7"
d="m 161.91299,53.307999 c -0.59201,-0.560997 -1.28601,-1.034 -2.085,-1.418999 -0.79801,-0.383999 -1.64099,-0.577 -2.528,-0.577 -0.681,0 -1.30899,0.133999 -1.885,0.398998 -0.57699,0.267002 -0.865,0.726002 -0.865,1.375 0,0.621002 0.317,1.064003 0.953,1.331001 0.636,0.266998 1.664,0.562 3.08299,0.887001 0.82801,0.177998 1.664,0.43 2.50701,0.754997 0.843,0.324997 1.604,0.754005 2.28399,1.286003 0.68001,0.531998 1.22701,1.182999 1.64202,1.951996 0.41299,0.769005 0.62098,1.686005 0.62098,2.75 0,1.391006 -0.28099,2.565002 -0.84298,3.526001 -0.56201,0.960999 -1.29401,1.737 -2.19602,2.329002 -0.902,0.592002 -1.91499,1.019997 -3.03799,1.286003 -1.12399,0.266998 -2.248,0.398994 -3.371,0.398994 -1.80499,0 -3.571,-0.287994 -5.302,-0.864998 C 149.161,68.146002 147.719,67.294996 146.566,66.170995 l 4.08099,-4.303001 c 0.649,0.710007 1.448,1.302002 2.395,1.774002 0.946,0.473999 1.952,0.709999 3.017,0.709999 0.592,0 1.176,-0.140999 1.752,-0.421997 0.577,-0.279999 0.86501,-0.776001 0.86501,-1.485001 0,-0.681 -0.35401,-1.182999 -1.06401,-1.509003 -0.71,-0.324997 -1.818,-0.664993 -3.327,-1.020996 -0.769,-0.177002 -1.53799,-0.413002 -2.30699,-0.709 -0.77001,-0.295998 -1.457,-0.694 -2.06202,-1.197998 -0.60598,-0.502007 -1.10199,-1.123001 -1.48599,-1.863007 -0.384,-0.737995 -0.576,-1.625996 -0.576,-2.660995 0,-1.331001 0.28,-2.462002 0.843,-3.394001 0.562,-0.931999 1.286,-1.692001 2.174,-2.284 0.88701,-0.591999 1.87001,-1.027 2.949,-1.308998 1.079,-0.281998 2.151,-0.422001 3.217,-0.422001 1.655,0 3.274,0.259998 4.856,0.776001 1.582,0.517998 2.921,1.293999 4.015,2.328999 l -3.995,4.127998 z"
inkscape:connector-curvature="0"
style="fill:#2c3c69" />
<path
id="svg_8"
d="m 179.56799,68.878998 0,-31.406998 21.114,0 0,6.388 -13.795,0 0,5.944 13.041,0 0,6.077 -13.041,0 0,6.521 14.594,0 0,6.476997 -21.913,0 z"
inkscape:connector-curvature="0"
style="fill:#2c3c69" />
<path
id="svg_9"
d="m 220.675,68.878998 0,-12.065994 c 0,-0.621002 -0.053,-1.212002 -0.155,-1.774002 -0.104,-0.562 -0.274,-1.057003 -0.511,-1.486 -0.237,-0.428001 -0.569,-0.769001 -0.998,-1.021 -0.429,-0.25 -0.96899,-0.377003 -1.619,-0.377003 -0.65001,0 -1.22,0.127003 -1.70799,0.377003 -0.487,0.251999 -0.89501,0.599998 -1.22001,1.042999 -0.32499,0.443001 -0.569,0.953999 -0.731,1.529999 -0.16299,0.577 -0.244,1.175999 -0.244,1.797001 l 0,11.976997 -7.319,0 0,-22.091 7.05301,0 0,3.061001 0.089,0 c 0.26699,-0.473 0.613,-0.938 1.043,-1.396 0.428,-0.459 0.932,-0.850998 1.50801,-1.175999 0.57699,-0.325001 1.20498,-0.591999 1.88598,-0.799 0.68001,-0.206001 1.40401,-0.311001 2.17301,-0.311001 1.479,0 2.735,0.266998 3.77099,0.799 1.036,0.532002 1.87001,1.220001 2.50701,2.062 0.636,0.842999 1.09401,1.812 1.375,2.904999 0.28,1.095001 0.421,2.189003 0.421,3.283001 l 0,13.661999 -7.321,0 0,9.99e-4 z"
inkscape:connector-curvature="0"
style="fill:#2c3c69" />
<path
id="svg_10"
d="m 246.71301,53.929001 c -0.41501,-0.532001 -0.977,-0.959999 -1.686,-1.285999 -0.70999,-0.325001 -1.43601,-0.488003 -2.174,-0.488003 -0.77,0 -1.464,0.155003 -2.085,0.466 -0.62101,0.310997 -1.153,0.726002 -1.59701,1.242001 -0.44299,0.518002 -0.79199,1.117001 -1.04299,1.797001 -0.251,0.681004 -0.377,1.404003 -0.377,2.174 0,0.768997 0.11799,1.493004 0.35499,2.173004 0.23601,0.681 0.58301,1.279999 1.04201,1.796997 0.45799,0.517998 1.005,0.924995 1.642,1.220001 0.636,0.295998 1.35299,0.443001 2.151,0.443001 0.73801,0 1.47099,-0.139999 2.19501,-0.421005 0.72401,-0.281006 1.30899,-0.687996 1.75198,-1.220001 l 4.03702,4.924004 c -0.91703,0.887001 -2.10102,1.582001 -3.54901,2.084999 -1.44899,0.501999 -2.987,0.753998 -4.61299,0.753998 -1.74501,0 -3.37401,-0.266998 -4.88701,-0.798996 -1.512,-0.531998 -2.82601,-1.308998 -3.941,-2.329002 -1.11599,-1.019997 -1.99299,-2.253998 -2.63299,-3.702995 -0.64,-1.448997 -0.959,-3.090004 -0.959,-4.924004 0,-1.804001 0.31898,-3.431 0.959,-4.880001 0.64,-1.447998 1.51699,-2.683998 2.63299,-3.703999 1.11499,-1.021 2.43,-1.804001 3.941,-2.351002 1.513,-0.546997 3.127,-0.820999 4.843,-0.820999 0.798,0 1.589,0.074 2.373,0.223 0.783,0.147003 1.53699,0.348 2.26199,0.599003 0.72501,0.251003 1.39002,0.562 1.996,0.931999 0.60599,0.369999 1.13202,0.776001 1.57502,1.219997 l -4.21201,4.877003 z"
inkscape:connector-curvature="0"
style="fill:#2c3c69" />
<path
id="svg_11"
d="m 268.03201,52.776001 c -0.32599,-0.089 -0.64401,-0.146999 -0.95401,-0.177002 -0.30999,-0.03 -0.61398,-0.045 -0.90899,-0.045 -0.97599,0 -1.797,0.177998 -2.46201,0.530998 -0.66498,0.354 -1.19699,0.781002 -1.59698,1.283001 -0.39902,0.500999 -0.68802,1.047001 -0.86503,1.636997 -0.177,0.589996 -0.26599,1.105003 -0.26599,1.548004 l 0,11.324997 -7.27499,0 0,-22.063999 7.009,0 0,3.194 0.089,0 c 0.56201,-1.132 1.35901,-2.055 2.396,-2.77 1.03402,-0.715 2.23202,-1.071999 3.59302,-1.071999 0.29498,0 0.58398,0.016 0.86499,0.045 0.27999,0.029 0.51001,0.074 0.68801,0.133003 L 268.03201,52.776 z"
inkscape:connector-curvature="0"
style="fill:#2c3c69" />
<path
id="svg_12"
d="m 285.12201,72.206001 c -0.44299,1.153 -0.939,2.181 -1.48599,3.083 -0.547,0.901001 -1.19702,1.669998 -1.95102,2.306999 -0.754,0.636002 -1.642,1.114998 -2.66199,1.441002 -1.01999,0.324997 -2.22601,0.487999 -3.61499,0.487999 -0.681,0 -1.38299,-0.045 -2.10602,-0.134003 -0.72598,-0.089 -1.354,-0.207001 -1.88598,-0.353996 L 272.215,72.916 c 0.354,0.116997 0.746,0.213997 1.17602,0.288002 0.42798,0.073 0.81998,0.110001 1.17499,0.110001 1.12399,0 1.93701,-0.259003 2.44,-0.776001 0.50199,-0.518005 0.931,-1.249001 1.28601,-2.195 l 0.70999,-1.818001 -9.22699,-21.736 8.073,0 4.92398,14.195 0.133,0 4.392,-14.195 7.71802,0 -9.89301,25.417 z"
inkscape:connector-curvature="0"
style="fill:#2c3c69" />
<path
id="svg_13"
d="m 321.496,57.745003 c 0,1.537994 -0.237,3.016998 -0.70999,4.435997 -0.474,1.419998 -1.16101,2.668999 -2.06201,3.748001 -0.90201,1.080002 -2.004,1.945 -3.30499,2.596001 -1.30201,0.649002 -2.78,0.975998 -4.43702,0.975998 -1.35998,0 -2.64599,-0.273003 -3.85901,-0.82 -1.21301,-0.546997 -2.15799,-1.293999 -2.83898,-2.239998 l -0.088,0 0,13.085999 -7.27502,0 0,-32.739002 6.92001,0 0,2.706001 0.133,0 c 0.681,-0.887001 1.61899,-1.662998 2.81698,-2.328999 C 307.98801,46.5 309.39999,46.167 311.02701,46.167 c 1.59698,0 3.04498,0.311001 4.34698,0.931999 1.301,0.621002 2.40201,1.464001 3.305,2.528 0.90298,1.063999 1.59701,2.299999 2.08502,3.704002 0.488,1.404999 0.73199,2.876999 0.73199,4.414001 z m -7.05301,0 c 0,-0.709999 -0.11001,-1.403999 -0.332,-2.085003 -0.22201,-0.68 -0.548,-1.278999 -0.97699,-1.797001 -0.42901,-0.516998 -0.96902,-0.938 -1.61902,-1.264 -0.64999,-0.326 -1.40399,-0.487999 -2.26199,-0.487999 -0.828,0 -1.56799,0.162998 -2.21799,0.487999 -0.651,0.325001 -1.20602,0.754002 -1.664,1.285999 -0.45901,0.532001 -0.81302,1.139 -1.06402,1.818001 -0.25199,0.681004 -0.37699,1.375004 -0.37699,2.085003 0,0.709999 0.125,1.404999 0.37699,2.084999 0.251,0.681 0.60501,1.285995 1.06402,1.818001 0.45798,0.531998 1.013,0.961998 1.664,1.286995 0.64899,0.325005 1.38999,0.487 2.21799,0.487 0.85699,0 1.61099,-0.161995 2.26199,-0.487 0.651,-0.325005 1.19001,-0.754997 1.61902,-1.286995 0.42902,-0.531998 0.75498,-1.146004 0.97699,-1.841003 0.22101,-0.693001 0.332,-1.394997 0.332,-2.104996 z"
inkscape:connector-curvature="0"
style="fill:#2c3c69" />
<path
id="svg_14"
d="m 333.11801,52.200001 0,8.461002 c 0,1.038994 0.20001,1.816994 0.60001,2.337997 0.39798,0.519997 1.11499,0.778 2.151,0.778 0.354,0 0.73099,-0.028 1.13098,-0.089 0.39902,-0.05901 0.73102,-0.147003 0.99802,-0.266006 l 0.089,5.323006 c -0.50299,0.176994 -1.139,0.332001 -1.90698,0.465996 -0.77002,0.133003 -1.53802,0.199005 -2.307,0.199005 -1.47901,0 -2.72202,-0.186005 -3.72702,-0.556007 -1.00599,-0.369995 -1.81199,-0.903999 -2.417,-1.601997 -0.60699,-0.695999 -1.043,-1.526001 -1.30899,-2.489998 C 326.15302,63.799005 326.021,62.724 326.021,61.538003 l 0,-9.338001 -3.54898,0 0,-5.412003 3.50399,0 0,-5.810997 7.142,0 0,5.810997 5.19,0 0,5.412003 -5.19,0 z"
inkscape:connector-curvature="0"
style="fill:#2c3c69" />
</g>
</g>
<path
id="svg_15"
d="m 145.00999,36.869999 c -2.18299,0 -3.89199,1.573002 -3.89199,3.582001 0,2.116001 1.43899,3.536999 3.582,3.536999 0.183,0 0.35599,-0.017 0.51899,-0.05 -0.343,1.566002 -1.852,2.690002 -3.27799,2.915001 l -0.29001,0.046 0,3.376999 0.376,-0.036 c 1.73,-0.165001 3.439,-0.951 4.691,-2.157001 1.632,-1.572998 2.49501,-3.843998 2.49501,-6.568001 0,-2.691998 -1.76799,-4.646 -4.20301,-4.646 z"
inkscape:connector-curvature="0"
style="fill:#2c3c69" />
</g>
<g
id="svg_16">
<path
id="svg_17"
d="m 46.488998,37.568001 -8.039997,0 0,-4.128002 c 0,-3.296997 -2.683002,-5.979 -5.98,-5.979 -3.297001,0 -5.979,2.683002 -5.979,5.979 l 0,4.128002 -8.040001,0 0,-4.128002 c 0,-7.73 6.288998,-14.019999 14.02,-14.019999 7.731002,0 14.02,6.289 14.02,14.019999 l 0,4.128002 -0.001,0 z"
inkscape:connector-curvature="0"
style="fill:#f9a11d" />
</g>
<path
id="svg_18"
d="m 49.731998,37.568001 -34.524998,0 c -1.474001,0 -2.68,1.205997 -2.68,2.68 l 0,25.540001 c 0,1.473999 1.205999,2.68 2.68,2.68 l 34.524998,0 c 1.474003,0 2.68,-1.206001 2.68,-2.68 l 0,-25.540001 c 0,-1.474003 -1.205997,-2.68 -2.68,-2.68 z m -15.512997,16.769001 0,3.460995 c 0,0.966003 -0.784,1.749001 -1.749001,1.749001 -0.965001,0 -1.749001,-0.783997 -1.749001,-1.749001 l 0,-3.459995 c -1.076,-0.611 -1.803001,-1.764 -1.803001,-3.09 0,-1.962002 1.591,-3.552002 3.552002,-3.552002 1.961998,0 3.551998,1.591 3.551998,3.552002 0,1.325001 -0.727001,2.478001 -1.802998,3.089001 z"
inkscape:connector-curvature="0"
style="fill:#2c3c69" />
<path
id="svg_19"
d="m 11.707001,33.759998 -8.331,0 c -1.351001,0 -2.446,-1.094997 -2.446,-2.445999 0,-1.351002 1.094999,-2.445999 2.446,-2.445999 l 8.331,0 c 1.351,0 2.445999,1.095001 2.445999,2.445999 0,1.350998 -1.096001,2.445999 -2.445999,2.445999 z"
inkscape:connector-curvature="0"
style="fill:#f9a11d" />
<path
id="svg_20"
d="m 17.575001,20.655001 c -0.546001,0 -1.097,-0.182001 -1.552,-0.557001 l -6.59,-5.418999 C 8.39,13.820999 8.239001,12.280001 9.098,11.236 9.956,10.193001 11.497,10.042 12.541001,10.9 l 6.59,5.419001 c 1.042999,0.858 1.194,2.399 0.334999,3.442999 -0.483,0.589001 -1.184,0.893002 -1.890999,0.893002 z"
inkscape:connector-curvature="0"
style="fill:#f9a11d" />
<path
id="svg_21"
d="m 32.469002,14.895 c -1.351002,0 -2.446003,-1.095001 -2.446003,-2.446001 l 0,-8.396999 c 0,-1.351 1.095001,-2.446 2.446003,-2.446 1.351002,0 2.445999,1.095 2.445999,2.446 l 0,8.396999 c 0,1.351 -1.095001,2.446001 -2.445999,2.446001 z"
inkscape:connector-curvature="0"
style="fill:#f9a11d" />
<g
id="svg_22">
<g
id="svg_23">
<path
id="svg_24"
d="M 47.362999,20.655001 C 46.655998,20.655001 45.956001,20.351 45.472,19.761999 44.613998,18.719 44.764,17.177 45.806999,16.319 l 6.59,-5.419001 c 1.044003,-0.858 2.585003,-0.706999 3.442997,0.336 0.858002,1.042999 0.708,2.584999 -0.334999,3.443001 l -6.589996,5.418999 C 48.459999,20.472999 47.91,20.655 47.362999,20.655 z"
inkscape:connector-curvature="0"
style="fill:#f9a11d" />
</g>
</g>
<path
id="svg_25"
d="m 61.563004,33.759998 -8.410004,0 c -1.351002,0 -2.445999,-1.094997 -2.445999,-2.445999 0,-1.351002 1.094997,-2.445999 2.445999,-2.445999 l 8.410004,0 c 1.350998,0 2.445999,1.095001 2.445999,2.445999 0,1.350998 -1.095001,2.445999 -2.445999,2.445999 z"
inkscape:connector-curvature="0"
style="fill:#f9a11d" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

BIN
docs/img/mantl-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

5394
docs/img/overview.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 52 KiB

BIN
docs/img/traefik.icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
docs/img/traefik.logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
docs/img/zenika.logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

File diff suppressed because it is too large Load Diff

1529
docs/toml.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
# Clustering / High Availability
This guide explains how tu use Træfɪk in high availability mode.
In order to deploy and configure multiple Træfɪk instances, without copying the same configuration file on each instance, we will use a distributed Key-Value store.
## Prerequisites
You will need a working KV store cluster.
## File configuration to KV store migration
We created a special Træfɪk command to help configuring your Key Value store from a Træfɪk TOML configuration file.
Please refer to [this section](/user-guide/kv-config/#store-configuration-in-key-value-store) to get more details.
## Deploy a Træfɪk cluster
Once your Træfɪk configuration is uploaded on your KV store, you can start each Træfɪk instance.
A Træfɪk cluster is based on a master/slave model. When starting, Træfɪk will elect a master. If this instance fails, another master will be automatically elected.

133
docs/user-guide/examples.md Normal file
View File

@@ -0,0 +1,133 @@
# Examples
You will find here some configuration examples of Træfɪk.
## HTTP only
```
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":80"
```
## HTTP + HTTPS (with SNI)
```
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
CertFile = "integration/fixtures/https/snitest.com.cert"
KeyFile = "integration/fixtures/https/snitest.com.key"
[[entryPoints.https.tls.certificates]]
CertFile = "integration/fixtures/https/snitest.org.cert"
KeyFile = "integration/fixtures/https/snitest.org.key"
```
Note that we can either give path to certificate file or directly the file content itself ([like in this TOML example](/user-guide/kv-config/#upload-the-configuration-in-the-key-value-store)).
## HTTP redirect on HTTPS
```
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
certFile = "tests/traefik.crt"
keyFile = "tests/traefik.key"
```
## Let's Encrypt support
```
[entryPoints]
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
# certs used as default certs
[[entryPoints.https.tls.certificates]]
certFile = "tests/traefik.crt"
keyFile = "tests/traefik.key"
[acme]
email = "test@traefik.io"
storageFile = "acme.json"
onDemand = true
caServer = "http://172.18.0.1:4000/directory"
entryPoint = "https"
[[acme.domains]]
main = "local1.com"
sans = ["test1.local1.com", "test2.local1.com"]
[[acme.domains]]
main = "local2.com"
sans = ["test1.local2.com", "test2x.local2.com"]
[[acme.domains]]
main = "local3.com"
[[acme.domains]]
main = "local4.com"
```
## Override entrypoints in frontends
```
[frontends]
[frontends.frontend1]
backend = "backend2"
[frontends.frontend1.routes.test_1]
rule = "Host:test.localhost"
[frontends.frontend2]
backend = "backend1"
passHostHeader = true
entrypoints = ["https"] # overrides defaultEntryPoints
[frontends.frontend2.routes.test_1]
rule = "Host:{subdomain:[a-z]+}.localhost"
[frontends.frontend3]
entrypoints = ["http", "https"] # overrides defaultEntryPoints
backend = "backend2"
rule = "Path:/test"
```
## Enable Basic authentication in an entrypoint
With two user/pass:
- `test`:`test`
- `test2`:`test2`
Passwords are encoded in MD5: you can use htpasswd to generate those ones.
```
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.auth.basic]
users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"]
```
## Pass Authenticated user to application via headers
Providing an authentication method as described above, it is possible to pass the user to the application
via a configurable header value
```
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.auth]
headerField = "X-WebAuth-User"
[entryPoints.http.auth.basic]
users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"]
```

View File

@@ -0,0 +1,430 @@
# Kubernetes Ingress Controller
This guide explains how to use Træfɪk as an Ingress controller in a Kubernetes cluster.
If you are not familiar with Ingresses in Kubernetes you might want to read the [Kubernetes user guide](http://kubernetes.io/docs/user-guide/ingress/)
The config files used in this guide can be found in the [examples directory](https://github.com/containous/traefik/tree/master/examples/k8s)
## Prerequisites
1. A working Kubernetes cluster. If you want to follow along with this guide, you should setup [minikube](http://kubernetes.io/docs/getting-started-guides/minikube/)
on your machine, as it is the quickest way to get a local Kubernetes cluster setup for experimentation and development.
2. The `kubectl` binary should be [installed on your workstation](http://kubernetes.io/docs/getting-started-guides/minikube/#download-kubectl).
## Deploy Træfɪk
We are going to deploy Træfɪk with a
[Deployment](http://kubernetes.io/docs/user-guide/deployments/), as this will
allow you to easily roll out config changes or update the image.
```yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: traefik-ingress-controller
namespace: kube-system
labels:
k8s-app: traefik-ingress-lb
spec:
replicas: 1
selector:
matchLabels:
k8s-app: traefik-ingress-lb
template:
metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
terminationGracePeriodSeconds: 60
containers:
- image: traefik
name: traefik-ingress-lb
resources:
limits:
cpu: 200m
memory: 30Mi
requests:
cpu: 100m
memory: 20Mi
ports:
- containerPort: 80
hostPort: 80
- containerPort: 8080
args:
- --web
- --kubernetes
```
[examples/k8s/traefik.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/traefik.yaml)
> notice that we binding port 80 on the Træfɪk container to port 80 on the host.
> With a multi node cluster we might expose Træfɪk with a NodePort or LoadBalancer service
> and run more than 1 replica of Træfɪk for high availability.
To deploy Træfɪk to your cluster start by submitting the deployment to the cluster with `kubectl`:
```sh
kubectl apply -f examples/k8s/traefik.yaml
```
### Check the deployment
Now lets check if our deployment was successful.
Start by listing the pods in the `kube-system` namespace:
```sh
$kubectl --namespace=kube-system get pods
NAME READY STATUS RESTARTS AGE
kube-addon-manager-minikubevm 1/1 Running 0 4h
kubernetes-dashboard-s8krj 1/1 Running 0 4h
traefik-ingress-controller-678226159-eqseo 1/1 Running 0 7m
```
You should see that after submitting the Deployment to Kubernetes it has launched
a pod, and it is now running. _It might take a few moments for kubernetes to pull
the Træfɪk image and start the container._
> You could also check the deployment with the Kubernetes dashboard, run
> `minikube dashboard` to open it in your browser, then choose the `kube-system`
> namespace from the menu at the top right of the screen.
You should now be able to access Træfɪk on port 80 of your minikube instance.
```sh
curl $(minikube ip)
404 page not found
```
> We expect to see a 404 response here as we haven't yet given Træfɪk any configuration.
## Submitting An Ingress to the cluster.
Lets start by creating a Service and an Ingress that will expose the
[Træfɪk Web UI](https://github.com/containous/traefik#web-ui).
```yaml
apiVersion: v1
kind: Service
metadata:
name: traefik-web-ui
namespace: kube-system
spec:
selector:
k8s-app: traefik-ingress-lb
ports:
- port: 80
targetPort: 8080
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-web-ui
namespace: kube-system
spec:
rules:
- host: traefik-ui.local
http:
paths:
- backend:
serviceName: traefik-web-ui
servicePort: 80
```
[examples/k8s/ui.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/ui.yaml)
```sh
kubectl apply -f examples/k8s/ui.yaml
```
Now lets setup an entry in our /etc/hosts file to route `traefik-ui.local`
to our cluster.
> In production you would want to set up real dns entries.
> You can get the ip address of your minikube instance by running `minikube ip`
```
echo "$(minikube ip) traefik-ui.local" | sudo tee -a /etc/hosts
```
We should now be able to visit [traefik-ui.local](http://traefik-ui.local) in the browser and view the Træfɪk Web UI.
## Name based routing
In this example we are going to setup websites for 3 of the United Kingdoms
best loved cheeses, Cheddar, Stilton and Wensleydale.
First lets start by launching the 3 pods for the cheese websites.
```yaml
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: stilton
labels:
app: cheese
cheese: stilton
spec:
replicas: 2
selector:
matchLabels:
app: cheese
task: stilton
template:
metadata:
labels:
app: cheese
task: stilton
version: v0.0.1
spec:
containers:
- name: cheese
image: errm/cheese:stilton
resources:
requests:
cpu: 100m
memory: 50Mi
limits:
cpu: 100m
memory: 50Mi
ports:
- containerPort: 80
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: cheddar
labels:
app: cheese
cheese: cheddar
spec:
replicas: 2
selector:
matchLabels:
app: cheese
task: cheddar
template:
metadata:
labels:
app: cheese
task: cheddar
version: v0.0.1
spec:
containers:
- name: cheese
image: errm/cheese:cheddar
resources:
requests:
cpu: 100m
memory: 50Mi
limits:
cpu: 100m
memory: 50Mi
ports:
- containerPort: 80
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: wensleydale
labels:
app: cheese
cheese: wensleydale
spec:
replicas: 2
selector:
matchLabels:
app: cheese
task: wensleydale
template:
metadata:
labels:
app: cheese
task: wensleydale
version: v0.0.1
spec:
containers:
- name: cheese
image: errm/cheese:wensleydale
resources:
requests:
cpu: 100m
memory: 50Mi
limits:
cpu: 100m
memory: 50Mi
ports:
- containerPort: 80
```
[examples/k8s/cheese-deployments.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/cheese-deployments.yaml)
```sh
kubectl apply -f examples/k8s/cheese-deployments.yaml
```
Next we need to setup a service for each of the cheese pods.
```yaml
---
apiVersion: v1
kind: Service
metadata:
name: stilton
spec:
ports:
- name: http
targetPort: 80
port: 80
selector:
app: cheese
task: stilton
---
apiVersion: v1
kind: Service
metadata:
name: cheddar
spec:
ports:
- name: http
targetPort: 80
port: 80
selector:
app: cheese
task: cheddar
---
apiVersion: v1
kind: Service
metadata:
name: wensleydale
annotations:
traefik.backend.circuitbreaker: "NetworkErrorRatio() > 0.5"
spec:
ports:
- name: http
targetPort: 80
port: 80
selector:
app: cheese
task: wensleydale
```
> Notice that we also set a [circuit breaker expression](https://docs.traefik.io/basics/#backends) for one of the backends
> by setting the `traefik.backend.circuitbreaker` annotation on the service.
[examples/k8s/cheese-services.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/cheese-services.yaml)
```sh
kubectl apply -f examples/k8s/cheese-services.yaml
```
Now we can submit an ingress for the cheese websites.
```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cheese
spec:
rules:
- host: stilton.local
http:
paths:
- path: /
backend:
serviceName: stilton
servicePort: http
- host: cheddar.local
http:
paths:
- path: /
backend:
serviceName: cheddar
servicePort: http
- host: wensleydale.local
http:
paths:
- path: /
backend:
serviceName: wensleydale
servicePort: http
```
[examples/k8s/cheese-ingress.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/cheese-ingress.yaml)
> Notice that we list each hostname, and add a backend service.
```sh
kubectl apply -f examples/k8s/cheese-ingress.yaml
```
Now visit the [Træfɪk dashboard](http://traefik-ui.local/) and you should
see a frontend for each host. Along with a backend listing for each service
with a Server set up for each pod.
If you edit your `/etc/hosts` again you should be able to access the cheese
websites in your browser.
```sh
echo "$(minikube ip) stilton.local cheddar.local wensleydale.local" | sudo tee -a /etc/hosts
```
* [Stilton](http://stilton.local/)
* [Cheddar](http://cheddar.local/)
* [Wensleydale](http://wensleydale.local/)
## Path based routing
Now lets suppose that our fictional client has decided that while they are
super happy about our cheesy web design, when they asked for 3 websites
they had not really bargained on having to buy 3 domain names.
No problem, we say, why don't we reconfigure the sites to host all 3 under one domain.
```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cheeses
annotations:
traefik.frontend.rule.type: pathprefixstrip
spec:
rules:
- host: cheeses.local
http:
paths:
- path: /stilton
backend:
serviceName: stilton
servicePort: http
- path: /cheddar
backend:
serviceName: cheddar
servicePort: http
- path: /wensleydale
backend:
serviceName: wensleydale
servicePort: http
```
[examples/k8s/cheeses-ingress.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/cheeses-ingress.yaml)
> Notice that we are configuring Træfɪk to strip the prefix from the url path
> with the `traefik.frontend.rule.type` annotation so that we can use
> the containers from the previous example without modification.
```sh
kubectl apply -f examples/k8s/cheeses-ingress.yaml
```
```sh
echo "$(minikube ip) cheeses.local" | sudo tee -a /etc/hosts
```
You should now be able to visit the websites in your browser.
* [cheeses.local/stilton](http://cheeses.local/stilton/)
* [cheeses.local/cheddar](http://cheeses.local/cheddar/)
* [cheeses.local/wensleydale](http://cheeses.local/wensleydale/)

View File

@@ -0,0 +1,328 @@
# Key-value store configuration
Both [static global configuration](/user-guide/kv-config/#static-configuration-in-key-value-store) and [dynamic](/user-guide/kv-config/#dynamic-configuration-in-key-value-store) configuration can be sorted in a Key-value store.
This section explains how to launch Træfɪk using a configuration loaded from a Key-value store.
Træfɪk supports several Key-value stores:
- [Consul](https://consul.io)
- [etcd](https://coreos.com/etcd/)
- [ZooKeeper](https://zookeeper.apache.org/)
- [boltdb](https://github.com/boltdb/bolt)
# Static configuration in Key-value store
We will see the steps to set it up with an easy example.
Note that we could do the same with any other Key-value Store.
## docker-compose file for Consul
The Træfɪk global configuration will be getted from a [Consul](https://consul.io) store.
First we have to launch Consul in a container.
The [docker-compose file](https://docs.docker.com/compose/compose-file/) allows us to launch Consul and four instances of the trivial app [emilevauge/whoamI](https://github.com/emilevauge/whoamI) :
```yml
consul:
image: progrium/consul
command: -server -bootstrap -log-level debug -ui-dir /ui
ports:
- "8400:8400"
- "8500:8500"
- "8600:53/udp"
expose:
- "8300"
- "8301"
- "8301/udp"
- "8302"
- "8302/udp"
whoami1:
image: emilevauge/whoami
whoami2:
image: emilevauge/whoami
whoami3:
image: emilevauge/whoami
whoami4:
image: emilevauge/whoami
```
## Upload the configuration in the Key-value store
We should now fill the store with the Træfɪk global configuration, as we do with a [TOML file configuration](/toml).
To do that, we can send the Key-value pairs via [curl commands](https://www.consul.io/intro/getting-started/kv.html) or via the [Web UI](https://www.consul.io/intro/getting-started/ui.html).
Hopefully, Træfɪk allows automation of this process using the `storeconfig` subcommand.
Please refer to the [store Træfɪk configuration](/user-guide/kv-config/#store-configuration-in-key-value-store) section to get documentation on it.
Here is the toml configuration we would like to store in the Key-value Store :
```toml
logLevel = "DEBUG"
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
CertFile = "integration/fixtures/https/snitest.com.cert"
KeyFile = "integration/fixtures/https/snitest.com.key"
[[entryPoints.https.tls.certificates]]
CertFile = """-----BEGIN CERTIFICATE-----
<cert file content>
-----END CERTIFICATE-----"""
KeyFile = """-----BEGIN CERTIFICATE-----
<key file content>
-----END CERTIFICATE-----"""
[consul]
endpoint = "127.0.0.1:8500"
watch = true
prefix = "traefik"
[web]
address = ":8081"
```
And there, the same global configuration in the Key-value Store (using `prefix = "traefik"`):
| Key | Value |
|-----------------------------------------------------------|---------------------------------------------------------------|
| `/traefik/loglevel` | `DEBUG` |
| `/traefik/defaultentrypoints/0` | `http` |
| `/traefik/defaultentrypoints/1` | `https` |
| `/traefik/entrypoints/http/address` | `:80` |
| `/traefik/entrypoints/https/address` | `:443` |
| `/traefik/entrypoints/https/tls/certificates/0/certfile` | `integration/fixtures/https/snitest.com.cert` |
| `/traefik/entrypoints/https/tls/certificates/0/keyfile` | `integration/fixtures/https/snitest.com.key` |
| `/traefik/entrypoints/https/tls/certificates/1/certfile` | `--BEGIN CERTIFICATE--<cert file content>--END CERTIFICATE--` |
| `/traefik/entrypoints/https/tls/certificates/1/keyfile` | `--BEGIN CERTIFICATE--<key file content>--END CERTIFICATE--` |
| `/traefik/consul/endpoint` | `127.0.0.1:8500` |
| `/traefik/consul/watch` | `true` |
| `/traefik/consul/prefix` | `traefik` |
| `/traefik/web/address` | `:8081` |
In case you are setting key values manually,:
- Remember to specify the indexes (`0`,`1`, `2`, ... ) under prefixes `/traefik/defaultentrypoints/` and `/traefik/entrypoints/https/tls/certificates/` in order to match the global configuration structure.
- Be careful to give the correct IP address and port on the key `/traefik/consul/endpoint`.
Note that we can either give path to certificate file or directly the file content itself.
## Launch Træfɪk
We will now launch Træfɪk in a container.
We use CLI flags to setup the connection between Træfɪk and Consul.
All the rest of the global configuration is stored in Consul.
Here is the [docker-compose file](https://docs.docker.com/compose/compose-file/) :
```yml
traefik:
image: traefik
command: --consul --consul.endpoint=127.0.0.1:8500
ports:
- "80:80"
- "8080:8080"
```
NB : Be careful to give the correct IP address and port in the flag `--consul.endpoint`.
## TLS support
So far, only [Consul](https://consul.io) and [etcd](https://coreos.com/etcd/) support TLS connections.
To set it up, we should enable [consul security](https://www.consul.io/docs/internals/security.html) (or [etcd security](https://coreos.com/etcd/docs/latest/security.html)).
Then, we have to provide CA, Cert and Key to Træfɪk using `consul` flags :
- `--consul.tls`
- `--consul.tls.ca=path/to/the/file`
- `--consul.tls.cert=path/to/the/file`
- `--consul.tls.key=path/to/the/file`
Or etcd flags :
- `--etcd.tls`
- `--etcd.tls.ca=path/to/the/file`
- `--etcd.tls.cert=path/to/the/file`
- `--etcd.tls.key=path/to/the/file`
Note that we can either give directly directly the file content itself (instead of the path to certificate) in a TOML file configuration.
Remember the command `traefik --help` to display the updated list of flags.
# Dynamic configuration in Key-value store
Following our example, we will provide backends/frontends rules to Træfɪk.
Note that this section is independent of the way Træfɪk got its static configuration.
It means that the static configuration can either come from the same Key-value store or from any other sources.
## Key-value storage structure
Here is the toml configuration we would like to store in the store :
```toml
[file]
# rules
[backends]
[backends.backend1]
[backends.backend1.circuitbreaker]
expression = "NetworkErrorRatio() > 0.5"
[backends.backend1.servers.server1]
url = "http://172.17.0.2:80"
weight = 10
[backends.backend1.servers.server2]
url = "http://172.17.0.3:80"
weight = 1
[backends.backend2]
[backends.backend1.maxconn]
amount = 10
extractorfunc = "request.host"
[backends.backend2.LoadBalancer]
method = "drr"
[backends.backend2.servers.server1]
url = "http://172.17.0.4:80"
weight = 1
[backends.backend2.servers.server2]
url = "http://172.17.0.5:80"
weight = 2
[frontends]
[frontends.frontend1]
backend = "backend2"
[frontends.frontend1.routes.test_1]
rule = "Host:test.localhost"
[frontends.frontend2]
backend = "backend1"
passHostHeader = true
priority = 10
entrypoints = ["https"] # overrides defaultEntryPoints
[frontends.frontend2.routes.test_1]
rule = "Host:{subdomain:[a-z]+}.localhost"
[frontends.frontend3]
entrypoints = ["http", "https"] # overrides defaultEntryPoints
backend = "backend2"
rule = "Path:/test"
```
And there, the same dynamic configuration in a KV Store (using `prefix = "traefik"`):
- backend 1
| Key | Value |
|--------------------------------------------------------|-----------------------------|
| `/traefik/backends/backend1/circuitbreaker/expression` | `NetworkErrorRatio() > 0.5` |
| `/traefik/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` |
| `/traefik/backends/backend1/servers/server1/weight` | `10` |
| `/traefik/backends/backend1/servers/server2/url` | `http://172.17.0.3:80` |
| `/traefik/backends/backend1/servers/server2/weight` | `1` |
| `/traefik/backends/backend1/servers/server2/tags` | `api,helloworld` |
- backend 2
| Key | Value |
|-----------------------------------------------------|------------------------|
| `/traefik/backends/backend2/maxconn/amount` | `10` |
| `/traefik/backends/backend2/maxconn/extractorfunc` | `request.host` |
| `/traefik/backends/backend2/loadbalancer/method` | `drr` |
| `/traefik/backends/backend2/servers/server1/url` | `http://172.17.0.4:80` |
| `/traefik/backends/backend2/servers/server1/weight` | `1` |
| `/traefik/backends/backend2/servers/server2/url` | `http://172.17.0.5:80` |
| `/traefik/backends/backend2/servers/server2/weight` | `2` |
| `/traefik/backends/backend2/servers/server2/tags` | `web` |
- frontend 1
| Key | Value |
|---------------------------------------------------|-----------------------|
| `/traefik/frontends/frontend1/backend` | `backend2` |
| `/traefik/frontends/frontend1/routes/test_1/rule` | `Host:test.localhost` |
- frontend 2
| Key | Value |
|----------------------------------------------------|--------------------|
| `/traefik/frontends/frontend2/backend` | `backend1` |
| `/traefik/frontends/frontend2/passHostHeader` | `true` |
| `/traefik/frontends/frontend2/priority` | `10` |
| `/traefik/frontends/frontend2/entrypoints` | `http,https` |
| `/traefik/frontends/frontend2/routes/test_2/rule` | `PathPrefix:/test` |
## Atomic configuration changes
Træfɪk can watch the backends/frontends configuration changes and generate its configuration automatically.
Note that only backends/frontends rules are dynamic, the rest of the Træfɪk configuration stay static.
The [Etcd](https://github.com/coreos/etcd/issues/860) and [Consul](https://github.com/hashicorp/consul/issues/886) backends do not support updating multiple keys atomically. As a result, it may be possible for Træfɪk to read an intermediate configuration state despite judicious use of the `--providersThrottleDuration` flag. To solve this problem, Træfɪk supports a special key called `/traefik/alias`. If set, Træfɪk use the value as an alternative key prefix.
Given the key structure below, Træfɪk will use the `http://172.17.0.2:80` as its only backend (frontend keys have been omitted for brevity).
| Key | Value |
|-------------------------------------------------------------------------|-----------------------------|
| `/traefik/alias` | `/traefik_configurations/1` |
| `/traefik_configurations/1/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` |
| `/traefik_configurations/1/backends/backend1/servers/server1/weight` | `10` |
When an atomic configuration change is required, you may write a new configuration at an alternative prefix. Here, although the `/traefik_configurations/2/...` keys have been set, the old configuration is still active because the `/traefik/alias` key still points to `/traefik_configurations/1`:
| Key | Value |
|-------------------------------------------------------------------------|-----------------------------|
| `/traefik/alias` | `/traefik_configurations/1` |
| `/traefik_configurations/1/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` |
| `/traefik_configurations/1/backends/backend1/servers/server1/weight` | `10` |
| `/traefik_configurations/2/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` |
| `/traefik_configurations/2/backends/backend1/servers/server1/weight` | `5` |
| `/traefik_configurations/2/backends/backend1/servers/server2/url` | `http://172.17.0.3:80` |
| `/traefik_configurations/2/backends/backend1/servers/server2/weight` | `5` |
Once the `/traefik/alias` key is updated, the new `/traefik_configurations/2` configuration becomes active atomically. Here, we have a 50% balance between the `http://172.17.0.3:80` and the `http://172.17.0.4:80` hosts while no traffic is sent to the `172.17.0.2:80` host:
| Key | Value |
|-------------------------------------------------------------------------|-----------------------------|
| `/traefik/alias` | `/traefik_configurations/2` |
| `/traefik_configurations/1/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` |
| `/traefik_configurations/1/backends/backend1/servers/server1/weight` | `10` |
| `/traefik_configurations/2/backends/backend1/servers/server1/url` | `http://172.17.0.3:80` |
| `/traefik_configurations/2/backends/backend1/servers/server1/weight` | `5` |
| `/traefik_configurations/2/backends/backend1/servers/server2/url` | `http://172.17.0.4:80` |
| `/traefik_configurations/2/backends/backend1/servers/server2/weight` | `5` |
Note that Træfɪk *will not watch for key changes in the `/traefik_configurations` prefix*. It will only watch for changes in the `/traefik/alias`.
Further, if the `/traefik/alias` key is set, all other configuration with `/traefik/backends` or `/traefik/frontends` prefix are ignored.
# Store configuration in Key-value store
Don't forget to [setup the connection between Træfɪk and Key-value store](/user-guide/kv-config/#launch-trfk).
The static Træfɪk configuration in a key-value store can be automatically created and updated, using the [`storeconfig` subcommand](/basics/#commands).
```bash
$ traefik storeconfig [flags] ...
```
This command is here only to automate the [process which upload the configuration into the Key-value store](/user-guide/kv-config/#upload-the-configuration-in-the-key-value-store).
Træfɪk will not start but the [static configuration](/basics/#static-trfk-configuration) will be uploaded into the Key-value store.
If you configured ACME (Let's Encrypt), your registration account and your certificates will also be uploaded.
To upload your ACME certificates to the KV store, get your traefik TOML file and add the new `storage` option in the `acme` section:
```
[acme]
email = "test@traefik.io"
storage = "traefik/acme/account" # the key where to store your certificates in the KV store
storageFile = "acme.json" # your old certificates store
```
Call `traefik storeconfig` to upload your config in the KV store.
Then remove the line `storageFile = "acme.json"` from your TOML config file.
That's it!

View File

@@ -0,0 +1,307 @@
# Docker Swarm (mode) cluster
This section explains how to create a multi-host docker cluster with
swarm mode using [docker-machine](https://docs.docker.com/machine) and
how to deploy Træfɪk on it.
The cluster consists of:
- 3 servers
- 1 manager
- 2 workers
- 1 [overlay](https://docs.docker.com/engine/userguide/networking/dockernetworks/#an-overlay-network) network
(multi-host networking)
## Prerequisites
1. You will need to install [docker-machine](https://docs.docker.com/machine/)
2. You will need the latest [VirtualBox](https://www.virtualbox.org/wiki/Downloads)
## Cluster provisioning
First, let's create all the required nodes. It's a shorter version of
the [swarm tutorial](https://docs.docker.com/engine/swarm/swarm-tutorial/).
```sh
docker-machine create -d virtualbox manager
docker-machine create -d virtualbox worker1
docker-machine create -d virtualbox worker2
```
Then, let's setup the cluster, in order :
1. initialize the cluster
2. get the token for other host to join
3. on both workers, join the cluster with the token
```sh
docker-machine ssh manager "docker swarm init \
--listen-addr $(docker-machine ip manager) \
--advertise-addr $(docker-machine ip manager)"
export worker_token=$(docker-machine ssh manager "docker swarm \
join-token worker -q")
docker-machine ssh worker1 "docker swarm join \
--token=${worker_token} \
--listen-addr $(docker-machine ip worker1) \
--advertise-addr $(docker-machine ip worker1) \
$(docker-machine ip manager)"
docker-machine ssh worker2 "docker swarm join \
--token=${worker_token} \
--listen-addr $(docker-machine ip worker2) \
--advertise-addr $(docker-machine ip worker2) \
$(docker-machine ip manager)"
```
Let's validate the cluster is up and running.
```sh
docker-machine ssh manager docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
2a770ov9vixeadep674265u1n worker1 Ready Active
dbi3or4q8ii8elbws70g4hkdh * manager Ready Active Leader
esbhhy6vnqv90xomjaomdgy46 worker2 Ready Active
```
Finally, let's create a network for Træfik to use.
```sh
docker-machine ssh manager "docker network create --driver=overlay traefik-net"
```
## Deploy Træfik
Let's deploy Træfik as a docker service in our cluster. The only
requirement for Træfik to work with swarm mode is that it needs to run
on a manager node — we are going to use a
[constraint](https://docs.docker.com/engine/reference/commandline/service_create/#/specify-service-constraints-constraint) for
that.
```
docker-machine ssh manager "docker service create \
--name traefik \
--constraint=node.role==manager \
--publish 80:80 --publish 8080:8080 \
--mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
--network traefik-net \
traefik \
--docker \
--docker.swarmmode \
--docker.domain=traefik \
--docker.watch \
--web"
```
Let's explain this command:
- `--publish 80:80 --publish 8080:8080`: we publish port `80` and
`8080` on the cluster.
- `--constraint=node.role==manager`: we ask docker to schedule Træfik
on a manager node.
- `--mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock`:
we bind mount the docker socket where Træfik is scheduled to be able
to speak to the daemon.
- `--network traefik-net`: we attach the Træfik service (and thus
the underlying container) to the `traefik-net` network.
- `--docker`: enable docker backend, and `--docker.swarmmode` to
enable the swarm mode on Træfik.
- `--web`: activate the webUI on port 8080
## Deploy your apps
We can now deploy our app on the cluster,
here [whoami](https://github.com/emilevauge/whoami), a simple web
server in Go. We start 2 services, on the `traefik-net` network.
```sh
docker-machine ssh manager "docker service create \
--name whoami0 \
--label traefik.port=80 \
--network traefik-net \
emilevauge/whoami"
docker-machine ssh manager "docker service create \
--name whoami1 \
--label traefik.port=80 \
--network traefik-net \
--label traefik.backend.loadbalancer.sticky=true \
emilevauge/whoami"
```
Note that we set whoami1 to use sticky sessions (`--label traefik.backend.loadbalancer.sticky=true`). We'll demonstrate that later.
If using `docker stack deploy`, there is [a specific way that the labels must be defined in the docker-compose file](https://github.com/containous/traefik/issues/994#issuecomment-269095109).
Check that everything is scheduled and started:
```sh
docker-machine ssh manager "docker service ls"
ID NAME REPLICAS IMAGE COMMAND
ab046gpaqtln whoami0 1/1 emilevauge/whoami
cgfg5ifzrpgm whoami1 1/1 emilevauge/whoami
dtpl249tfghc traefik 1/1 traefik --docker --docker.swarmmode --docker.domain=traefik --docker.watch --web
```
## Access to your apps through Træfɪk
```sh
curl -H Host:whoami0.traefik http://$(docker-machine ip manager)
Hostname: 8147a7746e7a
IP: 127.0.0.1
IP: ::1
IP: 10.0.9.3
IP: fe80::42:aff:fe00:903
IP: 172.18.0.3
IP: fe80::42:acff:fe12:3
GET / HTTP/1.1
Host: 10.0.9.3:80
User-Agent: curl/7.35.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 192.168.99.1
X-Forwarded-Host: 10.0.9.3:80
X-Forwarded-Proto: http
X-Forwarded-Server: 8fbc39271b4c
curl -H Host:whoami1.traefik http://$(docker-machine ip manager)
Hostname: ba2c21488299
IP: 127.0.0.1
IP: ::1
IP: 10.0.9.4
IP: fe80::42:aff:fe00:904
IP: 172.18.0.2
IP: fe80::42:acff:fe12:2
GET / HTTP/1.1
Host: 10.0.9.4:80
User-Agent: curl/7.35.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 192.168.99.1
X-Forwarded-Host: 10.0.9.4:80
X-Forwarded-Proto: http
X-Forwarded-Server: 8fbc39271b4c
```
Note that as Træfik is published, you can access it from any machine
and not only the manager.
```sh
curl -H Host:whoami0.traefik http://$(docker-machine ip worker1)
Hostname: 8147a7746e7a
IP: 127.0.0.1
IP: ::1
IP: 10.0.9.3
IP: fe80::42:aff:fe00:903
IP: 172.18.0.3
IP: fe80::42:acff:fe12:3
GET / HTTP/1.1
Host: 10.0.9.3:80
User-Agent: curl/7.35.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 192.168.99.1
X-Forwarded-Host: 10.0.9.3:80
X-Forwarded-Proto: http
X-Forwarded-Server: 8fbc39271b4c
curl -H Host:whoami1.traefik http://$(docker-machine ip worker2)
Hostname: ba2c21488299
IP: 127.0.0.1
IP: ::1
IP: 10.0.9.4
IP: fe80::42:aff:fe00:904
IP: 172.18.0.2
IP: fe80::42:acff:fe12:2
GET / HTTP/1.1
Host: 10.0.9.4:80
User-Agent: curl/7.35.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 192.168.99.1
X-Forwarded-Host: 10.0.9.4:80
X-Forwarded-Proto: http
X-Forwarded-Server: 8fbc39271b4c
```
## Scale both services
```sh
docker-machine ssh manager "docker service scale whoami0=5"
docker-machine ssh manager "docker service scale whoami1=5"
```
Check that we now have 5 replicas of each `whoami` service:
```sh
docker-machine ssh manager "docker service ls"
ID NAME REPLICAS IMAGE COMMAND
ab046gpaqtln whoami0 5/5 emilevauge/whoami
cgfg5ifzrpgm whoami1 5/5 emilevauge/whoami
dtpl249tfghc traefik 1/1 traefik --docker --docker.swarmmode --docker.domain=traefik --docker.watch --web
```
## Access to your whoami0 through Træfɪk multiple times.
Repeat the following command multiple times and note that the Hostname changes each time as Traefik load balances each request against the 5 tasks.
```sh
curl -H Host:whoami0.traefik http://$(docker-machine ip manager)
Hostname: 8147a7746e7a
IP: 127.0.0.1
IP: ::1
IP: 10.0.9.3
IP: fe80::42:aff:fe00:903
IP: 172.18.0.3
IP: fe80::42:acff:fe12:3
GET / HTTP/1.1
Host: 10.0.9.3:80
User-Agent: curl/7.35.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 192.168.99.1
X-Forwarded-Host: 10.0.9.3:80
X-Forwarded-Proto: http
X-Forwarded-Server: 8fbc39271b4c
```
Do the same against whoami1.
```sh
curl -H Host:whoami1.traefik http://$(docker-machine ip manager)
Hostname: ba2c21488299
IP: 127.0.0.1
IP: ::1
IP: 10.0.9.4
IP: fe80::42:aff:fe00:904
IP: 172.18.0.2
IP: fe80::42:acff:fe12:2
GET / HTTP/1.1
Host: 10.0.9.4:80
User-Agent: curl/7.35.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 192.168.99.1
X-Forwarded-Host: 10.0.9.4:80
X-Forwarded-Proto: http
X-Forwarded-Server: 8fbc39271b4c
```
Wait, I thought we added the sticky flag to whoami1? Traefik relies on a cookie to maintain stickyness so you'll need to test this with a browser.
First you need to add whoami1.traefik to your hosts file:
```ssh
if [ -n "$(grep whoami1.traefik /etc/hosts)" ];
then
echo "whoami1.traefik already exists (make sure the ip is current)";
else
sudo -- sh -c -e "echo '$(docker-machine ip manager)\twhoami1.traefik'
>> /etc/hosts";
fi
```
Now open your browser and go to http://whoami1.traefik/
You will now see that stickyness is maintained.
![](http://i.giphy.com/ujUdrdpX7Ok5W.gif)

170
docs/user-guide/swarm.md Normal file
View File

@@ -0,0 +1,170 @@
# Swarm cluster
This section explains how to create a multi-host [swarm](https://docs.docker.com/swarm) cluster using [docker-machine](https://docs.docker.com/machine/) and how to deploy Træfɪk on it.
The cluster consists of:
- 2 servers
- 1 swarm master
- 2 swarm nodes
- 1 [overlay](https://docs.docker.com/engine/userguide/networking/dockernetworks/#an-overlay-network) network (multi-host networking)
## Prerequisites
1. You need to install [docker-machine](https://docs.docker.com/machine/)
2. You need the latest [VirtualBox](https://www.virtualbox.org/wiki/Downloads)
## Cluster provisioning
We first follow [this guide](https://docs.docker.com/engine/userguide/networking/get-started-overlay/) to create the cluster.
### Create machine `mh-keystore`
This machine is the service registry of our cluster.
```sh
docker-machine create -d virtualbox mh-keystore
```
Then we install the service registry [Consul](https://consul.io) on this machine:
```sh
eval "$(docker-machine env mh-keystore)"
docker run -d \
-p "8500:8500" \
-h "consul" \
progrium/consul -server -bootstrap
```
### Create machine `mhs-demo0`
This machine is a swarm master and a swarm agent on it.
```sh
docker-machine create -d virtualbox \
--swarm --swarm-master \
--swarm-discovery="consul://$(docker-machine ip mh-keystore):8500" \
--engine-opt="cluster-store=consul://$(docker-machine ip mh-keystore):8500" \
--engine-opt="cluster-advertise=eth1:2376" \
mhs-demo0
```
### Create machine `mhs-demo1`
This machine have a swarm agent on it.
```sh
docker-machine create -d virtualbox \
--swarm \
--swarm-discovery="consul://$(docker-machine ip mh-keystore):8500" \
--engine-opt="cluster-store=consul://$(docker-machine ip mh-keystore):8500" \
--engine-opt="cluster-advertise=eth1:2376" \
mhs-demo1
```
### Create the overlay Network
Create the overlay network on the swarm master:
```sh
eval $(docker-machine env --swarm mhs-demo0)
docker network create --driver overlay --subnet=10.0.9.0/24 my-net
```
## Deploy Træfɪk
Deploy Træfɪk:
```sh
docker $(docker-machine config mhs-demo0) run \
-d \
-p 80:80 -p 8080:8080 \
--net=my-net \
-v /var/lib/boot2docker/:/ssl \
traefik \
-l DEBUG \
-c /dev/null \
--docker \
--docker.domain=traefik \
--docker.endpoint=tcp://$(docker-machine ip mhs-demo0):3376 \
--docker.tls \
--docker.tls.ca=/ssl/ca.pem \
--docker.tls.cert=/ssl/server.pem \
--docker.tls.key=/ssl/server-key.pem \
--docker.tls.insecureSkipVerify \
--docker.watch \
--web
```
Let's explain this command:
- `-p 80:80 -p 8080:8080`: we bind ports 80 and 8080
- `--net=my-net`: run the container on the network my-net
- `-v /var/lib/boot2docker/:/ssl`: mount the ssl keys generated by docker-machine
- `-c /dev/null`: empty config file
- `--docker`: enable docker backend
- `--docker.endpoint=tcp://172.18.0.1:3376`: connect to the swarm master using the docker_gwbridge network
- `--docker.tls`: enable TLS using the docker-machine keys
- `--web`: activate the webUI on port 8080
## Deploy your apps
We can now deploy our app on the cluster, here [whoami](https://github.com/emilevauge/whoami), a simple web server in GO, on the network `my-net`:
```sh
eval $(docker-machine env --swarm mhs-demo0)
docker run -d --name=whoami0 --net=my-net --env="constraint:node==mhs-demo0" emilevauge/whoami
docker run -d --name=whoami1 --net=my-net --env="constraint:node==mhs-demo1" emilevauge/whoami
```
Check that everything is started:
```sh
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ba2c21488299 emilevauge/whoami "/whoamI" 8 seconds ago Up 9 seconds 80/tcp mhs-demo1/whoami1
8147a7746e7a emilevauge/whoami "/whoamI" 19 seconds ago Up 20 seconds 80/tcp mhs-demo0/whoami0
8fbc39271b4c traefik "/traefik -l DEBUG -c" 36 seconds ago Up 37 seconds 192.168.99.101:80->80/tcp, 192.168.99.101:8080->8080/tcp mhs-demo0/serene_bhabha
```
## Access to your apps through Træfɪk
```sh
curl -H Host:whoami0.traefik http://$(docker-machine ip mhs-demo0)
Hostname: 8147a7746e7a
IP: 127.0.0.1
IP: ::1
IP: 10.0.9.3
IP: fe80::42:aff:fe00:903
IP: 172.18.0.3
IP: fe80::42:acff:fe12:3
GET / HTTP/1.1
Host: 10.0.9.3:80
User-Agent: curl/7.35.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 192.168.99.1
X-Forwarded-Host: 10.0.9.3:80
X-Forwarded-Proto: http
X-Forwarded-Server: 8fbc39271b4c
curl -H Host:whoami1.traefik http://$(docker-machine ip mhs-demo0)
Hostname: ba2c21488299
IP: 127.0.0.1
IP: ::1
IP: 10.0.9.4
IP: fe80::42:aff:fe00:904
IP: 172.18.0.2
IP: fe80::42:acff:fe12:2
GET / HTTP/1.1
Host: 10.0.9.4:80
User-Agent: curl/7.35.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 192.168.99.1
X-Forwarded-Host: 10.0.9.4:80
X-Forwarded-Proto: http
X-Forwarded-Server: 8fbc39271b4c
```
![](http://i.giphy.com/ujUdrdpX7Ok5W.gif)

2
examples/accessLog/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
exampleHandler
exampleHandler.exe

View File

@@ -0,0 +1,46 @@
/*
Simple program to start a web server on a specified port
*/
package main
import (
"flag"
"fmt"
"net/http"
"os"
)
var (
name string
port int
help *bool
)
func init() {
flag.StringVar(&name, "n", "", "Name of handler for messages")
flag.IntVar(&port, "p", 0, "Port number to listen")
help = flag.Bool("h", false, "Displays help message")
}
func usage() {
fmt.Printf("Usage: example -n name -p port \n")
os.Exit(2)
}
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%s: Received query %s!\n", name, r.URL.Path[1:])
}
func main() {
flag.Parse()
if *help || len(name) == 0 || port <= 0 {
usage()
}
http.HandleFunc("/", handler)
fmt.Printf("%s: Listening on :%d...\n", name, port)
if er := http.ListenAndServe(fmt.Sprintf(":%d", port), nil); er != nil {
fmt.Printf("%s: Error from ListenAndServe: %s", name, er.Error())
os.Exit(1)
}
fmt.Printf("%s: How'd we get past listen and serve???\n", name)
}

122
examples/accessLog/runAb.sh Executable file
View File

@@ -0,0 +1,122 @@
#!/bin/bash
usage()
{
echo 'runAb.sh - Run Apache Benchmark to test access log'
echo ' Usage: runAb.sh [--conn nnn] [--log xxx] [--num nnn] [--time nnn] [--wait nn]'
echo ' -c|--conn - number of simultaneous connections (default 100)'
echo ' -l|--log - name of logfile (default benchmark.log)'
echo ' -n|--num - number of requests (default 50000); ignored when -t specified'
echo ' -t|--time - time in seconds for benchmark (default no limit)'
echo ' -w|--wait - number of seconds to wait for Traefik to initialize (default 15)'
echo ' '
exit
}
# Parse options
conn=100
num=50000
wait=15
time=0
logfile=""
while [[ $1 =~ ^- ]]
do
case $1 in
-c|--conn)
conn=$2
shift
;;
-h|--help)
usage
;;
-l|--log|--logfile)
logfile=$2
shift
;;
-n|--num)
num=$2
shift
;;
-t|--time)
time=$2
shift
;;
-w|--wait)
wait=$2
shift
;;
*)
echo Unknown option "$1"
usage
esac
shift
done
if [ -z "$logfile" ] ; then
logfile="benchmark.log"
fi
# Change to accessLog examples directory
[ -d examples/accessLog ] && cd examples/accessLog
if [ ! -r exampleHandler.go ] ; then
echo Please run this script either from the traefik repo root or from the examples/accessLog directory
exit
fi
# Kill traefik and any running example processes
sudo pkill -f traefik
pkill -f exampleHandler
[ ! -d log ] && mkdir log
# Start new example processes
go build exampleHandler.go
[ $? -ne 0 ] && exit $?
./exampleHandler -n Handler1 -p 8081 &
[ $? -ne 0 ] && exit $?
./exampleHandler -n Handler2 -p 8082 &
[ $? -ne 0 ] && exit $?
./exampleHandler -n Handler3 -p 8083 &
[ $? -ne 0 ] && exit $?
# Wait a couple of seconds for handlers to initialize and start Traefik
cd ../..
sleep 2s
echo Starting Traefik...
sudo ./traefik -c examples/accessLog/traefik.ab.toml &
[ $? -ne 0 ] && exit $?
# Wait for Traefik to initialize and run ab
echo Waiting $wait seconds before starting ab benchmark
sleep ${wait}s
echo
stime=`date '+%s'`
if [ $time -eq 0 ] ; then
echo Benchmark starting `date` with $conn connections until $num requests processed | tee $logfile
echo | tee -a $logfile
echo ab -k -c $conn -n $num http://127.0.0.1/test | tee -a $logfile
echo | tee -a $logfile
ab -k -c $conn -n $num http://127.0.0.1/test 2>&1 | tee -a $logfile
else
if [ $num -ne 50000 ] ; then
echo Request count ignored when --time specified
fi
echo Benchmark starting `date` with $conn connections for $time seconds | tee $logfile
echo | tee -a $logfile
echo ab -k -c $conn -t $time -n 100000000 http://127.0.0.1/test | tee -a $logfile
echo | tee -a $logfile
ab -k -c $conn -t $time -n 100000000 http://127.0.0.1/test 2>&1 | tee -a $logfile
fi
etime=`date '+%s'`
let "dt=$etime - $stime"
let "ds=$dt % 60"
let "dm=($dt / 60) % 60"
let "dh=$dt / 3600"
echo | tee -a $logfile
printf "Benchmark ended `date` after %d:%02d:%02d\n" $dh $dm $ds | tee -a $logfile
echo Results available in $logfile

View File

@@ -0,0 +1,40 @@
#!/bin/bash
# Script to run a three-server example. This script runs the three servers and restarts Traefik
# Once it is running, use the command:
#
# curl http://127.0.0.1:80/test{1,2,2}
#
# to send requests to send test requests to the servers. You should see a response like:
#
# Handler1: received query test1!
# Handler2: received query test2!
# Handler3: received query test2!
#
# and can then inspect log/access.log to see frontend, backend, and timing
# Kill traefik and any running example processes
sudo pkill -f traefik
pkill -f exampleHandler
[ ! -d log ] && mkdir log
# Start new example processes
cd examples/accessLog
go build exampleHandler.go
[ $? -ne 0 ] && exit $?
./exampleHandler -n Handler1 -p 8081 &
[ $? -ne 0 ] && exit $?
./exampleHandler -n Handler2 -p 8082 &
[ $? -ne 0 ] && exit $?
./exampleHandler -n Handler3 -p 8083 &
[ $? -ne 0 ] && exit $?
# Wait a couple of seconds for handlers to initialize and start Traefik
cd ../..
sleep 2s
echo Starting Traefik...
sudo ./traefik -c examples/accessLog/traefik.example.toml &
[ $? -ne 0 ] && exit $?
echo Sample handlers and traefik started successfully!
echo 'Use command curl http://127.0.0.1:80/test{1,2,2} to drive test'
echo Then inspect log/access.log to verify it contains frontend, backend, and timing

View File

@@ -0,0 +1,37 @@
################################################################
# Global configuration
################################################################
traefikLogsFile = "log/traefik.log"
accessLogsFile = "log/access.log"
logLevel = "DEBUG"
################################################################
# Web configuration backend
################################################################
[web]
address = ":7888"
################################################################
# File configuration backend
################################################################
[file]
################################################################
# rules
################################################################
[backends]
[backends.backend]
[backends.backend.LoadBalancer]
method = "drr"
[backends.backend.servers.server1]
url = "http://127.0.0.1:8081"
[backends.backend.servers.server2]
url = "http://127.0.0.1:8082"
[backends.backend.servers.server3]
url = "http://127.0.0.1:8083"
[frontends]
[frontends.frontend]
backend = "backend"
passHostHeader = true
[frontends.frontend.routes.test]
rule = "Path: /test"

View File

@@ -0,0 +1,42 @@
################################################################
# Global configuration
################################################################
traefikLogsFile = "log/traefik.log"
accessLogsFile = "log/access.log"
logLevel = "DEBUG"
################################################################
# Web configuration backend
################################################################
[web]
address = ":7888"
################################################################
# File configuration backend
################################################################
[file]
################################################################
# rules
################################################################
[backends]
[backends.backend1]
[backends.backend1.servers.server1]
url = "http://127.0.0.1:8081"
[backends.backend2]
[backends.backend2.LoadBalancer]
method = "drr"
[backends.backend2.servers.server1]
url = "http://127.0.0.1:8082"
[backends.backend2.servers.server2]
url = "http://127.0.0.1:8083"
[frontends]
[frontends.frontend1]
backend = "backend1"
[frontends.frontend1.routes.test_1]
rule = "Path: /test1"
[frontends.frontend2]
backend = "backend2"
passHostHeader = true
[frontends.frontend2.routes.test_2]
rule = "Path: /test2"

View File

@@ -0,0 +1,25 @@
version: '2'
services:
consul:
image: progrium/consul
command: -server -bootstrap -advertise 12.0.0.254 -log-level debug -ui-dir /ui
ports:
- "8400:8400"
- "8500:8500"
- "8600:53/udp"
expose:
- "8300"
- "8301"
- "8301/udp"
- "8302"
- "8302/udp"
registrator:
depends_on:
- consul
image: gliderlabs/registrator:master
command: -internal consul://consul:8500
volumes:
- /var/run/docker.sock:/tmp/docker.sock
links:
- consul

View File

@@ -0,0 +1,4 @@
etcd:
image: gcr.io/google_containers/etcd:2.2.1
net: host
command: ['/usr/local/bin/etcd', '--addr=127.0.0.1:2379', '--bind-addr=0.0.0.0:2379', '--data-dir=/var/etcd/data']

11
examples/compose-k8s.yaml Normal file
View File

@@ -0,0 +1,11 @@
kubelet:
image: gcr.io/google_containers/hyperkube-amd64:v1.5.2
privileged: true
pid: host
net : host
volumes:
- /sys:/sys:rw
- /var/lib/docker/:/var/lib/docker:rw
- /var/lib/kubelet/:/var/lib/kubelet:rw,shared
- /var/run:/var/run:rw
command: ['/hyperkube', 'kubelet', '--hostname-override=127.0.0.1', '--api-servers=http://localhost:8080', '--config=/etc/kubernetes/manifests', '--allow-privileged=true', '--v=2', '--cluster-dns=10.0.0.10', '--cluster-domain=cluster.local']

View File

@@ -0,0 +1,59 @@
version: '2'
services:
zookeeper:
image: netflixoss/exhibitor:1.5.2
hostname: zookeeper
ports:
- "2181:2181"
mesos-master:
image: mesosphere/marathon:v1.2.0-RC6
hostname: mesos-master
entrypoint: [ "mesos-master" ]
ports:
- "5050:5050"
links:
- zookeeper
environment:
- MESOS_CLUSTER=local
- MESOS_HOSTNAME=mesos-master.docker
- MESOS_LOG_DIR=/var/log
- MESOS_WORK_DIR=/var/lib/mesos
- MESOS_QUORUM=1
- MESOS_ZK=zk://zookeeper:2181/mesos
mesos-slave:
image: mesosphere/mesos-slave-dind:0.2.4_mesos-0.27.2_docker-1.8.2_ubuntu-14.04.4
entrypoint:
- mesos-slave
privileged: true
hostname: mesos-slave
ports:
- "5051:5051"
links:
- zookeeper
- mesos-master
environment:
- 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]
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
marathon:
image: mesosphere/marathon:v1.2.0-RC6
ports:
- "8080:8080"
links:
- zookeeper
- mesos-master
extra_hosts:
- "mesos-slave:172.17.0.1"
environment:
- MARATHON_ZK=zk://zookeeper:2181/marathon
- MARATHON_MASTER=zk://zookeeper:2181/mesos

View File

@@ -0,0 +1,10 @@
traefik:
image: traefik
command: --web --rancher --rancher.domain=rancher.localhost --logLevel=DEBUG
labels:
io.rancher.container.agent.role: environment
io.rancher.container.create_agent: 'true'
ports:
- "80:80"
- "443:443"
- "8080:8080"

View File

@@ -0,0 +1,20 @@
traefik:
image: traefik
command: -c /dev/null --web --docker --docker.domain=docker.localhost --logLevel=DEBUG
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
whoami1:
image: emilevauge/whoami
labels:
- "traefik.backend=whoami"
- "traefik.frontend.rule=Host:whoami.docker.localhost"
whoami2:
image: emilevauge/whoami
labels:
- "traefik.backend=whoami"
- "traefik.frontend.rule=Host:whoami.docker.localhost"

View File

@@ -16,10 +16,10 @@ curl -i -H "Accept: application/json" -X PUT -d "2" ht
# frontend 1
curl -i -H "Accept: application/json" -X PUT -d "backend2" http://localhost:8500/v1/kv/traefik/frontends/frontend1/backend
curl -i -H "Accept: application/json" -X PUT -d "Host" http://localhost:8500/v1/kv/traefik/frontends/frontend1/routes/test_1/rule
curl -i -H "Accept: application/json" -X PUT -d "test.localhost" http://localhost:8500/v1/kv/traefik/frontends/frontend1/routes/test_1/value
curl -i -H "Accept: application/json" -X PUT -d "http" http://localhost:8500/v1/kv/traefik/frontends/frontend1/entrypoints
curl -i -H "Accept: application/json" -X PUT -d "Host:test.localhost" http://localhost:8500/v1/kv/traefik/frontends/frontend1/routes/test_1/rule
# frontend 2
curl -i -H "Accept: application/json" -X PUT -d "backend1" http://localhost:8500/v1/kv/traefik/frontends/frontend2/backend
curl -i -H "Accept: application/json" -X PUT -d "Path" http://localhost:8500/v1/kv/traefik/frontends/frontend2/routes/test_2/rule
curl -i -H "Accept: application/json" -X PUT -d "/test" http://localhost:8500/v1/kv/traefik/frontends/frontend2/routes/test_2/value
curl -i -H "Accept: application/json" -X PUT -d "http" http://localhost:8500/v1/kv/traefik/frontends/frontend2/entrypoints
curl -i -H "Accept: application/json" -X PUT -d "Path:/test" http://localhost:8500/v1/kv/traefik/frontends/frontend2/routes/test_2/rule

25
examples/etcd-config.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/sh
# backend 1
curl -i -H "Accept: application/json" -X PUT -d value="NetworkErrorRatio() > 0.5" http://localhost:2379/v2/keys/traefik/backends/backend1/circuitbreaker/expression
curl -i -H "Accept: application/json" -X PUT -d value="http://172.17.0.2:80" http://localhost:2379/v2/keys/traefik/backends/backend1/servers/server1/url
curl -i -H "Accept: application/json" -X PUT -d value="10" http://localhost:2379/v2/keys/traefik/backends/backend1/servers/server1/weight
curl -i -H "Accept: application/json" -X PUT -d value="http://172.17.0.3:80" http://localhost:2379/v2/keys/traefik/backends/backend1/servers/server2/url
curl -i -H "Accept: application/json" -X PUT -d value="1" http://localhost:2379/v2/keys/traefik/backends/backend1/servers/server2/weight
# backend 2
curl -i -H "Accept: application/json" -X PUT -d value="drr" http://localhost:2379/v2/keys/traefik/backends/backend2/loadbalancer/method
curl -i -H "Accept: application/json" -X PUT -d value="http://172.17.0.4:80" http://localhost:2379/v2/keys/traefik/backends/backend2/servers/server1/url
curl -i -H "Accept: application/json" -X PUT -d value="1" http://localhost:2379/v2/keys/traefik/backends/backend2/servers/server1/weight
curl -i -H "Accept: application/json" -X PUT -d value="http://172.17.0.5:80" http://localhost:2379/v2/keys/traefik/backends/backend2/servers/server2/url
curl -i -H "Accept: application/json" -X PUT -d value="2" http://localhost:2379/v2/keys/traefik/backends/backend2/servers/server2/weight
# frontend 1
curl -i -H "Accept: application/json" -X PUT -d value="backend2" http://localhost:2379/v2/keys/traefik/frontends/frontend1/backend
curl -i -H "Accept: application/json" -X PUT -d value="http" http://localhost:2379/v2/keys/traefik/frontends/frontend1/entrypoints
curl -i -H "Accept: application/json" -X PUT -d value="Host:test.localhost" http://localhost:2379/v2/keys/traefik/frontends/frontend1/routes/test_1/rule
# frontend 2
curl -i -H "Accept: application/json" -X PUT -d value="backend1" http://localhost:2379/v2/keys/traefik/frontends/frontend2/backend
curl -i -H "Accept: application/json" -X PUT -d value="http" http://localhost:2379/v2/keys/traefik/frontends/frontend2/entrypoints
curl -i -H "Accept: application/json" -X PUT -d value="Path:/test" http://localhost:2379/v2/keys/traefik/frontends/frontend2/routes/test_2/rule

6
examples/k8s.namespace.yaml Executable file
View File

@@ -0,0 +1,6 @@
kind: Namespace
apiVersion: v1
metadata:
name: kube-system
labels:
name: kube-system

View File

@@ -0,0 +1,99 @@
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: stilton
labels:
app: cheese
cheese: stilton
spec:
replicas: 2
selector:
matchLabels:
app: cheese
task: stilton
template:
metadata:
labels:
app: cheese
task: stilton
version: v0.0.1
spec:
containers:
- name: cheese
image: errm/cheese:stilton
resources:
requests:
cpu: 100m
memory: 50Mi
limits:
cpu: 100m
memory: 50Mi
ports:
- containerPort: 80
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: cheddar
labels:
app: cheese
cheese: cheddar
spec:
replicas: 2
selector:
matchLabels:
app: cheese
task: cheddar
template:
metadata:
labels:
app: cheese
task: cheddar
version: v0.0.1
spec:
containers:
- name: cheese
image: errm/cheese:cheddar
resources:
requests:
cpu: 100m
memory: 50Mi
limits:
cpu: 100m
memory: 50Mi
ports:
- containerPort: 80
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: wensleydale
labels:
app: cheese
cheese: wensleydale
spec:
replicas: 2
selector:
matchLabels:
app: cheese
task: wensleydale
template:
metadata:
labels:
app: cheese
task: wensleydale
version: v0.0.1
spec:
containers:
- name: cheese
image: errm/cheese:wensleydale
resources:
requests:
cpu: 100m
memory: 50Mi
limits:
cpu: 100m
memory: 50Mi
ports:
- containerPort: 80

View File

@@ -0,0 +1,27 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cheese
spec:
rules:
- host: stilton.local
http:
paths:
- path: /
backend:
serviceName: stilton
servicePort: http
- host: cheddar.local
http:
paths:
- path: /
backend:
serviceName: cheddar
servicePort: http
- host: wensleydale.local
http:
paths:
- path: /
backend:
serviceName: wensleydale
servicePort: http

View File

@@ -0,0 +1,39 @@
---
apiVersion: v1
kind: Service
metadata:
name: stilton
spec:
ports:
- name: http
targetPort: 80
port: 80
selector:
app: cheese
task: stilton
---
apiVersion: v1
kind: Service
metadata:
name: cheddar
spec:
ports:
- name: http
targetPort: 80
port: 80
selector:
app: cheese
task: cheddar
---
apiVersion: v1
kind: Service
metadata:
name: wensleydale
spec:
ports:
- name: http
targetPort: 80
port: 80
selector:
app: cheese
task: wensleydale

View File

@@ -0,0 +1,23 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cheeses
annotations:
traefik.frontend.rule.type: pathprefixstrip
spec:
rules:
- host: cheeses.local
http:
paths:
- path: /stilton
backend:
serviceName: stilton
servicePort: http
- path: /cheddar
backend:
serviceName: cheddar
servicePort: http
- path: /wensleydale
backend:
serviceName: wensleydale
servicePort: http

42
examples/k8s/traefik.yaml Normal file
View File

@@ -0,0 +1,42 @@
apiVersion: v1
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: traefik-ingress-controller
namespace: kube-system
labels:
k8s-app: traefik-ingress-lb
spec:
replicas: 1
selector:
matchLabels:
k8s-app: traefik-ingress-lb
template:
metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
terminationGracePeriodSeconds: 60
hostNetwork: true
containers:
- image: traefik
name: traefik-ingress-lb
resources:
limits:
cpu: 200m
memory: 30Mi
requests:
cpu: 100m
memory: 20Mi
ports:
- name: http
containerPort: 80
hostPort: 80
- name: admin
containerPort: 8081
args:
- -d
- --web
- --web.address=:8081
- --kubernetes

28
examples/k8s/ui.yaml Normal file
View File

@@ -0,0 +1,28 @@
---
apiVersion: v1
kind: Service
metadata:
name: traefik-web-ui
namespace: kube-system
spec:
selector:
k8s-app: traefik-ingress-lb
ports:
- name: web
port: 80
targetPort: 8081
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-web-ui
namespace: kube-system
spec:
rules:
- host: traefik-ui.local
http:
paths:
- path: /
backend:
serviceName: traefik-web-ui
servicePort: web

View File

@@ -0,0 +1,40 @@
{
"id": "/foo",
"groups": [
{
"id": "/foo/bar",
"apps": [
{
"id": "whoami",
"cpus": 0.1,
"mem": 64.0,
"instances": 3,
"container": {
"type": "DOCKER",
"docker": {
"image": "emilevauge/whoami",
"network": "BRIDGE",
"portMappings": [
{
"containerPort": 80,
"hostPort": 0,
"protocol": "tcp"
}
]
}
},
"healthChecks": [
{
"protocol": "HTTP",
"portIndex": 0,
"path": "/",
"gracePeriodSeconds": 5,
"intervalSeconds": 20,
"maxConsecutiveFailures": 3
}
]
}
]
}
]
}

View File

@@ -10,14 +10,7 @@
"network": "BRIDGE",
"portMappings": [
{ "containerPort": 80, "hostPort": 0, "protocol": "tcp" }
],
"parameters": [{
"key": "log-driver",
"value": "gelf"
}, {
"key": "log-opt",
"value": "gelf-address=udp://172.17.42.1:12201"
}]
]
}
},
"healthChecks": [
@@ -32,8 +25,8 @@
],
"labels": {
"traefik.weight": "1",
"traefik.protocole": "https",
"traefik.frontend.rule": "Path",
"traefik.frontend.value": "/test"
"traefik.protocol": "http",
"traefik.frontend.rule" : "Host:test.marathon.localhost",
"traefik.frontend.priority" : "10"
}
}

View File

@@ -3,9 +3,7 @@ Copyright
*/
//go:generate rm -vf autogen/gen.go
//go:generate mkdir -p static
//go:generate go-bindata -pkg autogen -o autogen/gen.go ./static/... ./templates/...
//go:generate mkdir -p vendor/github.com/docker/docker/autogen/dockerversion
//go:generate cp script/dockerversion vendor/github.com/docker/docker/autogen/dockerversion/dockerversion.go
package main

767
glide.lock generated Normal file
View File

@@ -0,0 +1,767 @@
hash: 741ec5fae23f12e6c0fa0e4c7c00c0af06fac1ddc199dd4b45c904856890b347
updated: 2017-03-15T10:48:05.202095822+01:00
imports:
- name: bitbucket.org/ww/goautoneg
version: 75cd24fc2f2c2a2088577d12123ddee5f54e0675
- name: cloud.google.com/go
version: c116c7972ec94f148459a304d07a67ecbc770d4b
subpackages:
- compute/metadata
- name: github.com/abbot/go-http-auth
version: cb4372376e1e00e9f6ab9ec142e029302c9e7140
- name: github.com/ArthurHlt/go-eureka-client
version: ba361cd0f9f571b4e871421423d2f02f5689c3d2
subpackages:
- eureka
- name: github.com/ArthurHlt/gominlog
version: 068c01ce147ad68fca25ef3fa29ae5395ae273ab
- name: github.com/aws/aws-sdk-go
version: 3f8f870ec9939e32b3372abf74d24e468bcd285d
subpackages:
- aws
- aws/awserr
- aws/awsutil
- aws/client
- aws/client/metadata
- aws/corehandlers
- aws/credentials
- aws/credentials/ec2rolecreds
- aws/credentials/endpointcreds
- aws/credentials/stscreds
- aws/defaults
- aws/ec2metadata
- aws/endpoints
- aws/request
- aws/session
- aws/signer/v4
- private/protocol
- private/protocol/ec2query
- private/protocol/json/jsonutil
- private/protocol/jsonrpc
- private/protocol/query
- private/protocol/query/queryutil
- private/protocol/rest
- private/protocol/restxml
- private/protocol/xml/xmlutil
- private/waiter
- service/ec2
- service/ecs
- service/route53
- service/sts
- name: github.com/Azure/azure-sdk-for-go
version: 1620af6b32398bfc91827ceae54a8cc1f55df04d
subpackages:
- arm/dns
- name: github.com/Azure/go-autorest
version: 32cc2321122a649b7ba4e323527bcb145134fd47
subpackages:
- autorest
- autorest/azure
- autorest/date
- autorest/to
- autorest/validation
- name: github.com/beorn7/perks
version: b965b613227fddccbfffe13eae360ed3fa822f8d
subpackages:
- quantile
- name: github.com/blang/semver
version: 3a37c301dda64cbe17f16f661b4c976803c0e2d2
- name: github.com/boltdb/bolt
version: 5cc10bbbc5c141029940133bb33c9e969512a698
- name: github.com/BurntSushi/toml
version: 99064174e013895bbd9b025c31100bd1d9b590ca
- name: github.com/BurntSushi/ty
version: 6add9cd6ad42d389d6ead1dde60b4ad71e46fd74
subpackages:
- fun
- name: github.com/cenk/backoff
version: 8edc80b07f38c27352fb186d971c628a6c32552b
- name: github.com/codahale/hdrhistogram
version: 9208b142303c12d8899bae836fd524ac9338b4fd
- name: github.com/codegangsta/cli
version: bf4a526f48af7badd25d2cb02d587e1b01be3b50
- name: github.com/codegangsta/negroni
version: dc6b9d037e8dab60cbfc09c61d6932537829be8b
- name: github.com/containous/flaeg
version: a731c034dda967333efce5f8d276aeff11f8ff87
- name: github.com/containous/mux
version: a819b77bba13f0c0cbe36e437bc2e948411b3996
- name: github.com/containous/staert
version: 1e26a71803e428fd933f5f9c8e50a26878f53147
- name: github.com/coreos/etcd
version: c400d05d0aa73e21e431c16145e558d624098018
subpackages:
- Godeps/_workspace/src/github.com/ugorji/go/codec
- Godeps/_workspace/src/golang.org/x/net/context
- client
- pkg/pathutil
- pkg/types
- name: github.com/coreos/go-oidc
version: 9e117111587506b9dc83b7b38263268bf48352ea
subpackages:
- http
- jose
- key
- oauth2
- oidc
- name: github.com/coreos/go-systemd
version: 48702e0da86bd25e76cfef347e2adeb434a0d0a6
subpackages:
- daemon
- name: github.com/coreos/pkg
version: 2c77715c4df99b5420ffcae14ead08f52104065d
subpackages:
- capnslog
- health
- httputil
- timeutil
- name: github.com/davecgh/go-spew
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
subpackages:
- spew
- name: github.com/daviddengcn/go-colortext
version: 3b18c8575a432453d41fdafb340099fff5bba2f7
- name: github.com/decker502/dnspod-go
version: f6b1d56f1c048bd94d7e42ac36efb4d57b069b6f
- name: github.com/dgrijalva/jwt-go
version: 9ed569b5d1ac936e6494082958d63a6aa4fff99a
- name: github.com/docker/distribution
version: 325b0804fef3a66309d962357aac3c2ce3f4d329
subpackages:
- context
- digest
- reference
- registry/api/errcode
- registry/api/v2
- registry/client
- registry/client/auth
- registry/client/auth/challenge
- registry/client/transport
- registry/storage/cache
- registry/storage/cache/memory
- uuid
- name: github.com/docker/docker
version: 49bf474f9ed7ce7143a59d1964ff7b7fd9b52178
subpackages:
- api/types
- api/types/backend
- api/types/blkiodev
- api/types/container
- api/types/filters
- api/types/mount
- api/types/network
- api/types/registry
- api/types/strslice
- api/types/swarm
- api/types/versions
- builder
- builder/dockerignore
- cliconfig
- cliconfig/configfile
- daemon/graphdriver
- image
- image/v1
- layer
- namesgenerator
- oci
- opts
- pkg/archive
- pkg/chrootarchive
- pkg/fileutils
- pkg/gitutils
- pkg/homedir
- pkg/httputils
- pkg/idtools
- pkg/ioutils
- pkg/jsonlog
- pkg/jsonmessage
- pkg/longpath
- pkg/mount
- pkg/namesgenerator
- pkg/plugingetter
- pkg/plugins
- pkg/plugins/transport
- pkg/pools
- pkg/progress
- pkg/promise
- pkg/random
- pkg/reexec
- pkg/signal
- pkg/stdcopy
- pkg/streamformatter
- pkg/stringid
- pkg/symlink
- pkg/system
- pkg/tarsum
- pkg/term
- pkg/term/windows
- pkg/urlutil
- plugin/v2
- reference
- registry
- runconfig/opts
- name: github.com/docker/engine-api
version: 3d1601b9d2436a70b0dfc045a23f6503d19195df
subpackages:
- client
- client/transport
- client/transport/cancellable
- types
- types/blkiodev
- types/container
- types/events
- types/filters
- types/network
- types/reference
- types/registry
- types/strslice
- types/swarm
- types/time
- types/versions
- name: github.com/docker/go-connections
version: 990a1a1a70b0da4c4cb70e117971a4f0babfbf1a
subpackages:
- nat
- sockets
- tlsconfig
- name: github.com/docker/go-units
version: 0dadbb0345b35ec7ef35e228dabb8de89a65bf52
- name: github.com/docker/leadership
version: bfc7753dd48af19513b29deec23c364bf0f274eb
- name: github.com/docker/libkv
version: 35d3e2084c650109e7bcc7282655b1bc8ba924ff
subpackages:
- store
- store/boltdb
- store/consul
- store/etcd
- store/zookeeper
- name: github.com/donovanhide/eventsource
version: fd1de70867126402be23c306e1ce32828455d85b
- name: github.com/eapache/channels
version: 47238d5aae8c0fefd518ef2bee46290909cf8263
- name: github.com/eapache/queue
version: 44cc805cf13205b55f69e14bcb69867d1ae92f98
- name: github.com/edeckers/auroradnsclient
version: 8b777c170cfd377aa16bb4368f093017dddef3f9
subpackages:
- records
- requests
- requests/errors
- tokens
- zones
- name: github.com/elazarl/go-bindata-assetfs
version: 57eb5e1fc594ad4b0b1dbea7b286d299e0cb43c2
- name: github.com/emicklei/go-restful
version: 892402ba11a2e2fd5e1295dd633481f27365f14d
subpackages:
- log
- swagger
- name: github.com/gambol99/go-marathon
version: 6b00a5b651b1beb2c6821863f7c60df490bd46c8
- name: github.com/ghodss/yaml
version: 04f313413ffd65ce25f2541bfd2b2ceec5c0908c
- name: github.com/go-ini/ini
version: 6f66b0e091edb3c7b380f7c4f0f884274d550b67
- name: github.com/go-kit/kit
version: f66b0e13579bfc5a48b9e2a94b1209c107ea1f41
subpackages:
- metrics
- metrics/internal/lv
- metrics/prometheus
- name: github.com/go-openapi/jsonpointer
version: 8d96a2dc61536b690bd36b2e9df0b3c0b62825b2
- name: github.com/go-openapi/jsonreference
version: 36d33bfe519efae5632669801b180bf1a245da3b
- name: github.com/go-openapi/spec
version: 34b5ffff717ab4535aef76e3dd90818bddde571b
- name: github.com/go-openapi/swag
version: 96d7b9ebd181a1735a1c9ac87914f2b32fbf56c9
- name: github.com/gogo/protobuf
version: 909568be09de550ed094403c2bf8a261b5bb730a
subpackages:
- proto
- sortkeys
- name: github.com/golang/glog
version: fca8c8854093a154ff1eb580aae10276ad6b1b5f
- name: github.com/golang/protobuf
version: 5677a0e3d5e89854c9974e1256839ee23f8233ca
subpackages:
- proto
- name: github.com/google/go-github
version: c8ebe3a4d7f0791a6315b7410353d4084c58805d
subpackages:
- github
- name: github.com/google/go-querystring
version: 9235644dd9e52eeae6fa48efd539fdc351a0af53
subpackages:
- query
- name: github.com/google/gofuzz
version: 44d81051d367757e1c7c6a5a86423ece9afcf63c
- name: github.com/gorilla/context
version: 1ea25387ff6f684839d82767c1733ff4d4d15d0a
- name: github.com/gorilla/websocket
version: 4873052237e4eeda85cf50c071ef33836fe8e139
- name: github.com/hashicorp/consul
version: fce7d75609a04eeb9d4bf41c8dc592aac18fc97d
subpackages:
- api
- name: github.com/hashicorp/go-cleanhttp
version: 875fb671b3ddc66f8e2f0acc33829c8cb989a38d
- name: github.com/hashicorp/go-version
version: e96d3840402619007766590ecea8dd7af1292276
- name: github.com/hashicorp/serf
version: 6c4672d66fc6312ddde18399262943e21175d831
subpackages:
- coordinate
- serf
- name: github.com/JamesClonk/vultr
version: 9ec0427d51411407c0402b093a1771cb75af9679
subpackages:
- lib
- name: github.com/jmespath/go-jmespath
version: bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d
- name: github.com/jonboulle/clockwork
version: 72f9bd7c4e0c2a40055ab3d0f09654f730cce982
- name: github.com/juju/ratelimit
version: 77ed1c8a01217656d2080ad51981f6e99adaa177
- name: github.com/mailgun/manners
version: a585afd9d65c0e05f6c003f921e71ebc05074f4f
- name: github.com/mailgun/timetools
version: fd192d755b00c968d312d23f521eb0cdc6f66bd0
- name: github.com/mailru/easyjson
version: 9d6630dc8c577b56cb9687a9cf9e8578aca7298a
subpackages:
- buffer
- jlexer
- jwriter
- name: github.com/mattn/go-shellwords
version: 525bedee691b5a8df547cb5cf9f86b7fb1883e24
- name: github.com/matttproud/golang_protobuf_extensions
version: fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a
subpackages:
- pbutil
- name: github.com/mesos/mesos-go
version: 068d5470506e3780189fe607af40892814197c5e
subpackages:
- detector
- detector/zoo
- mesos
- mesosproto
- mesosutil
- upid
- name: github.com/mesosphere/mesos-dns
version: b47dc4c19f215e98da687b15b4c64e70f629bea5
repo: https://github.com/containous/mesos-dns.git
vcs: git
subpackages:
- detect
- errorutil
- logging
- models
- records
- records/labels
- records/state
- util
- name: github.com/Microsoft/go-winio
version: ce2922f643c8fd76b46cadc7f404a06282678b34
- name: github.com/miekg/dns
version: 8060d9f51305bbe024b99679454e62f552cd0b0b
- name: github.com/mitchellh/mapstructure
version: f3009df150dadf309fdee4a54ed65c124afad715
- name: github.com/mvdan/xurls
version: fa08908f19eca8c491d68c6bd8b4b44faea6daf8
- name: github.com/NYTimes/gziphandler
version: 6710af535839f57c687b62c4c23d649f9545d885
- name: github.com/ogier/pflag
version: 45c278ab3607870051a2ea9040bb85fcb8557481
- name: github.com/opencontainers/runc
version: 1a81e9ab1f138c091fe5c86d0883f87716088527
subpackages:
- libcontainer/configs
- libcontainer/devices
- libcontainer/system
- libcontainer/user
- name: github.com/ovh/go-ovh
version: a8a4c0bc40e56322142649bda7b2b4bb15145b6e
subpackages:
- ovh
- name: github.com/pborman/uuid
version: 5007efa264d92316c43112bc573e754bc889b7b1
- name: github.com/pkg/errors
version: bfd5150e4e41705ded2129ec33379de1cb90b513
- name: github.com/pmezard/go-difflib
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
subpackages:
- difflib
- name: github.com/prometheus/client_golang
version: c5b7fccd204277076155f10851dad72b76a49317
subpackages:
- prometheus
- prometheus/promhttp
- name: github.com/prometheus/client_model
version: fa8ad6fec33561be4280a8f0514318c79d7f6cb6
subpackages:
- go
- name: github.com/prometheus/common
version: ffe929a3f4c4faeaa10f2b9535c2b1be3ad15650
subpackages:
- expfmt
- model
- name: github.com/prometheus/procfs
version: 454a56f35412459b5e684fd5ec0f9211b94f002a
- name: github.com/PuerkitoBio/purell
version: 0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4
- name: github.com/PuerkitoBio/urlesc
version: 5bd2802263f21d8788851d5305584c82a5c75d7e
- name: github.com/pyr/egoscale
version: ab4b0d7ff424c462da486aef27f354cdeb29a319
subpackages:
- src/egoscale
- name: github.com/rancher/go-rancher
version: 5b8f6cc26b355ba03d7611fce3844155b7baf05b
subpackages:
- client
- name: github.com/ryanuber/go-glob
version: 572520ed46dbddaed19ea3d9541bdd0494163693
- name: github.com/samuel/go-zookeeper
version: e64db453f3512cade908163702045e0f31137843
subpackages:
- zk
- name: github.com/satori/go.uuid
version: 879c5887cd475cd7864858769793b2ceb0d44feb
- name: github.com/Sirupsen/logrus
version: a283a10442df8dc09befd873fab202bf8a253d6a
- name: github.com/spf13/pflag
version: 5644820622454e71517561946e3d94b9f9db6842
- name: github.com/streamrail/concurrent-map
version: 65a174a3a4188c0b7099acbc6cfa0c53628d3287
- name: github.com/stretchr/objx
version: cbeaeb16a013161a98496fad62933b1d21786672
- name: github.com/stretchr/testify
version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0
subpackages:
- assert
- mock
- name: github.com/thoas/stats
version: 152b5d051953fdb6e45f14b6826962aadc032324
- name: github.com/timewasted/linode
version: 37e84520dcf74488f67654f9c775b9752c232dc1
subpackages:
- dns
- name: github.com/tv42/zbase32
version: 03389da7e0bf9844767f82690f4d68fc097a1306
- name: github.com/ugorji/go
version: ea9cd21fa0bc41ee4bdd50ac7ed8cbc7ea2ed960
subpackages:
- codec
- name: github.com/unrolled/render
version: 198ad4d8b8a4612176b804ca10555b222a086b40
- name: github.com/vdemeester/docker-events
version: be74d4929ec1ad118df54349fda4b0cba60f849b
- name: github.com/vulcand/oxy
version: f88530866c561d24a6b5aac49f76d6351b788b9f
repo: https://github.com/containous/oxy.git
vcs: git
subpackages:
- cbreaker
- connlimit
- forward
- memmetrics
- roundrobin
- stream
- utils
- name: github.com/vulcand/predicate
version: 19b9dde14240d94c804ae5736ad0e1de10bf8fe6
- name: github.com/vulcand/route
version: cb89d787ddbb1c5849a7ac9f79004c1fd12a4a32
- name: github.com/vulcand/vulcand
version: 42492a3a85e294bdbdd1bcabb8c12769a81ea284
subpackages:
- conntracker
- plugin
- plugin/rewrite
- router
- name: github.com/weppos/dnsimple-go
version: 65c1ca73cb19baf0f8b2b33219b7f57595a3ccb0
subpackages:
- dnsimple
- name: github.com/xenolf/lego
version: ce8fb060cb8361a9ff8b5fb7c2347fa907b6fcac
subpackages:
- acme
- providers/dns
- providers/dns/auroradns
- providers/dns/azure
- providers/dns/cloudflare
- providers/dns/digitalocean
- providers/dns/dnsimple
- providers/dns/dnsmadeeasy
- providers/dns/dnspod
- providers/dns/dyn
- providers/dns/exoscale
- providers/dns/gandi
- providers/dns/googlecloud
- providers/dns/linode
- providers/dns/namecheap
- providers/dns/ns1
- providers/dns/ovh
- providers/dns/pdns
- providers/dns/rackspace
- providers/dns/rfc2136
- providers/dns/route53
- providers/dns/vultr
- name: golang.org/x/crypto
version: 4ed45ec682102c643324fae5dff8dab085b6c300
subpackages:
- bcrypt
- blowfish
- ocsp
- name: golang.org/x/net
version: 242b6b35177ec3909636b6cf6a47e8c2c6324b5d
subpackages:
- context
- context/ctxhttp
- http2
- http2/hpack
- idna
- lex/httplex
- proxy
- publicsuffix
- name: golang.org/x/oauth2
version: 3046bc76d6dfd7d3707f6640f85e42d9c4050f50
subpackages:
- google
- internal
- jws
- jwt
- name: golang.org/x/sys
version: eb2c74142fd19a79b3f237334c7384d5167b1b46
subpackages:
- unix
- windows
- name: golang.org/x/text
version: a49bea13b776691cb1b49873e5d8df96ec74831a
repo: https://github.com/golang/text.git
vcs: git
subpackages:
- .
- transform
- unicode/norm
- width
- name: google.golang.org/api
version: 9bf6e6e569ff057f75d9604a46c52928f17d2b54
subpackages:
- dns/v1
- gensupport
- googleapi
- googleapi/internal/uritemplates
- name: google.golang.org/appengine
version: 12d5545dc1cfa6047a286d5e853841b6471f4c19
subpackages:
- internal
- internal/app_identity
- internal/base
- internal/datastore
- internal/log
- internal/modules
- internal/remote_api
- internal/urlfetch
- urlfetch
- name: google.golang.org/cloud
version: f20d6dcccb44ed49de45ae3703312cb46e627db1
subpackages:
- compute/metadata
- internal
- name: gopkg.in/fsnotify.v1
version: a8a77c9133d2d6fd8334f3260d06f60e8d80a5fb
- name: gopkg.in/inf.v0
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
- name: gopkg.in/ini.v1
version: 6f66b0e091edb3c7b380f7c4f0f884274d550b67
- name: gopkg.in/mgo.v2
version: 29cc868a5ca65f401ff318143f9408d02f4799cc
subpackages:
- bson
- name: gopkg.in/ns1/ns1-go.v2
version: d8d10b7f448291ddbdce48d4594fb1b667014c8b
subpackages:
- rest
- rest/model/account
- rest/model/data
- rest/model/dns
- rest/model/filter
- rest/model/monitor
- name: gopkg.in/square/go-jose.v1
version: e3f973b66b91445ec816dd7411ad1b6495a5a2fc
subpackages:
- cipher
- json
- name: gopkg.in/yaml.v2
version: bef53efd0c76e49e6de55ead051f886bea7e9420
- name: k8s.io/client-go
version: 1195e3a8ee1a529d53eed7c624527a68555ddf1f
subpackages:
- 1.5/discovery
- 1.5/kubernetes
- 1.5/kubernetes/typed/apps/v1alpha1
- 1.5/kubernetes/typed/authentication/v1beta1
- 1.5/kubernetes/typed/authorization/v1beta1
- 1.5/kubernetes/typed/autoscaling/v1
- 1.5/kubernetes/typed/batch/v1
- 1.5/kubernetes/typed/certificates/v1alpha1
- 1.5/kubernetes/typed/core/v1
- 1.5/kubernetes/typed/extensions/v1beta1
- 1.5/kubernetes/typed/policy/v1alpha1
- 1.5/kubernetes/typed/rbac/v1alpha1
- 1.5/kubernetes/typed/storage/v1beta1
- 1.5/pkg/api
- 1.5/pkg/api/errors
- 1.5/pkg/api/install
- 1.5/pkg/api/meta
- 1.5/pkg/api/meta/metatypes
- 1.5/pkg/api/resource
- 1.5/pkg/api/unversioned
- 1.5/pkg/api/v1
- 1.5/pkg/api/validation/path
- 1.5/pkg/apimachinery
- 1.5/pkg/apimachinery/announced
- 1.5/pkg/apimachinery/registered
- 1.5/pkg/apis/apps
- 1.5/pkg/apis/apps/install
- 1.5/pkg/apis/apps/v1alpha1
- 1.5/pkg/apis/authentication
- 1.5/pkg/apis/authentication/install
- 1.5/pkg/apis/authentication/v1beta1
- 1.5/pkg/apis/authorization
- 1.5/pkg/apis/authorization/install
- 1.5/pkg/apis/authorization/v1beta1
- 1.5/pkg/apis/autoscaling
- 1.5/pkg/apis/autoscaling/install
- 1.5/pkg/apis/autoscaling/v1
- 1.5/pkg/apis/batch
- 1.5/pkg/apis/batch/install
- 1.5/pkg/apis/batch/v1
- 1.5/pkg/apis/batch/v2alpha1
- 1.5/pkg/apis/certificates
- 1.5/pkg/apis/certificates/install
- 1.5/pkg/apis/certificates/v1alpha1
- 1.5/pkg/apis/extensions
- 1.5/pkg/apis/extensions/install
- 1.5/pkg/apis/extensions/v1beta1
- 1.5/pkg/apis/policy
- 1.5/pkg/apis/policy/install
- 1.5/pkg/apis/policy/v1alpha1
- 1.5/pkg/apis/rbac
- 1.5/pkg/apis/rbac/install
- 1.5/pkg/apis/rbac/v1alpha1
- 1.5/pkg/apis/storage
- 1.5/pkg/apis/storage/install
- 1.5/pkg/apis/storage/v1beta1
- 1.5/pkg/auth/user
- 1.5/pkg/conversion
- 1.5/pkg/conversion/queryparams
- 1.5/pkg/fields
- 1.5/pkg/genericapiserver/openapi/common
- 1.5/pkg/labels
- 1.5/pkg/runtime
- 1.5/pkg/runtime/serializer
- 1.5/pkg/runtime/serializer/json
- 1.5/pkg/runtime/serializer/protobuf
- 1.5/pkg/runtime/serializer/recognizer
- 1.5/pkg/runtime/serializer/streaming
- 1.5/pkg/runtime/serializer/versioning
- 1.5/pkg/selection
- 1.5/pkg/third_party/forked/golang/reflect
- 1.5/pkg/types
- 1.5/pkg/util
- 1.5/pkg/util/cert
- 1.5/pkg/util/clock
- 1.5/pkg/util/errors
- 1.5/pkg/util/flowcontrol
- 1.5/pkg/util/framer
- 1.5/pkg/util/integer
- 1.5/pkg/util/intstr
- 1.5/pkg/util/json
- 1.5/pkg/util/labels
- 1.5/pkg/util/net
- 1.5/pkg/util/parsers
- 1.5/pkg/util/rand
- 1.5/pkg/util/runtime
- 1.5/pkg/util/sets
- 1.5/pkg/util/uuid
- 1.5/pkg/util/validation
- 1.5/pkg/util/validation/field
- 1.5/pkg/util/wait
- 1.5/pkg/util/yaml
- 1.5/pkg/version
- 1.5/pkg/watch
- 1.5/pkg/watch/versioned
- 1.5/plugin/pkg/client/auth
- 1.5/plugin/pkg/client/auth/gcp
- 1.5/plugin/pkg/client/auth/oidc
- 1.5/rest
- 1.5/tools/cache
- 1.5/tools/clientcmd/api
- 1.5/tools/metrics
- 1.5/transport
testImports:
- name: github.com/Azure/go-ansiterm
version: fa152c58bc15761d0200cb75fe958b89a9d4888e
subpackages:
- winterm
- name: github.com/cloudfoundry-incubator/candiedyaml
version: 99c3df83b51532e3615f851d8c2dbb638f5313bf
- name: github.com/docker/libcompose
version: d1876c1d68527a49c0aac22a0b161acc7296b740
subpackages:
- config
- docker
- docker/builder
- docker/client
- docker/network
- labels
- logger
- lookup
- project
- project/events
- project/options
- utils
- version
- yaml
- name: github.com/flynn/go-shlex
version: 3f9db97f856818214da2e1057f8ad84803971cff
- name: github.com/go-check/check
version: 11d3bc7aa68e238947792f30573146a3231fc0f1
- name: github.com/gorilla/mux
version: e444e69cbd2e2e3e0749a2f3c717cec491552bbf
- name: github.com/libkermit/compose
version: cadc5a3b83a15790174bd7fbc75ea2529785e772
subpackages:
- check
- name: github.com/libkermit/docker
version: 55e3595409924fcfbb850811e5a7cdbe8960a0b7
- name: github.com/libkermit/docker-check
version: cbe0ef03b3d23070eac4d00ba8828f2cc7f7e5a3
- name: github.com/opencontainers/runtime-spec
version: 06479209bdc0d4135911688c18157bd39bd99c22
subpackages:
- specs-go
- name: github.com/vbatts/tar-split
version: 6810cedb21b2c3d0b9bb8f9af12ff2dc7a2f14df
subpackages:
- archive/tar
- tar/asm
- tar/storage
- name: github.com/vdemeester/shakers
version: 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
- name: github.com/xeipuuv/gojsonpointer
version: e0fe6f68307607d540ed8eac07a342c33fa1b54a
- name: github.com/xeipuuv/gojsonreference
version: e02fc20de94c78484cd5ffb007f8af96be030a45
- name: github.com/xeipuuv/gojsonschema
version: 00f9fafb54d2244d291b86ab63d12c38bd5c3886
- name: golang.org/x/time
version: a4bde12657593d5e90d0533a3e4fd95e635124cb
subpackages:
- rate

View File

@@ -1,144 +1,141 @@
package: main
package: github.com/containous/traefik
import:
- package: github.com/coreos/go-etcd
ref: cc90c7b091275e606ad0ca7102a23fb2072f3f5e
subpackages:
- etcd
- package: github.com/docker/distribution
ref: 9038e48c3b982f8e82281ea486f078a73731ac4e
- package: github.com/mailgun/log
ref: 44874009257d4d47ba9806f1b7f72a32a015e4d8
- package: github.com/mailgun/oxy
ref: 547c334d658398c05b346c0b79d8f47ba2e1473b
subpackages:
- cbreaker
- forward
- memmetrics
- roundrobin
- utils
- package: github.com/hashicorp/consul
ref: de080672fee9e6104572eeea89eccdca135bb918
subpackages:
- api
- package: github.com/samuel/go-zookeeper
ref: fa6674abf3f4580b946a01bf7a1ce4ba8766205b
subpackages:
- zk
- package: github.com/docker/libtrust
ref: 9cbd2a1374f46905c68a4eb3694a130610adc62a
- package: gopkg.in/check.v1
ref: 11d3bc7aa68e238947792f30573146a3231fc0f1
- package: golang.org/x/net
ref: d9558e5c97f85372afee28cf2b6059d7d3818919
subpackages:
- context
- package: github.com/gorilla/handlers
ref: 40694b40f4a928c062f56849989d3e9cd0570e5f
- package: github.com/docker/libkv
ref: 3732f7ff1b56057c3158f10bceb1e79133025373
- package: github.com/alecthomas/template
ref: b867cc6ab45cece8143cfcc6fc9c77cf3f2c23c0
- package: github.com/vdemeester/shakers
ref: 8fe734f75f3a70b651cbfbf8a55a009da09e8dc5
- package: github.com/alecthomas/units
ref: 6b4e7dc5e3143b85ea77909c72caf89416fc2915
- package: github.com/gambol99/go-marathon
ref: 0ba31bcb0d7633ba1888d744c42990eb15281cf1
- package: github.com/mailgun/predicate
ref: cb0bff91a7ab7cf7571e661ff883fc997bc554a3
- package: github.com/thoas/stats
ref: 54ed61c2b47e263ae2f01b86837b0c4bd1da28e8
- package: github.com/samalba/dockerclient
ref: cfb489c624b635251a93e74e1e90eb0959c5367f
- package: github.com/Sirupsen/logrus
ref: 418b41d23a1bf978c06faea5313ba194650ac088
- package: github.com/unrolled/render
ref: 26b4e3aac686940fe29521545afad9966ddfc80c
- package: github.com/flynn/go-shlex
ref: 3f9db97f856818214da2e1057f8ad84803971cff
- package: github.com/fsouza/go-dockerclient
ref: 0239034d42f665efa17fd77c39f891c2f9f32922
- package: github.com/boltdb/bolt
ref: 51f99c862475898df9773747d3accd05a7ca33c1
- package: gopkg.in/mgo.v2
ref: 22287bab4379e1fbf6002fb4eb769888f3fb224c
subpackages:
- bson
- package: github.com/docker/docker
ref: f39987afe8d611407887b3094c03d6ba6a766a67
subpackages:
- autogen
- api
- cliconfig
- daemon/network
- graph/tags
- image
- opts
- pkg/archive
- pkg/fileutils
- pkg/homedir
- pkg/httputils
- pkg/ioutils
- pkg/jsonmessage
- pkg/mflag
- pkg/nat
- pkg/parsers
- pkg/pools
- pkg/promise
- pkg/random
- pkg/stdcopy
- pkg/stringid
- pkg/symlink
- pkg/system
- pkg/tarsum
- pkg/term
- pkg/timeutils
- pkg/tlsconfig
- pkg/ulimit
- pkg/units
- pkg/urlutil
- pkg/useragent
- pkg/version
- registry
- runconfig
- utils
- volume
- package: github.com/mailgun/timetools
ref: fd192d755b00c968d312d23f521eb0cdc6f66bd0
- package: github.com/codegangsta/negroni
ref: c7477ad8e330bef55bf1ebe300cf8aa67c492d1b
- package: gopkg.in/yaml.v2
ref: 7ad95dd0798a40da1ccdff6dff35fd177b5edf40
- package: github.com/opencontainers/runc
ref: 4ab132458fc3e9dbeea624153e0331952dc4c8d5
subpackages:
- libcontainer/user
- package: github.com/gorilla/mux
ref: f15e0c49460fd49eebe2bcc8486b05d1bef68d3a
- package: github.com/BurntSushi/ty
ref: 6add9cd6ad42d389d6ead1dde60b4ad71e46fd74
- package: github.com/elazarl/go-bindata-assetfs
ref: d5cac425555ca5cf00694df246e04f05e6a55150
- package: github.com/BurntSushi/toml
ref: bd2bdf7f18f849530ef7a1c29a4290217cab32a1
- package: gopkg.in/alecthomas/kingpin.v2
ref: 639879d6110b1b0409410c7b737ef0bb18325038
- package: github.com/docker/libcompose
ref: 79ef5d150f053a5b12f16b02d8844ed7cf33611a
subpackages:
- docker
- logger
- lookup
- project
- utils
- package: github.com/cenkalti/backoff
ref: 4dc77674aceaabba2c7e3da25d4c823edfb73f99
- package: gopkg.in/fsnotify.v1
ref: 96c060f6a6b7e0d6f75fddd10efeaca3e5d1bcb0
- package: github.com/mailgun/manners
ref: 37136f736785d7c6aa3b9a27b4b2dd1028ca6d79
- package: github.com/gorilla/context
ref: 215affda49addc4c8ef7e2534915df2c8c35c6cd
- package: github.com/codahale/hdrhistogram
ref: 954f16e8b9ef0e5d5189456aa4c1202758e04f17
- package: github.com/gorilla/websocket
- package: github.com/BurntSushi/toml
- package: github.com/BurntSushi/ty
subpackages:
- fun
- package: github.com/Sirupsen/logrus
- package: github.com/cenk/backoff
- package: github.com/containous/flaeg
version: a731c034dda967333efce5f8d276aeff11f8ff87
- package: github.com/vulcand/oxy
version: f88530866c561d24a6b5aac49f76d6351b788b9f
repo: https://github.com/containous/oxy.git
vcs: git
subpackages:
- cbreaker
- connlimit
- forward
- roundrobin
- stream
- utils
- package: github.com/containous/staert
version: 1e26a71803e428fd933f5f9c8e50a26878f53147
- package: github.com/docker/engine-api
version: v0.4.0
subpackages:
- client
- types
- types/events
- types/filters
- package: github.com/docker/go-connections
version: v0.2.1
subpackages:
- sockets
- tlsconfig
- package: github.com/docker/go-units
version: 0dadbb0345b35ec7ef35e228dabb8de89a65bf52
- package: github.com/docker/libkv
subpackages:
- store
- store/boltdb
- store/consul
- store/etcd
- store/zookeeper
- package: github.com/elazarl/go-bindata-assetfs
- package: github.com/containous/mux
- package: github.com/hashicorp/consul
subpackages:
- api
- package: github.com/mailgun/manners
- package: github.com/streamrail/concurrent-map
- package: github.com/stretchr/testify
subpackages:
- mock
- package: github.com/thoas/stats
version: 152b5d051953fdb6e45f14b6826962aadc032324
- package: github.com/unrolled/render
- package: github.com/vdemeester/docker-events
version: be74d4929ec1ad118df54349fda4b0cba60f849b
- package: github.com/vulcand/vulcand
version: 42492a3a85e294bdbdd1bcabb8c12769a81ea284
subpackages:
- plugin/rewrite
- package: github.com/xenolf/lego
version: ce8fb060cb8361a9ff8b5fb7c2347fa907b6fcac
subpackages:
- acme
- package: gopkg.in/fsnotify.v1
- package: github.com/docker/docker
version: v1.13.0
subpackages:
- namesgenerator
- package: github.com/mattn/go-shellwords
- package: github.com/ryanuber/go-glob
- package: github.com/mesos/mesos-go
subpackages:
- mesosproto
- mesos
- upid
- mesosutil
- detector
- package: github.com/miekg/dns
version: 8060d9f51305bbe024b99679454e62f552cd0b0b
- package: github.com/mesosphere/mesos-dns
version: b47dc4c19f215e98da687b15b4c64e70f629bea5
repo: https://github.com/containous/mesos-dns.git
vcs: git
- package: github.com/abbot/go-http-auth
- package: github.com/NYTimes/gziphandler
- package: github.com/docker/leadership
- package: github.com/satori/go.uuid
version: ^1.1.0
- package: k8s.io/client-go
version: ^v1.5.0
- package: github.com/gambol99/go-marathon
version: ^0.5.1
- package: github.com/ArthurHlt/go-eureka-client
subpackages:
- eureka
- package: github.com/coreos/go-systemd
version: v14
subpackages:
- daemon
- package: github.com/google/go-github
- package: github.com/hashicorp/go-version
- package: github.com/mvdan/xurls
- package: github.com/go-kit/kit
version: v0.3.0
subpackages:
- metrics
- package: github.com/eapache/channels
version: v1.1.0
- package: golang.org/x/net
version: 242b6b35177ec3909636b6cf6a47e8c2c6324b5d
subpackages:
- http2
- context
- package: github.com/docker/distribution
version: v2.6.0
- package: github.com/aws/aws-sdk-go
version: v1.6.18
subpackages:
- aws
- aws/credentials
- aws/defaults
- aws/ec2metadata
- aws/endpoints
- aws/request
- aws/session
- service/ec2
- service/ecs
- package: cloud.google.com/go
version: v0.6.0
subpackages:
- compute/metadata
- package: github.com/gogo/protobuf
version: v0.3
subpackages:
- proto
- package: github.com/rancher/go-rancher
version: 5b8f6cc26b355ba03d7611fce3844155b7baf05b

117
healthcheck/healthcheck.go Normal file
View File

@@ -0,0 +1,117 @@
package healthcheck
import (
"context"
"net/http"
"net/url"
"sync"
"time"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/vulcand/oxy/roundrobin"
)
var singleton *HealthCheck
var once sync.Once
// GetHealthCheck Get HealtchCheck Singleton
func GetHealthCheck() *HealthCheck {
once.Do(func() {
singleton = newHealthCheck()
})
return singleton
}
// BackendHealthCheck HealthCheck configuration for a backend
type BackendHealthCheck struct {
Path string
Interval time.Duration
DisabledURLs []*url.URL
lb loadBalancer
}
var launch = false
//HealthCheck struct
type HealthCheck struct {
Backends map[string]*BackendHealthCheck
cancel context.CancelFunc
}
type loadBalancer interface {
RemoveServer(u *url.URL) error
UpsertServer(u *url.URL, options ...roundrobin.ServerOption) error
Servers() []*url.URL
}
func newHealthCheck() *HealthCheck {
return &HealthCheck{make(map[string]*BackendHealthCheck), nil}
}
// NewBackendHealthCheck Instantiate a new BackendHealthCheck
func NewBackendHealthCheck(URL string, interval time.Duration, lb loadBalancer) *BackendHealthCheck {
return &BackendHealthCheck{URL, interval, nil, lb}
}
//SetBackendsConfiguration set backends configuration
func (hc *HealthCheck) SetBackendsConfiguration(parentCtx context.Context, backends map[string]*BackendHealthCheck) {
hc.Backends = backends
if hc.cancel != nil {
hc.cancel()
}
ctx, cancel := context.WithCancel(parentCtx)
hc.cancel = cancel
hc.execute(ctx)
}
func (hc *HealthCheck) execute(ctx context.Context) {
for backendID, backend := range hc.Backends {
currentBackend := backend
currentBackendID := backendID
safe.Go(func() {
for {
ticker := time.NewTicker(currentBackend.Interval)
select {
case <-ctx.Done():
log.Debugf("Stopping all current Healthcheck goroutines")
return
case <-ticker.C:
log.Debugf("Refreshing Healthcheck for currentBackend %s ", currentBackendID)
enabledURLs := currentBackend.lb.Servers()
var newDisabledURLs []*url.URL
for _, url := range currentBackend.DisabledURLs {
if checkHealth(url, currentBackend.Path) {
log.Debugf("HealthCheck is up [%s]: Upsert in server list", url.String())
currentBackend.lb.UpsertServer(url, roundrobin.Weight(1))
} else {
newDisabledURLs = append(newDisabledURLs, url)
}
}
currentBackend.DisabledURLs = newDisabledURLs
for _, url := range enabledURLs {
if !checkHealth(url, currentBackend.Path) {
log.Debugf("HealthCheck has failed [%s]: Remove from server list", url.String())
currentBackend.lb.RemoveServer(url)
currentBackend.DisabledURLs = append(currentBackend.DisabledURLs, url)
}
}
}
}
})
}
}
func checkHealth(serverURL *url.URL, path string) bool {
timeout := time.Duration(5 * time.Second)
client := http.Client{
Timeout: timeout,
}
resp, err := client.Get(serverURL.String() + path)
if err != nil || resp.StatusCode != 200 {
return false
}
return true
}

View File

@@ -0,0 +1,106 @@
package main
import (
"fmt"
"io/ioutil"
"net"
"net/http"
"net/http/httptest"
"os"
"os/exec"
"regexp"
"strings"
"time"
"github.com/go-check/check"
shellwords "github.com/mattn/go-shellwords"
checker "github.com/vdemeester/shakers"
)
// AccessLogSuite
type AccessLogSuite struct{ BaseSuite }
func (s *AccessLogSuite) TestAccessLog(c *check.C) {
// Ensure working directory is clean
os.Remove("access.log")
os.Remove("traefik.log")
// Start Traefik
cmd := exec.Command(traefikBinary, "--configFile=fixtures/access_log_config.toml")
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
defer os.Remove("access.log")
defer os.Remove("traefik.log")
time.Sleep(500 * time.Millisecond)
// Verify Traefik started OK
traefikLog, err := ioutil.ReadFile("traefik.log")
c.Assert(err, checker.IsNil)
if len(traefikLog) > 0 {
fmt.Printf("%s\n", string(traefikLog))
c.Assert(len(traefikLog), checker.Equals, 0)
}
// Start test servers
ts1 := startAccessLogServer(8081)
defer ts1.Close()
ts2 := startAccessLogServer(8082)
defer ts2.Close()
ts3 := startAccessLogServer(8083)
defer ts3.Close()
// Make some requests
_, err = http.Get("http://127.0.0.1:8000/test1")
c.Assert(err, checker.IsNil)
_, err = http.Get("http://127.0.0.1:8000/test2")
c.Assert(err, checker.IsNil)
_, err = http.Get("http://127.0.0.1:8000/test2")
c.Assert(err, checker.IsNil)
// Verify access.log output as expected
accessLog, err := ioutil.ReadFile("access.log")
c.Assert(err, checker.IsNil)
lines := strings.Split(string(accessLog), "\n")
count := 0
for i, line := range lines {
if len(line) > 0 {
count++
tokens, err := shellwords.Parse(line)
c.Assert(err, checker.IsNil)
c.Assert(len(tokens), checker.Equals, 13)
c.Assert(tokens[6], checker.Equals, "200")
c.Assert(tokens[9], checker.Equals, fmt.Sprintf("%d", i+1))
c.Assert(strings.HasPrefix(tokens[10], "frontend"), checker.True)
c.Assert(strings.HasPrefix(tokens[11], "http://127.0.0.1:808"), checker.True)
c.Assert(regexp.MustCompile("^\\d+ms$").MatchString(tokens[12]), checker.True)
}
}
c.Assert(count, checker.Equals, 3)
// Verify no other Traefik problems
traefikLog, err = ioutil.ReadFile("traefik.log")
c.Assert(err, checker.IsNil)
if len(traefikLog) > 0 {
fmt.Printf("%s\n", string(traefikLog))
c.Assert(len(traefikLog), checker.Equals, 0)
}
}
func startAccessLogServer(port int) (ts *httptest.Server) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Received query %s!\n", r.URL.Path[1:])
})
if listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port)); err != nil {
panic(err)
} else {
ts = &httptest.Server{
Listener: listener,
Config: &http.Server{Handler: handler},
}
ts.Start()
}
return
}

92
integration/acme_test.go Normal file
View File

@@ -0,0 +1,92 @@
package main
import (
"crypto/tls"
"net/http"
"os"
"os/exec"
"time"
"github.com/go-check/check"
"errors"
"github.com/containous/traefik/integration/utils"
checker "github.com/vdemeester/shakers"
)
// ACME test suites (using libcompose)
type AcmeSuite struct {
BaseSuite
}
func (s *AcmeSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "boulder")
s.composeProject.Start(c)
boulderHost := s.composeProject.Container(c, "boulder").NetworkSettings.IPAddress
// wait for boulder
err := utils.Try(120*time.Second, func() error {
resp, err := http.Get("http://" + boulderHost + ":4000/directory")
if err != nil {
return err
}
if resp.StatusCode != 200 {
return errors.New("Expected http 200 from boulder")
}
return nil
})
c.Assert(err, checker.IsNil)
}
func (s *AcmeSuite) TearDownSuite(c *check.C) {
// shutdown and delete compose project
if s.composeProject != nil {
s.composeProject.Stop(c)
}
}
func (s *AcmeSuite) TestRetrieveAcmeCertificate(c *check.C) {
boulderHost := s.composeProject.Container(c, "boulder").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/acme/acme.toml", struct{ BoulderHost string }{boulderHost})
defer os.Remove(file)
cmd := exec.Command(traefikBinary, "--configFile="+file)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
backend := startTestServer("9010", 200)
defer backend.Close()
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}
// wait for traefik (generating acme account take some seconds)
err = utils.Try(30*time.Second, func() error {
_, err := client.Get("https://127.0.0.1:5001")
if err != nil {
return err
}
return nil
})
c.Assert(err, checker.IsNil)
tr = &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
ServerName: "traefik.acme.wtf",
},
}
client = &http.Client{Transport: tr}
req, _ := http.NewRequest("GET", "https://127.0.0.1:5001/", nil)
req.Host = "traefik.acme.wtf"
req.Header.Set("Host", "traefik.acme.wtf")
req.Header.Set("Accept", "*/*")
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
// Expected a 200
c.Assert(resp.StatusCode, checker.Equals, 200)
}

View File

@@ -1,58 +1,51 @@
package main
import (
"fmt"
"net/http"
"os/exec"
"time"
"github.com/go-check/check"
"bytes"
checker "github.com/vdemeester/shakers"
check "gopkg.in/check.v1"
)
// SimpleSuite
type SimpleSuite struct{ BaseSuite }
func (s *SimpleSuite) TestNoOrInexistentConfigShouldFail(c *check.C) {
cmd := exec.Command(traefikBinary)
output, err := cmd.CombinedOutput()
c.Assert(err, checker.NotNil)
c.Assert(string(output), checker.Contains, "Error reading file: open traefik.toml: no such file or directory")
nonExistentFile := "non/existent/file.toml"
cmd = exec.Command(traefikBinary, nonExistentFile)
output, err = cmd.CombinedOutput()
c.Assert(err, checker.NotNil)
c.Assert(string(output), checker.Contains, fmt.Sprintf("Error reading file: open %s: no such file or directory", nonExistentFile))
}
func (s *SimpleSuite) TestInvalidConfigShouldFail(c *check.C) {
cmd := exec.Command(traefikBinary, "fixtures/invalid_configuration.toml")
output, err := cmd.CombinedOutput()
cmd := exec.Command(traefikBinary, "--configFile=fixtures/invalid_configuration.toml")
c.Assert(err, checker.NotNil)
c.Assert(string(output), checker.Contains, "Error reading file: Near line 1")
var b bytes.Buffer
cmd.Stdout = &b
cmd.Stderr = &b
cmd.Start()
time.Sleep(500 * time.Millisecond)
defer cmd.Process.Kill()
output := b.Bytes()
c.Assert(string(output), checker.Contains, "Near line 0 (last key parsed ''): Bare keys cannot contain '{'")
}
func (s *SimpleSuite) TestSimpleDefaultConfig(c *check.C) {
cmd := exec.Command(traefikBinary, "fixtures/simple_default.toml")
cmd := exec.Command(traefikBinary, "--configFile=fixtures/simple_default.toml")
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
time.Sleep(500 * time.Millisecond)
// TODO validate : run on 80
resp, err := http.Get("http://127.0.0.1/")
resp, err := http.Get("http://127.0.0.1:8000/")
// Expected a 404 as we did not comfigure anything
// Expected a 404 as we did not configure anything
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 404)
}
func (s *SimpleSuite) TestWithWebConfig(c *check.C) {
cmd := exec.Command(traefikBinary, "fixtures/simple_web.toml")
cmd := exec.Command(traefikBinary, "--configFile=fixtures/simple_web.toml")
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
@@ -64,3 +57,34 @@ func (s *SimpleSuite) TestWithWebConfig(c *check.C) {
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 200)
}
func (s *SimpleSuite) TestDefaultEntryPoints(c *check.C) {
cmd := exec.Command(traefikBinary, "--debug")
var b bytes.Buffer
cmd.Stdout = &b
cmd.Stderr = &b
cmd.Start()
time.Sleep(500 * time.Millisecond)
defer cmd.Process.Kill()
output := b.Bytes()
c.Assert(string(output), checker.Contains, "\\\"DefaultEntryPoints\\\":[\\\"http\\\"]")
}
func (s *SimpleSuite) TestPrintHelp(c *check.C) {
cmd := exec.Command(traefikBinary, "--help")
var b bytes.Buffer
cmd.Stdout = &b
cmd.Stderr = &b
cmd.Start()
time.Sleep(500 * time.Millisecond)
defer cmd.Process.Kill()
output := b.Bytes()
c.Assert(string(output), checker.Not(checker.Contains), "panic:")
c.Assert(string(output), checker.Contains, "Usage:")
}

View File

@@ -0,0 +1,209 @@
package main
import (
"net/http"
"os/exec"
"time"
"github.com/go-check/check"
"github.com/hashicorp/consul/api"
checker "github.com/vdemeester/shakers"
)
// Constraint test suite
type ConstraintSuite struct {
BaseSuite
consulIP string
consulClient *api.Client
}
func (s *ConstraintSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "constraints")
s.composeProject.Start(c)
consul := s.composeProject.Container(c, "consul")
s.consulIP = consul.NetworkSettings.IPAddress
config := api.DefaultConfig()
config.Address = s.consulIP + ":8500"
consulClient, err := api.NewClient(config)
if err != nil {
c.Fatalf("Error creating consul client")
}
s.consulClient = consulClient
// Wait for consul to elect itself leader
time.Sleep(2000 * time.Millisecond)
}
func (s *ConstraintSuite) registerService(name string, address string, port int, tags []string) error {
catalog := s.consulClient.Catalog()
_, err := catalog.Register(
&api.CatalogRegistration{
Node: address,
Address: address,
Service: &api.AgentService{
ID: name,
Service: name,
Address: address,
Port: port,
Tags: tags,
},
},
&api.WriteOptions{},
)
return err
}
func (s *ConstraintSuite) deregisterService(name string, address string) error {
catalog := s.consulClient.Catalog()
_, err := catalog.Deregister(
&api.CatalogDeregistration{
Node: address,
Address: address,
ServiceID: name,
},
&api.WriteOptions{},
)
return err
}
func (s *ConstraintSuite) TestMatchConstraintGlobal(c *check.C) {
cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--consulCatalog.domain=consul.localhost", "--configFile=fixtures/consul_catalog/simple.toml", "--constraints=tag==api")
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
nginx := s.composeProject.Container(c, "nginx")
err = s.registerService("test", nginx.NetworkSettings.IPAddress, 80, []string{"traefik.tags=api"})
c.Assert(err, checker.IsNil, check.Commentf("Error registering service"))
defer s.deregisterService("test", nginx.NetworkSettings.IPAddress)
time.Sleep(5000 * time.Millisecond)
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.consul.localhost"
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 200)
}
func (s *ConstraintSuite) TestDoesNotMatchConstraintGlobal(c *check.C) {
cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--consulCatalog.domain=consul.localhost", "--configFile=fixtures/consul_catalog/simple.toml", "--constraints=tag==api")
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
nginx := s.composeProject.Container(c, "nginx")
err = s.registerService("test", nginx.NetworkSettings.IPAddress, 80, []string{})
c.Assert(err, checker.IsNil, check.Commentf("Error registering service"))
defer s.deregisterService("test", nginx.NetworkSettings.IPAddress)
time.Sleep(5000 * time.Millisecond)
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.consul.localhost"
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 404)
}
func (s *ConstraintSuite) TestMatchConstraintProvider(c *check.C) {
cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--consulCatalog.domain=consul.localhost", "--configFile=fixtures/consul_catalog/simple.toml", "--consulCatalog.constraints=tag==api")
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
nginx := s.composeProject.Container(c, "nginx")
err = s.registerService("test", nginx.NetworkSettings.IPAddress, 80, []string{"traefik.tags=api"})
c.Assert(err, checker.IsNil, check.Commentf("Error registering service"))
defer s.deregisterService("test", nginx.NetworkSettings.IPAddress)
time.Sleep(5000 * time.Millisecond)
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.consul.localhost"
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 200)
}
func (s *ConstraintSuite) TestDoesNotMatchConstraintProvider(c *check.C) {
cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--consulCatalog.domain=consul.localhost", "--configFile=fixtures/consul_catalog/simple.toml", "--consulCatalog.constraints=tag==api")
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
nginx := s.composeProject.Container(c, "nginx")
err = s.registerService("test", nginx.NetworkSettings.IPAddress, 80, []string{})
c.Assert(err, checker.IsNil, check.Commentf("Error registering service"))
defer s.deregisterService("test", nginx.NetworkSettings.IPAddress)
time.Sleep(5000 * time.Millisecond)
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.consul.localhost"
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 404)
}
func (s *ConstraintSuite) TestMatchMultipleConstraint(c *check.C) {
cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--consulCatalog.domain=consul.localhost", "--configFile=fixtures/consul_catalog/simple.toml", "--consulCatalog.constraints=tag==api", "--constraints=tag!=us-*")
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
nginx := s.composeProject.Container(c, "nginx")
err = s.registerService("test", nginx.NetworkSettings.IPAddress, 80, []string{"traefik.tags=api", "traefik.tags=eu-1"})
c.Assert(err, checker.IsNil, check.Commentf("Error registering service"))
defer s.deregisterService("test", nginx.NetworkSettings.IPAddress)
time.Sleep(5000 * time.Millisecond)
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.consul.localhost"
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 200)
}
func (s *ConstraintSuite) TestDoesNotMatchMultipleConstraint(c *check.C) {
cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--consulCatalog.domain=consul.localhost", "--configFile=fixtures/consul_catalog/simple.toml", "--consulCatalog.constraints=tag==api", "--constraints=tag!=us-*")
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
nginx := s.composeProject.Container(c, "nginx")
err = s.registerService("test", nginx.NetworkSettings.IPAddress, 80, []string{"traefik.tags=api", "traefik.tags=us-1"})
c.Assert(err, checker.IsNil, check.Commentf("Error registering service"))
defer s.deregisterService("test", nginx.NetworkSettings.IPAddress)
time.Sleep(5000 * time.Millisecond)
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.consul.localhost"
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 404)
}

View File

@@ -0,0 +1,113 @@
package main
import (
"io/ioutil"
"net/http"
"os/exec"
"time"
"github.com/go-check/check"
"github.com/hashicorp/consul/api"
checker "github.com/vdemeester/shakers"
)
// Consul catalog test suites
type ConsulCatalogSuite struct {
BaseSuite
consulIP string
consulClient *api.Client
}
func (s *ConsulCatalogSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "consul_catalog")
s.composeProject.Start(c)
consul := s.composeProject.Container(c, "consul")
s.consulIP = consul.NetworkSettings.IPAddress
config := api.DefaultConfig()
config.Address = s.consulIP + ":8500"
consulClient, err := api.NewClient(config)
if err != nil {
c.Fatalf("Error creating consul client")
}
s.consulClient = consulClient
// Wait for consul to elect itself leader
time.Sleep(2000 * time.Millisecond)
}
func (s *ConsulCatalogSuite) registerService(name string, address string, port int, tags []string) error {
catalog := s.consulClient.Catalog()
_, err := catalog.Register(
&api.CatalogRegistration{
Node: address,
Address: address,
Service: &api.AgentService{
ID: name,
Service: name,
Address: address,
Port: port,
Tags: tags,
},
},
&api.WriteOptions{},
)
return err
}
func (s *ConsulCatalogSuite) deregisterService(name string, address string) error {
catalog := s.consulClient.Catalog()
_, err := catalog.Deregister(
&api.CatalogDeregistration{
Node: address,
Address: address,
ServiceID: name,
},
&api.WriteOptions{},
)
return err
}
func (s *ConsulCatalogSuite) TestSimpleConfiguration(c *check.C) {
cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--configFile=fixtures/consul_catalog/simple.toml")
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
time.Sleep(500 * time.Millisecond)
// TODO validate : run on 80
resp, err := http.Get("http://127.0.0.1:8000/")
// Expected a 404 as we did not configure anything
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 404)
}
func (s *ConsulCatalogSuite) TestSingleService(c *check.C) {
cmd := exec.Command(traefikBinary, "--consulCatalog", "--consulCatalog.endpoint="+s.consulIP+":8500", "--consulCatalog.domain=consul.localhost", "--configFile=fixtures/consul_catalog/simple.toml")
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
nginx := s.composeProject.Container(c, "nginx")
err = s.registerService("test", nginx.NetworkSettings.IPAddress, 80, []string{})
c.Assert(err, checker.IsNil, check.Commentf("Error registering service"))
defer s.deregisterService("test", nginx.NetworkSettings.IPAddress)
time.Sleep(5000 * time.Millisecond)
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.consul.localhost"
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 200)
_, err = ioutil.ReadAll(resp.Body)
c.Assert(err, checker.IsNil)
}

View File

@@ -5,21 +5,519 @@ import (
"os/exec"
"time"
"context"
"github.com/containous/staert"
"github.com/docker/libkv"
"github.com/docker/libkv/store"
"github.com/docker/libkv/store/consul"
"github.com/go-check/check"
"errors"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/integration/utils"
"github.com/containous/traefik/provider"
checker "github.com/vdemeester/shakers"
check "gopkg.in/check.v1"
"io/ioutil"
"os"
"strings"
"sync"
)
// Consul test suites (using libcompose)
type ConsulSuite struct {
BaseSuite
kv store.Store
}
func (s *ConsulSuite) setupConsul(c *check.C) {
s.createComposeProject(c, "consul")
s.composeProject.Start(c)
consul.Register()
kv, err := libkv.NewStore(
store.CONSUL,
[]string{s.composeProject.Container(c, "consul").NetworkSettings.IPAddress + ":8500"},
&store.Config{
ConnectionTimeout: 10 * time.Second,
},
)
if err != nil {
c.Fatal("Cannot create store consul")
}
s.kv = kv
// wait for consul
err = utils.Try(60*time.Second, func() error {
_, err := kv.Exists("test")
if err != nil {
return err
}
return nil
})
c.Assert(err, checker.IsNil)
}
func (s *ConsulSuite) setupConsulTLS(c *check.C) {
s.createComposeProject(c, "consul_tls")
s.composeProject.Start(c)
consul.Register()
clientTLS := &provider.ClientTLS{
CA: "resources/tls/ca.cert",
Cert: "resources/tls/consul.cert",
Key: "resources/tls/consul.key",
InsecureSkipVerify: true,
}
TLSConfig, err := clientTLS.CreateTLSConfig()
c.Assert(err, checker.IsNil)
kv, err := libkv.NewStore(
store.CONSUL,
[]string{s.composeProject.Container(c, "consul").NetworkSettings.IPAddress + ":8585"},
&store.Config{
ConnectionTimeout: 10 * time.Second,
TLS: TLSConfig,
},
)
if err != nil {
c.Fatal("Cannot create store consul")
}
s.kv = kv
// wait for consul
err = utils.Try(60*time.Second, func() error {
_, err := kv.Exists("test")
if err != nil {
return err
}
return nil
})
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) {
cmd := exec.Command(traefikBinary, "fixtures/consul/simple.toml")
s.setupConsul(c)
consulHost := s.composeProject.Container(c, "consul").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/consul/simple.toml", struct{ ConsulHost string }{consulHost})
defer os.Remove(file)
cmd := exec.Command(traefikBinary, "--configFile="+file)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
time.Sleep(500 * time.Millisecond)
// TODO validate : run on 80
resp, err := http.Get("http://127.0.0.1/")
resp, err := http.Get("http://127.0.0.1:8000/")
// Expected a 404 as we did not comfigure anything
// Expected a 404 as we did not configure anything
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 404)
}
func (s *ConsulSuite) TestNominalConfiguration(c *check.C) {
s.setupConsul(c)
consulHost := s.composeProject.Container(c, "consul").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/consul/simple.toml", struct{ ConsulHost string }{consulHost})
defer os.Remove(file)
cmd := exec.Command(traefikBinary, "--configFile="+file)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
whoami1 := s.composeProject.Container(c, "whoami1")
whoami2 := s.composeProject.Container(c, "whoami2")
whoami3 := s.composeProject.Container(c, "whoami3")
whoami4 := s.composeProject.Container(c, "whoami4")
backend1 := map[string]string{
"traefik/backends/backend1/circuitbreaker/expression": "NetworkErrorRatio() > 0.5",
"traefik/backends/backend1/servers/server1/url": "http://" + whoami1.NetworkSettings.IPAddress + ":80",
"traefik/backends/backend1/servers/server1/weight": "10",
"traefik/backends/backend1/servers/server2/url": "http://" + whoami2.NetworkSettings.IPAddress + ":80",
"traefik/backends/backend1/servers/server2/weight": "1",
}
backend2 := map[string]string{
"traefik/backends/backend2/loadbalancer/method": "drr",
"traefik/backends/backend2/servers/server1/url": "http://" + whoami3.NetworkSettings.IPAddress + ":80",
"traefik/backends/backend2/servers/server1/weight": "1",
"traefik/backends/backend2/servers/server2/url": "http://" + whoami4.NetworkSettings.IPAddress + ":80",
"traefik/backends/backend2/servers/server2/weight": "2",
}
frontend1 := map[string]string{
"traefik/frontends/frontend1/backend": "backend2",
"traefik/frontends/frontend1/entrypoints": "http",
"traefik/frontends/frontend1/priority": "1",
"traefik/frontends/frontend1/routes/test_1/rule": "Host:test.localhost",
}
frontend2 := map[string]string{
"traefik/frontends/frontend2/backend": "backend1",
"traefik/frontends/frontend2/entrypoints": "http",
"traefik/frontends/frontend2/priority": "10",
"traefik/frontends/frontend2/routes/test_2/rule": "Path:/test",
}
for key, value := range backend1 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range backend2 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range frontend1 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range frontend2 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
// wait for consul
err = utils.Try(60*time.Second, func() error {
_, err := s.kv.Exists("traefik/frontends/frontend2/routes/test_2/rule")
if err != nil {
return err
}
return nil
})
c.Assert(err, checker.IsNil)
// wait for traefik
err = utils.TryRequest("http://127.0.0.1:8081/api/providers", 60*time.Second, func(res *http.Response) error {
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
if !strings.Contains(string(body), "Path:/test") {
return errors.New("Incorrect traefik config")
}
return nil
})
c.Assert(err, checker.IsNil)
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.localhost"
response, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(response.StatusCode, checker.Equals, 200)
body, err := ioutil.ReadAll(response.Body)
c.Assert(err, checker.IsNil)
if !strings.Contains(string(body), whoami3.NetworkSettings.IPAddress) &&
!strings.Contains(string(body), whoami4.NetworkSettings.IPAddress) {
c.Fail()
}
req, err = http.NewRequest("GET", "http://127.0.0.1:8000/test", nil)
c.Assert(err, checker.IsNil)
response, err = client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(response.StatusCode, checker.Equals, 200)
body, err = ioutil.ReadAll(response.Body)
c.Assert(err, checker.IsNil)
if !strings.Contains(string(body), whoami1.NetworkSettings.IPAddress) &&
!strings.Contains(string(body), whoami2.NetworkSettings.IPAddress) {
c.Fail()
}
req, err = http.NewRequest("GET", "http://127.0.0.1:8000/test2", nil)
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 404)
req, err = http.NewRequest("GET", "http://127.0.0.1:8000/", nil)
req.Host = "test2.localhost"
resp, err = client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 404)
}
func (s *ConsulSuite) TestGlobalConfiguration(c *check.C) {
s.setupConsul(c)
consulHost := s.composeProject.Container(c, "consul").NetworkSettings.IPAddress
err := s.kv.Put("traefik/entrypoints/http/address", []byte(":8001"), nil)
c.Assert(err, checker.IsNil)
// wait for consul
err = utils.Try(60*time.Second, func() error {
_, err := s.kv.Exists("traefik/entrypoints/http/address")
if err != nil {
return err
}
return nil
})
c.Assert(err, checker.IsNil)
// start traefik
cmd := exec.Command(traefikBinary, "--configFile=fixtures/simple_web.toml", "--consul", "--consul.endpoint="+consulHost+":8500")
// cmd.Stdout = os.Stdout
// cmd.Stderr = os.Stderr
err = cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
whoami1 := s.composeProject.Container(c, "whoami1")
whoami2 := s.composeProject.Container(c, "whoami2")
whoami3 := s.composeProject.Container(c, "whoami3")
whoami4 := s.composeProject.Container(c, "whoami4")
backend1 := map[string]string{
"traefik/backends/backend1/circuitbreaker/expression": "NetworkErrorRatio() > 0.5",
"traefik/backends/backend1/servers/server1/url": "http://" + whoami1.NetworkSettings.IPAddress + ":80",
"traefik/backends/backend1/servers/server1/weight": "10",
"traefik/backends/backend1/servers/server2/url": "http://" + whoami2.NetworkSettings.IPAddress + ":80",
"traefik/backends/backend1/servers/server2/weight": "1",
}
backend2 := map[string]string{
"traefik/backends/backend2/loadbalancer/method": "drr",
"traefik/backends/backend2/servers/server1/url": "http://" + whoami3.NetworkSettings.IPAddress + ":80",
"traefik/backends/backend2/servers/server1/weight": "1",
"traefik/backends/backend2/servers/server2/url": "http://" + whoami4.NetworkSettings.IPAddress + ":80",
"traefik/backends/backend2/servers/server2/weight": "2",
}
frontend1 := map[string]string{
"traefik/frontends/frontend1/backend": "backend2",
"traefik/frontends/frontend1/entrypoints": "http",
"traefik/frontends/frontend1/priority": "1",
"traefik/frontends/frontend1/routes/test_1/rule": "Host:test.localhost",
}
frontend2 := map[string]string{
"traefik/frontends/frontend2/backend": "backend1",
"traefik/frontends/frontend2/entrypoints": "http",
"traefik/frontends/frontend2/priority": "10",
"traefik/frontends/frontend2/routes/test_2/rule": "Path:/test",
}
for key, value := range backend1 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range backend2 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range frontend1 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range frontend2 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
// wait for consul
err = utils.Try(60*time.Second, func() error {
_, err := s.kv.Exists("traefik/frontends/frontend2/routes/test_2/rule")
if err != nil {
return err
}
return nil
})
c.Assert(err, checker.IsNil)
// wait for traefik
err = utils.TryRequest("http://127.0.0.1:8080/api/providers", 60*time.Second, func(res *http.Response) error {
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
if !strings.Contains(string(body), "Path:/test") {
return errors.New("Incorrect traefik config")
}
return nil
})
c.Assert(err, checker.IsNil)
//check
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8001/", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.localhost"
response, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(response.StatusCode, checker.Equals, 200)
}
func (s *ConsulSuite) skipTestGlobalConfigurationWithClientTLS(c *check.C) {
c.Skip("wait for relative path issue in the composefile")
s.setupConsulTLS(c)
consulHost := s.composeProject.Container(c, "consul").NetworkSettings.IPAddress
err := s.kv.Put("traefik/web/address", []byte(":8081"), nil)
c.Assert(err, checker.IsNil)
// wait for consul
err = utils.Try(60*time.Second, func() error {
_, err := s.kv.Exists("traefik/web/address")
if err != nil {
return err
}
return nil
})
c.Assert(err, checker.IsNil)
// start traefik
cmd := exec.Command(traefikBinary, "--configFile=fixtures/simple_web.toml",
"--consul", "--consul.endpoint="+consulHost+":8585",
"--consul.tls.ca=resources/tls/ca.cert",
"--consul.tls.cert=resources/tls/consul.cert",
"--consul.tls.key=resources/tls/consul.key",
"--consul.tls.insecureskipverify")
// cmd.Stdout = os.Stdout
// cmd.Stderr = os.Stderr
err = cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
// wait for traefik
err = utils.TryRequest("http://127.0.0.1:8081/api/providers", 60*time.Second, func(res *http.Response) error {
_, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
return nil
})
c.Assert(err, checker.IsNil)
}
func (s *ConsulSuite) TestCommandStoreConfig(c *check.C) {
s.setupConsul(c)
consulHost := s.composeProject.Container(c, "consul").NetworkSettings.IPAddress
cmd := exec.Command(traefikBinary, "storeconfig", "--configFile=fixtures/simple_web.toml", "--consul.endpoint="+consulHost+":8500")
err := cmd.Start()
c.Assert(err, checker.IsNil)
// wait for traefik finish without error
cmd.Wait()
//CHECK
checkmap := map[string]string{
"/traefik/loglevel": "DEBUG",
"/traefik/defaultentrypoints/0": "http",
"/traefik/entrypoints/http/address": ":8000",
"/traefik/web/address": ":8080",
"/traefik/consul/endpoint": (consulHost + ":8500"),
}
for key, value := range checkmap {
var p *store.KVPair
err = utils.Try(60*time.Second, func() error {
p, err = s.kv.Get(key)
if err != nil {
return err
}
return nil
})
c.Assert(err, checker.IsNil)
c.Assert(string(p.Value), checker.Equals, value)
}
}
type TestStruct struct {
String string
Int int
}
func (s *ConsulSuite) TestDatastore(c *check.C) {
s.setupConsul(c)
consulHost := s.composeProject.Container(c, "consul").NetworkSettings.IPAddress
kvSource, err := staert.NewKvSource(store.CONSUL, []string{consulHost + ":8500"}, &store.Config{
ConnectionTimeout: 10 * time.Second,
}, "traefik")
c.Assert(err, checker.IsNil)
ctx := context.Background()
datastore1, err := cluster.NewDataStore(ctx, *kvSource, &TestStruct{}, nil)
c.Assert(err, checker.IsNil)
datastore2, err := cluster.NewDataStore(ctx, *kvSource, &TestStruct{}, nil)
c.Assert(err, checker.IsNil)
setter1, _, err := datastore1.Begin()
c.Assert(err, checker.IsNil)
err = setter1.Commit(&TestStruct{
String: "foo",
Int: 1,
})
c.Assert(err, checker.IsNil)
time.Sleep(2 * time.Second)
test1 := datastore1.Get().(*TestStruct)
c.Assert(test1.String, checker.Equals, "foo")
test2 := datastore2.Get().(*TestStruct)
c.Assert(test2.String, checker.Equals, "foo")
setter2, _, err := datastore2.Begin()
c.Assert(err, checker.IsNil)
err = setter2.Commit(&TestStruct{
String: "bar",
Int: 2,
})
c.Assert(err, checker.IsNil)
time.Sleep(2 * time.Second)
test1 = datastore1.Get().(*TestStruct)
c.Assert(test1.String, checker.Equals, "bar")
test2 = datastore2.Get().(*TestStruct)
c.Assert(test2.String, checker.Equals, "bar")
wg := &sync.WaitGroup{}
wg.Add(4)
go func() {
for i := 0; i < 100; i++ {
setter1, _, err := datastore1.Begin()
c.Assert(err, checker.IsNil)
err = setter1.Commit(&TestStruct{
String: "datastore1",
Int: i,
})
c.Assert(err, checker.IsNil)
}
wg.Done()
}()
go func() {
for i := 0; i < 100; i++ {
setter2, _, err := datastore2.Begin()
c.Assert(err, checker.IsNil)
err = setter2.Commit(&TestStruct{
String: "datastore2",
Int: i,
})
c.Assert(err, checker.IsNil)
}
wg.Done()
}()
go func() {
for i := 0; i < 100; i++ {
test1 := datastore1.Get().(*TestStruct)
c.Assert(test1, checker.NotNil)
}
wg.Done()
}()
go func() {
for i := 0; i < 100; i++ {
test2 := datastore2.Get().(*TestStruct)
c.Assert(test2, checker.NotNil)
}
wg.Done()
}()
wg.Wait()
}

View File

@@ -1,31 +1,190 @@
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
"strings"
"time"
"github.com/docker/docker/pkg/namesgenerator"
"github.com/go-check/check"
d "github.com/libkermit/docker"
docker "github.com/libkermit/docker-check"
checker "github.com/vdemeester/shakers"
check "gopkg.in/check.v1"
)
var (
// Label added to started container to identify them as part of the integration test
TestLabel = "io.traefik.test"
// Images to have or pull before the build in order to make it work
// FIXME handle this offline but loading them before build
RequiredImages = map[string]string{
"swarm": "1.0.0",
"nginx": "1",
}
)
// Docker test suites
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) 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) SetUpSuite(c *check.C) {
project := docker.NewProjectFromEnv(c)
s.project = project
// Pull required images
for repository, tag := range RequiredImages {
image := fmt.Sprintf("%s:%s", repository, tag)
s.project.Pull(c, image)
}
}
func (s *DockerSuite) TearDownTest(c *check.C) {
s.project.Clean(c, os.Getenv("CIRCLECI") != "")
}
func (s *DockerSuite) TestSimpleConfiguration(c *check.C) {
file := s.adaptFileForHost(c, "fixtures/docker/simple.toml")
defer os.Remove(file)
cmd := exec.Command(traefikBinary, file)
cmd := exec.Command(traefikBinary, "--configFile="+file)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
time.Sleep(500 * time.Millisecond)
// TODO validate : run on 80
resp, err := http.Get("http://127.0.0.1/")
resp, err := http.Get("http://127.0.0.1:8000/")
c.Assert(err, checker.IsNil)
// Expected a 404 as we did not comfigure anything
c.Assert(resp.StatusCode, checker.Equals, 404)
}
func (s *DockerSuite) TestDefaultDockerContainers(c *check.C) {
file := s.adaptFileForHost(c, "fixtures/docker/simple.toml")
defer os.Remove(file)
name := s.startContainer(c, "swarm:1.0.0", "manage", "token://blablabla")
// Start traefik
cmd := exec.Command(traefikBinary, "--configFile="+file)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
// FIXME Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
time.Sleep(1500 * time.Millisecond)
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8000/version", nil)
c.Assert(err, checker.IsNil)
req.Host = fmt.Sprintf("%s.docker.localhost", strings.Replace(name, "_", "-", -1))
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 200)
body, err := ioutil.ReadAll(resp.Body)
c.Assert(err, checker.IsNil)
var version map[string]interface{}
c.Assert(json.Unmarshal(body, &version), checker.IsNil)
c.Assert(version["Version"], checker.Equals, "swarm/1.0.0")
}
func (s *DockerSuite) TestDockerContainersWithLabels(c *check.C) {
file := s.adaptFileForHost(c, "fixtures/docker/simple.toml")
defer os.Remove(file)
// Start a container with some labels
labels := map[string]string{
"traefik.frontend.rule": "Host:my.super.host",
}
s.startContainerWithLabels(c, "swarm:1.0.0", labels, "manage", "token://blabla")
// Start traefik
cmd := exec.Command(traefikBinary, "--configFile="+file)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
// FIXME Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
time.Sleep(1500 * time.Millisecond)
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8000/version", nil)
c.Assert(err, checker.IsNil)
req.Host = fmt.Sprintf("my.super.host")
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 200)
body, err := ioutil.ReadAll(resp.Body)
c.Assert(err, checker.IsNil)
var version map[string]interface{}
c.Assert(json.Unmarshal(body, &version), checker.IsNil)
c.Assert(version["Version"], checker.Equals, "swarm/1.0.0")
}
func (s *DockerSuite) TestDockerContainersWithOneMissingLabels(c *check.C) {
file := s.adaptFileForHost(c, "fixtures/docker/simple.toml")
defer os.Remove(file)
// Start a container with some labels
labels := map[string]string{
"traefik.frontend.value": "my.super.host",
}
s.startContainerWithLabels(c, "swarm:1.0.0", labels, "manage", "token://blabla")
// Start traefik
cmd := exec.Command(traefikBinary, "--configFile="+file)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
// FIXME Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
time.Sleep(1500 * time.Millisecond)
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8000/version", nil)
c.Assert(err, checker.IsNil)
req.Host = fmt.Sprintf("my.super.host")
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 404)
killErr := cmd.Process.Kill()
c.Assert(killErr, checker.IsNil)
}

468
integration/etcd_test.go Normal file
View File

@@ -0,0 +1,468 @@
package main
import (
"github.com/go-check/check"
"net/http"
"os/exec"
"time"
checker "github.com/vdemeester/shakers"
"crypto/tls"
"errors"
"fmt"
"github.com/containous/traefik/integration/utils"
"github.com/docker/libkv"
"github.com/docker/libkv/store"
"github.com/docker/libkv/store/etcd"
"io/ioutil"
"os"
"strings"
)
// Etcd test suites (using libcompose)
type EtcdSuite struct {
BaseSuite
kv store.Store
}
func (s *EtcdSuite) SetUpTest(c *check.C) {
s.createComposeProject(c, "etcd")
s.composeProject.Start(c)
etcd.Register()
url := s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress + ":2379"
kv, err := libkv.NewStore(
store.ETCD,
[]string{url},
&store.Config{
ConnectionTimeout: 10 * time.Second,
},
)
if err != nil {
c.Fatal("Cannot create store etcd")
}
s.kv = kv
// wait for etcd
err = utils.Try(60*time.Second, func() error {
_, err := kv.Exists("test")
if err != nil {
return fmt.Errorf("Etcd connection error to %s: %v", url, err)
}
return nil
})
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) {
etcdHost := s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/etcd/simple.toml", struct{ EtcdHost string }{etcdHost})
defer os.Remove(file)
cmd := exec.Command(traefikBinary, "--configFile="+file)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
time.Sleep(1000 * time.Millisecond)
// TODO validate : run on 80
resp, err := http.Get("http://127.0.0.1:8000/")
// Expected a 404 as we did not configure anything
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 404)
}
func (s *EtcdSuite) TestNominalConfiguration(c *check.C) {
etcdHost := s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/etcd/simple.toml", struct{ EtcdHost string }{etcdHost})
defer os.Remove(file)
cmd := exec.Command(traefikBinary, "--configFile="+file)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
whoami1 := s.composeProject.Container(c, "whoami1")
whoami2 := s.composeProject.Container(c, "whoami2")
whoami3 := s.composeProject.Container(c, "whoami3")
whoami4 := s.composeProject.Container(c, "whoami4")
backend1 := map[string]string{
"/traefik/backends/backend1/circuitbreaker/expression": "NetworkErrorRatio() > 0.5",
"/traefik/backends/backend1/servers/server1/url": "http://" + whoami1.NetworkSettings.IPAddress + ":80",
"/traefik/backends/backend1/servers/server1/weight": "10",
"/traefik/backends/backend1/servers/server2/url": "http://" + whoami2.NetworkSettings.IPAddress + ":80",
"/traefik/backends/backend1/servers/server2/weight": "1",
}
backend2 := map[string]string{
"/traefik/backends/backend2/loadbalancer/method": "drr",
"/traefik/backends/backend2/servers/server1/url": "http://" + whoami3.NetworkSettings.IPAddress + ":80",
"/traefik/backends/backend2/servers/server1/weight": "1",
"/traefik/backends/backend2/servers/server2/url": "http://" + whoami4.NetworkSettings.IPAddress + ":80",
"/traefik/backends/backend2/servers/server2/weight": "2",
}
frontend1 := map[string]string{
"/traefik/frontends/frontend1/backend": "backend2",
"/traefik/frontends/frontend1/entrypoints": "http",
"/traefik/frontends/frontend1/priority": "1",
"/traefik/frontends/frontend1/routes/test_1/rule": "Host:test.localhost",
}
frontend2 := map[string]string{
"/traefik/frontends/frontend2/backend": "backend1",
"/traefik/frontends/frontend2/entrypoints": "http",
"/traefik/frontends/frontend2/priority": "10",
"/traefik/frontends/frontend2/routes/test_2/rule": "Path:/test",
}
for key, value := range backend1 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range backend2 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range frontend1 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range frontend2 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
// wait for etcd
err = utils.Try(60*time.Second, func() error {
_, err := s.kv.Exists("/traefik/frontends/frontend2/routes/test_2/rule")
if err != nil {
return err
}
return nil
})
c.Assert(err, checker.IsNil)
// wait for traefik
err = utils.TryRequest("http://127.0.0.1:8081/api/providers", 60*time.Second, func(res *http.Response) error {
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
if !strings.Contains(string(body), "Path:/test") {
return errors.New("Incorrect traefik config")
}
return nil
})
c.Assert(err, checker.IsNil)
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.localhost"
response, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(response.StatusCode, checker.Equals, 200)
body, err := ioutil.ReadAll(response.Body)
c.Assert(err, checker.IsNil)
if !strings.Contains(string(body), whoami3.NetworkSettings.IPAddress) &&
!strings.Contains(string(body), whoami4.NetworkSettings.IPAddress) {
c.Fail()
}
req, err = http.NewRequest("GET", "http://127.0.0.1:8000/test", nil)
c.Assert(err, checker.IsNil)
response, err = client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(response.StatusCode, checker.Equals, 200)
body, err = ioutil.ReadAll(response.Body)
c.Assert(err, checker.IsNil)
if !strings.Contains(string(body), whoami1.NetworkSettings.IPAddress) &&
!strings.Contains(string(body), whoami2.NetworkSettings.IPAddress) {
c.Fail()
}
req, err = http.NewRequest("GET", "http://127.0.0.1:8000/test2", nil)
req.Host = "test2.localhost"
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 404)
req, err = http.NewRequest("GET", "http://127.0.0.1:8000/", nil)
resp, err = client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 404)
}
func (s *EtcdSuite) TestGlobalConfiguration(c *check.C) {
etcdHost := s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress
err := s.kv.Put("/traefik/entrypoints/http/address", []byte(":8001"), nil)
c.Assert(err, checker.IsNil)
// wait for etcd
err = utils.Try(60*time.Second, func() error {
_, err := s.kv.Exists("/traefik/entrypoints/http/address")
if err != nil {
return err
}
return nil
})
c.Assert(err, checker.IsNil)
// start traefik
cmd := exec.Command(traefikBinary, "--configFile=fixtures/simple_web.toml", "--etcd", "--etcd.endpoint="+etcdHost+":4001")
// cmd.Stdout = os.Stdout
// cmd.Stderr = os.Stderr
err = cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
whoami1 := s.composeProject.Container(c, "whoami1")
whoami2 := s.composeProject.Container(c, "whoami2")
whoami3 := s.composeProject.Container(c, "whoami3")
whoami4 := s.composeProject.Container(c, "whoami4")
backend1 := map[string]string{
"/traefik/backends/backend1/circuitbreaker/expression": "NetworkErrorRatio() > 0.5",
"/traefik/backends/backend1/servers/server1/url": "http://" + whoami1.NetworkSettings.IPAddress + ":80",
"/traefik/backends/backend1/servers/server1/weight": "10",
"/traefik/backends/backend1/servers/server2/url": "http://" + whoami2.NetworkSettings.IPAddress + ":80",
"/traefik/backends/backend1/servers/server2/weight": "1",
}
backend2 := map[string]string{
"/traefik/backends/backend2/loadbalancer/method": "drr",
"/traefik/backends/backend2/servers/server1/url": "http://" + whoami3.NetworkSettings.IPAddress + ":80",
"/traefik/backends/backend2/servers/server1/weight": "1",
"/traefik/backends/backend2/servers/server2/url": "http://" + whoami4.NetworkSettings.IPAddress + ":80",
"/traefik/backends/backend2/servers/server2/weight": "2",
}
frontend1 := map[string]string{
"/traefik/frontends/frontend1/backend": "backend2",
"/traefik/frontends/frontend1/entrypoints": "http",
"/traefik/frontends/frontend1/priority": "1",
"/traefik/frontends/frontend1/routes/test_1/rule": "Host:test.localhost",
}
frontend2 := map[string]string{
"/traefik/frontends/frontend2/backend": "backend1",
"/traefik/frontends/frontend2/entrypoints": "http",
"/traefik/frontends/frontend2/priority": "10",
"/traefik/frontends/frontend2/routes/test_2/rule": "Path:/test",
}
for key, value := range backend1 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range backend2 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range frontend1 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range frontend2 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
// wait for etcd
err = utils.Try(60*time.Second, func() error {
_, err := s.kv.Exists("/traefik/frontends/frontend2/routes/test_2/rule")
if err != nil {
return err
}
return nil
})
c.Assert(err, checker.IsNil)
// wait for traefik
err = utils.TryRequest("http://127.0.0.1:8080/api/providers", 60*time.Second, func(res *http.Response) error {
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
if !strings.Contains(string(body), "Path:/test") {
return errors.New("Incorrect traefik config")
}
return nil
})
c.Assert(err, checker.IsNil)
//check
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8001/", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.localhost"
response, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(response.StatusCode, checker.Equals, 200)
}
func (s *EtcdSuite) TestCertificatesContentstWithSNIConfigHandshake(c *check.C) {
etcdHost := s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress
// start traefik
cmd := exec.Command(traefikBinary, "--configFile=fixtures/simple_web.toml", "--etcd", "--etcd.endpoint="+etcdHost+":4001")
// cmd.Stdout = os.Stdout
// cmd.Stderr = os.Stderr
whoami1 := s.composeProject.Container(c, "whoami1")
whoami2 := s.composeProject.Container(c, "whoami2")
whoami3 := s.composeProject.Container(c, "whoami3")
whoami4 := s.composeProject.Container(c, "whoami4")
//Copy the contents of the certificate files into ETCD
snitestComCert, err := ioutil.ReadFile("fixtures/https/snitest.com.cert")
c.Assert(err, checker.IsNil)
snitestComKey, err := ioutil.ReadFile("fixtures/https/snitest.com.key")
c.Assert(err, checker.IsNil)
snitestOrgCert, err := ioutil.ReadFile("fixtures/https/snitest.org.cert")
c.Assert(err, checker.IsNil)
snitestOrgKey, err := ioutil.ReadFile("fixtures/https/snitest.org.key")
c.Assert(err, checker.IsNil)
globalConfig := map[string]string{
"/traefik/entrypoints/https/address": ":4443",
"/traefik/entrypoints/https/tls/certificates/0/certfile": string(snitestComCert),
"/traefik/entrypoints/https/tls/certificates/0/keyfile": string(snitestComKey),
"/traefik/entrypoints/https/tls/certificates/1/certfile": string(snitestOrgCert),
"/traefik/entrypoints/https/tls/certificates/1/keyfile": string(snitestOrgKey),
"/traefik/defaultentrypoints/0": "https",
}
backend1 := map[string]string{
"/traefik/backends/backend1/circuitbreaker/expression": "NetworkErrorRatio() > 0.5",
"/traefik/backends/backend1/servers/server1/url": "http://" + whoami1.NetworkSettings.IPAddress + ":80",
"/traefik/backends/backend1/servers/server1/weight": "10",
"/traefik/backends/backend1/servers/server2/url": "http://" + whoami2.NetworkSettings.IPAddress + ":80",
"/traefik/backends/backend1/servers/server2/weight": "1",
}
backend2 := map[string]string{
"/traefik/backends/backend2/loadbalancer/method": "drr",
"/traefik/backends/backend2/servers/server1/url": "http://" + whoami3.NetworkSettings.IPAddress + ":80",
"/traefik/backends/backend2/servers/server1/weight": "1",
"/traefik/backends/backend2/servers/server2/url": "http://" + whoami4.NetworkSettings.IPAddress + ":80",
"/traefik/backends/backend2/servers/server2/weight": "2",
}
frontend1 := map[string]string{
"/traefik/frontends/frontend1/backend": "backend2",
"/traefik/frontends/frontend1/entrypoints": "http",
"/traefik/frontends/frontend1/priority": "1",
"/traefik/frontends/frontend1/routes/test_1/rule": "Host:snitest.com",
}
frontend2 := map[string]string{
"/traefik/frontends/frontend2/backend": "backend1",
"/traefik/frontends/frontend2/entrypoints": "http",
"/traefik/frontends/frontend2/priority": "10",
"/traefik/frontends/frontend2/routes/test_2/rule": "Host:snitest.org",
}
for key, value := range globalConfig {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range backend1 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range backend2 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range frontend1 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
for key, value := range frontend2 {
err := s.kv.Put(key, []byte(value), nil)
c.Assert(err, checker.IsNil)
}
// wait for etcd
err = utils.Try(60*time.Second, func() error {
_, err := s.kv.Exists("/traefik/frontends/frontend2/routes/test_2/rule")
if err != nil {
return err
}
return nil
})
c.Assert(err, checker.IsNil)
err = cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
// wait for traefik
err = utils.TryRequest("http://127.0.0.1:8080/api/providers", 60*time.Second, func(res *http.Response) error {
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
if !strings.Contains(string(body), "Host:snitest.org") {
return errors.New("Incorrect traefik config")
}
return nil
})
c.Assert(err, checker.IsNil)
//check
tlsConfig := &tls.Config{
InsecureSkipVerify: true,
ServerName: "snitest.com",
}
conn, err := tls.Dial("tcp", "127.0.0.1:4443", tlsConfig)
c.Assert(err, checker.IsNil, check.Commentf("failed to connect to server"))
defer conn.Close()
err = conn.Handshake()
c.Assert(err, checker.IsNil, check.Commentf("TLS handshake error"))
cs := conn.ConnectionState()
err = cs.PeerCertificates[0].VerifyHostname("snitest.com")
c.Assert(err, checker.IsNil, check.Commentf("certificate did not match SNI servername"))
}
func (s *EtcdSuite) TestCommandStoreConfig(c *check.C) {
etcdHost := s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress
cmd := exec.Command(traefikBinary, "storeconfig", "--configFile=fixtures/simple_web.toml", "--etcd.endpoint="+etcdHost+":4001")
err := cmd.Start()
c.Assert(err, checker.IsNil)
// wait for traefik finish without error
cmd.Wait()
//CHECK
checkmap := map[string]string{
"/traefik/loglevel": "DEBUG",
"/traefik/defaultentrypoints/0": "http",
"/traefik/entrypoints/http/address": ":8000",
"/traefik/web/address": ":8080",
"/traefik/etcd/endpoint": (etcdHost + ":4001"),
}
for key, value := range checkmap {
var p *store.KVPair
err = utils.Try(60*time.Second, func() error {
p, err = s.kv.Get(key)
if err != nil {
return err
}
return nil
})
c.Assert(err, checker.IsNil)
c.Assert(string(p.Value), checker.Equals, value)
}
}

111
integration/eureka_test.go Normal file
View File

@@ -0,0 +1,111 @@
package main
import (
"bytes"
"errors"
"io/ioutil"
"net/http"
"os"
"os/exec"
"strings"
"text/template"
"time"
"github.com/containous/traefik/integration/utils"
"github.com/go-check/check"
checker "github.com/vdemeester/shakers"
)
// Eureka test suites (using libcompose)
type EurekaSuite struct{ BaseSuite }
func (s *EurekaSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "eureka")
s.composeProject.Start(c)
}
func (s *EurekaSuite) TestSimpleConfiguration(c *check.C) {
eurekaHost := s.composeProject.Container(c, "eureka").NetworkSettings.IPAddress
whoami1Host := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/eureka/simple.toml", struct{ EurekaHost string }{eurekaHost})
defer os.Remove(file)
cmd := exec.Command(traefikBinary, "--configFile="+file)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
eurekaURL := "http://" + eurekaHost + ":8761/eureka/apps"
// wait for eureka
err = utils.TryRequest(eurekaURL, 60*time.Second, func(res *http.Response) error {
if err != nil {
return err
}
return nil
})
c.Assert(err, checker.IsNil)
eurekaTemplate := `
{
"instance": {
"hostName": "{{ .IP }}",
"app": "{{ .ID }}",
"ipAddr": "{{ .IP }}",
"status": "UP",
"port": {
"$": {{ .Port }},
"@enabled": "true"
},
"dataCenterInfo": {
"name": "MyOwn"
}
}
}`
tmpl, err := template.New("eurekaTemlate").Parse(eurekaTemplate)
c.Assert(err, checker.IsNil)
buf := new(bytes.Buffer)
templateVars := map[string]string{
"ID": "tests-integration-traefik",
"IP": whoami1Host,
"Port": "80",
}
// add in eureka
err = tmpl.Execute(buf, templateVars)
resp, err := http.Post(eurekaURL+"/tests-integration-traefik", "application/json", strings.NewReader(buf.String()))
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 204)
// wait for traefik
err = utils.TryRequest("http://127.0.0.1:8080/api/providers", 60*time.Second, func(res *http.Response) error {
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
if !strings.Contains(string(body), "Host:tests-integration-traefik") {
return errors.New("Incorrect traefik config")
}
return nil
})
c.Assert(err, checker.IsNil)
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil)
c.Assert(err, checker.IsNil)
req.Host = "tests-integration-traefik"
resp, err = client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 200)
// TODO validate : run on 80
resp, err = http.Get("http://127.0.0.1:8000/")
// Expected a 404 as we did not configure anything
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 404)
}

View File

@@ -5,18 +5,28 @@ import (
"os/exec"
"time"
"github.com/go-check/check"
checker "github.com/vdemeester/shakers"
check "gopkg.in/check.v1"
)
// File test suites
type FileSuite struct{ BaseSuite }
func (s *FileSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "file")
s.composeProject.Start(c)
}
func (s *FileSuite) TestSimpleConfiguration(c *check.C) {
cmd := exec.Command(traefikBinary, "fixtures/file/simple.toml")
cmd := exec.Command(traefikBinary, "--configFile=fixtures/file/simple.toml")
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
time.Sleep(500 * time.Millisecond)
resp, err := http.Get("http://127.0.0.1/")
time.Sleep(1000 * time.Millisecond)
resp, err := http.Get("http://127.0.0.1:8000/")
// Expected a 404 as we did not configure anything
c.Assert(err, checker.IsNil)
@@ -25,13 +35,13 @@ func (s *FileSuite) TestSimpleConfiguration(c *check.C) {
// #56 regression test, make sure it does not fail
func (s *FileSuite) TestSimpleConfigurationNoPanic(c *check.C) {
cmd := exec.Command(traefikBinary, "fixtures/file/56-simple-panic.toml")
cmd := exec.Command(traefikBinary, "--configFile=fixtures/file/56-simple-panic.toml")
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
time.Sleep(500 * time.Millisecond)
resp, err := http.Get("http://127.0.0.1/")
time.Sleep(1000 * time.Millisecond)
resp, err := http.Get("http://127.0.0.1:8000/")
// Expected a 404 as we did not configure anything
c.Assert(err, checker.IsNil)

View File

@@ -0,0 +1,46 @@
################################################################
# Global configuration
################################################################
traefikLogsFile = "traefik.log"
accessLogsFile = "access.log"
logLevel = "ERROR"
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":8000"
################################################################
# Web configuration backend
################################################################
[web]
address = ":7888"
################################################################
# File configuration backend
################################################################
[file]
################################################################
# rules
################################################################
[backends]
[backends.backend1]
[backends.backend1.servers.server1]
url = "http://127.0.0.1:8081"
[backends.backend2]
[backends.backend2.LoadBalancer]
method = "drr"
[backends.backend2.servers.server1]
url = "http://127.0.0.1:8082"
[backends.backend2.servers.server2]
url = "http://127.0.0.1:8083"
[frontends]
[frontends.frontend1]
backend = "backend1"
[frontends.frontend1.routes.test_1]
rule = "Path: /test1"
[frontends.frontend2]
backend = "backend2"
passHostHeader = true
[frontends.frontend2.routes.test_2]
rule = "Path: /test2"

View File

@@ -0,0 +1,32 @@
logLevel = "DEBUG"
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":8080"
[entryPoints.https]
address = ":5001"
[entryPoints.https.tls]
[acme]
email = "test@traefik.io"
storage = "/dev/null"
entryPoint = "https"
onDemand = true
caServer = "http://{{.BoulderHost}}:4000/directory"
[file]
[backends]
[backends.backend]
[backends.backend.servers.server1]
url = "http://127.0.0.1:9010"
[frontends]
[frontends.frontend]
backend = "backend"
[frontends.frontend.routes.test]
rule = "Host:traefik.acme.wtf"

View File

@@ -1,11 +1,16 @@
# Reverse proxy port
#
# Optional
# Default: ":80"
#
# port = ":80"
#
# LogLevel
defaultEntryPoints = ["http"]
logLevel = "DEBUG"
[entryPoints]
[entryPoints.http]
address = ":8000"
[consul]
endpoint = "{{.ConsulHost}}:8500"
watch = true
prefix = "traefik"
[web]
address = ":8081"

Some files were not shown because too many files have changed in this diff Show More