1
0
mirror of https://github.com/containous/traefik.git synced 2025-09-05 01:44:24 +03:00

Compare commits

...

500 Commits
v1.1 ... v1.3.0

Author SHA1 Message Date
Fernandez Ludovic
e1e07f7750 Prepare release v1.3.0 2017-05-31 10:11:16 -07:00
Fernandez Ludovic
4c4eba4b56 doc(changelog): replace GitHub API URL by HTML URL. 2017-05-30 19:48:01 +02:00
Fernandez Ludovic
dbfd2663c2 Prepare release v1.3.0-rc3 2017-05-24 15:32:29 +02:00
Fernandez Ludovic
5b896bb46c fix: Empty Rancher launch config. 2017-05-24 11:20:30 +02:00
Josh Toft
bc0121808a Fix behavior for PathPrefixStrip
When pushing data to downstream proxies; malformed requests were being
sent.

The corrected behavior is as follows:

| Route Stripped    |     URL                |  Passed to Backend |
| ----------------- | ---------------------- | ------------------ |
| /                 |     /                  |  /                 |

| Route Stripped    |     URL                |  Passed to Backend |
| ----------------- | ---------------------- | ------------------ |
| /stat             |     /stat              |  /                 |
| /stat             |     /stat/             |  /                 |
| /stat             |     /status            |  /status           |
| /stat             |     /stat/us           |  /us               |

| Route Stripped    |     URL                |  Passed to Backend |
| ----------------- | ---------------------- | ------------------ |
| /stat/            |     /stat              |  /stat             |
| /stat/            |     /stat/             |  /                 |
| /stat/            |     /status            |  /status           |
| /stat/            |     /stat/us           |  /us               |

Prior, we could strip the prefixing `/`, and we'd also ignore the case
where you want to serve something like `/api` as both the index and as a
subpath.

Additionally, this should resolve a myriad of issues relating to
kubernetes ingress `PathPrefixStrip`.
2017-05-24 10:50:12 +02:00
Timo Reimann
4293446111 Install github.com/stretchr/testify/require. 2017-05-24 00:51:48 +02:00
Timo Reimann
9967494996 [k8s] Ignore Ingresses with empty Endpoint subsets.
We previously fell back to using ClusterIPs. However, the approach can
lead to all kinds of problems since Ingresses rely on being able to talk
to Endpoints directly. For instance, it can break stickiness and
retries.
2017-05-23 21:15:06 +02:00
Timo Reimann
b392023c37 Add additional tests for PathStrip{Prefix}. 2017-05-23 17:31:34 +02:00
Timo Reimann
f7d9dfafd0 [k8s] Remove rule type path list.
Instead of doing sanity checks in the Kubernetes provider, we just
accept any non-empty value from the annotation and rely on the server
part to filter out unknown rules.

This allows us to automatically stay in sync with the currently
supported Path matchers/modifiers.
2017-05-23 17:31:34 +02:00
Timo Reimann
219a6372b0 Upgrade go-marathon to 15ea23e.
Our vendored copy contains a bug that causes unavailable Marathon nodes
to never be marked as available again due to a misconstruction in the
URL to the Marathon health check / ping endpoint used by go-marathon
internally.

A fix[1] has been published.

[1]https://github.com/gambol99/go-marathon/pull/283
2017-05-22 20:52:24 +02:00
Fernandez Ludovic
2e762e76f3 doc: update change log. 2017-05-22 10:26:05 +02:00
tanyadegurechaff
987ae92f53 Create log folder if not present 2017-05-19 15:49:02 +02:00
Ed Robinson
c1220b8765 Re Orginise k8s docs to make 1.6 usage easier
* Adds some raw.githubusercontent.com links to the kubectl examples to
make following along at home simpler.
* Dedupe the config for rbac so it can just be ommited if not needed.
2017-05-17 15:58:54 +02:00
Emile Vauge
bc6f764a87 Merge pull request #1578 from Stibbons/marathon_doc
Add Marathon guide.
2017-05-17 15:21:09 +02:00
Gaetan Semet
0b414ed482 Add Marathon guide
Copy/pasted from very comprehensive slack response from @ttr
https://traefik.slack.com/archives/C0CDT22PJ/p1494347929571784?thread_ts=1494339388.375916&cid=C0CDT22PJ

Signed-off-by: Gaetan Semet <gaetan@xeberon.net>
2017-05-17 14:59:28 +02:00
Emile Vauge
f521e72f15 Merge pull request #1612 from containous/fix-deploy
Fix deploy script, removes Docker version check
2017-05-16 17:53:47 +02:00
Emile Vauge
88ea0a037b Fix deploy script, removes Docker version check 2017-05-16 17:24:08 +02:00
Emile Vauge
c963cee3c8 Merge pull request #1606 from containous/prepare-release-v1.3.0-rc2
Prepare release v1.3.0-rc2
2017-05-16 16:15:05 +02:00
Emile Vauge
0be353d435 Merge pull request #1610 from ldez/beta-cluster
doc: Traefik cluster in beta.
2017-05-16 15:50:03 +02:00
Emile Vauge
6afff2d403 Merge pull request #1610 from ldez/beta-cluster
doc: Traefik cluster in beta.
2017-05-16 15:47:11 +02:00
Fernandez Ludovic
12fa144f2f doc: Traefik cluster in beta. 2017-05-16 15:28:18 +02:00
Emile Vauge
ac0e48b48c Merge pull request #1608 from ldez/feat-semaphoreci
SemaphoreCI on 1.3 branch
2017-05-16 15:08:39 +02:00
Attilio Borello
64aa37858b added retry function to validate script 2017-05-16 14:33:06 +02:00
Attilio Borello
5348d4dccd added retry function to tests script 2017-05-16 14:33:06 +02:00
Attilio Borello
c3c599241f removed unit and integration tests from travis 2017-05-16 14:33:06 +02:00
Attilio Borello
c19432f95c clean up apt-cache in webui/Dockerfile 2017-05-16 14:33:06 +02:00
Attilio Borello
bdf4f48d78 replaced docker images with alpine if available (nginx, rabbitmq) 2017-05-16 14:33:06 +02:00
Attilio Borello
21aa0ea2da added DOCKER_VERSION variable 2017-05-16 14:33:06 +02:00
Timo Reimann
f8e7b5595b Merge pull request #1585 from timoreimann/1-3-maintain-sticky-flag-on-lb-method-validation-failure
Maintain sticky flag on LB method validation failure.
2017-05-16 00:41:15 +02:00
Timo Reimann
f9839f7b1d Turn configureBackends into method. 2017-05-16 00:06:42 +02:00
Timo Reimann
2c45428c8a Maintain sticky flag on LB method validation failure.
We previously did not copy the sticky flag if the load-balancer
method validation failed, causing enabled stickiness to be dropped in
case of a validation error (which, technically, for us is the same as a
load-balancer configuration without an explicitly set method). This
change fixes that.

A few refactorings and improvements along the way:

- Move the frontend and backend configuration steps into separate
  methods/functions for better testability.
- Include the invalid method name in the error value and avoid log
  duplication.
- Add tests for the backend configuration part.
2017-05-16 00:06:42 +02:00
Emile Vauge
30aa5a82b3 Merge pull request #1577 from aantono/Issue1569
Fixed ReplacePath rule executing out of order, when combined with PathPrefixStrip
2017-05-15 23:21:53 +02:00
Alex Antonov
3f68e382fd Fixed ReplacePath rule executing out of order, when combined with PathPrefixStrip #1569 2017-05-15 10:08:18 -05:00
Emile Vauge
9e57a283d7 Merge pull request #1601 from containous/fix-fatal-auth
Fix empty basic auth
2017-05-15 17:00:52 +02:00
Emile Vauge
eaedc1b924 Fix empty basic auth
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-05-15 16:03:46 +02:00
Emile Vauge
e3ab4e4d63 Merge pull request #1598 from containous/fix-stats-hijack
Fix stats hijack
2017-05-15 15:04:23 +02:00
Emile Vauge
48a91d05b5 Add Recover tests 2017-05-15 09:17:33 +02:00
Emile Vauge
111251da05 Adds Panic Recover middleware
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-05-15 09:17:33 +02:00
Emile Vauge
71cec1580b Fix stats responseRecorder Hijacker
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-05-15 09:17:33 +02:00
Emile Vauge
ffe1104851 Merge pull request #1588 from containous/fix-exported-fields-providers
Fix exported fields providers
2017-05-11 22:58:00 +02:00
Emile Vauge
aa4ed088bb Unexport Kvclient & StoreType from kv Provider
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-05-11 19:33:32 +02:00
Emile Vauge
3a4ec19817 Add missing description tag
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-05-11 19:33:32 +02:00
Timo Reimann
d2b204a075 Merge pull request #1581 from timoreimann/1-3-kubernetes-ignore-missing-pass-host-header-annotation
[Kubernetes] Ignore missing pass host header annotation. [v1.3 - CHERRY-PICK]
2017-05-11 17:43:14 +02:00
Timo Reimann
fe6c35bc6b [Kubernetes] Ignore missing pass host header annotation.
A missing annotation would previously be handled in the default error
case, causing a noisy warning-level log message to be generated each
time.

We add another case statement to ignore the case where the annotation is
missing from the annotations map.

Also piggybacking a minor improvement to the log message.
2017-05-10 19:32:45 +02:00
Ludovic Fernandez
3fd6da06e0 Merge pull request #1556 from atbore-phx/hf-travis
[CI ] to run once travis before_deploy
2017-05-05 15:19:55 +02:00
Attilio Borello
95502aeec3 hot fix for release, travis runs before_deploy for each provider! we add a condition to run once 2017-05-05 14:17:08 +02:00
Ludovic Fernandez
58c786ca8c Merge pull request #1552 from atbore-phx/new-ci
[CI] Add SemaphoreCI
2017-05-05 09:33:43 +02:00
Attilio Borello
b6916d2f8c added initial ci conf 2017-05-04 22:04:20 +02:00
Ludovic Fernandez
840c131a98 Merge pull request #1546 from atbore-phx/rf-travis-ci
[CI] Enhance cross-binary builds and parallelism
2017-05-04 21:28:10 +02:00
Attilio Borello
219bcec40f crossbinary default is now executed before deploy using multiple make jobs in parallel 2017-05-04 20:23:48 +02:00
Ludovic Fernandez
ccda550ab1 Merge pull request #1553 from containous/prepare-release-v1.3.0-rc1
Prepare release v1.3.0-rc1
2017-05-04 20:15:20 +02:00
Emile Vauge
b5e73cfa07 Prepare release v1.3.0-rc1 2017-05-04 18:17:54 +02:00
Emile Vauge
ba928dd459 Merge pull request #1241 from vholovko/healthcheck_changes
using more sensible consul blocking query to detect health check changes
2017-05-04 17:25:12 +02:00
Volodymyr Holovko
6fd40dbaa9 Using more sensible consul blocking query to detect health check changes 2017-05-04 16:54:27 +02:00
Ludovic Fernandez
6ad273b9fa Merge pull request #1542 from maxwo/working-ui
Working UI
2017-05-04 02:38:45 +02:00
Maxime Wojtczak
5500658f5a feat(UI) : Working UI.
chore(Build) : Add Babel for build.
chore(Babel) : Add babel configuration.
style(Code) : Enhance code style.
2017-05-04 01:12:46 +02:00
Ludovic Fernandez
b4f9e3890f Merge pull request #1535 from atbore-phx/crossbinary-parallel
Makefile target to enable parallel jobs
2017-05-04 00:47:38 +02:00
Attilio Borello
df6741aeeb Makefile target to enable parallel jobs
- fixed dependencies order and renamed Makefile target
- extracted docker run params into DOCKER_RUN_OPTS
- crossbinary-default contains 64bit Linux, Win and Darwin
- crossbinary-others contains 32bit Linux, Win, Darwin and 32/64bit *bsd
- added dependencies to crossbinary-default and crossbinary-others targets
2017-05-04 00:02:45 +02:00
Ludovic Fernandez
5535318cda Merge pull request #1538 from containous/merge-v1.2.3-master
Merge v1.2.3 master
2017-05-03 23:49:47 +02:00
Emile Vauge
4e186cecf9 Merge v1.2.3 master 2017-05-03 23:24:53 +02:00
Emile Vauge
8ac281f9e3 Prepare release v1.2.3
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-05-03 22:53:58 +02:00
Emile Vauge
e7a73d3fb3 Fix too many redirect
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-05-03 22:53:58 +02:00
Emile Vauge
ca9e36ebe3 Prepare release v1.2.2
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-05-03 22:53:58 +02:00
Adam Geiger
138fea17ed Fix redirect empty backend
Issue-#679
2017-05-03 22:53:58 +02:00
Emile Vauge
bf3f6e2029 Fix Docker filter empty rule
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-05-03 22:53:58 +02:00
Emile Vauge
ec245d604a Fix postLoadConfig
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-05-03 22:53:58 +02:00
Emile Vauge
69e081f40f Merge pull request #1541 from containous/revert-73a1b17
Revert "First stage of access logging middleware.  Initially without …
2017-05-03 19:35:49 +02:00
Emile Vauge
82651985c4 Revert "First stage of access logging middleware. Initially without any output appenders."
This reverts commit 73a1b172ed.
2017-05-03 17:30:31 +02:00
Ludovic Fernandez
a5384bae47 Merge pull request #1540 from containous/marathon-add-tests-lost-during-1320-rebase
Add tests lost during PR 1320.
2017-05-03 17:15:10 +02:00
Timo Reimann
1dcf8d2ea6 Add tests lost during PR 1320.
The tests part of this change were originally in PR 1320 but got lost
during one of the rebases. Let's bring them back in.
2017-05-03 16:27:21 +02:00
Ludovic Fernandez
e86df016c3 Merge pull request #1537 from ldez/refactor-git-alias-safe
refactor: fix for PR with master branch.
2017-05-03 16:24:38 +02:00
Fernandez Ludovic
72baf746f4 refactor: fix for PR with master branch. 2017-05-03 15:54:43 +02:00
Ludovic Fernandez
91b4b47f04 Merge pull request #1523 from tanyadegurechaff/make-port-deterministic
Make port deterministic
2017-05-03 15:53:46 +02:00
tanyadegurechaff
79cbe56a41 Make port deterministic 2017-05-03 15:28:53 +02:00
Ludovic Fernandez
f621d7a2c4 Merge pull request #1525 from guilhem/fix-watchdog
Fix systemd watchdog feature
2017-05-03 15:25:15 +02:00
Guilhem Lettron
3c33eab35e Fix systemd watchdog feature
Commit coreos/go-systemd@0c088e introduce cleaning environment.
First usage of sdnotify (for type=notify) was clearing NOTIFY_SOCKET environment variable.
sdnotify in watchdog was unable to ping back.

Fix #1353
2017-05-03 14:44:51 +02:00
Ludovic Fernandez
b67a27d0c7 Merge pull request #1527 from yyekhlef/master
feat(rancher): added constraint management for rancher provider
2017-05-03 14:32:01 +02:00
Youcef Yekhlef
8de107866f feat(rancher): added constraint management for rancher provider 2017-05-03 13:48:44 +02:00
Ludovic Fernandez
b5283391dd Merge pull request #1488 from alpe/k8s-auth
Add basic auth to kubernetes provider
2017-05-03 13:37:05 +02:00
Fernandez Ludovic
420a6db3b4 doc: add k8s basic auth. 2017-05-03 13:18:40 +02:00
Alex Peters
89da3b15a4 Add basic auth to kubernetes provider 2017-05-03 13:18:40 +02:00
Emile Vauge
dcc4d92983 Merge pull request #1524 from jangie/update-dep-go-marathon
[Marathon] Bump go-marathon dep
2017-05-03 13:06:36 +02:00
Bruce Lee
12c2d398a7 retry using 'script/glide.sh update'
fix docker dependency

remove unneeded docker dependency files

further cleanup
2017-05-03 11:43:37 +02:00
jangie
4e238280bc [Marathon] Bump go-marathon dep
attempt to remove glide from integration

glide trim

Revert "attempt to remove glide from integration"

This reverts commit c5b42b6cdebb44e730080a0cf20a871c11ef095b.
2017-05-03 11:43:37 +02:00
Ludovic Fernandez
bd6056c269 Merge pull request #1534 from containous/revert-1464-vendor-autogen
Revert "Vendor generated file"
2017-05-03 10:40:38 +02:00
Fernandez Ludovic
acb0492e26 Merge pull request #1464 from vdemeester/vendor-autogen 2017-05-03 10:02:14 +02:00
Emile Vauge
a0d6594e99 Merge pull request #1464 from vdemeester/vendor-autogen
Vendor generated file
2017-05-01 19:07:15 +02:00
Vincent Demeester
65f81990a7 Update script to use /usr/bin/env bash…
… instead of /bin/bash, to work better on more platforms.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2017-05-01 18:32:40 +02:00
Vincent Demeester
1b85dd0455 Vendor generated file
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2017-05-01 18:32:40 +02:00
Emile Vauge
bec45bc7d6 Merge pull request #1516 from ldez/refactor/documentation-review
doc: small documentation review
2017-05-01 18:32:20 +02:00
Fernandez Ludovic
4c4b05d024 refactor: small documentation review 2017-05-01 18:09:22 +02:00
Ludovic Fernandez
228ad9a244 Merge pull request #1517 from gottwald/safe-tests
Add unit tests for package safe
2017-05-01 17:33:16 +02:00
Ingo Gottwald
2f06f339ec Add unit tests for package safe
Also fix a bug in the code found due to the tests.
2017-05-01 16:21:26 +02:00
Emile Vauge
eefcf026d2 Merge pull request #1515 from ldez/github-template-again
doc: enhance Github templates.
2017-05-01 16:08:14 +02:00
Fernandez Ludovic
ccb1a4ff8c doc: enhance Github templates.
- suppress the mini user guide.
- explain the 'traefik bug' command.
2017-05-01 15:35:57 +02:00
Emile Vauge
78f1b4216e Merge pull request #1343 from uqf/improve-rancher-provider
Improve rancher provider handling of service and container health states
2017-05-01 12:34:59 +02:00
Matthew Kelch
44db6e9290 mprove Rancher provider functionality:
- Improves default filtering behavior to filter by container health/healthState
- Optionally allows filtering by service health/healthState
- Allows configuration of refresh interval
2017-04-29 15:37:54 -04:00
Timo Reimann
e2fdc27d64 Merge pull request #1338 from containous/add-global-option-for-healthcheck-interval
Add global health check interval parameter.
2017-04-28 21:35:29 +02:00
Timo Reimann
25345427c3 Add global health check interval parameter.
The new parameter allows to set a health check interval valid for all
backends. Custom values set per provider may override the global one.
2017-04-28 20:51:29 +02:00
Timo Reimann
ce492895e2 Merge pull request #1320 from containous/configure-healthcheck-via-marathon-label
Make Traefik health checks label-configurable with Marathon.
2017-04-28 18:59:35 +02:00
Timo Reimann
5d43b9e16a Add HealthCheckSuite to list of integration tests. 2017-04-28 18:17:25 +02:00
Timo Reimann
71a2c8bdcd Fix health check integration test suite typo. 2017-04-28 18:17:25 +02:00
Timo Reimann
8fd6160758 Fix health check path key name in Marathon template. 2017-04-28 18:17:25 +02:00
Timo Reimann
d57f83c31c Make Traefik health checks label-configurable with Marathon.
For the two existing health check parameters (path and interval), we add
support for Marathon labels.

Changes in detail:

- Extend the Marathon provider and template.
- Refactor Server.loadConfig to reduce duplication.
- Refactor the healthcheck package slightly to accommodate the changes
  and allow extending by future parameters.
- Update documentation.
2017-04-28 18:17:25 +02:00
Ludovic Fernandez
441d5442a1 Merge pull request #1339 from seguins/928-fix-regex-pathstrip
Fix regex with PathStrip
2017-04-28 18:01:05 +02:00
Stéphane Seguin
bf3673879f Fix regex with PathStrip 2017-04-28 17:33:14 +02:00
Ludovic Fernandez
74925ba996 Merge pull request #1357 from tcolgate/libkvuname
Add libkv Username and Password
2017-04-28 16:51:41 +02:00
Tristan Colgate
de6d771bc2 Add libkv Username and Password 2017-04-28 16:28:57 +02:00
Ludovic Fernandez
2f1a7cbf26 Merge pull request #1436 from Regner/1307-fix-k8s-tests-missing-endpoints
Updating Kubernetes tests to properly test missing endpoints code path
2017-04-28 15:54:33 +02:00
Regner Blok-Andersen
d24ba90900 Updating Kubernetes tests to properly test missing endpoints code path
This fixes #1307
2017-04-28 15:25:03 +02:00
Ludovic Fernandez
9ed55e9eae Merge pull request #1337 from SantoDE/fix/rancher_docs
make docs more clear about how to work with the current api
2017-04-28 10:40:29 +02:00
Manuel Laufenberg
a0c3d6a421 make docs more clear about how to work with the current api 2017-04-28 10:21:18 +02:00
Ludovic Fernandez
521e295349 Merge pull request #1374 from ssttevee/path-replace-rule
Add Path Replacement Rule
2017-04-27 10:38:41 +02:00
ssttevee
aa8375e82b added path replacement rule 2017-04-26 23:33:32 -07:00
Timo Reimann
5a8215a1e4 Merge pull request #1345 from diegooliveira/IP-Per-Task-Fix-Hostname
[Marathon] Detect proper hostname automatically.
2017-04-26 12:14:01 +02:00
Timo Reimann
7eb3051a57 Improve and extend TestGetBackendServer.
- Cover error cases.
- Use sub-tests.
2017-04-26 11:35:30 +02:00
Timo Reimann
a4355569af Extract index functionality into generic helper function.
Allows to move specific test cases to dedicated tests for new function.
2017-04-26 11:35:30 +02:00
Timo Reimann
16c86022bb Cosmetic changes. 2017-04-26 11:35:30 +02:00
Timo Reimann
e615e833bc Use go-spew to display diffs. 2017-04-26 11:35:30 +02:00
Diego de Oliveira
592a12dca2 Fix unsound behavior
The IP-Per-Task feature changed the behavior for
clients without this configuration (using the task IP instead
of task hostname). This patch make the new behavior available
just for Mesos installation with IP-Per-Task enabled. It also
make it possible to force the use of task's hostname.
2017-04-26 11:35:30 +02:00
Timo Reimann
97a3564945 Merge pull request #1497 from containous/re-exclude-dist-traefik-in-dockerignore
Re-exclude /dist/traefik from .dockerignore.
2017-04-26 10:34:20 +02:00
Timo Reimann
f1ee471b6b Re-exclude /dist/traefik from .dockerignore.
Required for the 'image' Makefile target to succeed since it copies the
binary into the image.
2017-04-26 10:01:43 +02:00
Timo Reimann
750fa22cff Merge pull request #1474 from containous/marathon-check-port-label-overwrite-earlier
Check for explicitly defined Marathon port first.
2017-04-26 03:21:33 +02:00
Timo Reimann
099d605aed Check for explicitly defined Marathon port first.
Previously, we did the check too late resulting in the traefik.port
label not being effective.

The change comes with additional refactorings in production and tests.
2017-04-25 23:18:30 +02:00
Timo Reimann
f1bc80ca12 Change getLabel signature to return bool instead of error.
The comma ok idiom fits better.
2017-04-25 23:18:30 +02:00
Timo Reimann
49a9aeb95f Merge pull request #1489 from containous/docker-move-test-providers-into-run-body
Move Docker test provider instantiation into t.Run body.
2017-04-25 15:30:37 +02:00
Timo Reimann
25abf8b8f8 Stop retrying unit tests on Travis. 2017-04-25 14:56:43 +02:00
Timo Reimann
962fb908c0 Pass through TESTDIRS env var to Docker build container. 2017-04-25 14:56:43 +02:00
Timo Reimann
b44aca64e3 Move Docker test provider instantiation into t.Run body. 2017-04-25 14:56:43 +02:00
Ludovic Fernandez
34b21b9374 Merge pull request #1482 from ldez/docs/github-template
doc: enhance GitHub template.
2017-04-25 12:10:10 +02:00
Fernandez Ludovic
972579e2a0 refactor(bugCmd): update issue template.
- fix collides with imported package name.
2017-04-25 11:14:31 +02:00
Fernandez Ludovic
ccff8a80f5 doc: enhance GitHub template.
- add issue and PR guide.
- rewrite templates
2017-04-25 11:14:31 +02:00
Ludovic Fernandez
4f2a2d573d Merge pull request #1486 from containous/fix-consul-catalog-flags
Fix Consul catalog prefix flags
2017-04-25 11:13:28 +02:00
Emile Vauge
af1d0a7dce Fix Consul catalog prefix flags
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-25 10:51:03 +02:00
Vincent Demeester
37e40bc776 Merge pull request #1470 from vdemeester/update-dockerignore
Update dockerignore to ignore dist and sites
2017-04-25 09:55:24 +02:00
Vincent Demeester
d9fd412e0e Update dockerignore ignore dist and sites
As of now, it does nothing (`/dist/` doesn't filter the dist folder)
and sending anything from `dist` doesn't make sense as it's mounted
anyway.

Removing the traefik binary from whitelist as the integration script
compiles the binary before running, so we don't need to send it via
the build context.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2017-04-25 09:02:07 +02:00
Emile Vauge
4bc2f17b08 Merge pull request #1368 from containous/update-doc
License 2017, Træfɪk => Træfik
2017-04-24 16:20:55 +02:00
Emile Vauge
d1b65adfb1 Traefik logo license
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-24 15:34:12 +02:00
Emile Vauge
19a7d22eef License 2017, Træfɪk => Træfik
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-24 15:12:44 +02:00
Vincent Demeester
6012a0f3c5 Merge pull request #1437 from ldez/feat/backends-filter
feat(webui): Dashboard filter
2017-04-24 10:25:46 +02:00
Fernandez Ludovic
4e81d41d06 doc: update web ui documentation
- update web ui dev documentation
- update Dashboard screenshot.
2017-04-24 10:04:58 +02:00
Fernandez Ludovic
f4579e5f12 refactor: clean code
- remove dead code
- replace Fprintf by Fprint.
2017-04-24 10:04:57 +02:00
Fernandez Ludovic
a8cbe7ef5e feat(webui): Add dashboard filter.
- Convert Object properties to and array for backends and frondends for each providers.
- Remove unused parameters.
- Add filter.
2017-04-24 10:04:57 +02:00
Timo Reimann
6ba17847ab Merge pull request #1179 from gstackio/master
Fix error in documentation for Docker labels
2017-04-23 02:30:53 +02:00
Benjamin Gandon
378a34c454 Fix error in documentation for Docker labels 2017-04-23 01:58:26 +02:00
Timo Reimann
f38d117a31 Merge pull request #1408 from hmrc/access-logging
New access logger.
2017-04-23 01:57:41 +02:00
Richard Shepherd
73a1b172ed First stage of access logging middleware. Initially without any output appenders. 2017-04-23 00:46:45 +02:00
Timo Reimann
4310bdf3ca Merge pull request #1458 from ben-st/update_readme
update wording
2017-04-23 00:44:44 +02:00
Benjamin
6cb8df9d1e update wording 2017-04-22 23:49:38 +02:00
Timo Reimann
93e123b489 Merge pull request #1467 from mattcollier/patch-1
Fix typo in command line help.
2017-04-22 23:01:03 +02:00
mattcollier
8764c43eaf Fix typo in command line help. 2017-04-21 14:01:45 +02:00
Timo Reimann
10e22c0b3f Merge pull request #1469 from containous/improve-frontend-rule-documentation
Improve documentation for frontend rules.
2017-04-21 01:10:13 +02:00
Timo Reimann
051f0c6855 Improve documentation for frontend rules.
Includes guidelines on proper usage of the more complex path matchers.
2017-04-21 00:30:27 +02:00
Timo Reimann
809103f4b2 Merge pull request #1473 from mattcollier/patch-2
Correct typo in code comment.
2017-04-20 22:01:16 +02:00
mattcollier
b7c2e2d3f1 Correct typo and use Godoc convention in comment. 2017-04-20 14:02:29 -04:00
Vincent Demeester
d866a62b56 Merge pull request #1468 from containous/traefik-pronunciation-pages
Mention Traefik pronunciation in docs too.
2017-04-20 14:00:44 +02:00
Timo Reimann
22ac60205a Mention Traefik pronunciation in docs too.
Also replace Træfɪk with Træfik.
2017-04-20 12:08:12 +02:00
Vincent Demeester
de557d031b Merge pull request #1449 from vdemeester/more-extraction
Extract some code in packages
2017-04-20 11:37:40 +02:00
Vincent Demeester
7fcb7b86d3 Extract some code in packages
- This will help split stuff in smaller, better tested packages
- This moves some stuff like the traefik command to package `cmd`

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2017-04-20 10:06:41 +02:00
Vincent Demeester
9c9015a7b1 Merge pull request #1398 from containous/fix-default-timeouts-for-marathon-provider
Fix default timeouts for Marathon provider.
2017-04-20 08:37:20 +02:00
Timo Reimann
360e8e19ce Fix default timeouts for Marathon provider.
The timeouts were given without a unit, which caused nanoseconds scale
to be applied when we switched the type from int to flaeg.Duration.
2017-04-20 01:51:10 +02:00
Timo Reimann
dd52ee9f9b Merge pull request #1147 from SantoDE/feature-http-basic-auth-frontend
Add Basic Auth per Frontend.
2017-04-20 00:26:39 +02:00
Manuel Laufenberg
8a892b21e1 Add Basic Auth per Frontend for Rancher & Docker Dynamic Provider 2017-04-19 21:05:43 +02:00
Vincent Demeester
4e0f131fcd Merge pull request #1453 from martinbaillie/rancher-provider-pagination-fixes
Fix Rancher API pagination limits
2017-04-19 13:36:55 +02:00
Martin Baillie
d1ee72b308 Merge branch 'master' into rancher-provider-pagination-fixes 2017-04-19 20:47:30 +10:00
Vincent Demeester
f03a9e502f Merge pull request #1444 from vdemeester/extract-providers
Extract providers to their own packages
2017-04-18 22:54:49 +02:00
Vincent Demeester
542c3673e4 Extract providers to their own package
This is just doing that and making it compile :)

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2017-04-18 13:24:17 +02:00
Vincent Demeester
2d00758b2e Merge pull request #1455 from martinbaillie/fix-traefik-sample-toml
Fix Rancher backend left in uncommented state
2017-04-18 11:56:37 +02:00
Martin Baillie
73f09f389e Fix Rancher API pagination limits
This fix allows the Traefik Rancher provider to obtain a complete view
of the environments, services and containers being managed by the
Rancher deployment.
2017-04-18 19:48:43 +10:00
Martin Baillie
29bada9ae3 Fix Rancher backend left in uncommented state 2017-04-18 15:00:18 +10:00
Vincent Demeester
4ce2c8cc34 Merge pull request #1448 from vdemeester/fix-master-windows-compilation
Update golang.org/x/sys to fix windows compilation
2017-04-17 20:44:07 +02:00
Vincent Demeester
b02b11a606 Update golang.org/x/sys to fix windows compilation
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2017-04-17 20:08:40 +02:00
Vincent Demeester
e38fa25412 Merge pull request #1447 from vdemeester/dont-binary-twice
[ci] Don't run binary twice
2017-04-17 19:34:39 +02:00
Vincent Demeester
38b2362a31 Don't run binary twice
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2017-04-17 18:51:37 +02:00
Vincent Demeester
13754f06e3 Merge pull request #1445 from vdemeester/pull-in-pre
Pull images before running CI
2017-04-17 18:13:10 +02:00
Vincent Demeester
ade223cf2e Pull images before running CI
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2017-04-17 17:28:34 +02:00
Vincent Demeester
2118f6992a Merge pull request #1440 from vdemeester/docker-provider-refacto
Few refactoring around the docker provider
2017-04-17 17:28:13 +02:00
Vincent Demeester
b04ba36682 Update some docker provider test
- Split the file into smaller ones (docker, swarm and service tests)
- Use some builder to reduce a little bit the noise for creating containers

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2017-04-17 15:40:55 +02:00
Vincent Demeester
3f293ee25b Move docker provider to its own package 👼
Makes it simpler to manage :)

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2017-04-17 15:40:55 +02:00
Timo Reimann
dc01094863 Merge pull request #1442 from martinbaillie/master
Pass stripped prefix downstream as header (#985)
2017-04-17 09:07:13 +02:00
Martin Baillie
fa683fa7e4 Pass stripped prefix downstream as header 2017-04-16 19:24:26 +10:00
Timo Reimann
1da47dfcbb Merge pull request #1404 from aolwas/k8s-rbac-doc-update
Add documentation for k8s RBAC configuration.
2017-04-13 01:13:52 +02:00
Maxime Cottret
fc3cc9a919 Add documentation for k8s RBAC configuration 2017-04-13 00:27:16 +02:00
Emile Vauge
12a0026e21 Merge pull request #1383 from containous/merge-v1.2.1-master
Merge v1.2.1 master
2017-04-12 09:13:03 +02:00
Emile Vauge
aeb17182b4 Merge v1.2.1-master
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-11 22:36:56 +02:00
Emile Vauge
a590155b0b Prepare release v1.2.1
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-11 22:36:55 +02:00
Emile Vauge
87ce060737 bump lego 0e2937900
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-11 22:36:55 +02:00
Timo Reimann
f2297dd3ed k8s: Do not log service fields when GetService is failing.
Update tests too.
2017-04-11 22:36:55 +02:00
Emile Vauge
2cd4c82092 Prepare release v1.2.0
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-11 22:36:55 +02:00
Emile Vauge
6edc0926eb sub-tests + Fatalf/Errorf
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-11 22:36:55 +02:00
Emile Vauge
a456d36cc6 Add Docker task list test
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-11 22:36:55 +02:00
yshay
5c2d91ab84 Add check on task status in addition to desired status 2017-04-11 22:36:55 +02:00
Sebastian
a73fee50dc 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-04-11 22:36:55 +02:00
Regner Blok-Andersen
b02393915e 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-04-11 22:36:55 +02:00
Emile Vauge
b99a919bb4 Refactor k8s client config
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-11 22:36:55 +02:00
Emile Vauge
51f3f6ba9c Removed unused log
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-11 22:36:55 +02:00
Emile Vauge
736f9b30ef Fix default config in generic Mesos provider
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-11 22:36:55 +02:00
Timo Reimann
b385ffaee7 Revert "Pass context to ListReleases when checking for new versions."
This reverts commit 07db6a2df1.
2017-04-11 22:36:55 +02:00
Timo Reimann
b02e289734 Update github.com/containous/oxy only. 2017-04-11 22:36:55 +02:00
Timo Reimann
fd1cf2484c Reset glide files to versions from upstream/v1.2. 2017-04-11 22:36:55 +02:00
Attila Kanto
5250c9c04d Update vulcand and pin deps in glide.yaml 2017-04-11 22:36:55 +02:00
Timo Reimann
e011792a90 Pass context to ListReleases when checking for new versions.
Required by go-github update.
2017-04-11 22:36:55 +02:00
Timo Reimann
a507cb4835 Rename health check URL parameter to path.
Also improve documentation.
2017-04-11 22:36:55 +02:00
Matevz Mihalic
f324983946 Fix metrics registering 2017-04-11 22:36:55 +02:00
Owen Marshall
c876462eb0 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-04-11 22:36:55 +02:00
Timo Reimann
ec7ba15955 Docs: Update default value for DefaultMaxIdleConnsPerHost. 2017-04-11 22:36:55 +02:00
dtomcej
ef83a5936d update oxy hash 2017-04-11 22:36:55 +02:00
Manuel Laufenberg
8d650da2f8 Bump go-rancher version 2017-04-11 22:36:55 +02:00
Emile Vauge
bd127168b3 Merge pull request #1421 from containous/move-crossbinary-travis-deploy
Move make cross binary to Travis deploy step
2017-04-11 22:35:49 +02:00
Emile Vauge
1ecdadb283 Move make cross binary to Travis deploy step
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-11 20:47:25 +02:00
Emile Vauge
d8c21639f7 Merge pull request #1407 from containous/glide-sh-push-get-param-to-array
glide.sh: Push argument to GLIDE_ARGS array.
2017-04-10 20:37:35 +02:00
Timo Reimann
d2df47d382 glide.sh: Push argument to GLIDE_ARGS array.
The array is empty in the beginning, so referencing ${GLIDE_ARGS[@]}
produces an error due to nounset.
2017-04-10 10:42:33 +02:00
Vincent Demeester
0cc3d05515 Merge pull request #1319 from containous/start-healthcheck-early
Start health checks early.
2017-04-08 12:41:36 +02:00
Timo Reimann
60ea9199e5 Start health checks early.
Do not wait a full tick cycle to execute the first health check.

Additional changes:

- Make request timeout configurable (for testing purposes).
- Support synchronizing on health check goroutine termination through an
  internal wait group (for testing purposes).
- Stop leaking by closing the HTTP response body.
- Extend health check logging and use WARNING level for (continuously)
  failing health checks.
2017-04-07 19:13:15 +02:00
Emile Vauge
637c7e250c Merge pull request #1178 from errm/k8s-client-2
Upgrade k8s.io/client-go to version 2
2017-04-07 14:22:50 +02:00
Ed Robinson
6f4c5dd4ce Upgrade k8s.io/client-go to version 2 2017-04-07 11:52:18 +01:00
Ed Robinson
a3b95f798b Update lego 2017-04-07 11:52:18 +01:00
Ed Robinson
65284441fa Update dependencies 2017-04-07 11:52:18 +01:00
Emile Vauge
51e4dcbb1f Merge pull request #1367 from seguins/chart-k8s
Add documentation about k8s Helm Chart
2017-04-07 11:53:30 +02:00
Stéphane Seguin
e38bf0accb Add documentation about k8s chart 2017-04-06 21:52:39 +02:00
Emile Vauge
08c1871c98 Merge pull request #1394 from containous/nicgrayson-master
Allow traefik.port to not be in the list of marathon ports
2017-04-06 20:57:58 +02:00
Nic Grayson
4eb779e596 Allow traefik.port to not be in the list of marathon ports 2017-04-06 18:47:35 +02:00
Emile Vauge
e1aa16ae70 Merge pull request #1196 from klausenbusk/url
kv: Ignore backend servers with no url
2017-04-06 11:14:57 +02:00
Kristian Klausen
b4dfb7223b kv: Extend test with support for specifying custom error for Get/List 2017-04-06 10:28:11 +02:00
Kristian Klausen
f621a46a2e kv: Log error when checking existence of server url key 2017-04-06 10:28:11 +02:00
Kristian Klausen
c864d80270 kv: Add test for server without url key 2017-04-06 10:28:11 +02:00
Kristian Klausen
020a8e31ab kv: Ignore backend servers with no url
Currently with a kv tree like:
/traefik/backends/b1/servers/ẁeb1
/traefik/backends/b1/servers/web2
/traefik/backends/b1/servers/web2/url
Traefik would try to forward traffic to web1, which is impossible as
traefik doesn't know the url of web1.

This commit solve that, by ignoring backend server with no url "key"
when generating the config.

This is very useful, for people who use etcd TTL feature. They can then
just "renew" the url key every X second, and if the server goes down, it
is automatic removed from traefik after the TTL.
2017-04-06 10:28:11 +02:00
Timo Reimann
69c31276f2 Merge pull request #1386 from mihaitodor/patch-1
Fix typo in server.go
2017-04-04 21:37:54 +02:00
Mihai Todor
06c47134c9 Fix typo
Fix "loadd-balancer" typo in log debug message in server.go
2017-04-04 17:23:55 +01:00
Ben Parli
c9d23494b9 Add IdleConnTimeout to Traefik's http.server settings (#1340)
* Add IdleTimeout setting to http.server

Without such a timeout there is a risk of resource leakage from piling up connections, particularly when exposing Traefik to the Internet.

Set the default to be 180 seconds

* Add IdleConnTimeout to Traefik's http.server settings

Without enforcing a timeout Traefik is susceptible to resource leakage, particularly when deployed as a public facing proxy exposed to the Internet.

Set the default to be 180 seconds

* tweak

* Update configuration.go

* add some documentation for the idletimeout setting

* need to cast idletimeout

* update doc to refect format specifics
2017-04-04 11:36:23 +02:00
Timo Reimann
7d256c9bb9 Merge pull request #1350 from containous/toml-compatible-duration-type
Use TOML-compatible duration type.
2017-04-03 19:30:33 +02:00
Timo Reimann
056fe9ac0a Switch duration configuration parameters over to flaeg.Duration. 2017-04-03 18:36:23 +02:00
Timo Reimann
e375ba98f0 Update vendored dependencies. 2017-04-03 18:36:23 +02:00
Timo Reimann
d6d93db13b Update to latest github.com/containous/flaeg. 2017-04-03 18:36:23 +02:00
Emile Vauge
3389908238 Merge pull request #1235 from tcoupin/feat-use-docker-compose-labels
Use docker-compose labels for frontend and backend names
2017-04-03 11:46:20 +02:00
tcoupin
5c16860486 Use service.project.domain instead of project-service.domain 2017-04-03 11:00:04 +02:00
tcoupin
0a7f9b5a71 Use docker-compose labels for frontend and backend names 2017-04-03 11:00:04 +02:00
Timo Reimann
df685fa050 Merge pull request #1324 from containous/ask-for-debug-log-output-in-template
Append template section asking for debug log output.
2017-04-01 07:22:42 +02:00
Timo Reimann
2c079b3d6f Append template section asking for debug log output. 2017-03-31 17:38:48 +02:00
Timo Reimann
35973f1243 Merge pull request #1369 from Starefossen/patch-2
Make toml Bucket array homogeneous
2017-03-31 17:06:45 +02:00
Hans Kristian Flaatten
9281f4fbbc Make toml Bucket array homogeneous 2017-03-31 14:01:56 +02:00
Timo Reimann
0e0a231e5a Merge pull request #1303 from ruslansennov/patch-1
fix consul sample endpoints
2017-03-29 21:19:56 +02:00
Ruslan Sennov
b22716c5ba fix consul sample endpoints
It took few minutes to understand what is wrong, when I just uncommented sample config :)
2017-03-29 14:03:20 +02:00
Manuel Laufenberg
240b2be1a8 Merge pull request #1233 from tcoupin/feature-web-pathprefix
Feature web root path
2017-03-24 18:35:32 +01:00
tcoupin
c5125cee71 Add path parameter for web provider 2017-03-24 17:51:53 +01:00
Timo Reimann
1cf1fbf99b Merge pull request #1276 from kekoav/go-1.8-update-tls-ciphers
Update TLS Ciphers for Go 1.8
2017-03-24 13:58:26 +01:00
Kekoa Vincent
1ed68b1278 Updated available cipher suites for Go 1.8. 2017-03-24 09:37:46 +01:00
Timo Reimann
84e1ec6607 Merge pull request #1259 from containous/bump-go-1.8
Bump go 1.8
2017-03-24 09:34:29 +01:00
Emile Vauge
1140ee6c64 Update vendor dependencies
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-03-23 22:51:59 +01:00
Emile Vauge
8401cccff2 Replace mailgun/manners with go 1.8 graceful shutdown
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-03-23 22:47:29 +01:00
Emile Vauge
836f617286 Bump go 1.8
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-03-23 22:39:53 +01:00
Vincent Demeester
1bc8c9912e Merge pull request #1329 from containous/makefile-image-target-depend-on-binary
Make image Makefile target depend on binary instead of build.
2017-03-22 19:00:04 +01:00
Timo Reimann
b5430803b8 Make image Makefile target depend on binary instead of build.
build only builds the build container without the binary.
2017-03-22 16:33:02 +01:00
Vincent Demeester
a7bc8c8aa4 Merge pull request #1274 from sroze/patch-1
Change a word in the documentation
2017-03-22 09:48:32 +01:00
Samuel ROZE
9ab8e08d59 s/Hopefully/Fortunately/ 2017-03-21 22:44:54 +01:00
Emile Vauge
677899d9ff Merge pull request #1158 from tskinn/add-dynamodb-provider
add dynamodb backend
2017-03-17 18:02:02 +01:00
Taylor Skinner
72e35af39f add dynamo
Signed-off-by: Taylor Skinner <tskinn12@gmail.com>

add some comments

Signed-off-by: Taylor Skinner <tskinn12@gmail.com>

update readmes

make test runnable

Signed-off-by: Taylor Skinner <tskinn12@gmail.com>

make test

squash! add dynamo

add glide.lock

format imports

gofmt

update glide.lock

fixes for review

golint

clean up and reorganize tests

add dynamodb integration test

remove default region. clean up tests. consistent docs

forgot the region is required

DRY

make validate

update readme and commit dependencies
2017-03-16 10:12:26 -06:00
Timo Reimann
2a61c9049f Merge pull request #1257 from benoitf/docker-services
Allow multiple rules from docker labels containers with traefik.<servicename>.* properties
2017-03-14 10:31:58 +01:00
Florent BENOIT
1158eba7ac Adding docker labels traefik.<servicename>.* properties like
- traefik.mycustomservice.port=443
  -  traefik.mycustomservice.frontend.rule=Path:/mycustomservice
   - traefik.anothercustomservice.port=8080
  -  traefik.anothercustomservice.frontend.rule=Path:/anotherservice

all traffic to frontend /mycustomservice is redirected to the port 443 of the container while using /anotherservice will redirect to the port 8080 of the docker container

More documentation in the docs/toml.md file

Change-Id: Ifaa3bb00ef0a0f38aa189e0ca1586fde8c5ed862
Signed-off-by: Florent BENOIT <fbenoit@codenvy.com>
2017-03-14 08:45:47 +01:00
Emile Vauge
22c5bf7630 Merge pull request #1273 from timoreimann/rpr-force-with-lease
.github/rpr.sh: Use --force-with-lease instead of --force.
2017-03-11 11:36:37 +01:00
Timo Reimann
4148266ed0 .github/rpr.sh: Use --force-with-lease instead of --force.
This prevents accidentally overriding a branch that has been changed
remotely by another party.
2017-03-10 21:32:34 +01:00
Timo Reimann
6e8e597ff5 Merge pull request #1189 from krancour/usersfile
Allow usersFile to be specified for basic or digest auth
2017-03-10 07:45:39 +01:00
Kent Rancourt
7357417f48 Allow usersFile to be specified for basic or digest auth 2017-03-09 20:24:44 -05:00
Timo Reimann
91bf627275 Merge pull request #1144 from timoreimann/vendor-dependencies
Vendor dependencies.
2017-03-09 16:23:26 +01:00
Timo Reimann
55b57c736b Vendor integration dependencies. 2017-03-09 13:13:03 +01:00
Timo Reimann
dd5e3fba01 Vendor main dependencies. 2017-03-09 13:13:02 +01:00
Timo Reimann
49a09ab7dd Prepare for dependency vendoring.
- Add helper script to simplify glide usage.
- Add validation script for unwanted changes to vendoring.
- Relax/tighten up .{git,docker}ignore to cover vendored files properly.
- .validate: Protect from unbound variable in case of nounset setting.
- Install more recent hg version in the build container.
- Remove glide installation steps from Dockerfile.
- Update documentation.
2017-03-08 22:21:12 +01:00
Emile Vauge
dae28f7f17 Merge pull request #1227 from dtomcej/tighter-regex
Tighten regex match for wildcard certs [Addendum to #1018]
2017-03-07 16:59:52 +01:00
Daniel Tomcej
9cd76f122e remove dot from regex 2017-03-07 15:21:08 +01:00
Timo Reimann
920b5bb15d Support cluster-external Kubernetes client. (#1159)
Detect whether in-cluster or cluster-external Kubernetes client should
be used based on the KUBERNETES_SERVICE_{HOST,PORT} environment
variables.

Adds bearer token and CA certificate file path parameters.
2017-03-07 13:09:11 +01:00
Emile Vauge
3611818eda Add @trecloux to Maintainers (#1226) 2017-03-07 00:38:44 +01:00
Emile Vauge
7d83027954 Merge pull request #1208 from containous/merge-v1.2.0-rc2-master
Merge v1.2.0 rc2 master
2017-03-06 18:37:03 +01:00
Emile Vauge
ea190b6898 Prepare release v1.2.0-rc2
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-03-06 17:45:58 +01:00
Bruce Lee
aa75d5458d 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-03-06 17:45:58 +01:00
Christophe Robin
4172a7c62e Add task parser unit test for docker provider 2017-03-06 17:45:58 +01:00
Christophe Robin
355b4706d3 Fix docker issues with global and dead tasks 2017-03-06 17:45:58 +01:00
Manuel Laufenberg
eb1ffae01b Small fixes and improvments 2017-03-06 17:45:58 +01:00
Emile Vauge
cc0733a4fa Fix stats race condition
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-03-06 17:45:58 +01:00
Luke Petre
c786bbbc5b Try harder to query all the possible ec2 instances, and filter on instance state / lack of IP address 2017-03-06 17:45:58 +01:00
Julien Salleyron
f87b1c2fcd Wrong tests docker images 2017-03-06 17:45:58 +01:00
Julien Salleyron
14fd53c915 Add doc 2017-03-06 17:45:58 +01:00
Julien Salleyron
aa2edcc6e5 Add some integration test 2017-03-06 17:45:58 +01:00
Julien Salleyron
6b6f010851 Add healthcheck interval 2017-03-06 17:45:58 +01:00
Rickard von Essen
5e8805f24d 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-03-06 17:45:58 +01:00
Emile Vauge
3848944d35 Fix travis deploy
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-03-06 17:45:58 +01:00
Emile Vauge
9d7df45b7c Changelog for v1.2.0-rc1
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-03-06 17:45:58 +01:00
Emile Vauge
7a164ed401 Add v1.2 codename
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-03-06 17:45:57 +01:00
Regner Blok-Andersen
f530284031 Adding support for Traefik to respect the K8s ingress class annotation (#1182) 2017-03-03 20:30:22 +01:00
Timo Reimann
38c0cf7007 Merge pull request #1151 from timoreimann/refactor-k8s-rule-type-annotation-logic
Refactor k8s rule type annotation parsing/retrieval.
2017-03-03 18:48:59 +01:00
Timo Reimann
f3598e6b0f Refactor k8s rule type annotation parsing/retrieval.
- Move annotation logic into function.
- Constantify strings.
- Refactor TestRuleType.
- Add test for GetRuleTypeFromAnnotations.
2017-03-03 13:33:00 +01:00
Vincent Demeester
291ca860af Merge pull request #1216 from timoreimann/elaborate-on-regexp
Motivate and explain regular expression rules.
2017-03-03 10:09:30 +01:00
Timo Reimann
7d20871f0d Fix typos. 2017-03-03 00:27:33 +01:00
Timo Reimann
6942b063ee Motivate and explain regular expression rules. 2017-03-02 23:00:25 +01:00
Timo Reimann
e56bd27c1e Remove blank space. 2017-03-02 23:00:25 +01:00
Timo Reimann
a3beec6b9c Merge pull request #1214 from timoreimann/avoid-validate-glide-output-suppression
Evaluate glide-hash result without reading $?.
2017-03-02 23:00:01 +01:00
Timo Reimann
04a1ecc4f4 Evaluate glide-hash result without reading $?.
validate-glide is called with errexit enabled (in script/make.sh that
sources validate-glide), which means that grep returning a non-zero exit
code will cause the script to terminate prematurely. Thus, we will never
get to the point where we see the error message.

The fix is to embed the grep check directly inside the if statement.
2017-03-02 18:49:13 +01:00
Manuel Laufenberg
7707814f2e Merge pull request #1215 from timoreimann/add-timoreimann-to-maintainer-list
Add @timoreimann to list of maintainers.
2017-03-02 17:59:00 +01:00
Timo Reimann
4d4f2b62aa Add @timoreimann to list of maintainers. 2017-03-02 02:00:53 +01:00
Emile Vauge
5abffe402f Merge pull request #1194 from timoreimann/example-ip-addr-binding
Add Traefik TOML sample section on how to bind to specific IP addr.
2017-02-28 09:57:23 +01:00
Timo Reimann
38ec32a146 Add Traefik TOML sample section on how to bind to specific IP addr. 2017-02-25 21:44:01 +01:00
Vincent Demeester
d77ad42326 Merge pull request #1149 from Regner/kubernetes-support-externalname-service
Kubernetes support externalname service
2017-02-22 10:52:35 +01:00
Regner Blok-Andersen
4106f0fa9e Merge branch 'master' into kubernetes-support-externalname-service 2017-02-21 16:19:01 -08:00
Vincent Demeester
a0a0bf0577 Merge pull request #1170 from timoreimann/upgrade-go-marathon-to-v0.7.0
Upgrade dependencies.
2017-02-21 20:45:22 +01:00
Regner Blok-Andersen
71c7920d0f Merge branch 'master' into kubernetes-support-externalname-service 2017-02-21 10:02:34 -08:00
Timo Reimann
9bb1b01742 Upgrade dependencies.
Brings github.com/gambol99/go-marathon version 0.7.1.
2017-02-21 16:10:45 +01:00
Vincent Demeester
8c824680ce Merge pull request #1157 from solidnerd/fix-prometheus-in-traefik-example-toml
Fix prometheus metrics example
2017-02-21 09:52:27 +01:00
solidnerd
60b3f74be8 Fix prometheus metrics example
Traefik won’t start correctly if heterogeneous numbers in a toml array.  This commit makes all numbers homogene.

Signed-off-by: solidnerd <niclas@mietz.io>
2017-02-21 07:55:50 +01:00
Vincent Demeester
dfb09bf2ab Merge pull request #1172 from timoreimann/stop-considering-glide-lock-as-binary-in-git
Remove .gitattributes file.
2017-02-20 21:34:55 +01:00
Timo Reimann
98d6a43e1e Remove .gitattributes file.
Makes git diff Glide lock files as text, which is helpful to see changes
introduced by a 'glide update' run.
2017-02-18 22:56:24 +01:00
Regner Blok-Andersen
49466d0d14 Added documentation about defining the passing of host header globaly 2017-02-15 16:11:31 -08:00
Regner Blok-Andersen
66cc9a075c First pass of documentation for passHostHeader kubernetes annotation 2017-02-15 13:37:47 -08:00
Regner Blok-Andersen
1e10fc2e30 Simplifying else if statement to be cleaner 2017-02-14 14:57:09 -08:00
Regner Blok-Andersen
c8cf5f8c44 Added a test to make sure passing an invalid value to traefik.frontend.passHostHeader results in falling back correctly. 2017-02-14 11:54:27 -08:00
Regner Blok-Andersen
96e6c9cef2 Split the if/or statement when requesting endpoints from the k8s service so that it now provides two unique log statements. 2017-02-14 11:53:35 -08:00
Regner Blok-Andersen
931ee55e1d Added default case for PassHostHeader that logs a warning. 2017-02-14 11:52:54 -08:00
Regner Blok-Andersen
4d3aede5d3 Added tests for ingress passHostHeader annotation 2017-02-10 03:27:30 -08:00
Regner Blok-Andersen
0b1dd69b01 Added support for passHostHeader annotation on ingresses 2017-02-10 03:05:59 -08:00
Regner Blok-Andersen
0947aa901e Initial support for Kubernetes ExternalName service type 2017-02-09 17:25:38 -08:00
Vincent Demeester
01e3d7952a Merge pull request #1133 from timoreimann/build-binary-for-test-integration-makefile-target
Build binary for test-integration Makefile target.
2017-02-08 09:30:08 +01:00
Timo Reimann
84b224b9db Build binary for test-integration Makefile target. 2017-02-07 15:08:17 +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
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
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
Ed Robinson
874ea62dd5 Adds misspell to validate target 2016-11-16 11:04:26 +00: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
Bruce Lee
e068ee09ca Allow specification of dialertimeout
Address documentation comments
2016-11-14 10:57:46 -05: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
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
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
acf425b6cf Merge pull request #817 from gomes/master
Marathon ExposedByDefault is true by default
2016-11-10 11:34:00 +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
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
djalal
952fcf5d09 fix typos 2016-11-05 23:02:43 +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
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
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
5229 changed files with 1846358 additions and 5014 deletions

View File

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

1
.gitattributes vendored
View File

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

View File

@@ -2,7 +2,7 @@
### 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.
You need either [Docker](https://github.com/docker/docker) and `make` (Method 1), or `go` (Method 2) in order to build traefik. For changes to its dependencies, the `glide` dependency management tool and `glide-vc` plugin are required.
#### Method 1: Using `Docker` and `Makefile`
@@ -12,7 +12,7 @@ You need to run the `binary` target. This will create binaries for Linux platfor
$ 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
Step 0 : FROM golang:1.7
---> 8c6473912976
Step 1 : RUN go get github.com/Masterminds/glide
[...]
@@ -26,15 +26,14 @@ $ ls dist/
traefik*
```
#### Method 2: Using `go` and `glide`
#### Method 2: Using `go`
###### Setting up your `go` environment
- You need `go` v1.5+ (1.7 is acceptable)
- You need to set `$ export GO15VENDOREXPERIMENT=1` environment variable if you are using go v1.5 (it is already enabled in 1.6+)
- 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)
- You need `go` v1.7+
- It is recommended you clone Træfik 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:
```
```bash
$ export GOPATH=~/go
$ export PATH=$PATH:$GOPATH/bin
```
@@ -43,27 +42,33 @@ 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
#### Setting up `glide` and `glide-vc` for dependency management
- Glide is not required for building; however, it is necessary to modify dependencies (i.e., add, update, or remove third-party packages)
- Glide can be installed either via homebrew: `$ brew install glide` or via the official glide script: `$ curl https://glide.sh/get | sh`
- The glide plugin `glide-vc` must be installed from source: `go get github.com/sgotti/glide-vc`
The idea behind `glide` is the following :
If you want to add a dependency, use `$ glide get` to have glide put it into the vendor folder and update the glide manifest/lock files (`glide.yaml` and `glide.lock`, respectively). A following `glide-vc` run should be triggered to trim down the size of the vendor folder. The final result must be committed into VCS.
- when checkout(ing) a project, run `$ glide install` 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`.
Dependencies for the integration tests in the `integration` folder are managed in a separate `integration/glide.yaml` file using the same toolset.
Care must be taken to choose the right arguments to `glide` when dealing with either main or integration test dependencies, or otherwise risk ending up with a broken build. For that reason, the helper script `script/glide.sh` encapsulates the gory details and conveniently calls `glide-vc` as well. Call it without parameters for basic usage instructions.
Here's a full example:
```bash
$ glide install
# install the new main dependency github.com/foo/bar and minimize vendor size
$ ./script/glide.sh get github.com/foo/bar
# install another dependency, this time for the integration tests
$ ( cd integration && ../script/glide.sh get github.com/baz/quuz )
# 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}}"
-output="dist/traefik_{{.OS}}-{{.Arch}}" \
./cmd/traefik
# run other commands like tests
```
@@ -90,7 +95,7 @@ Test success
```
For development purposes, you can specify which tests to run by using:
```
```bash
# Run every tests in the MyTest suite
TESTFLAGS="-check.f MyTestSuite" make test-integration
@@ -106,7 +111,7 @@ TESTFLAGS="-check.f MyTestSuite.*Test" make test-integration
More: https://labix.org/gocheck
##### Method 2: `go` and `glide`
##### Method 2: `go`
- Tests can be run from the cloned directory, by `$ go test ./...` which should return `ok` similar to:
```
@@ -119,7 +124,7 @@ The [documentation site](http://docs.traefik.io/) is built with [mkdocs](http://
First make sure you have python and pip installed
```
```shell
$ python --version
Python 2.7.2
$ pip --version
@@ -128,13 +133,13 @@ pip 1.5.2
Then install mkdocs with pip
```
```shell
$ pip install mkdocs
```
To test documentation locally run `mkdocs serve` in the root directory, this should start a server locally to preview your changes.
```
```shell
$ 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

58
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,58 @@
<!--
PLEASE READ THIS MESSAGE.
Please keep in mind that the GitHub issue tracker is not intended as a general support forum, but for reporting bugs and feature requests.
For other type of questions, consider using one of:
- the Traefik community Slack channel: https://traefik.herokuapp.com
- StackOverflow: https://stackoverflow.com/questions/tagged/traefik
HOW TO WRITE A GOOD ISSUE?
- if it's possible use the command `traefik bug`. See https://www.youtube.com/watch?v=Lyz62L8m93I.
- The title must be short and descriptive.
- Explain the conditions which led you to write this issue: the context.
- The context should lead to something, an idea or a problem that youre facing.
- Remain clear and concise.
- Format your messages to help the reader focus on what matters and understand the structure of your message, use Markdown syntax https://help.github.com/articles/github-flavored-markdown
-->
### Do you want to request a *feature* or report a *bug*?
### What did you do?
### What did you expect to see?
### What did you see instead?
### Output of `traefik version`: (_What version of Traefik are you using?_)
```
(paste your output here)
```
### What is your environment & configuration (arguments, toml, provider, platform, ...)?
```toml
# (paste your configuration here)
```
<!--
Add more configuration information here.
-->
### If applicable, please paste the log output in debug mode (`--debug` switch)
```
(paste your output here)
```

23
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,23 @@
<!--
PLEASE READ THIS MESSAGE.
HOW TO WRITE A GOOD PULL REQUEST?
- Make it small.
- Do only one thing.
- Avoid re-formatting.
- Make sure the code builds.
- Make sure all tests pass.
- Add tests.
- Write useful descriptions and titles.
- Address review comments in terms of additional commits.
- Do not amend/squash existing ones unless the PR is trivial.
- Read the contributing guide: https://github.com/containous/traefik/blob/master/.github/CONTRIBUTING.md.
-->
### Description
<!--
Briefly describe the pull request in a few paragraphs.
-->

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 -b "$pr--$branch" $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 "$pr--$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 --force-with-lease $remote "$pr--$branch"

12
.gitignore vendored
View File

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

11
.semaphoreci/setup.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -e
sudo -E apt-get -yq update
sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install docker-engine=${DOCKER_VERSION}*
docker version
pip install --user -r requirements.txt
make pull-images
ci_retry make validate

6
.semaphoreci/tests.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -e
make test-unit
ci_retry make test-integration
make -j${N_MAKE_JOBS} crossbinary-default-parallel

41
.semaphoreci/vars Normal file
View File

@@ -0,0 +1,41 @@
#!/usr/bin/env bash
set -e
export 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='
export REPO='containous/traefik'
export DOCKER_VERSION=1.12.6
if VERSION=$(git describe --exact-match --abbrev=0 --tags);
then
export VERSION
else
export VERSION=''
fi
export CODENAME=raclette
export N_MAKE_JOBS=2
function ci_retry {
local NRETRY=3
local NSLEEP=5
local n=0
until [ $n -ge $NRETRY ]
do
"$@" && break
n=$[$n+1]
echo "$@ failed, attempt ${n}/${NRETRY}"
sleep $NSLEEP
done
[ $n -lt $NRETRY ]
}
export -f ci_retry

View File

@@ -1,34 +1,59 @@
branches:
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: camembert
matrix:
- DOCKER_VERSION=1.9.1
- DOCKER_VERSION=1.10.1
sudo: required
services:
- docker
install:
- sudo service docker stop
- sudo curl https://get.docker.com/builds/Linux/x86_64/docker-${DOCKER_VERSION} -o /usr/bin/docker
- sudo chmod +x /usr/bin/docker
- sudo service docker start
- sleep 5
- docker version
- pip install --user mkdocs
- pip install --user pymdown-extensions
- pip install --user mkdocs-bootswatch
before_script:
- make validate
- make binary
- CODENAME: raclette
- N_MAKE_JOBS: 2
- DOCKER_VERSION: 1.12.6
script:
- make test-unit
- make test-integration
- make crossbinary
- make image
after_success:
- make deploy
- make deploy-pr
- echo "Skipping tests... (Tests are executed on SemaphoreCI)"
before_deploy:
- >
if ! [ "$BEFORE_DEPLOY_RUN" ]; then
export BEFORE_DEPLOY_RUN=1;
sudo -E apt-get -yq update;
sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install docker-engine=${DOCKER_VERSION}*;
docker version;
pip install --user -r requirements.txt;
make -j${N_MAKE_JOBS} crossbinary-parallel;
make image;
mkdocs build --clean;
tar cfz dist/traefik-${VERSION}.src.tar.gz --exclude-vcs --exclude dist .;
fi
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

View File

@@ -1,5 +1,526 @@
# Change Log
## [v1.3.0](https://github.com/containous/traefik/tree/v1.3.0) (2017-05-31)
[All Commits](https://github.com/containous/traefik/compare/v1.2.0-rc1...v1.3.0)
**Enhancements:**
- **[acme]** Tighten regex match for wildcard certs [Addendum to #1018] ([#1227](https://github.com/containous/traefik/pull/1227) by [dtomcej](https://github.com/dtomcej))
- **[api,webui]** Feature web root path ([#1233](https://github.com/containous/traefik/pull/1233) by [tcoupin](https://github.com/tcoupin))
- **[authentication,docker,rancher]** Add Basic Auth per Frontend ([#1147](https://github.com/containous/traefik/pull/1147) by [SantoDE](https://github.com/SantoDE))
- **[authentication]** Allow usersFile to be specified for basic or digest auth ([#1189](https://github.com/containous/traefik/pull/1189) by [krancour](https://github.com/krancour))
- **[docker]** Allow multiple rules from docker labels containers with traefik.&lt;servicename&gt;.* properties ([#1257](https://github.com/containous/traefik/pull/1257) by [benoitf](https://github.com/benoitf))
- **[docker]** Use docker-compose labels for frontend and backend names ([#1235](https://github.com/containous/traefik/pull/1235) by [tcoupin](https://github.com/tcoupin))
- **[dynamodb]** add dynamodb backend ([#1158](https://github.com/containous/traefik/pull/1158) by [tskinn](https://github.com/tskinn))
- **[healthcheck,consul]** using more sensible consul blocking query to detect health check changes ([#1241](https://github.com/containous/traefik/pull/1241) by [vholovko](https://github.com/vholovko))
- **[healthcheck]** Add global health check interval parameter. ([#1338](https://github.com/containous/traefik/pull/1338) by [timoreimann](https://github.com/timoreimann))
- **[healthcheck]** Start health checks early. ([#1319](https://github.com/containous/traefik/pull/1319) by [timoreimann](https://github.com/timoreimann))
- **[k8s]** Upgrade k8s.io/client-go to version 2 ([#1178](https://github.com/containous/traefik/pull/1178) by [errm](https://github.com/errm))
- **[k8s]** Support cluster-external Kubernetes client. ([#1159](https://github.com/containous/traefik/pull/1159) by [timoreimann](https://github.com/timoreimann))
- **[k8s]** Add basic auth to kubernetes provider ([#1488](https://github.com/containous/traefik/pull/1488) by [alpe](https://github.com/alpe))
- **[k8s]** Adding support for Traefik to respect the K8s ingress class annotation ([#1182](https://github.com/containous/traefik/pull/1182) by [Regner](https://github.com/Regner))
- **[k8s]** Refactor k8s rule type annotation parsing/retrieval. ([#1151](https://github.com/containous/traefik/pull/1151) by [timoreimann](https://github.com/timoreimann))
- **[k8s]** Kubernetes support externalname service ([#1149](https://github.com/containous/traefik/pull/1149) by [Regner](https://github.com/Regner))
- **[kv]** Add libkv Username and Password ([#1357](https://github.com/containous/traefik/pull/1357) by [tcolgate](https://github.com/tcolgate))
- **[kv]** kv: Ignore backend servers with no url ([#1196](https://github.com/containous/traefik/pull/1196) by [klausenbusk](https://github.com/klausenbusk))
- **[logs]** New access logger ([#1408](https://github.com/containous/traefik/pull/1408) by [rjshep](https://github.com/rjshep))
- **[logs]** Revert &#34;New access logger&#34; ([#1541](https://github.com/containous/traefik/pull/1541) by [emilevauge](https://github.com/emilevauge))
- **[marathon]** Allow traefik.port to not be in the list of marathon ports ([#1394](https://github.com/containous/traefik/pull/1394) by [emilevauge](https://github.com/emilevauge))
- **[marathon]** Add tests lost during PR 1320. ([#1540](https://github.com/containous/traefik/pull/1540) by [timoreimann](https://github.com/timoreimann))
- **[marathon]** Make Traefik health checks label-configurable with Marathon. ([#1320](https://github.com/containous/traefik/pull/1320) by [timoreimann](https://github.com/timoreimann))
- **[marathon]** Detect proper hostname automatically. ([#1345](https://github.com/containous/traefik/pull/1345) by [diegooliveira](https://github.com/diegooliveira))
- **[rancher]** Added constraint management for Rancher provider ([#1527](https://github.com/containous/traefik/pull/1527) by [yyekhlef](https://github.com/yyekhlef))
- **[rancher]** Improve rancher provider handling of service and container health states ([#1343](https://github.com/containous/traefik/pull/1343) by [kelchm](https://github.com/kelchm))
- **[rancher]** Fix Rancher API pagination limits ([#1453](https://github.com/containous/traefik/pull/1453) by [martinbaillie](https://github.com/martinbaillie))
- **[rancher]** Fix Rancher backend left in uncommented state ([#1455](https://github.com/containous/traefik/pull/1455) by [martinbaillie](https://github.com/martinbaillie))
- **[rules]** Add Path Replacement Rule ([#1374](https://github.com/containous/traefik/pull/1374) by [ssttevee](https://github.com/ssttevee))
- **[rules]** Add PathStripRegex rule ([#1339](https://github.com/containous/traefik/pull/1339) by [seguins](https://github.com/seguins))
- **[webui]** Working UI ([#1542](https://github.com/containous/traefik/pull/1542) by [maxwo](https://github.com/maxwo))
- **[webui]** Dashboard filter ([#1437](https://github.com/containous/traefik/pull/1437) by [ldez](https://github.com/ldez))
- Upgrade dependencies. ([#1170](https://github.com/containous/traefik/pull/1170) by [timoreimann](https://github.com/timoreimann))
- Bump go 1.8 ([#1259](https://github.com/containous/traefik/pull/1259) by [emilevauge](https://github.com/emilevauge))
- Update TLS Ciphers for Go 1.8 ([#1276](https://github.com/containous/traefik/pull/1276) by [kekoav](https://github.com/kekoav))
- Add IdleConnTimeout to Traefik&#39;s http.server settings ([#1340](https://github.com/containous/traefik/pull/1340) by [bparli](https://github.com/bparli))
- Pass stripped prefix downstream as header ([#1442](https://github.com/containous/traefik/pull/1442) by [martinbaillie](https://github.com/martinbaillie))
- Extract some code in packages ([#1449](https://github.com/containous/traefik/pull/1449) by [vdemeester](https://github.com/vdemeester))
- Vendor generated file ([#1464](https://github.com/containous/traefik/pull/1464) by [vdemeester](https://github.com/vdemeester))
- Add unit tests for package safe ([#1517](https://github.com/containous/traefik/pull/1517) by [gottwald](https://github.com/gottwald))
- Use TOML-compatible duration type. ([#1350](https://github.com/containous/traefik/pull/1350) by [timoreimann](https://github.com/timoreimann))
- Get testify/require dependency. ([#1658](https://github.com/containous/traefik/pull/1658) by [timoreimann](https://github.com/timoreimann))
**Bug fixes:**
- **[consul]** fix consul sample endpoints ([#1303](https://github.com/containous/traefik/pull/1303) by [ruslansennov](https://github.com/ruslansennov))
- **[consul]** Fix Consul catalog prefix flags ([#1486](https://github.com/containous/traefik/pull/1486) by [emilevauge](https://github.com/emilevauge))
- **[docker]** Make port deterministic ([#1523](https://github.com/containous/traefik/pull/1523) by [tanyadegurechaff](https://github.com/tanyadegurechaff))
- **[k8s]** Remove rule type path list. ([#1630](https://github.com/containous/traefik/pull/1630) by [timoreimann](https://github.com/timoreimann))
- **[k8s]** Ignore Ingresses with empty Endpoint subsets. ([#1604](https://github.com/containous/traefik/pull/1604) by [timoreimann](https://github.com/timoreimann))
- **[k8s]** Ignore missing pass host header annotation. ([#1581](https://github.com/containous/traefik/pull/1581) by [timoreimann](https://github.com/timoreimann))
- **[logs]** Fix empty basic auth ([#1601](https://github.com/containous/traefik/pull/1601) by [emilevauge](https://github.com/emilevauge))
- **[logs]** Create log folder if not present ([#1507](https://github.com/containous/traefik/pull/1507) by [tanyadegurechaff](https://github.com/tanyadegurechaff))
- **[marathon]** Upgrade go-marathon to 15ea23e. ([#1635](https://github.com/containous/traefik/pull/1635) by [timoreimann](https://github.com/timoreimann))
- **[marathon]** Fix default timeouts for Marathon provider. ([#1398](https://github.com/containous/traefik/pull/1398) by [timoreimann](https://github.com/timoreimann))
- **[marathon]** Check for explicitly defined Marathon port first. ([#1474](https://github.com/containous/traefik/pull/1474) by [timoreimann](https://github.com/timoreimann))
- **[marathon]** Bump go-marathon dep ([#1524](https://github.com/containous/traefik/pull/1524) by [jangie](https://github.com/jangie))
- **[middleware,rules]** Fix behavior for PathPrefixStrip ([#1638](https://github.com/containous/traefik/pull/1638) by [seryl](https://github.com/seryl))
- **[middleware,websocket]** Fix stats hijack ([#1598](https://github.com/containous/traefik/pull/1598) by [emilevauge](https://github.com/emilevauge))
- **[provider]** Fix exported fields providers ([#1588](https://github.com/containous/traefik/pull/1588) by [emilevauge](https://github.com/emilevauge))
- **[rancher]** fix: Empty Rancher Service Labels. ([#1654](https://github.com/containous/traefik/pull/1654) by [ldez](https://github.com/ldez))
- **[sticky-session]** Maintain sticky flag on LB method validation failure. ([#1585](https://github.com/containous/traefik/pull/1585) by [timoreimann](https://github.com/timoreimann))
- Revert &#34;Vendor generated file&#34; ([#1534](https://github.com/containous/traefik/pull/1534) by [ldez](https://github.com/ldez))
- Update golang.org/x/sys to fix windows compilation ([#1448](https://github.com/containous/traefik/pull/1448) by [vdemeester](https://github.com/vdemeester))
- Fix systemd watchdog feature ([#1525](https://github.com/containous/traefik/pull/1525) by [guilhem](https://github.com/guilhem))
- Fixed ReplacePath rule executing out of order, when combined with PathPrefixStrip ([#1577](https://github.com/containous/traefik/pull/1577) by [aantono](https://github.com/aantono))
**Documentation:**
- **[cluster]** doc: Traefik cluster in beta. ([#1610](https://github.com/containous/traefik/pull/1610) by [ldez](https://github.com/ldez))
- **[docker]** Fix error in documentation for Docker labels ([#1179](https://github.com/containous/traefik/pull/1179) by [bgandon](https://github.com/bgandon))
- **[k8s]** Re Organise k8s docs to make 1.6 usage easier ([#1602](https://github.com/containous/traefik/pull/1602) by [errm](https://github.com/errm))
- **[k8s]** Add documentation for k8s RBAC configuration ([#1404](https://github.com/containous/traefik/pull/1404) by [aolwas](https://github.com/aolwas))
- **[k8s]** Add documentation about k8s Helm Chart ([#1367](https://github.com/containous/traefik/pull/1367) by [seguins](https://github.com/seguins))
- **[marathon]** Add Marathon guide. ([#1578](https://github.com/containous/traefik/pull/1578) by [Stibbons](https://github.com/Stibbons))
- **[metrics]** Fix prometheus metrics example ([#1157](https://github.com/containous/traefik/pull/1157) by [solidnerd](https://github.com/solidnerd))
- **[metrics]** Make toml Bucket array homogeneous ([#1369](https://github.com/containous/traefik/pull/1369) by [Starefossen](https://github.com/Starefossen))
- **[rancher]** make docs more clear about how to work with the current api ([#1337](https://github.com/containous/traefik/pull/1337) by [SantoDE](https://github.com/SantoDE))
- **[rules]** Motivate and explain regular expression rules. ([#1216](https://github.com/containous/traefik/pull/1216) by [timoreimann](https://github.com/timoreimann))
- **[rules]** Improve documentation for frontend rules. ([#1469](https://github.com/containous/traefik/pull/1469) by [timoreimann](https://github.com/timoreimann))
- License 2017, Træfɪk =&gt; Træfik ([#1368](https://github.com/containous/traefik/pull/1368) by [emilevauge](https://github.com/emilevauge))
- update wording ([#1458](https://github.com/containous/traefik/pull/1458) by [ben-st](https://github.com/ben-st))
- Fix typo in command line help. ([#1467](https://github.com/containous/traefik/pull/1467) by [mattcollier](https://github.com/mattcollier))
- Mention Traefik pronunciation in docs too. ([#1468](https://github.com/containous/traefik/pull/1468) by [timoreimann](https://github.com/timoreimann))
- Correct typo in code comment. ([#1473](https://github.com/containous/traefik/pull/1473) by [mattcollier](https://github.com/mattcollier))
- Change a word in the documentation ([#1274](https://github.com/containous/traefik/pull/1274) by [sroze](https://github.com/sroze))
- Add @trecloux to Maintainers ([#1226](https://github.com/containous/traefik/pull/1226) by [emilevauge](https://github.com/emilevauge))
- doc: enhance GitHub template. ([#1482](https://github.com/containous/traefik/pull/1482) by [ldez](https://github.com/ldez))
- Add @timoreimann to list of maintainers. ([#1215](https://github.com/containous/traefik/pull/1215) by [timoreimann](https://github.com/timoreimann))
- Add Traefik TOML sample section on how to bind to specific IP addr. ([#1194](https://github.com/containous/traefik/pull/1194) by [timoreimann](https://github.com/timoreimann))
- doc: enhance Github templates. ([#1515](https://github.com/containous/traefik/pull/1515) by [ldez](https://github.com/ldez))
- doc: small documentation review ([#1516](https://github.com/containous/traefik/pull/1516) by [ldez](https://github.com/ldez))
**Misc:**
- **[docker]** Few refactoring around the docker provider ([#1440](https://github.com/containous/traefik/pull/1440) by [vdemeester](https://github.com/vdemeester))
- **[k8s]** Updating Kubernetes tests to properly test missing endpoints code path ([#1436](https://github.com/containous/traefik/pull/1436) by [Regner](https://github.com/Regner))
- **[provider]** Extract providers to their own packages ([#1444](https://github.com/containous/traefik/pull/1444) by [vdemeester](https://github.com/vdemeester))
- Fix typo in server.go ([#1386](https://github.com/containous/traefik/pull/1386) by [mihaitodor](https://github.com/mihaitodor))
- Vendor dependencies ([#1144](https://github.com/containous/traefik/pull/1144) by [timoreimann](https://github.com/timoreimann))
- Prepare release v1.3.0-rc3 ([#1661](https://github.com/containous/traefik/pull/1661) by [ldez](https://github.com/ldez))
- Prepare release v1.3.0-rc2 ([#1606](https://github.com/containous/traefik/pull/1606) by [emilevauge](https://github.com/emilevauge))
- Prepare release v1.3.0-rc1 ([#1553](https://github.com/containous/traefik/pull/1553) by [emilevauge](https://github.com/emilevauge))
- Merge v1.2.3 master ([#1538](https://github.com/containous/traefik/pull/1538) by [emilevauge](https://github.com/emilevauge))
- Merge v1.2.1 master ([#1383](https://github.com/containous/traefik/pull/1383) by [emilevauge](https://github.com/emilevauge))
- Merge v1.2.0 rc2 master ([#1208](https://github.com/containous/traefik/pull/1208) by [emilevauge](https://github.com/emilevauge))
## [v1.3.0-rc3](https://github.com/containous/traefik/tree/v1.3.0-rc3) (2017-05-24)
[All Commits](https://github.com/containous/traefik/compare/v1.3.0-rc2...v1.3.0-rc3)
**Enhancements:**
- [#1658](https://github.com/containous/traefik/issues/1658) Get testify/require dependency. ([timoreimann](https://github.com/timoreimann))
**Bug fixes:**
- [#1507](https://github.com/containous/traefik/issues/1507) Create log folder if not present ([tanyadegurechaff](https://github.com/tanyadegurechaff))
- [#1604](https://github.com/containous/traefik/issues/1604) [k8s] Ignore Ingresses with empty Endpoint subsets. ([timoreimann](https://github.com/timoreimann))
- [#1630](https://github.com/containous/traefik/issues/1630) [k8s] Remove rule type path list. ([timoreimann](https://github.com/timoreimann))
- [#1635](https://github.com/containous/traefik/issues/1635) Upgrade go-marathon to 15ea23e. ([timoreimann](https://github.com/timoreimann))
- [#1638](https://github.com/containous/traefik/issues/1638) Fix behavior for PathPrefixStrip ([seryl](https://github.com/seryl))
- [#1654](https://github.com/containous/traefik/issues/1654) fix: Empty Rancher Service Labels. ([ldez](https://github.com/ldez))
**Documentation:**
- [#1578](https://github.com/containous/traefik/issues/1578) Add Marathon guide. ([Stibbons](https://github.com/Stibbons))
- [#1602](https://github.com/containous/traefik/issues/1602) Re Orginise k8s docs to make 1.6 usage easier ([errm](https://github.com/errm))
- [#1642](https://github.com/containous/traefik/issues/1642) Update changelog ([ldez](https://github.com/ldez))
## [v1.3.0-rc2](https://github.com/containous/traefik/tree/v1.3.0-rc2) (2017-05-16)
[All Commits](https://github.com/containous/traefik/compare/v1.3.0-rc1...v1.3.0-rc2)
**Enhancements:**
- Fixed ReplacePath rule executing out of order, when combined with PathPrefixStrip [#1577](https://github.com/containous/traefik/issues/1577) ([aantono](https://github.com/aantono))
**Bug fixes:**
- [Kubernetes] Ignore missing pass host header annotation. [#1581](https://github.com/containous/traefik/issues/1581) ([timoreimann](https://github.com/timoreimann))
- Maintain sticky flag on LB method validation failure. [#1585](https://github.com/containous/traefik/issues/1585) ([timoreimann](https://github.com/timoreimann))
- Fix exported fields providers [#1588](https://github.com/containous/traefik/issues/1588) ([emilevauge](https://github.com/emilevauge))
- Fix stats hijack [#1598](https://github.com/containous/traefik/issues/1598) ([emilevauge](https://github.com/emilevauge))
- Fix empty basic auth [#1601](https://github.com/containous/traefik/issues/1601) ([emilevauge](https://github.com/emilevauge))
**Documentation:**
- doc: Traefik cluster in beta. [#1610](https://github.com/containous/traefik/issues/1610) ([ldez](https://github.com/ldez))
## [v1.3.0-rc1](https://github.com/containous/traefik/tree/v1.3.0-rc1) (2017-05-05)
[All Commits](https://github.com/containous/traefik/compare/v1.2.0-rc1...v1.3.0-rc1)
**Enhancements:**
- Add Basic Auth per Frontend [#1147](https://github.com/containous/traefik/issues/1147) ([SantoDE](https://github.com/SantoDE))
- Kubernetes support externalname service [#1149](https://github.com/containous/traefik/issues/1149) ([Regner](https://github.com/Regner))
- add dynamodb backend [#1158](https://github.com/containous/traefik/issues/1158) ([tskinn](https://github.com/tskinn))
- Support cluster-external Kubernetes client. [#1159](https://github.com/containous/traefik/issues/1159) ([timoreimann](https://github.com/timoreimann))
- Add Traefik TOML sample section on how to bind to specific IP addr. [#1194](https://github.com/containous/traefik/issues/1194) ([timoreimann](https://github.com/timoreimann))
- kv: Ignore backend servers with no url [#1196](https://github.com/containous/traefik/issues/1196) ([klausenbusk](https://github.com/klausenbusk))
- Tighten regex match for wildcard certs [Addendum to #1018] [#1227](https://github.com/containous/traefik/issues/1227) ([dtomcej](https://github.com/dtomcej))
- Feature web root path [#1233](https://github.com/containous/traefik/issues/1233) ([tcoupin](https://github.com/tcoupin))
- using more sensible consul blocking query to detect health check changes [#1241](https://github.com/containous/traefik/issues/1241) ([vholovko](https://github.com/vholovko))
- Allow multiple rules from docker labels containers with traefik.&lt;servicename&gt;.* properties [#1257](https://github.com/containous/traefik/issues/1257) ([benoitf](https://github.com/benoitf))
- Update TLS Ciphers for Go 1.8 [#1276](https://github.com/containous/traefik/issues/1276) ([kekoav](https://github.com/kekoav))
- Start health checks early. [#1319](https://github.com/containous/traefik/issues/1319) ([timoreimann](https://github.com/timoreimann))
- Make Traefik health checks label-configurable with Marathon. [#1320](https://github.com/containous/traefik/issues/1320) ([timoreimann](https://github.com/timoreimann))
- Append template section asking for debug log output. [#1324](https://github.com/containous/traefik/issues/1324) ([timoreimann](https://github.com/timoreimann))
- Add global health check interval parameter. [#1338](https://github.com/containous/traefik/issues/1338) ([timoreimann](https://github.com/timoreimann))
- Fix regex with PathStrip [#1339](https://github.com/containous/traefik/issues/1339) ([seguins](https://github.com/seguins))
- Add IdleConnTimeout to Traefik&#39;s http.server settings [#1340](https://github.com/containous/traefik/issues/1340) ([bparli](https://github.com/bparli))
- Improve rancher provider handling of service and container health states [#1343](https://github.com/containous/traefik/issues/1343) ([kelchm](https://github.com/kelchm))
- [Marathon] Detect proper hostname automatically. [#1345](https://github.com/containous/traefik/issues/1345) ([diegooliveira](https://github.com/diegooliveira))
- Use TOML-compatible duration type. [#1350](https://github.com/containous/traefik/issues/1350) ([timoreimann](https://github.com/timoreimann))
- Add libkv Username and Password [#1357](https://github.com/containous/traefik/issues/1357) ([tcolgate](https://github.com/tcolgate))
- Make toml Bucket array homogeneous [#1369](https://github.com/containous/traefik/issues/1369) ([Starefossen](https://github.com/Starefossen))
- Add Path Replacement Rule [#1374](https://github.com/containous/traefik/issues/1374) ([ssttevee](https://github.com/ssttevee))
- New access logger [#1408](https://github.com/containous/traefik/issues/1408) ([rjshep](https://github.com/rjshep))
- feat(webui): Dashboard filter [#1437](https://github.com/containous/traefik/issues/1437) ([ldez](https://github.com/ldez))
- Pass stripped prefix downstream as header (#985) [#1442](https://github.com/containous/traefik/issues/1442) ([martinbaillie](https://github.com/martinbaillie))
- Extract some code in packages [#1449](https://github.com/containous/traefik/issues/1449) ([vdemeester](https://github.com/vdemeester))
- Fix Rancher API pagination limits [#1453](https://github.com/containous/traefik/issues/1453) ([martinbaillie](https://github.com/martinbaillie))
- Fix Rancher backend left in uncommented state [#1455](https://github.com/containous/traefik/issues/1455) ([martinbaillie](https://github.com/martinbaillie))
- Vendor generated file [#1464](https://github.com/containous/traefik/issues/1464) ([vdemeester](https://github.com/vdemeester))
- Add basic auth to kubernetes provider [#1488](https://github.com/containous/traefik/issues/1488) ([alpe](https://github.com/alpe))
- Add unit tests for package safe [#1517](https://github.com/containous/traefik/issues/1517) ([gottwald](https://github.com/gottwald))
- feat(rancher): added constraint management for rancher provider [#1527](https://github.com/containous/traefik/issues/1527) ([yyekhlef](https://github.com/yyekhlef))
- refactor: fix for PR with master branch. [#1537](https://github.com/containous/traefik/issues/1537) ([ldez](https://github.com/ldez))
- Add tests lost during PR 1320. [#1540](https://github.com/containous/traefik/issues/1540) ([timoreimann](https://github.com/timoreimann))
- Working UI [#1542](https://github.com/containous/traefik/issues/1542) ([maxwo](https://github.com/maxwo))
**Bug fixes:**
- Fix default timeouts for Marathon provider. [#1398](https://github.com/containous/traefik/issues/1398) ([timoreimann](https://github.com/timoreimann))
- Update golang.org/x/sys to fix windows compilation [#1448](https://github.com/containous/traefik/issues/1448) ([vdemeester](https://github.com/vdemeester))
- Check for explicitly defined Marathon port first. [#1474](https://github.com/containous/traefik/issues/1474) ([timoreimann](https://github.com/timoreimann))
- Fix Consul catalog prefix flags [#1486](https://github.com/containous/traefik/issues/1486) ([emilevauge](https://github.com/emilevauge))
- Move Docker test provider instantiation into t.Run body. [#1489](https://github.com/containous/traefik/issues/1489) ([timoreimann](https://github.com/timoreimann))
- Make port deterministic [#1523](https://github.com/containous/traefik/issues/1523) ([tanyadegurechaff](https://github.com/tanyadegurechaff))
- [Marathon] Bump go-marathon dep [#1524](https://github.com/containous/traefik/issues/1524) ([jangie](https://github.com/jangie))
- Fix systemd watchdog feature [#1525](https://github.com/containous/traefik/issues/1525) ([guilhem](https://github.com/guilhem))
- Revert &#34;Vendor generated file&#34; [#1534](https://github.com/containous/traefik/issues/1534) ([ldez](https://github.com/ldez))
**Documentation:**
- Fix prometheus metrics example [#1157](https://github.com/containous/traefik/issues/1157) ([solidnerd](https://github.com/solidnerd))
- Fix error in documentation for Docker labels [#1179](https://github.com/containous/traefik/issues/1179) ([bgandon](https://github.com/bgandon))
- Motivate and explain regular expression rules. [#1216](https://github.com/containous/traefik/issues/1216) ([timoreimann](https://github.com/timoreimann))
- Add @trecloux to Maintainers [#1226](https://github.com/containous/traefik/issues/1226) ([emilevauge](https://github.com/emilevauge))
- Change a word in the documentation [#1274](https://github.com/containous/traefik/issues/1274) ([sroze](https://github.com/sroze))
- make docs more clear about how to work with the current api [#1337](https://github.com/containous/traefik/issues/1337) ([SantoDE](https://github.com/SantoDE))
- Add documentation about k8s Helm Chart [#1367](https://github.com/containous/traefik/issues/1367) ([seguins](https://github.com/seguins))
- License 2017, Træfɪk =&gt; Træfik [#1368](https://github.com/containous/traefik/issues/1368) ([emilevauge](https://github.com/emilevauge))
- Add documentation for k8s RBAC configuration [#1404](https://github.com/containous/traefik/issues/1404) ([aolwas](https://github.com/aolwas))
- update wording [#1458](https://github.com/containous/traefik/issues/1458) ([ben-st](https://github.com/ben-st))
- Fix typo in command line help. [#1467](https://github.com/containous/traefik/issues/1467) ([mattcollier](https://github.com/mattcollier))
- Mention Traefik pronunciation in docs too. [#1468](https://github.com/containous/traefik/issues/1468) ([timoreimann](https://github.com/timoreimann))
- Improve documentation for frontend rules. [#1469](https://github.com/containous/traefik/issues/1469) ([timoreimann](https://github.com/timoreimann))
- Correct typo in code comment. [#1473](https://github.com/containous/traefik/issues/1473) ([mattcollier](https://github.com/mattcollier))
- doc: enhance GitHub template. [#1482](https://github.com/containous/traefik/issues/1482) ([ldez](https://github.com/ldez))
- doc: enhance Github templates. [#1515](https://github.com/containous/traefik/issues/1515) ([ldez](https://github.com/ldez))
- doc: small documentation review [#1516](https://github.com/containous/traefik/issues/1516) ([ldez](https://github.com/ldez))
**Misc:**
- Vendor dependencies [#1144](https://github.com/containous/traefik/issues/1144) ([timoreimann](https://github.com/timoreimann))
- Refactor k8s rule type annotation parsing/retrieval. [#1151](https://github.com/containous/traefik/issues/1151) ([timoreimann](https://github.com/timoreimann))
- Upgrade dependencies. [#1170](https://github.com/containous/traefik/issues/1170) ([timoreimann](https://github.com/timoreimann))
- Remove .gitattributes file. [#1172](https://github.com/containous/traefik/issues/1172) ([timoreimann](https://github.com/timoreimann))
- Upgrade k8s.io/client-go to version 2 [#1178](https://github.com/containous/traefik/issues/1178) ([errm](https://github.com/errm))
- Adding support for Traefik to respect the K8s ingress class annotation [#1182](https://github.com/containous/traefik/issues/1182) ([Regner](https://github.com/Regner))
- Allow usersFile to be specified for basic or digest auth [#1189](https://github.com/containous/traefik/issues/1189) ([krancour](https://github.com/krancour))
- Merge v1.2.0 rc2 master [#1208](https://github.com/containous/traefik/issues/1208) ([emilevauge](https://github.com/emilevauge))
- Add @timoreimann to list of maintainers. [#1215](https://github.com/containous/traefik/issues/1215) ([timoreimann](https://github.com/timoreimann))
- Use docker-compose labels for frontend and backend names [#1235](https://github.com/containous/traefik/issues/1235) ([tcoupin](https://github.com/tcoupin))
- Bump go 1.8 [#1259](https://github.com/containous/traefik/issues/1259) ([emilevauge](https://github.com/emilevauge))
- fix consul sample endpoints [#1303](https://github.com/containous/traefik/issues/1303) ([ruslansennov](https://github.com/ruslansennov))
- Merge v1.2.1 master [#1383](https://github.com/containous/traefik/issues/1383) ([emilevauge](https://github.com/emilevauge))
- Fix typo in server.go [#1386](https://github.com/containous/traefik/issues/1386) ([mihaitodor](https://github.com/mihaitodor))
- Allow traefik.port to not be in the list of marathon ports [#1394](https://github.com/containous/traefik/issues/1394) ([emilevauge](https://github.com/emilevauge))
- Updating Kubernetes tests to properly test missing endpoints code path [#1436](https://github.com/containous/traefik/issues/1436) ([Regner](https://github.com/Regner))
- Few refactoring around the docker provider [#1440](https://github.com/containous/traefik/issues/1440) ([vdemeester](https://github.com/vdemeester))
- Extract providers to their own packages [#1444](https://github.com/containous/traefik/issues/1444) ([vdemeester](https://github.com/vdemeester))
- Merge v1.2.3 master [#1538](https://github.com/containous/traefik/issues/1538) ([emilevauge](https://github.com/emilevauge))
- Revert &#34;First stage of access logging middleware. Initially without … [#1541](https://github.com/containous/traefik/issues/1541) ([emilevauge](https://github.com/emilevauge))
- Prepare release v1.3.0-rc1 [#1553](https://github.com/containous/traefik/issues/1553) ([emilevauge](https://github.com/emilevauge))
## [v1.2.3](https://github.com/containous/traefik/tree/v1.2.3) (2017-04-13)
[Full Changelog](https://github.com/containous/traefik/compare/v1.2.2...v1.2.3)
**Merged pull requests:**
- Fix too many redirect [\#1433](https://github.com/containous/traefik/pull/1433) ([emilevauge](https://github.com/emilevauge))
## [v1.2.2](https://github.com/containous/traefik/tree/v1.2.2) (2017-04-11)
[Full Changelog](https://github.com/containous/traefik/compare/v1.2.1...v1.2.2)
**Merged pull requests:**
- Carry PR 1271 [\#1417](https://github.com/containous/traefik/pull/1417) ([emilevauge](https://github.com/emilevauge))
- Fix postloadconfig acme & Docker filter empty rule [\#1401](https://github.com/containous/traefik/pull/1401) ([emilevauge](https://github.com/emilevauge))
## [v1.2.1](https://github.com/containous/traefik/tree/v1.2.1) (2017-03-27)
[Full Changelog](https://github.com/containous/traefik/compare/v1.2.0...v1.2.1)
**Merged pull requests:**
- bump lego 0e2937900 [\#1347](https://github.com/containous/traefik/pull/1347) ([emilevauge](https://github.com/emilevauge))
- k8s: Do not log service fields when GetService is failing. [\#1331](https://github.com/containous/traefik/pull/1331) ([timoreimann](https://github.com/timoreimann))
## [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)
@@ -616,4 +1137,4 @@
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
\* *This Change Log was automatically generated by [gcg](https://github.com/ldez/gcg)*

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2016 Containous SAS, Emile Vauge, emile@vauge.com
Copyright (c) 2016-2017 Containous SAS
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -6,21 +6,25 @@ TRAEFIK_ENVS := \
-e TESTFLAGS \
-e VERBOSE \
-e VERSION \
-e CODENAME
-e CODENAME \
-e TESTDIRS
SRCS = $(shell git ls-files '*.go' | grep -v '^external/')
SRCS = $(shell git ls-files '*.go' | grep -v '^vendor/' | grep -v '^integration/vendor/')
BIND_DIR := "dist"
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),"containous/traefik")
INTEGRATION_OPTS := $(if $(MAKE_DOCKER_HOST),-e "DOCKER_HOST=$(MAKE_DOCKER_HOST)", -v "/var/run/docker.sock:/var/run/docker.sock")
DOCKER_BUILD_ARGS := $(if $(DOCKER_VERSION), "--build-arg=DOCKER_VERSION=$(DOCKER_VERSION)",)
DOCKER_RUN_TRAEFIK := docker run $(INTEGRATION_OPTS) -it $(TRAEFIK_ENVS) $(TRAEFIK_MOUNT) "$(TRAEFIK_DEV_IMAGE)"
DOCKER_RUN_OPTS := $(TRAEFIK_ENVS) $(TRAEFIK_MOUNT) "$(TRAEFIK_DEV_IMAGE)"
DOCKER_RUN_TRAEFIK := docker run $(INTEGRATION_OPTS) -it $(DOCKER_RUN_OPTS)
DOCKER_RUN_TRAEFIK_NOTTY := docker run $(INTEGRATION_OPTS) -i $(DOCKER_RUN_OPTS)
print-%: ; @echo $*=$($*)
@@ -35,6 +39,24 @@ binary: generate-webui build ## build the linux binary
crossbinary: generate-webui build ## cross build the non-linux binaries
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate crossbinary
crossbinary-parallel:
$(MAKE) generate-webui
$(MAKE) build crossbinary-default crossbinary-others
crossbinary-default: generate-webui build
$(DOCKER_RUN_TRAEFIK_NOTTY) ./script/make.sh generate crossbinary-default
crossbinary-default-parallel:
$(MAKE) generate-webui
$(MAKE) build crossbinary-default
crossbinary-others: generate-webui build
$(DOCKER_RUN_TRAEFIK_NOTTY) ./script/make.sh generate crossbinary-others
crossbinary-others-parallel:
$(MAKE) generate-webui
$(MAKE) build crossbinary-others
test: build ## run the unit and integration tests
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate test-unit binary test-integration
@@ -42,10 +64,10 @@ test-unit: build ## run the unit tests
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate test-unit
test-integration: build ## run the integration tests
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate test-integration
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate binary test-integration
validate: build ## validate gofmt, golint and go vet
$(DOCKER_RUN_TRAEFIK) ./script/make.sh validate-gofmt validate-govet validate-golint
$(DOCKER_RUN_TRAEFIK) ./script/make.sh validate-glide validate-gofmt validate-govet validate-golint validate-misspell validate-vendor
build: dist
docker build $(DOCKER_BUILD_ARGS) -t "$(TRAEFIK_DEV_IMAGE)" -f build.Dockerfile .
@@ -59,7 +81,7 @@ build-no-cache: dist
shell: build ## start a shell inside the build env
$(DOCKER_RUN_TRAEFIK) /bin/bash
image: build ## build a docker traefik image
image: binary ## build a docker traefik image
docker build -t $(TRAEFIK_IMAGE) .
dist:
@@ -83,11 +105,10 @@ lint:
fmt:
gofmt -s -l -w $(SRCS)
deploy:
./script/deploy.sh
deploy-pr:
./script/deploy-pr.sh
pull-images:
for f in $(shell find ./integration/resources/compose/ -type f); do \
docker-compose -f $$f pull; \
done
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)

View File

@@ -1,19 +1,19 @@
<p align="center">
<img src="docs/img/traefik.logo.png" alt="Træfɪk" title="Træfɪk" />
<img src="docs/img/traefik.logo.png" alt="Træfik" title="Træfik" />
</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/kubernetes/helm)](http://goreportcard.com/report/containous/traefik)
[![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](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), Rest API, file...) to manage its configuration automatically and dynamically.
Træfik (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), [Amazon DynamoDB](https://aws.amazon.com/dynamodb/), Rest API, file...) to manage its configuration automatically and dynamically.
## Overview
@@ -28,11 +28,11 @@ But a microservices architecture is dynamic... Services are added, removed, kill
Traditional reverse-proxies are not natively dynamic. You can't change their configuration and hot-reload easily.
Here enters Træfɪk.
Here enters Træfik.
![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.
Træfik 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!
@@ -64,21 +64,21 @@ Run it and forget it!
## Quickstart
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.
You can have a quick look at Træfik in this [Katacoda tutorial](https://www.katacoda.com/courses/traefik/deploy-load-balancer) that shows how to load balance requests between multiple Docker containers.
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.
You will learn fundamental Træfik 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.
You will learn fundamental Træfik 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
You can access to a simple HTML frontend of Træfik.
You can access the simple HTML frontend of Træfik.
![Web UI Providers](docs/img/web.frontend.png)
![Web UI Health](docs/img/traefik-health.png)
@@ -88,7 +88,6 @@ You can access to a simple HTML frontend of Træfik.
- [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
## Test it
@@ -128,33 +127,6 @@ Please note that this project is released with a [Contributor Code of Conduct](C
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>.
## Træfɪk here and there
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)
- Project [Mantl](https://mantl.io/) from Cisco
![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.
- Project [Apollo](http://capgemini.github.io/devops/apollo/) from Cap Gemini
![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.
## Partners
[![Zenika](docs/img/zenika.logo.png)](https://zenika.com)
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.
[![Asteris](docs/img/asteris.logo.png)](https://aster.is)
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)
@@ -163,7 +135,13 @@ Founded in 2014, Asteris creates next-generation infrastructure software for the
- Ed Robinson [@errm](https://github.com/errm)
- Daniel Tomcej [@dtomcej](https://github.com/dtomcej)
- Manuel Laufenberg [@SantoDE](https://github.com/SantoDE)
- Thomas Recloux [@trecloux](https://github.com/trecloux)
- Timo Reimann [@timoreimann](https://github.com/timoreimann)
## Credits
Kudos to [Peka](http://peka.byethost11.com/photoblog/) for his awesome work on the logo ![logo](docs/img/traefik.icon.png)
Kudos to [Peka](http://peka.byethost11.com/photoblog/) for his awesome work on the logo ![logo](docs/img/traefik.icon.png).
Traefik's logo licensed under the Creative Commons 3.0 Attributions license.
Traefik's logo was inspired by the gopher stickers made by Takuya Ueda (https://twitter.com/tenntenn).
The original Go gopher was designed by Renee French (http://reneefrench.blogspot.com/).

View File

@@ -7,11 +7,14 @@ import (
"crypto/tls"
"crypto/x509"
"errors"
"github.com/containous/traefik/log"
"github.com/xenolf/lego/acme"
"reflect"
"sort"
"strings"
"sync"
"time"
"github.com/containous/traefik/log"
"github.com/xenolf/lego/acme"
)
// Account is used to store lets encrypt registration info
@@ -106,6 +109,38 @@ type DomainsCertificates struct {
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()
@@ -116,7 +151,15 @@ func (dc *DomainsCertificates) Init() error {
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
}
@@ -192,7 +235,7 @@ func (dc *DomainsCertificate) needRenew() bool {
// If there's an error, we assume the cert is broken, and needs update
return true
}
// <= 7 days left, renew certificate
// <= 30 days left, renew certificate
if crt.NotAfter.Before(time.Now().Add(time.Duration(24 * 30 * time.Hour))) {
return true
}

View File

@@ -1,9 +1,17 @@
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"
@@ -11,13 +19,14 @@ import (
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/containous/traefik/types"
"github.com/eapache/channels"
"github.com/xenolf/lego/acme"
"golang.org/x/net/context"
"io/ioutil"
fmtlog "log"
"os"
"strings"
"time"
"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
@@ -30,11 +39,16 @@ type ACME struct {
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
@@ -79,7 +93,11 @@ type Domain struct {
}
func (a *ACME) init() error {
acme.Logger = fmtlog.New(ioutil.Discard, "", 0)
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 {
@@ -91,6 +109,7 @@ func (a *ACME) init() error {
log.Warnf("ACME.StorageFile is deprecated, use ACME.Storage instead")
a.Storage = a.StorageFile
}
a.jobs = channels.NewInfiniteChannel()
return nil
}
@@ -106,6 +125,7 @@ func (a *ACME) CreateClusterConfig(leadership *cluster.Leadership, tlsConfig *tl
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()
@@ -142,9 +162,7 @@ func (a *ACME) CreateClusterConfig(leadership *cluster.Leadership, tlsConfig *tl
case <-ctx.Done():
return
case <-ticker.C:
if err := a.renewCertificates(); err != nil {
log.Errorf("Error renewing ACME certificate: %s", err.Error())
}
a.renewCertificates()
}
}
})
@@ -205,12 +223,10 @@ func (a *ACME) CreateClusterConfig(leadership *cluster.Leadership, tlsConfig *tl
if err != nil {
return err
}
safe.Go(func() {
a.retrieveCertificates()
if err := a.renewCertificates(); err != nil {
log.Errorf("Error renewing ACME certificate %+v: %s", account, err.Error())
}
})
a.retrieveCertificates()
a.renewCertificates()
a.runJobs()
}
return nil
})
@@ -229,7 +245,7 @@ func (a *ACME) CreateLocalConfig(tlsConfig *tls.Config, checkOnDemandDomain func
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}
@@ -295,19 +311,14 @@ func (a *ACME) CreateLocalConfig(tlsConfig *tls.Config, checkOnDemandDomain func
return err
}
safe.Go(func() {
a.retrieveCertificates()
if err := a.renewCertificates(); err != nil {
log.Errorf("Error renewing ACME certificate %+v: %s", account, err.Error())
}
})
a.retrieveCertificates()
a.renewCertificates()
a.runJobs()
ticker := time.NewTicker(24 * time.Hour)
safe.Go(func() {
for range ticker.C {
if err := a.renewCertificates(); err != nil {
log.Errorf("Error renewing ACME certificate %+v: %s", account, err.Error())
}
a.renewCertificates()
}
})
@@ -317,6 +328,14 @@ func (a *ACME) CreateLocalConfig(tlsConfig *tls.Config, checkOnDemandDomain func
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
@@ -336,83 +355,101 @@ func (a *ACME) getCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificat
}
func (a *ACME) retrieveCertificates() {
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
}
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
if err = transaction.Commit(account); err != nil {
log.Errorf("Error Saving ACME account %+v: %s", account, err.Error())
continue
}
}
}
log.Infof("Retrieved ACME certificates")
}
log.Infof("Retrieved ACME certificates")
}
func (a *ACME) renewCertificates() error {
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)
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 {
return err
}
account = object.(*Account)
err = account.DomainsCertificate.renewCertificates(renewedACMECert, certificateResource.Domains)
if err != nil {
log.Errorf("Error renewing certificate: %v", err)
continue
}
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
if err = transaction.Commit(account); err != nil {
log.Errorf("Error Saving ACME account %+v: %s", account, err.Error())
continue
}
}
}
}
return nil
}
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) {
@@ -425,8 +462,28 @@ func (a *ACME) buildACMEClient(account *Account) (*acme.Client, error) {
if err != nil {
return nil, err
}
client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.DNS01})
err = client.SetChallengeProvider(acme.TLSSNI01, a.challengeProvider)
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
}
@@ -462,8 +519,9 @@ func (a *ACME) loadCertificateOnDemand(clientHello *tls.ClientHelloInfo) (*tls.C
// LoadCertificateForDomains loads certificates from ACME for given domains
func (a *ACME) LoadCertificateForDomains(domains []string) {
domains = fun.Map(types.CanonicalDomain, domains).([]string)
safe.Go(func() {
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")
@@ -475,7 +533,7 @@ func (a *ACME) LoadCertificateForDomains(domains []string) {
}
ebo := backoff.NewExponentialBackOff()
ebo.MaxElapsedTime = 30 * time.Second
err := backoff.RetryNotify(operation, ebo, notify)
err := backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify)
if err != nil {
log.Errorf("Error getting ACME client: %v", err)
return
@@ -517,14 +575,14 @@ func (a *ACME) LoadCertificateForDomains(domains []string) {
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)
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)
@@ -538,3 +596,12 @@ func (a *ACME) getDomainsCertificates(domains []string) (*Certificate, error) {
Certificate: certificate.Certificate,
}, nil
}
func (a *ACME) runJobs() {
safe.Go(func() {
for job := range a.jobs.Out() {
function := job.(func())
function()
}
})
}

View File

@@ -1,9 +1,15 @@
package acme
import (
"encoding/base64"
"net/http"
"net/http/httptest"
"reflect"
"sync"
"testing"
"time"
"github.com/xenolf/lego/acme"
)
func TestDomainsSet(t *testing.T) {
@@ -62,6 +68,8 @@ func TestDomainsSetAppend(t *testing.T) {
}
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{
@@ -73,55 +81,8 @@ func TestCertificatesRenew(t *testing.T) {
Domain: "foo1.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: []byte(`
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA6OqHGdwGy20+3Jcz9IgfN4IR322X2Hhwk6n8Hss/Ws7FeTZo
PvXW8uHeI1bmQJsy9C6xo3odzO64o7prgMZl5eDw5fk1mmUij3J3nM3gwtc/Cc+8
ADXGldauASdHBFTRvWQge0Pv/Q5U0fyL2VCHoR9mGv4CQ7nRNKPus0vYJMbXoTbO
8z4sIbNz3Ov9o/HGMRb8D0rNPTMdC62tHSbiO1UoxLXr9dcBOGt786AsiRTJ8bq9
GCVQgzd0Wftb8z6ddW2YuWrmExlkHdfC4oG0D5SU1QB4ldPyl7fhVWlfHwC1NX+c
RnDSEeYkAcdvvIekdM/yH+z62XhwToM0E9TCzwIDAQABAoIBACq3EC3S50AZeeTU
qgeXizoP1Z1HKQjfFa5PB1jSZ30M3LRdIQMi7NfASo/qmPGSROb5RUS42YxC34PP
ZXXJbNiaxzM13/m/wHXURVFxhF3XQc1X1p+nPRMvutulS2Xk9E4qdbaFgBbFsRKN
oUwqc6U97+jVWq72/gIManNhXnNn1n1SRLBEkn+WStMPn6ZvWRlpRMjhy0c1mpwg
u6em92HvMvfKPQ60naUhdKp+q0rsLp2YKWjiytos9ENSYI5gAGLIDhKeqiD8f92E
4FGPmNRipwxCE2SSvZFlM26tRloWVcBPktRN79hUejE8iopiqVS0+4h/phZ2wG0D
18cqVpECgYEA+qmagnhm0LLvwVkUN0B2nRARQEFinZDM4Hgiv823bQvc9I8dVTqJ
aIQm5y4Y5UA3xmyDsRoO7GUdd0oVeh9GwTONzMRCOny/mOuOC51wXPhKHhI0O22u
sfbOHszl+bxl6ZQMUJa2/I8YIWBLU5P+fTgrfNwBEgZ3YPwUV5tyHNcCgYEA7eAv
pjQkbJNRq/fv/67sojN7N9QoH84egN5cZFh5d8PJomnsvy5JDV4WaG1G6mJpqjdD
YRVdFw5oZ4L8yCVdCeK9op896Uy51jqvfSe3+uKmNqE0qDHgaLubQNI8yYc5sacW
fYJBmDR6rNIeE7Q2240w3CdKfREuXdDnhyTTEskCgYBFeAnFTP8Zqe2+hSSQJ4J4
BwLw7u4Yww+0yja/N5E1XItRD/TOMRnx6GYrvd/ScVjD2kEpLRKju2ZOMC8BmHdw
hgwvitjcAsTK6cWFPI3uhjVsXhkxuzUmR0Naz+iQrQEFmi1LjGmMV1AVt+1IbYSj
SZTr1sFJMJeXPmWY3hDjIwKBgQC4H9fCJoorIL0PB5NVreishHzT8fw84ibqSTPq
2DDtazcf6C3AresN1c4ydqN1uUdg4fXdp9OujRBzTwirQ4CIrmFrBye89g7CrBo6
Hgxivh06G/3OUw0JBG5f9lvnAiy+Pj9CVxi+36A1NU7ioZP0zY0MW71koW/qXlFY
YkCfQQKBgBqwND/c3mPg7iY4RMQ9XjrKfV9o6FMzA51lAinjujHlNgsBmqiR951P
NA3kWZQ73D3IxeLEMaGHpvS7andPN3Z2qPhe+FbJKcF6ZZNTrFQkh/Fpz3wmYPo1
GIL4+09kNgMRWapaROqI+/3+qJQ+GVJZIPfYC0poJOO6vYqifWe8
-----END RSA PRIVATE KEY-----
`),
Certificate: []byte(`
-----BEGIN CERTIFICATE-----
MIIC+TCCAeGgAwIBAgIJAK78ukR/Qu4rMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV
BAMMCGZvbzEuY29tMB4XDTE2MDYxOTIyMDMyM1oXDTI2MDYxNzIyMDMyM1owEzER
MA8GA1UEAwwIZm9vMS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQDo6ocZ3AbLbT7clzP0iB83ghHfbZfYeHCTqfweyz9azsV5Nmg+9dby4d4jVuZA
mzL0LrGjeh3M7rijumuAxmXl4PDl+TWaZSKPcneczeDC1z8Jz7wANcaV1q4BJ0cE
VNG9ZCB7Q+/9DlTR/IvZUIehH2Ya/gJDudE0o+6zS9gkxtehNs7zPiwhs3Pc6/2j
8cYxFvwPSs09Mx0Lra0dJuI7VSjEtev11wE4a3vzoCyJFMnxur0YJVCDN3RZ+1vz
Pp11bZi5auYTGWQd18LigbQPlJTVAHiV0/KXt+FVaV8fALU1f5xGcNIR5iQBx2+8
h6R0z/If7PrZeHBOgzQT1MLPAgMBAAGjUDBOMB0GA1UdDgQWBBRFLH1wF6BT51uq
yWNqBnCrPFIglzAfBgNVHSMEGDAWgBRFLH1wF6BT51uqyWNqBnCrPFIglzAMBgNV
HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAr7aH3Db6TeAZkg4Zd7SoF2q11
erzv552PgQUyezMZcRBo2q1ekmUYyy2600CBiYg51G+8oUqjJKiKnBuaqbMX7pFa
FsL7uToZCGA57cBaVejeB+p24P5bxoJGKCMeZcEBe5N93Tqu5WBxNEX7lQUo6TSs
gSN2Olf3/grNKt5V4BduSIQZ+YHlPUWLTaz5B1MXKSUqjmabARP9lhjO14u9USvi
dMBDFskJySQ6SUfz3fyoXELoDOVbRZETuSodpw+aFCbEtbcQCLT3A0FG+BEPayZH
tt19zKUlr6e+YFpyjQPGZ7ZkY7iMgHEkhKrXx2DiZ1+cif3X1xfXWQr0S5+E
-----END CERTIFICATE-----
`),
PrivateKey: foo1Key,
Certificate: foo1Cert,
},
},
{
@@ -132,113 +93,19 @@ tt19zKUlr6e+YFpyjQPGZ7ZkY7iMgHEkhKrXx2DiZ1+cif3X1xfXWQr0S5+E
Domain: "foo2.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: []byte(`
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA7rIVuSrZ3FfYXhR3qaWwfVcgiqKS//yXFzNqkJS6mz9nRCNT
lPawvrCFIRKdR7UO7xD7A5VTcbrGOAaTvrEaH7mB/4FGL+gN4AiTbVFpKXngAYEW
A3//zeBZ7XUSWaQ+CNC+l796JeoDvQD++KwCke4rVD1pGN1hpVEeGhwzyKOYPKLo
4+AGVe1LFWw4U/v8Iil1/gBBehZBILuhASpXy4W132LJPl76/EbGqh0nVz2UlFqU
HRxO+2U2ba4YIpI+0/VOQ9Cq/TzHSUdTTLfBHE/Qb+aDBfptMWTRvAngLqUglOcZ
Fi6SAljxEkJO6z6btmoVUWsoKBpbIHDC5++dZwIDAQABAoIBAAD8rYhRfAskNdnV
vdTuwXcTOCg6md8DHWDULpmgc9EWhwfKGZthFcQEGNjVKd9VCVXFvTP7lxe+TPmI
VW4Rb2k4LChxUWf7TqthfbKTBptMTLfU39Ft4xHn3pdTx5qlSjhhHJimCwxDFnbe
nS9MDsqpsHYtttSKfc/gMP6spS4sNPZ/r9zseT3eWkBEhn+FQABxJiuPcQ7q7S+Q
uOghmr7f3FeYvizQOhBtULsLrK/hsmQIIB4amS1QlpNWKbIoiUPNPjCA5PVQyAER
waYjuc7imBbeD98L/z8bRTlEskSKjtPSEXGVHa9OYdBU+02Ci6TjKztUp6Ho7JE9
tcHj+eECgYEA+9Ntv6RqIdpT/4/52JYiR+pOem3U8tweCOmUqm/p/AWyfAJTykqt
cJ8RcK1MfM+uoa5Sjm8hIcA2XPVEqH2J50PC4w04Q3xtfsz3xs7KJWXQCoha8D0D
ZIFNroEPnld0qOuJzpIIteXTrCLhSu17ZhN+Wk+5gJ7Ewu/QMM5OPjECgYEA8qbw
zfwSjE6jkrqO70jzqSxgi2yjo0vMqv+BNBuhxhDTBXnKQI1KsHoiS0FkSLSJ9+DS
CT3WEescD2Lumdm2s9HXvaMmnDSKBY58NqCGsNzZifSgmj1H/yS9FX8RXfSjXcxq
RDvTbD52/HeaCiOxHZx8JjmJEb+ZKJC4MDvjtxcCgYBM516GvgEjYXdxfliAiijh
6W4Z+Vyk5g/ODPc3rYG5U0wUjuljx7Z7xDghPusy2oGsIn5XvRxTIE35yXU0N1Jb
69eiWzEpeuA9bv7kGdal4RfNf6K15wwYL1y3w/YvFuorg/LLwNEkK5Ge6e//X9Ll
c2KM1fgCjXntRitAHGDMoQKBgDnkgodioLpA+N3FDN0iNqAiKlaZcOFA8G/LzfO0
tAAhe3dO+2YzT6KTQSNbUqXWDSTKytHRowVbZrJ1FCA4xVJZunNQPaH/Fv8EY7ZU
zk3cIzq61qZ2AHtrNIGwc2BLQb7bSm9FJsgojxLlJidNJLC/6Q7lo0JMyCnZfVhk
sYu5AoGAZt/MfyFTKm674UddSNgGEt86PyVYbLMnRoAXOaNB38AE12kaYHPil1tL
FnL8OQLpbX5Qo2JGgeZRlpMJ4Jxw2zzvUKr/n+6khaLxHmtX48hMu2QM7ZvnkZCs
Kkgz6v+Wcqm94ugtl3HSm+u9xZzVQxN6gu/jZQv3VpQiAZHjPYc=
-----END RSA PRIVATE KEY-----
`),
Certificate: []byte(`
-----BEGIN CERTIFICATE-----
MIIC+TCCAeGgAwIBAgIJAK25/Z9Jz6IBMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV
BAMMCGZvbzIuY29tMB4XDTE2MDYyMDA5MzUyNloXDTI2MDYxODA5MzUyNlowEzER
MA8GA1UEAwwIZm9vMi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQDushW5KtncV9heFHeppbB9VyCKopL//JcXM2qQlLqbP2dEI1OU9rC+sIUhEp1H
tQ7vEPsDlVNxusY4BpO+sRofuYH/gUYv6A3gCJNtUWkpeeABgRYDf//N4FntdRJZ
pD4I0L6Xv3ol6gO9AP74rAKR7itUPWkY3WGlUR4aHDPIo5g8oujj4AZV7UsVbDhT
+/wiKXX+AEF6FkEgu6EBKlfLhbXfYsk+Xvr8RsaqHSdXPZSUWpQdHE77ZTZtrhgi
kj7T9U5D0Kr9PMdJR1NMt8EcT9Bv5oMF+m0xZNG8CeAupSCU5xkWLpICWPESQk7r
Ppu2ahVRaygoGlsgcMLn751nAgMBAAGjUDBOMB0GA1UdDgQWBBQ6FZWqB9qI4NN+
2jFY6xH8uoUTnTAfBgNVHSMEGDAWgBQ6FZWqB9qI4NN+2jFY6xH8uoUTnTAMBgNV
HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCRhuf2dQhIEOmSOGgtRELF2wB6
NWXt0lCty9x4u+zCvITXV8Z0C34VQGencO3H2bgyC3ZxNpPuwZfEc2Pxe8W6bDc/
OyLckk9WLo00Tnr2t7rDOeTjEGuhXFZkhIbJbKdAH8cEXrxKR8UXWtZgTv/b8Hv/
g6tbeH6TzBsdMoFtUCsyWxygYwnLU+quuYvE2s9FiCegf2mdYTCh/R5J5n/51gfB
uC+NakKMfaCvNg3mOAFSYC/0r0YcKM/5ldKGTKTCVJAMhnmBnyRc/70rKkVRFy2g
iIjUFs+9aAgfCiL0WlyyXYAtIev2gw4FHUVlcT/xKks+x8Kgj6e5LTIrRRwW
-----END CERTIFICATE-----
`),
PrivateKey: foo2Key,
Certificate: foo2Cert,
},
},
},
}
foo1Cert, foo1Key, _ = generateKeyPair("foo1.com", time.Now())
newCertificate := &Certificate{
Domain: "foo1.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: []byte(`
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA1OdSuXK2zeSLf0UqgrI4pjkpaqhra++pnda4Li4jXo151svi
Sn7DSynJOoq1jbfRJAoyDhxsBC4S4RuD54U5elJ4wLPZXmHRsvb+NwiHs9VmDqwu
It21btuqeNMebkab5cnDnC6KKufMhXRcRAlluYXyCkQe/+N+LlUQd6Js34TixMpk
eQOX4/OVrokSyVRnIq4u+o0Ufe7z5+41WVH63tcy7Hwi7244aLUzZCs+QQa2Dw6f
qEwjbonr974fM68UxDjTZEQy9u24yDzajhDBp1OTAAklh7U+li3g9dSyNVBFXqEu
nW2fyBvLqeJOSTihqfcrACB/YYhYOX94vMXELQIDAQABAoIBAFYK3t3fxI1VTiMz
WsjTKh3TgC+AvVkz1ILbojfXoae22YS7hUrCDD82NgMYx+LsZPOBw1T8m5Lc4/hh
3F8W8nHDHtYSWUjRk6QWOgsXwXAmUEahw0uH+qlA0ZZfDC9ZDexCLHHURTat03Qj
4J4GhjwCLB2GBlk4IWisLCmNVR7HokrpfIw4oM1aB5E21Tl7zh/x7ikRijEkUsKw
7YhaMeLJqBnMnAdV63hhF7FaDRjl8P2s/3octz/6pqDIABrDrUW3KAkNYCZIWdhF
Kk0wRMbZ/WrYT9GIGoJe7coQC7ezTrlrEkAFEIPGHCLkgXB/0TyuSy0yY59e4zmi
VvHoWUECgYEA/rOL2KJ/p+TZW7+YbsUzs0+F+M+G6UCr0nWfYN9MKmNtmns3eLDG
+pIpBMc5mjqeJR/sCCdkD8OqHC202Y8e4sr0pKSBeBofh2BmXtpyu3QQ50Pa63RS
SK6mYUrFqPmFFDbNGpFI4sIeI+Vf6hm96FQPnyPtUTGqk39m0RbWM/UCgYEA1f04
Nf3wbqwqIHZjYpPmymfjleyMn3hGUjpi7pmI6inXGMk3nkeG1cbOhnfPxL5BWD12
3RqHI2B4Z4r0BMyjctDNb1TxhMIpm5+PKm5KeeKfoYA85IS0mEeq6VdMm3mL1x/O
3LYvcUvAEVf6pWX/+ZFLMudqhF3jbTrdNOC6ZFkCgYBKpEeJdyW+CD0CvEVpwPUD
yXxTjE3XMZKpHLtWYlop2fWW3iFFh1jouci3k8L3xdHuw0oioZibXhYOJ/7l+yFs
CVpknakrj0xKGiAmEBKriLojbClN80rh7fzoakc+29D6OY0mCgm4GndGwcO4EU8s
NOZXFupHbyy0CRQSloSzuQKBgQC1Z/MtIlefGuijmHlsakGuuR+gS2ZzEj1bHBAe
gZ4mFM46PuqdjblqpR0TtaI3AarXqVOI4SJLBU9NR+jR4MF3Zjeh9/q/NvKa8Usn
B1Svu0TkXphAiZenuKnVIqLY8tNvzZFKXlAd1b+/dDwR10SHR3rebnxINmfEg7Bf
UVvyEQKBgAEjI5O6LSkLNpbVn1l2IO8u8D2RkFqs/Sbx78uFta3f9Gddzb4wMnt3
jVzymghCLp4Qf1ump/zC5bcQ8L97qmnjJ+H8X9HwmkqetuI362JNnz+12YKVDIWi
wI7SJ8BwDqYMrLw6/nE+degn39KedGDH8gz5cZcdlKTZLjbuBOfU
-----END RSA PRIVATE KEY-----
`),
Certificate: []byte(`
-----BEGIN CERTIFICATE-----
MIIC+TCCAeGgAwIBAgIJAPQiOiQcwYaRMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV
BAMMCGZvbzEuY29tMB4XDTE2MDYxOTIyMTE1NFoXDTI2MDYxNzIyMTE1NFowEzER
MA8GA1UEAwwIZm9vMS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQDU51K5crbN5It/RSqCsjimOSlqqGtr76md1rguLiNejXnWy+JKfsNLKck6irWN
t9EkCjIOHGwELhLhG4PnhTl6UnjAs9leYdGy9v43CIez1WYOrC4i3bVu26p40x5u
RpvlycOcLooq58yFdFxECWW5hfIKRB7/434uVRB3omzfhOLEymR5A5fj85WuiRLJ
VGciri76jRR97vPn7jVZUfre1zLsfCLvbjhotTNkKz5BBrYPDp+oTCNuiev3vh8z
rxTEONNkRDL27bjIPNqOEMGnU5MACSWHtT6WLeD11LI1UEVeoS6dbZ/IG8up4k5J
OKGp9ysAIH9hiFg5f3i8xcQtAgMBAAGjUDBOMB0GA1UdDgQWBBQPfkS5ehpstmSb
8CGJE7GxSCxl2DAfBgNVHSMEGDAWgBQPfkS5ehpstmSb8CGJE7GxSCxl2DAMBgNV
HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQA99A+itS9ImdGRGgHZ5fSusiEq
wkK5XxGyagL1S0f3VM8e78VabSvC0o/xdD7DHVg6Az8FWxkkksH6Yd7IKfZZUzvs
kXQhlOwWpxgmguSmAs4uZTymIoMFRVj3nG664BcXkKu4Yd9UXKNOWP59zgvrCJMM
oIsmYiq5u0MFpM31BwfmmW3erqIcfBI9OJrmr1XDzlykPZNWtUSSfVuNQ8d4bim9
XH8RfVLeFbqDydSTCHIFvYthH/ESbpRCiGJHoJ8QLfOkhD1k2fI0oJZn5RVtG2W8
bZME3gHPYCk1QFZUptriMCJ5fMjCgxeOTR+FAkstb/lTRuCc4UyILJguIMar
-----END CERTIFICATE-----
`),
PrivateKey: foo1Key,
Certificate: foo1Cert,
}
err := domainsCertificates.renewCertificates(
@@ -256,3 +123,157 @@ bZME3gHPYCk1QFZUptriMCJ5fMjCgxeOTR+FAkstb/lTRuCc4UyILJguIMar
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.")
}
}

View File

@@ -2,15 +2,16 @@ package acme
import (
"crypto/tls"
"fmt"
"strings"
"sync"
"time"
"fmt"
"github.com/cenk/backoff"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/xenolf/lego/acme"
"time"
)
var _ acme.ChallengeProviderTimeout = (*challengeProvider)(nil)
@@ -49,7 +50,7 @@ func (c *challengeProvider) getCertificate(domain string) (cert *tls.Certificate
}
ebo := backoff.NewExponentialBackOff()
ebo.MaxElapsedTime = 60 * time.Second
err := backoff.RetryNotify(operation, ebo, notify)
err := backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify)
if err != nil {
log.Errorf("Error getting cert: %v", err)
return nil, false

View File

@@ -17,34 +17,44 @@ import (
)
func generateDefaultCertificate() (*tls.Certificate, error) {
rsaPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, err
}
rsaPrivPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(rsaPrivKey)})
randomBytes := make([]byte, 100)
_, err = rand.Read(randomBytes)
_, 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:])
tempCertPEM, err := generatePemCert(rsaPrivKey, domain)
certPEM, keyPEM, err := generateKeyPair(domain, time.Time{})
if err != nil {
return nil, err
}
certificate, err := tls.X509KeyPair(tempCertPEM, rsaPrivPEM)
certificate, err := tls.X509KeyPair(certPEM, keyPEM)
if err != nil {
return nil, err
}
return &certificate, nil
}
func generatePemCert(privKey *rsa.PrivateKey, domain string) ([]byte, error) {
derBytes, err := generateDerCert(privKey, time.Time{}, domain)
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
}
@@ -93,7 +103,7 @@ func TLSSNI01ChallengeCert(keyAuth string) (ChallengeCert, string, error) {
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)
tempCertPEM, err := generatePemCert(rsaPrivKey, domain, time.Time{})
if err != nil {
return ChallengeCert{}, "", err
}

View File

@@ -3,10 +3,12 @@ package acme
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"sync"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/log"
"io/ioutil"
"sync"
)
var _ cluster.Store = (*LocalStore)(nil)
@@ -37,7 +39,17 @@ func (s *LocalStore) Load() (cluster.Object, error) {
s.storageLock.Lock()
defer s.storageLock.Unlock()
account := &Account{}
file, err := ioutil.ReadFile(s.file)
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
}

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

@@ -1,25 +1,35 @@
FROM golang:1.7
FROM golang:1.8
RUN go get github.com/Masterminds/glide \
&& go get github.com/jteeuwen/go-bindata/... \
# Install a more recent version of mercurial to avoid mismatching results
# between glide run on a decently updated host system and the build container.
RUN awk '$1 ~ "^deb" { $3 = $3 "-backports"; print; exit }' /etc/apt/sources.list > /etc/apt/sources.list.d/backports.list && \
DEBIAN_FRONTEND=noninteractive apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -t jessie-backports --yes --no-install-recommends mercurial=3.9.1-1~bpo8+1 && \
rm -fr /var/lib/apt/lists/
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/kisielk/errcheck \
&& go get github.com/client9/misspell/cmd/misspell \
&& go get github.com/mattfarina/glide-hash \
&& go get github.com/sgotti/glide-vc
# Which docker version to test on
ARG DOCKER_VERSION=1.10.1
ARG DOCKER_VERSION=1.10.3
# 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}
# Set the default Docker to be run
RUN ln -s /usr/local/bin/docker-${DOCKER_VERSION} /usr/local/bin/docker
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'
WORKDIR /go/src/github.com/containous/traefik
COPY glide.yaml glide.yaml
COPY glide.lock glide.lock
RUN glide install
COPY . /go/src/github.com/containous/traefik

View File

@@ -1,36 +0,0 @@
machine:
pre:
- sudo docker -d -e lxc -s btrfs -H tcp://0.0.0.0:2375:
background: true
- curl --retry 15 --retry-delay 3 -v http://172.17.42.1:2375/version
environment:
REPO: $CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME
DOCKER_HOST: tcp://172.17.42.1:2375
MAKE_DOCKER_HOST: $DOCKER_HOST
VERSION: v1.0.alpha.$CIRCLE_BUILD_NUM
dependencies:
pre:
- docker version
- go get github.com/tcnksm/ghr
- make validate
override:
- make binary
test:
override:
- make test-unit
- make test-integration
post:
- make crossbinary
- make image
deployment:
hub:
branch: master
commands:
- ghr -t $GITHUB_TOKEN -u $CIRCLE_PROJECT_USERNAME -r $CIRCLE_PROJECT_REPONAME --prerelease ${VERSION} dist/
- docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
- docker push ${REPO,,}:latest
- docker tag ${REPO,,}:latest ${REPO,,}:${VERSION}
- docker push ${REPO,,}:${VERSION}

View File

@@ -1,17 +1,19 @@
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"
"golang.org/x/net/context"
"sync"
"time"
)
// Metadata stores Object plus metadata
@@ -108,7 +110,7 @@ func (d *Datastore) watchChanges() error {
notify := func(err error, time time.Duration) {
log.Errorf("Error in watch datastore: %+v, retrying in %s", err, time)
}
err := backoff.RetryNotify(operation, job.NewBackOff(backoff.NewExponentialBackOff()), notify)
err := backoff.RetryNotify(safe.OperationWithRecover(operation), job.NewBackOff(backoff.NewExponentialBackOff()), notify)
if err != nil {
log.Errorf("Error in watch datastore: %v", err)
}
@@ -175,7 +177,7 @@ func (d *Datastore) Begin() (Transaction, Object, error) {
}
ebo := backoff.NewExponentialBackOff()
ebo.MaxElapsedTime = 60 * time.Second
err = backoff.RetryNotify(operation, ebo, notify)
err = backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify)
if err != nil {
return nil, nil, fmt.Errorf("Datastore cannot sync: %v", err)
}
@@ -230,24 +232,24 @@ 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")
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 err
return fmt.Errorf("Marshall error: %s", err)
}
err = s.kv.StoreConfig(s.Datastore.meta)
if err != nil {
return err
return fmt.Errorf("StoreConfig error: %s", err)
}
err = s.remoteLock.Unlock()
if err != nil {
return err
return fmt.Errorf("Unlock error: %s", err)
}
s.dirty = true
log.Debugf("Transaction commited %s", s.id)
log.Debugf("Transaction committed %s", s.id)
return nil
}

View File

@@ -1,13 +1,14 @@
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"
"golang.org/x/net/context"
"time"
)
// Leadership allows leadership election using a KV store
@@ -15,7 +16,7 @@ type Leadership struct {
*safe.Pool
*types.Cluster
candidate *leadership.Candidate
leader safe.Safe
leader *safe.Safe
listeners []LeaderListener
}
@@ -26,6 +27,7 @@ func NewLeadership(ctx context.Context, cluster *types.Cluster) *Leadership {
Cluster: cluster,
candidate: leadership.NewCandidate(cluster.Store, cluster.Store.Prefix+"/leader", cluster.Node, 20*time.Second),
listeners: []LeaderListener{},
leader: safe.New(false),
}
}
@@ -45,7 +47,7 @@ func (l *Leadership) Participate(pool *safe.Pool) {
notify := func(err error, time time.Duration) {
log.Errorf("Leadership election error %+v, retrying in %s", err, time)
}
err := backoff.RetryNotify(operation, backOff, notify)
err := backoff.RetryNotify(safe.OperationWithRecover(operation), backOff, notify)
if err != nil {
log.Errorf("Cannot elect leadership %+v", err)
}

152
cmd/traefik/bug.go Normal file
View File

@@ -0,0 +1,152 @@
package main
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 = `<!--
PLEASE READ THIS MESSAGE.
Please keep in mind that the GitHub issue tracker is not intended as a general support forum, but for reporting bugs and feature requests.
For other type of questions, consider using one of:
- the Traefik community Slack channel: https://traefik.herokuapp.com
- StackOverflow: https://stackoverflow.com/questions/tagged/traefik
HOW TO WRITE A GOOD ISSUE?
- if it's possible use the command` + "`" + `traefik bug` + "`" + `. See https://www.youtube.com/watch?v=Lyz62L8m93I.
- The title must be short and descriptive.
- Explain the conditions which led you to write this issue: the context.
- The context should lead to something, an idea or a problem that youre facing.
- Remain clear and concise.
- Format your messages to help the reader focus on what matters and understand the structure of your message, use Markdown syntax https://help.github.com/articles/github-flavored-markdown
-->
### Do you want to request a *feature* or report a *bug*?
### What did you do?
### What did you expect to see?
### What did you see instead?
### Output of ` + "`" + `traefik version` + "`" + `: (_What version of Traefik are you using?_)
` + "```" + `
{{.Version}}
` + "```" + `
### What is your environment & configuration (arguments, toml, provider, platform, ...)?
` + "```" + `toml
{{.Configuration}}
` + "```" + `
<!--
Add more configuration information here.
-->
### If applicable, please paste the log output in debug mode (` + "`" + `--debug` + "`" + ` switch)
` + "```" + `
(paste your output here)
` + "```" + `
`
)
// 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)
}

313
cmd/traefik/traefik.go Normal file
View File

@@ -0,0 +1,313 @@
package main
import (
"crypto/tls"
"encoding/json"
"fmt"
fmtlog "log"
"net/http"
"os"
"path/filepath"
"reflect"
"runtime"
"strings"
"time"
"github.com/Sirupsen/logrus"
"github.com/containous/flaeg"
"github.com/containous/staert"
"github.com/containous/traefik/acme"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/log"
"github.com/containous/traefik/middlewares"
"github.com/containous/traefik/provider/kubernetes"
"github.com/containous/traefik/safe"
"github.com/containous/traefik/server"
"github.com/containous/traefik/types"
"github.com/containous/traefik/version"
"github.com/coreos/go-systemd/daemon"
"github.com/docker/libkv/store"
"github.com/satori/go.uuid"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
//traefik config inits
traefikConfiguration := server.NewTraefikConfiguration()
traefikPointersConfiguration := server.NewTraefikDefaultPointersConfiguration()
//traefik Command init
traefikCmd := &flaeg.Command{
Name: "traefik",
Description: `traefik is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease.
Complete documentation is available at https://traefik.io`,
Config: traefikConfiguration,
DefaultPointersConfig: traefikPointersConfiguration,
Run: func() error {
run(traefikConfiguration)
return nil
},
}
//storeconfig Command init
var kv *staert.KvSource
var err error
storeconfigCmd := &flaeg.Command{
Name: "storeconfig",
Description: `Store the static traefik configuration into a Key-value stores. Traefik will not start.`,
Config: traefikConfiguration,
DefaultPointersConfig: traefikPointersConfiguration,
Run: func() error {
if kv == nil {
return fmt.Errorf("Error using command storeconfig, no Key-value store defined")
}
jsonConf, err := json.Marshal(traefikConfiguration.GlobalConfiguration)
if err != nil {
return err
}
fmtlog.Printf("Storing configuration: %s\n", jsonConf)
err = kv.StoreConfig(traefikConfiguration.GlobalConfiguration)
if err != nil {
return err
}
if traefikConfiguration.GlobalConfiguration.ACME != nil && len(traefikConfiguration.GlobalConfiguration.ACME.StorageFile) > 0 {
// convert ACME json file to KV store
store := acme.NewLocalStore(traefikConfiguration.GlobalConfiguration.ACME.StorageFile)
object, err := store.Load()
if err != nil {
return err
}
meta := cluster.NewMetadata(object)
err = meta.Marshall()
if err != nil {
return err
}
source := staert.KvSource{
Store: kv,
Prefix: traefikConfiguration.GlobalConfiguration.ACME.Storage,
}
err = source.StoreConfig(meta)
if err != nil {
return err
}
}
return nil
},
Metadata: map[string]string{
"parseAllSources": "true",
},
}
//init flaeg source
f := flaeg.New(traefikCmd, os.Args[1:])
//add custom parsers
f.AddParser(reflect.TypeOf(server.EntryPoints{}), &server.EntryPoints{})
f.AddParser(reflect.TypeOf(server.DefaultEntryPoints{}), &server.DefaultEntryPoints{})
f.AddParser(reflect.TypeOf(types.Constraints{}), &types.Constraints{})
f.AddParser(reflect.TypeOf(kubernetes.Namespaces{}), &kubernetes.Namespaces{})
f.AddParser(reflect.TypeOf([]acme.Domain{}), &acme.Domains{})
f.AddParser(reflect.TypeOf(types.Buckets{}), &types.Buckets{})
//add commands
f.AddCommand(newVersionCmd())
f.AddCommand(newBugCmd(traefikConfiguration, traefikPointersConfiguration))
f.AddCommand(storeconfigCmd)
usedCmd, err := f.GetCommand()
if err != nil {
fmtlog.Println(err)
os.Exit(-1)
}
if _, err := f.Parse(usedCmd); err != nil {
fmtlog.Printf("Error parsing command: %s\n", err)
os.Exit(-1)
}
//staert init
s := staert.NewStaert(traefikCmd)
//init toml source
toml := staert.NewTomlSource("traefik", []string{traefikConfiguration.ConfigFile, "/etc/traefik/", "$HOME/.traefik/", "."})
//add sources to staert
s.AddSource(toml)
s.AddSource(f)
if _, err := s.LoadConfig(); err != nil {
fmtlog.Println(fmt.Errorf("Error reading TOML config file %s : %s", toml.ConfigFileUsed(), err))
os.Exit(-1)
}
traefikConfiguration.ConfigFile = toml.ConfigFileUsed()
kv, err = CreateKvSource(traefikConfiguration)
if err != nil {
fmtlog.Printf("Error creating kv store: %s\n", err)
os.Exit(-1)
}
// IF a KV Store is enable and no sub-command called in args
if kv != nil && usedCmd == traefikCmd {
if traefikConfiguration.Cluster == nil {
traefikConfiguration.Cluster = &types.Cluster{Node: uuid.NewV4().String()}
}
if traefikConfiguration.Cluster.Store == nil {
traefikConfiguration.Cluster.Store = &types.Store{Prefix: kv.Prefix, Store: kv.Store}
}
s.AddSource(kv)
if _, err := s.LoadConfig(); err != nil {
fmtlog.Printf("Error loading configuration: %s\n", err)
os.Exit(-1)
}
}
if err := s.Run(); err != nil {
fmtlog.Printf("Error running traefik: %s\n", err)
os.Exit(-1)
}
os.Exit(0)
}
func run(traefikConfiguration *server.TraefikConfiguration) {
fmtlog.SetFlags(fmtlog.Lshortfile | fmtlog.LstdFlags)
// load global configuration
globalConfiguration := traefikConfiguration.GlobalConfiguration
http.DefaultTransport.(*http.Transport).MaxIdleConnsPerHost = globalConfiguration.MaxIdleConnsPerHost
if globalConfiguration.InsecureSkipVerify {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
}
loggerMiddleware := middlewares.NewLogger(globalConfiguration.AccessLogsFile)
defer loggerMiddleware.Close()
if globalConfiguration.File != nil && len(globalConfiguration.File.Filename) == 0 {
// no filename, setting to global config file
if len(traefikConfiguration.ConfigFile) != 0 {
globalConfiguration.File.Filename = traefikConfiguration.ConfigFile
} else {
log.Errorln("Error using file configuration backend, no filename defined")
}
}
if len(globalConfiguration.EntryPoints) == 0 {
globalConfiguration.EntryPoints = map[string]*server.EntryPoint{"http": {Address: ":80"}}
globalConfiguration.DefaultEntryPoints = []string{"http"}
}
if globalConfiguration.Debug {
globalConfiguration.LogLevel = "DEBUG"
}
// logging
level, err := logrus.ParseLevel(strings.ToLower(globalConfiguration.LogLevel))
if err != nil {
log.Error("Error getting level", err)
}
log.SetLevel(level)
if len(globalConfiguration.TraefikLogsFile) > 0 {
dir := filepath.Dir(globalConfiguration.TraefikLogsFile)
err := os.MkdirAll(dir, 0755)
if err != nil {
log.Errorf("Failed to create log path %s: %s", dir, err)
}
fi, err := os.OpenFile(globalConfiguration.TraefikLogsFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
defer func() {
if err := fi.Close(); err != nil {
log.Error("Error closing file", err)
}
}()
if err != nil {
log.Error("Error opening file", err)
} else {
log.SetOutput(fi)
log.SetFormatter(&logrus.TextFormatter{DisableColors: true, FullTimestamp: true, DisableSorting: true})
}
} else {
log.SetFormatter(&logrus.TextFormatter{FullTimestamp: true, DisableSorting: true})
}
jsonConf, _ := json.Marshal(globalConfiguration)
log.Infof("Traefik version %s built on %s", version.Version, version.BuildDate)
if globalConfiguration.CheckNewVersion {
ticker := time.NewTicker(24 * time.Hour)
safe.Go(func() {
version.CheckNewVersion()
for {
select {
case <-ticker.C:
version.CheckNewVersion()
}
}
})
}
if len(traefikConfiguration.ConfigFile) != 0 {
log.Infof("Using TOML configuration file %s", traefikConfiguration.ConfigFile)
}
log.Debugf("Global configuration loaded %s", string(jsonConf))
svr := server.NewServer(globalConfiguration)
svr.Start()
defer svr.Close()
sent, err := daemon.SdNotify(false, "READY=1")
if !sent && err != nil {
log.Error("Fail to notify", err)
}
t, err := daemon.SdWatchdogEnabled(false)
if err != nil {
log.Error("Problem with watchdog", err)
} else if t != 0 {
// Send a ping each half time given
t = t / 2
log.Info("Watchdog activated with timer each ", t)
safe.Go(func() {
tick := time.Tick(t)
for range tick {
if ok, _ := daemon.SdNotify(false, "WATCHDOG=1"); !ok {
log.Error("Fail to tick watchdog")
}
}
})
}
svr.Wait()
log.Info("Shutting down")
}
// CreateKvSource creates KvSource
// TLS support is enable for Consul and Etcd backends
func CreateKvSource(traefikConfiguration *server.TraefikConfiguration) (*staert.KvSource, error) {
var kv *staert.KvSource
var store store.Store
var err error
switch {
case traefikConfiguration.Consul != nil:
store, err = traefikConfiguration.Consul.CreateStore()
kv = &staert.KvSource{
Store: store,
Prefix: traefikConfiguration.Consul.Prefix,
}
case traefikConfiguration.Etcd != nil:
store, err = traefikConfiguration.Etcd.CreateStore()
kv = &staert.KvSource{
Store: store,
Prefix: traefikConfiguration.Etcd.Prefix,
}
case traefikConfiguration.Zookeeper != nil:
store, err = traefikConfiguration.Zookeeper.CreateStore()
kv = &staert.KvSource{
Store: store,
Prefix: traefikConfiguration.Zookeeper.Prefix,
}
case traefikConfiguration.Boltdb != nil:
store, err = traefikConfiguration.Boltdb.CreateStore()
kv = &staert.KvSource{
Store: store,
Prefix: traefikConfiguration.Boltdb.Prefix,
}
}
return kv, err
}

63
cmd/traefik/version.go Normal file
View File

@@ -0,0 +1,63 @@
package main
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

@@ -4,7 +4,8 @@ Description=Traefik
[Service]
Type=notify
ExecStart=/usr/bin/traefik --configFile=/etc/traefik.toml
Restart=on-failure
Restart=always
WatchdogSec=1s
[Install]
WantedBy=multi-user.target

View File

@@ -13,12 +13,12 @@ Let's take our example from the [overview](https://docs.traefik.io/#overview) ag
> ![Architecture](img/architecture.png)
Let's zoom on Træfɪk and have an overview of its internal architecture:
Let's zoom on Træfik 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...).
- Incoming requests end on [entrypoints](#entrypoints), as the name suggests, they are the network entry points into Træfik (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.
@@ -26,7 +26,7 @@ Routes are created using requests fields (`Host`, `Path`, `Headers`...) and can
## Entrypoints
Entrypoints are the network entry points into Træfɪk.
Entrypoints are the network entry points into Træfik.
They can be defined using:
- a port (80, 443...)
@@ -73,23 +73,62 @@ And here is another example with client certificate authentication:
## 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:
A frontend consists of a set of rules that determine how incoming requests are forwarded from an entrypoint to a backend.
- `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.
Rules may be classified in one of two groups: Modifiers and matchers.
You can use multiple rules by separating them by `;`
### Modifiers
Modifier rules only modify the request. They do not have any impact on routing decisions being made.
Following is the list of existing modifier rules:
- `AddPrefix: /products`: Add path prefix to the existing request path prior to forwarding the request to the backend.
- `ReplacePath: /serverless-path`: Replaces the path and adds the old path to the `X-Replaced-Path` header. Useful for mapping to AWS Lambda or Google Cloud Functions.
### Matchers
Matcher rules determine if a particular request should be forwarded to a backend.
Separate multiple rule values by `,` (comma) in order to enable ANY semantics (i.e., forward a request if any rule matches). Does not work for `Headers` and `HeadersRegexp`.
Separate multiple rule values by `;` (semicolon) in order to enable ALL semantics (i.e., forward a request if all rules match).
You can optionally enable `passHostHeader` to forward client `Host` header to the backend.
Following is the list of existing matcher rules along with examples:
- `Headers: Content-Type, application/json`: Match HTTP header. It accepts a comma-separated key/value pair where both key and value must be literals.
- `HeadersRegexp: Content-Type, application/(text|json)`: Match HTTP header. It accepts a comma-separated key/value pair where the key must be a literal and the value may be a literal or a regular expression.
- `Host: traefik.io, www.traefik.io`: Match request host. It accepts a sequence of literal hosts.
- `HostRegexp: traefik.io, {subdomain:[a-z]+}.traefik.io`: Match request host. It accepts a sequence of literal and regular expression hosts.
- `Method: GET, POST, PUT`: Match request HTTP method. It accepts a sequence of HTTP methods.
- `Path: /products/, /articles/{category}/{id:[0-9]+}`: Match exact request path. It accepts a sequence of literal and regular expression paths.
- `PathStrip: /products/`: Match exact path and strip off the path prior to forwarding the request to the backend. It accepts a sequence of literal paths.
- `PathStripRegex: /articles/{category}/{id:[0-9]+}`: Match exact path and strip off the path prior to forwarding the request to the backend. It accepts a sequence of literal and regular expression paths.
- `PathPrefix: /products/, /articles/{category}/{id:[0-9]+}`: Match request prefix path. It accepts a sequence of literal and regular expression prefix paths.
- `PathPrefixStrip: /products/`: Match request prefix path and strip off the path prefix prior to forwarding the request to the backend. It accepts a sequence of literal prefix paths. Starting with Traefik 1.3, the stripped prefix path will be available in the `X-Forwarded-Prefix` header.
- `PathPrefixStripRegex: /articles/{category}/{id:[0-9]+}`: Match request prefix path and strip off the path prefix prior to forwarding the request to the backend. It accepts a sequence of literal and regular expression prefix paths. Starting with Traefik 1.3, the stripped prefix path will be available in the `X-Forwarded-Prefix` header.
In order to use regular expressions with Host and Path matchers, you must declare an arbitrarily named variable followed by the colon-separated regular expression, all enclosed in curly braces. Any pattern supported by [Go's regexp package](https://golang.org/pkg/regexp/) may be used. Example: `/posts/{id:[0-9]+}`.
(Note that the variable has no special meaning; however, it is required by the gorilla/mux dependency which embeds the regular expression and defines the syntax.)
#### Path Matcher Usage Guidelines
This section explains when to use the various path matchers.
Use `Path` if your backend listens on the exact path only. For instance, `Path: /products` would match `/products` but not `/products/shoes`.
Use a `*Prefix*` matcher if your backend listens on a particular base path but also serves requests on sub-paths. For instance, `PathPrefix: /products` would match `/products` but also `/products/shoes` and `/products/shirts`. Since the path is forwarded as-is, your backend is expected to listen on `/products`.
Use a `*Strip` matcher if your backend listens on the root path (`/`) but should be routeable on a specific prefix. For instance, `PathPrefixStrip: /products` would match `/products` but also `/products/shoes` and `/products/shirts`. Since the path is stripped prior to forwarding, your backend is expected to listen on `/`.
If your backend is serving assets (e.g., images or Javascript files), chances are it must return properly constructed relative URLs. Continuing on the example, the backend should return `/products/shoes/image.png` (and not `/images.png` which Traefik would likely not be able to associate with the same backend). The `X-Forwarded-Prefix` header (available since Traefik 1.3) can be queried to build such URLs dynamically.
Instead of distinguishing your backends by path only, you can add a Host matcher to the mix. That way, namespacing of your backends happens on the basis of hosts in addition to paths.
### Examples
Here is an example of frontends definition:
```toml
@@ -104,7 +143,7 @@ Here is an example of frontends definition:
priority = 10
entrypoints = ["https"] # overrides defaultEntryPoints
[frontends.frontend2.routes.test_1]
rule = "Host:localhost,{subdomain:[a-z]+}.localhost"
rule = "HostRegexp:localhost,{subdomain:[a-z]+}.localhost"
[frontends.frontend3]
backend = "backend2"
[frontends.frontend3.routes.test_1]
@@ -122,36 +161,55 @@ 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"
[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"
[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"
[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"
```
### Rules Order
When combining `Modifier` rules with `Matcher` rules, it is important to remember that `Modifier` rules **ALWAYS** apply after the `Matcher` rules.
The following rules are both `Matchers` and `Modifiers`, so the `Matcher` portion of the rule will apply first, and the `Modifier` will apply later.
- `PathStrip`
- `PathStripRegex`
- `PathPrefixStrip`
- `PathPrefixStripRegex`
`Modifiers` will be applied in a pre-determined order regardless of their order in the `rule` configuration section.
1. `PathStrip`
2. `PathPrefixStrip`
3. `PathStripRegex`
4. `PathPrefixStripRegex`
5. `AddPrefix`
6. `ReplacePath`
### Priorities
By default, routes will be sorted (in descending order) using rules length (to avoid path overlap):
@@ -159,20 +217,20 @@ By default, routes will be sorted (in descending order) using rules length (to a
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"
```toml
[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`).
@@ -180,16 +238,16 @@ 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 is supported:
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 if condition matches, CB enters Tripped state, where it responds with predefines code or redirects to another frontend.
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 if the condition does not match and recovery timer expires, CB enters Standby state.
In case the condition does not match and recovery timer expires, CB enters Standby state.
It can be configured using:
@@ -233,6 +291,26 @@ For example:
[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).
@@ -268,17 +346,17 @@ Here is an example of backends and servers definition:
# Configuration
Træfɪk's configuration has two parts:
Træfik's configuration has two parts:
- The [static Træfɪk configuration](/basics#static-trfk-configuration) which is loaded only at the begining.
- The [dynamic Træfɪk configuration](/basics#dynamic-trfk-configuration) which can be hot-reloaded (no need to restart the process).
- The [static Træfik configuration](/basics#static-trfk-configuration) which is loaded only at the beginning.
- The [dynamic Træfik configuration](/basics#dynamic-trfk-configuration) which can be hot-reloaded (no need to restart the process).
## Static Træfɪk configuration
## Static Træfik configuration
The static configuration is the global configuration which setting up connections to configuration backends and entrypoints.
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.
Træfik 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)
@@ -286,11 +364,11 @@ Each item takes precedence over the item below it:
- [Configuration file](/basics/#configuration-file)
- Default
It means that arguments overrides configuration file, and Key-value Store overrides arguments.
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:
By default, Træfik will try to find a `traefik.toml` in the following places:
- `/etc/traefik/`
- `$HOME/.traefik/`
@@ -316,7 +394,7 @@ Note that all default values will be displayed as well.
### Key-value stores
Træfɪk supports several Key-value stores:
Træfik supports several Key-value stores:
- [Consul](https://consul.io)
- [etcd](https://coreos.com/etcd/)
@@ -325,7 +403,7 @@ Træfɪk supports several Key-value stores:
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
## Dynamic Træfik configuration
The dynamic configuration concerns :
@@ -333,9 +411,9 @@ The dynamic configuration concerns :
- [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).
Træfik 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.
We only need to enable `watch` option to make Træfik 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.
@@ -344,19 +422,19 @@ Please refer to the [configuration backends](/toml/#configuration-backends) sect
Usage: `traefik [command] [--flag=flag_argument]`
List of Træfɪk available commands with description :                                                             
List of Træfik 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.
- `storeconfig` : Store the static traefik configuration into a Key-value stores. Please refer to the [Store Træfik 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
$ traefik [command] --help
```
Note that each command is described at the begining of the help section:
Note that each command is described at the beginning of the help section:
```bash
$ traefik --help

View File

@@ -117,7 +117,7 @@ server {
Here is the `traefik.toml` file used:
```
```toml
MaxIdleConnsPerHost = 100000
defaultEntryPoints = ["http"]
@@ -145,7 +145,7 @@ defaultEntryPoints = ["http"]
## Results
### whoami:
```
```shell
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
@@ -164,7 +164,7 @@ Transfer/sec: 6.40MB
```
### nginx:
```
```shell
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
@@ -183,7 +183,7 @@ Transfer/sec: 4.97MB
```
### traefik:
```
```shell
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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 255 KiB

View File

@@ -1,5 +1,5 @@
<p align="center">
<img src="img/traefik.logo.png" alt="Træfɪk" title="Træfɪk" />
<img src="img/traefik.logo.png" alt="Træfik" title="Træfik" />
</p>
[![Build Status](https://travis-ci.org/containous/traefik.svg?branch=master)](https://travis-ci.org/containous/traefik)
@@ -10,8 +10,8 @@
[![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](https://www.docker.com/), [Swarm](https://docs.docker.com/swarm), [Mesos/Marathon](https://mesosphere.github.io/marathon/), [Consul](https://www.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æfik (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), [Mesos/Marathon](https://mesosphere.github.io/marathon/), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Zookeeper](https://zookeeper.apache.org), [BoltDB](https://github.com/boltdb/bolt), [Amazon ECS](https://aws.amazon.com/ecs/), [Amazon DynamoDB](https://aws.amazon.com/dynamodb/), Rest API, file...) to manage its configuration automatically and dynamically.
## Overview
@@ -26,27 +26,27 @@ But a microservices architecture is dynamic... Services are added, removed, kill
Traditional reverse-proxies are not natively dynamic. You can't change their configuration and hot-reload easily.
Here enters Træfɪk.
Here enters Træfik.
![Architecture](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.
Træfik 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!
## Quickstart
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.
You can have a quick look at Træfik in this [Katacoda tutorial](https://www.katacoda.com/courses/traefik/deploy-load-balancer) that shows how to load balance requests between multiple Docker containers.
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.
You will learn fundamental Træfik 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.
You will learn fundamental Træfik 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)
@@ -70,41 +70,65 @@ docker run -d -p 8080:8080 -p 80:80 -v $PWD/traefik.toml:/etc/traefik/traefik.to
## Test it
You can test Træfɪk easily using [Docker compose](https://docs.docker.com/compose), with this `docker-compose.yml` file:
You can test Træfik easily using [Docker compose](https://docs.docker.com/compose), with this `docker-compose.yml` file in a folder named `traefik`:
```yaml
traefik:
image: traefik
command: --web --docker --docker.domain=docker.localhost --logLevel=DEBUG
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /dev/null:/traefik.toml
version: '2'
whoami1:
image: emilevauge/whoami
labels:
- "traefik.backend=whoami"
- "traefik.frontend.rule=Host:whoami.docker.localhost"
services:
proxy:
image: traefik
command: --web --docker --docker.domain=docker.localhost --logLevel=DEBUG
networks:
- webgateway
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /dev/null:/traefik.toml
whoami2:
image: emilevauge/whoami
labels:
- "traefik.backend=whoami"
- "traefik.frontend.rule=Host:whoami.docker.localhost"
networks:
webgateway:
driver: bridge
```
Then, start it:
Start it from within the `traefik` folder:
docker-compose up -d
In a browser you may open `http://localhost:8080` to access Træfik's dashboard and observe the following magic.
Now, create a folder named `test` and create a `docker-compose.yml` in it with this content:
```yaml
version: '2'
services:
whoami:
image: emilevauge/whoami
networks:
- web
labels:
- "traefik.backend=whoami"
- "traefik.frontend.rule=Host:whoami.docker.localhost"
networks:
web:
external:
name: traefik_webgateway
```
Then, start and scale it in the `test` folder:
```shell
docker-compose up -d
docker-compose scale whoami=2
```
Finally, test load-balancing between the two servers `whoami1` and `whoami2`:
Finally, test load-balancing between the two services `test_whoami_1` and `test_whoami_2`:
```bash
```shell
$ curl -H Host:whoami.docker.localhost http://127.0.0.1
Hostname: ef194d07634a
IP: 127.0.0.1

View File

@@ -9,13 +9,15 @@
# Global configuration
################################################################
# Timeout in seconds.
# Duration to give active requests a chance to finish during hot-reloads
# Duration to give active requests a chance to finish during hot-reloads.
# Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw
# values (digits). If no units are provided, the value is parsed assuming
# seconds.
#
# Optional
# Default: 10
# Default: "10s"
#
# graceTimeOut = 10
# graceTimeOut = "10s"
# Enable debug mode
#
@@ -56,17 +58,32 @@
# Backends throttle duration: minimum duration in seconds 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.
# Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw
# values (digits). If no units are provided, the value is parsed assuming
# seconds.
#
# Optional
# Default: "2"
# Default: "2s"
#
# ProvidersThrottleDuration = "5"
# ProvidersThrottleDuration = "2s"
# If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used.
# If you encounter 'too many open files' errors, you can either change this value, or change `ulimit` value.
# IdleTimeout: maximum amount of time an idle (keep-alive) connection will remain idle before closing itself.
# This is set to enforce closing of stale client connections.
# Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw
# values (digits). If no units are provided, the value is parsed assuming seconds.
#
# Optional
# Default: http.DefaultMaxIdleConnsPerHost
# Default: "180s"
#
# IdleTimeout = "360s"
# Controls the maximum idle (keep-alive) connections to keep per-host. If zero, DefaultMaxIdleConnsPerHost
# from the Go standard library net/http module is used.
# If you encounter 'too many open files' errors, you can either increase this
# value or change the `ulimit`.
#
# Optional
# Default: 200
#
# MaxIdleConnsPerHost = 200
@@ -88,9 +105,9 @@
### Constraints
In a micro-service architecture, with a central service discovery, setting constraints limits Træfɪk scope to a smaller number of routes.
In a micro-service architecture, with a central service discovery, setting constraints limits Træfik scope to a smaller number of routes.
Træfɪk filters services according to service attributes/tags set in your configuration backends.
Træfik filters services according to service attributes/tags set in your configuration backends.
Supported backends:
@@ -100,12 +117,13 @@ Supported backends:
- Zookeeper
- Etcd
- Consul Catalog
- Rancher
Supported filters:
- ```tag```
- `tag`
```
```toml
# Constraints definition
#
# Optional
@@ -191,20 +209,24 @@ Supported filters:
# To enable basic auth on an entrypoint
# with 2 user/pass: test:test and test2:test2
# Passwords can be encoded in MD5, SHA1 and BCrypt: you can use htpasswd to generate those ones
# Users can be specified directly in the toml file, or indirectly by referencing an external file; if both are provided, the two are merged, with external file contents having precedence
# [entryPoints]
# [entryPoints.http]
# address = ":80"
# [entryPoints.http.auth.basic]
# users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"]
# usersFile = "/path/to/.htpasswd"
#
# To enable digest auth on an entrypoint
# with 2 user/realm/pass: test:traefik:test and test2:traefik:test2
# You can use htdigest to generate those ones
# Users can be specified directly in the toml file, or indirectly by referencing an external file; if both are provided, the two are merged, with external file contents having precedence
# [entryPoints]
# [entryPoints.http]
# address = ":80"
# [entryPoints.http.auth.basic]
# users = ["test:traefik:a2688e031edb4be6a3797f3882655c05 ", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"]
# usersFile = "/path/to/.htdigest"
#
# To specify an https entrypoint with a minimum TLS version, and specifying an array of cipher suites (from crypto/tls):
# [entryPoints]
@@ -248,6 +270,27 @@ Supported filters:
# attempts = 3
```
## Health check configuration
```toml
# Enable custom health check options.
#
# Optional
#
[healthcheck]
# Set the default health check interval. Will only be effective if health check
# paths are defined. Given provider-specific support, the value may be
# overridden on a per-backend basis.
# Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw
# values (digits). If no units are provided, the value is parsed assuming
# seconds.
#
# Optional
# Default: "30s"
#
# interval = "30s"
```
## ACME (Let's Encrypt) configuration
```toml
@@ -282,13 +325,50 @@ email = "test@traefik.io"
#
storage = "acme.json" # or "traefik/acme/account" if using KV store
# Entrypoint to proxy acme challenge to.
# Entrypoint to proxy acme challenge/apply certificates to.
# WARNING, must point to an entrypoint on port 443
#
# Required
#
entryPoint = "https"
# Use a DNS based acme challenge rather than external HTTPS access, e.g. for a firewalled server
# Select the provider that matches the DNS domain that will host the challenge TXT record,
# and provide environment variables with access keys to enable setting it:
# - cloudflare: CLOUDFLARE_EMAIL, CLOUDFLARE_API_KEY
# - digitalocean: DO_AUTH_TOKEN
# - dnsimple: DNSIMPLE_EMAIL, DNSIMPLE_API_KEY
# - dnsmadeeasy: DNSMADEEASY_API_KEY, DNSMADEEASY_API_SECRET
# - exoscale: EXOSCALE_API_KEY, EXOSCALE_API_SECRET
# - gandi: GANDI_API_KEY
# - linode: LINODE_API_KEY
# - manual: none, but run traefik interactively & turn on acmeLogging to see instructions & press Enter
# - namecheap: NAMECHEAP_API_USER, NAMECHEAP_API_KEY
# - rfc2136: RFC2136_TSIG_KEY, RFC2136_TSIG_SECRET, RFC2136_TSIG_ALGORITHM, RFC2136_NAMESERVER
# - route53: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, or configured user/instance IAM profile
# - dyn: DYN_CUSTOMER_NAME, DYN_USER_NAME, DYN_PASSWORD
# - vultr: VULTR_API_KEY
# - ovh: OVH_ENDPOINT, OVH_APPLICATION_KEY, OVH_APPLICATION_SECRET, OVH_CONSUMER_KEY
# - pdns: PDNS_API_KEY, PDNS_API_URL
#
# Optional
#
# dnsProvider = "digitalocean"
# By default, the dnsProvider will verify the TXT DNS challenge record before letting ACME verify
# If delayDontCheckDNS is greater than zero, avoid this & instead just wait so many seconds.
# Useful if internal networks block external DNS queries
#
# Optional
#
# delayDontCheckDNS = 0
# If true, display debug log messages from the acme client library
#
# Optional
#
# acmeLogging = true
# 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.
# WARNING, TLS handshakes will be slow when requesting a hostname certificate for the first time, this can leads to DoS attacks.
# WARNING, Take note that Let's Encrypt have rate limiting: https://letsencrypt.org/docs/rate-limits
@@ -341,7 +421,7 @@ entryPoint = "https"
## File backend
Like any other reverse proxy, Træfɪk can be configured with a file. You have two choices:
Like any other reverse proxy, Træfik can be configured with a file. You have two choices:
- simply add your configuration at the end of the global configuration file `traefik.toml`:
@@ -475,7 +555,7 @@ filename = "rules.toml"
rule = "Path:/test"
```
If you want Træfɪk to watch file changes automatically, just add:
If you want Træfik to watch file changes automatically, just add:
```toml
[file]
@@ -491,6 +571,12 @@ To enable it:
[web]
address = ":8080"
# Set the root path for webui and API
#
# Optional
#
# path = "/mypath"
#
# SSL certificate and key used
#
# Optional
@@ -503,17 +589,28 @@ address = ":8080"
# Optional
# ReadOnly = false
#
# To enable more detailed statistics
# [web.statistics]
# RecentErrors = 10
#
# To enable Traefik to export internal metrics to Prometheus
# [web.metrics.prometheus]
# Buckets=[0.1,0.3,1.2,5.0]
#
# To enable basic auth on the webui
# with 2 user/pass: test:test and test2:test2
# Passwords can be encoded in MD5, SHA1 and BCrypt: you can use htpasswd to generate those ones
# Users can be specified directly in the toml file, or indirectly by referencing an external file; if both are provided, the two are merged, with external file contents having precedence
# [web.auth.basic]
# users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"]
# usersFile = "/path/to/.htpasswd"
# To enable digest auth on the webui
# with 2 user/realm/pass: test:traefik:test and test2:traefik:test2
# You can use htdigest to generate those ones
# Users can be specified directly in the toml file, or indirectly by referencing an external file; if both are provided, the two are merged, with external file contents having precedence
# [web.auth.digest]
# users = ["test:traefik:a2688e031edb4be6a3797f3882655c05 ", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"]
# usersFile = "/path/to/.htdigest"
```
- `/`: provides a simple HTML frontend of Træfik
@@ -523,7 +620,7 @@ address = ":8080"
- `/ping`: `GET` simple endpoint to check for Træfik process liveness.
```sh
```shell
$ curl -sv "http://localhost:8080/ping"
* Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
@@ -543,14 +640,14 @@ OK
- `/health`: `GET` json metrics
```sh
```shell
$ curl -s "http://localhost:8080/health" | jq .
{
// Træfɪk PID
// Træfik PID
"pid": 2458,
// Træfɪk server uptime (formated time)
// Træfik server uptime (formated time)
"uptime": "39m6.885931127s",
// Træfɪk server uptime in seconds
// Træfik server uptime in seconds
"uptime_sec": 2346.885931127,
// current server date
"time": "2015-10-07 18:32:24.362238909 +0200 CEST",
@@ -560,7 +657,7 @@ $ curl -s "http://localhost:8080/health" | jq .
"status_code_count": {
"502": 1
},
// count HTTP response status code since Træfɪk started
// count HTTP response status code since Træfik started
"total_status_code_count": {
"200": 7,
"404": 21,
@@ -577,13 +674,32 @@ $ curl -s "http://localhost:8080/health" | jq .
// average response time (formated time)
"average_response_time": "864.8016ms",
// average response time in seconds
"average_response_time_sec": 0.8648016000000001
"average_response_time_sec": 0.8648016000000001,
// request statistics [requires --web.statistics to be set]
// ten most recent requests with 4xx and 5xx status codes
"recent_errors": [
{
// status code
"status_code": 500,
// description of status code
"status": "Internal Server Error",
// request HTTP method
"method": "GET",
// request hostname
"host": "localhost",
// request path
"path": "/path",
// RFC 3339 formatted date/time
"time": "2016-10-21T16:59:15.418495872-07:00"
}
]
}
```
- `/api`: `GET` configuration for all providers
```sh
```shell
$ curl -s "http://localhost:8080/api" | jq .
{
"file": {
@@ -655,10 +771,15 @@ $ curl -s "http://localhost:8080/api" | jq .
- `/api/providers/{provider}/frontends/{frontend}/routes`: `GET` routes in a frontend
- `/api/providers/{provider}/frontends/{frontend}/routes/{route}`: `GET` a route in a frontend
- `/metrics`: You can enable Traefik to export internal metrics to different monitoring systems (Only Prometheus is supported at the moment).
```bash
$ traefik --web.metrics.prometheus --web.metrics.prometheus.buckets="0.1,0.3,1.2,5.0"
```
## Docker backend
Træfɪk can be configured to use Docker as a backend configuration:
Træfik can be configured to use Docker as a backend configuration:
```toml
################################################################
@@ -697,6 +818,7 @@ watch = true
# filename = "docker.tmpl"
# Expose containers by default in traefik
# If set to false, containers that don't have `traefik.enable=true` will be ignored
#
# Optional
# Default: true
@@ -729,27 +851,40 @@ swarmmode = false
Labels can be used on containers to override default behaviour:
- `traefik.backend=foo`: assign the container to `foo` backend
- `traefik.backend=foo`: give the name `backend-foo` to the generated backend for this container.
- `traefik.backend.maxconn.amount=10`: set a maximum number of connections to the backend. Must be used in conjunction with the below label to take effect.
- `traefik.backend.maxconn.extractorfunc=client.ip`: set the function to be used against the request to determine what to limit maximum connections to the backend by. Must be used in conjunction with the above label to take effect.
- `traefik.backend.loadbalancer.method=drr`: override the default `wrr` load balancer algorithm
- `traefik.backend.loadbalancer.sticky=true`: enable backend sticky sessions
- `traefik.backend.loadbalancer.swarm=true `: use Swarm's inbuilt load balancer (only relevant under Swarm Mode).
- `traefik.backend.circuitbreaker.expression=NetworkErrorRatio() > 0.5`: create a [circuit breaker](/basics/#backends) to be used against the backend
- `traefik.port=80`: register this port. Useful when the container exposes multiples ports.
- `traefik.protocol=https`: override the default `http` protocol
- `traefik.weight=10`: assign this weight to the container
- `traefik.enable=false`: disable this container in Træfɪk
- `traefik.frontend.rule=Host:test.traefik.io`: override the default frontend rule (Default: `Host:{containerName}.{domain}`).
- `traefik.enable=false`: disable this container in Træfik
- `traefik.frontend.rule=Host:test.traefik.io`: override the default frontend rule (Default: `Host:{containerName}.{domain}` or `Host:{service}.{project_name}.{domain}` if you are using `docker-compose`).
- `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend.
- `traefik.frontend.priority=10`: override default frontend priority
- `traefik.frontend.entryPoints=http,https`: assign this frontend to entry points `http` and `https`. Overrides `defaultEntryPoints`.
- `traefik.docker.network`: Set the docker network to use for connections to this container
- `traefik.frontend.auth.basic=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0`: Sets a Basic Auth for that frontend with the users test:test and test2:test2
- `traefik.docker.network`: Set the docker network to use for connections to this container. If a container is linked to several networks, be sure to set the proper network name (you can check with docker inspect <container_id>) otherwise it will randomly pick one (depending on how docker is returning them). For instance when deploying docker `stack` from compose files, the compose defined networks will be prefixed with the `stack` name.
NB: when running inside a container, Træfɪk will need network access through `docker network connect <network> <traefik-container>`
If several ports need to be exposed from a container, the services labels can be used
- `traefik.<service-name>.port=443`: create a service binding with frontend/backend using this port. Overrides `traefik.port`.
- `traefik.<service-name>.protocol=https`: assign `https` protocol. Overrides `traefik.protocol`.
- `traefik.<service-name>.weight=10`: assign this service weight. Overrides `traefik.weight`.
- `traefik.<service-name>.frontend.backend=fooBackend`: assign this service frontend to `foobackend`. Default is to assign to the service backend.
- `traefik.<service-name>.frontend.entryPoints=http`: assign this service entrypoints. Overrides `traefik.frontend.entrypoints`.
- `traefik.<service-name>.frontend.auth.basic=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0` Sets a Basic Auth for that frontend with the users test:test and test2:test2.
- `traefik.<service-name>.frontend.passHostHeader=true`: Forward client `Host` header to the backend. Overrides `traefik.frontend.passHostHeader`.
- `traefik.<service-name>.frontend.priority=10`: assign the service frontend priority. Overrides `traefik.frontend.priority`.
- `traefik.<service-name>.frontend.rule=Path:/foo`: assign the service frontend rule. Overrides `traefik.frontend.rule`.
NB: when running inside a container, Træfik will need network access through `docker network connect <network> <traefik-container>`
## Marathon backend
Træfɪk can be configured to use Marathon as a backend configuration:
Træfik can be configured to use Marathon as a backend configuration:
```toml
@@ -792,7 +927,7 @@ domain = "marathon.localhost"
# Expose Marathon apps by default in traefik
#
# Optional
# Default: false
# Default: true
#
# exposedByDefault = true
@@ -825,6 +960,9 @@ domain = "marathon.localhost"
# Optional
#
# [marathon.TLS]
# CA = "/etc/ssl/ca.crt"
# Cert = "/etc/ssl/marathon.cert"
# Key = "/etc/ssl/marathon.key"
# InsecureSkipVerify = true
# DCOSToken for DCOS environment, This will override the Authorization header
@@ -832,6 +970,37 @@ domain = "marathon.localhost"
# Optional
#
# dcosToken = "xxxxxx"
# Override DialerTimeout
# Amount of time to allow the Marathon provider to wait to open a TCP connection
# to a Marathon master.
# Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw
# values (digits). If no units are provided, the value is parsed assuming
# seconds.
#
# Optional
# Default: "60s"
# dialerTimeout = "60s"
# Set the TCP Keep Alive interval for the Marathon HTTP Client.
# Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw
# values (digits). If no units are provided, the value is parsed assuming
# seconds.
#
# Optional
# Default: "10s"
#
# keepAlive = "10s"
# By default, a task's IP address (as returned by the Marathon API) is used as
# backend server if an IP-per-task configuration can be found; otherwise, the
# name of the host running the task is used.
# The latter behavior can be enforced by enabling this switch.
#
# Optional
# Default: false
#
# forceTaskHostname: false
```
Labels can be used on containers to override default behaviour:
@@ -842,11 +1011,13 @@ Labels can be used on containers to override default behaviour:
- `traefik.backend.loadbalancer.method=drr`: override the default `wrr` load balancer algorithm
- `traefik.backend.loadbalancer.sticky=true`: enable backend sticky sessions
- `traefik.backend.circuitbreaker.expression=NetworkErrorRatio() > 0.5`: create a [circuit breaker](/basics/#backends) to be used against the backend
- `traefik.backend.healthcheck.path=/health`: set the Traefik health check path [default: no health checks]
- `traefik.backend.healthcheck.interval=5s`: sets a custom health check interval in Go-parseable (`time.ParseDuration`) format [default: 30s]
- `traefik.portIndex=1`: register port by index in the application's ports array. Useful when the application exposes multiple ports.
- `traefik.port=80`: register the explicit application port value. Cannot be used alongside `traefik.portIndex`.
- `traefik.protocol=https`: override the default `http` protocol
- `traefik.weight=10`: assign this weight to the application
- `traefik.enable=false`: disable this application in Træfɪk
- `traefik.enable=false`: disable this application in Træfik
- `traefik.frontend.rule=Host:test.traefik.io`: override the default frontend rule (Default: `Host:{containerName}.{domain}`).
- `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend.
- `traefik.frontend.priority=10`: override default frontend priority
@@ -855,7 +1026,7 @@ Labels can be used on containers to override default behaviour:
## Mesos generic backend
Træfɪk can be configured to use Mesos as a backend configuration:
Træfik can be configured to use Mesos as a backend configuration:
```toml
@@ -914,12 +1085,14 @@ domain = "mesos.localhost"
# Zookeeper timeout (in seconds)
#
# Optional
# Default: 30
#
# ZkDetectionTimeout = 30
# Polling interval (in seconds)
#
# Optional
# Default: 30
#
# RefreshSeconds = 30
@@ -932,14 +1105,15 @@ domain = "mesos.localhost"
# HTTP Timeout (in seconds)
#
# Optional
# Default: 30
#
# StateTimeoutSecond = "host"
# StateTimeoutSecond = "30"
```
## Kubernetes Ingress backend
Træfɪk can be configured to use Kubernetes Ingress as a backend configuration:
Træfik can be configured to use Kubernetes Ingress as a backend configuration:
```toml
################################################################
@@ -953,17 +1127,46 @@ Træfɪk can be configured to use Kubernetes Ingress as a backend configuration:
# Kubernetes server endpoint
#
# When deployed as a replication controller in Kubernetes,
# Traefik will use env variable KUBERNETES_SERVICE_HOST
# and KUBERNETES_SERVICE_PORT_HTTPS as endpoint
# When deployed as a replication controller in Kubernetes, Traefik will use
# the environment variables KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT
# to construct the endpoint.
# Secure token will be found in /var/run/secrets/kubernetes.io/serviceaccount/token
# and SSL CA cert in /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
#
# Optional
# The endpoint may be given to override the environment variable values.
#
# When the environment variables are not found, Traefik will try to connect to
# the Kubernetes API server with an external-cluster client. In this case, the
# endpoint is required. Specifically, it may be set to the URL used by
# `kubectl proxy` to connect to a Kubernetes cluster from localhost.
#
# Optional for in-cluster configuration, required otherwise
# Default: empty
#
# endpoint = "http://localhost:8080"
# namespaces = ["default","production"]
# Bearer token used for the Kubernetes client configuration.
#
# Optional
# Default: empty
#
# token = "my token"
# Path to the certificate authority file used for the Kubernetes client
# configuration.
#
# Optional
# Default: empty
#
# certAuthFilePath = "/my/ca.crt"
# Array of namespaces to watch.
#
# Optional
# Default: ["default"].
#
# namespaces = ["default", "production"]
# See: http://kubernetes.io/docs/user-guide/labels/#list-and-watch-filtering
# labelselector = "A and not B"
#
@@ -973,11 +1176,36 @@ Annotations can be used on containers to override default behaviour for the whol
- `traefik.frontend.rule.type: PathPrefixStrip`: override the default frontend rule type (Default: `PathPrefix`).
Annotations can be used on the Kubernetes service to override default behaviour:
- `traefik.backend.loadbalancer.method=drr`: override the default `wrr` load balancer algorithm
- `traefik.backend.loadbalancer.sticky=true`: enable backend sticky sessions
You can find here an example [ingress](https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-ingress.yaml) and [replication controller](https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik.yaml).
Additionally, an annotation can be used on Kubernetes services to set the [circuit breaker expression](https://docs.traefik.io/basics/#backends) for a backend.
- `traefik.backend.circuitbreaker: <expression>`: set the circuit breaker expression for the backend (Default: nil).
### Authentication
Is possible to add additional authentication annotations in the Ingress rule.
The source of the authentication is a secret that contains usernames and passwords inside the the key auth.
- `ingress.kubernetes.io/auth-type`: `basic`
- `ingress.kubernetes.io/auth-secret`: contains the usernames and passwords with access to the paths defined in the Ingress Rule.
The secret must be created in the same namespace as the Ingress rule.
Limitations:
- Basic authentication only.
- Realm not configurable; only `traefik` default.
- Secret must contain only single file.
## Consul backend
Træfɪk can be configured to use Consul as a backend configuration:
Træfik can be configured to use Consul as a backend configuration:
```toml
################################################################
@@ -1029,7 +1257,7 @@ Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-val
## Consul catalog backend
Træfɪk can be configured to use service discovery catalog of Consul as a backend configuration:
Træfik can be configured to use service discovery catalog of Consul as a backend configuration:
```toml
################################################################
@@ -1066,7 +1294,7 @@ used in consul.
Additional settings can be defined using Consul Catalog tags:
- `traefik.enable=false`: disable this container in Træfɪk
- `traefik.enable=false`: disable this container in Træfik
- `traefik.protocol=https`: override the default `http` protocol
- `traefik.backend.weight=10`: assign this weight to the container
- `traefik.backend.circuitbreaker=NetworkErrorRatio() > 0.5`
@@ -1080,7 +1308,7 @@ Additional settings can be defined using Consul Catalog tags:
## Etcd backend
Træfɪk can be configured to use Etcd as a backend configuration:
Træfik can be configured to use Etcd as a backend configuration:
```toml
################################################################
@@ -1117,6 +1345,13 @@ prefix = "/traefik"
#
# filename = "etcd.tmpl"
# Use etcd user/pass authentication
#
# Optional
#
# username = foo
# password = bar
# Enable etcd TLS connection
#
# Optional
@@ -1133,7 +1368,7 @@ Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-val
## Zookeeper backend
Træfɪk can be configured to use Zookeeper as a backend configuration:
Træfik can be configured to use Zookeeper as a backend configuration:
```toml
################################################################
@@ -1162,7 +1397,7 @@ watch = true
#
# Optional
#
prefix = "/traefik"
prefix = "traefik"
# Override default configuration template. For advanced users :)
#
@@ -1175,7 +1410,7 @@ Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-val
## BoltDB backend
Træfɪk can be configured to use BoltDB as a backend configuration:
Træfik can be configured to use BoltDB as a backend configuration:
```toml
################################################################
@@ -1213,4 +1448,297 @@ prefix = "/traefik"
# filename = "boltdb.tmpl"
```
## Eureka backend
Træfik can be configured to use Eureka as a backend configuration:
```toml
################################################################
# Eureka configuration backend
################################################################
# Enable Eureka configuration backend
#
# Optional
#
[eureka]
# Eureka server endpoint.
# endpoint := "http://my.eureka.server/eureka"
#
# Required
#
endpoint = "http://my.eureka.server/eureka"
# Override default configuration time between refresh
#
# Optional
# default 30s
delay = "1m"
# Override default configuration template. For advanced users :)
#
# Optional
#
# filename = "eureka.tmpl"
```
Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-value-storage-structure) section to get documentation on traefik KV structure.
## ECS backend
Træfik can be configured to use Amazon ECS as a backend configuration:
```toml
################################################################
# ECS configuration backend
################################################################
# Enable ECS configuration backend
#
# Optional
#
[ecs]
# ECS Cluster Name
#
# Optional
# Default: "default"
#
Cluster = "default"
# Enable watch ECS changes
#
# Optional
# Default: true
#
Watch = true
# Polling interval (in seconds)
#
# Optional
# Default: 15
#
RefreshSeconds = 15
# Expose ECS services by default in traefik
#
# Optional
# Default: true
#
ExposedByDefault = false
# Region to use when connecting to AWS
#
# Optional
#
# Region = "us-east-1"
# AccessKeyID to use when connecting to AWS
#
# Optional
#
# AccessKeyID = "abc"
# SecretAccessKey to use when connecting to AWS
#
# Optional
#
# SecretAccessKey = "123"
```
Labels can be used on task containers to override default behaviour:
- `traefik.protocol=https`: override the default `http` protocol
- `traefik.weight=10`: assign this weight to the container
- `traefik.enable=false`: disable this container in Træfik
- `traefik.frontend.rule=Host:test.traefik.io`: override the default frontend rule (Default: `Host:{containerName}.{domain}`).
- `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend.
- `traefik.frontend.priority=10`: override default frontend priority
- `traefik.frontend.entryPoints=http,https`: assign this frontend to entry points `http` and `https`. Overrides `defaultEntryPoints`.
If `AccessKeyID`/`SecretAccessKey` is not given credentials will be resolved in the following order:
- From environment variables; `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN`.
- Shared credentials, determined by `AWS_PROFILE` and `AWS_SHARED_CREDENTIALS_FILE`, defaults to `default` and `~/.aws/credentials`.
- EC2 instance role or ECS task role
Træfik needs the following policy to read ECS information:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Traefik ECS read access",
"Effect": "Allow",
"Action": [
"ecs:ListTasks",
"ecs:DescribeTasks",
"ecs:DescribeContainerInstances",
"ecs:DescribeTaskDefinition",
"ec2:DescribeInstances"
],
"Resource": [
"*"
]
}
]
}
```
# Rancher backend
Træfik can be configured to use Rancher as a backend configuration:
```toml
################################################################
# Rancher configuration backend
################################################################
# Enable Rancher configuration backend
#
# Optional
#
[rancher]
# Default domain used.
# Can be overridden by setting the "traefik.domain" label on an service.
#
# Required
#
domain = "rancher.localhost"
# Enable watch Rancher changes
#
# Optional
# Default: true
#
Watch = true
# Polling interval (in seconds)
#
# Optional
#
RefreshSeconds = 15
# Expose Rancher services by default in traefik
#
# Optional
# Default: true
#
ExposedByDefault = false
# Filter services with unhealthy states and health states
#
# Optional
# Default: false
#
EnableServiceHealthFilter = false
# Endpoint to use when connecting to Rancher
#
# Required
# Endpoint = "http://rancherserver.example.com/v1"
# AccessKey to use when connecting to Rancher
#
# Required
# AccessKey = "XXXXXXXXXXXXXXXXXXXX"
# SecretKey to use when connecting to Rancher
#
# Required
# SecretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```
As traefik needs access to the rancher API, you need to set the `endpoint`, `accesskey` and `secretkey` parameters.
To enable traefik to fetch information about the Environment it's deployed in only, you need to create an `Environment API Key`. This can be found within the API Key advanced options.
Labels can be used on task containers to override default behaviour:
- `traefik.protocol=https`: override the default `http` protocol
- `traefik.weight=10`: assign this weight to the container
- `traefik.enable=false`: disable this container in Træfik
- `traefik.frontend.rule=Host:test.traefik.io`: override the default frontend rule (Default: `Host:{containerName}.{domain}`).
- `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend.
- `traefik.frontend.priority=10`: override default frontend priority
- `traefik.frontend.entryPoints=http,https`: assign this frontend to entry points `http` and `https`. Overrides `defaultEntryPoints`.
- `traefik.frontend.auth.basic=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0`: Sets a Basic Auth for that frontend with the users test:test and test2:test2
## DynamoDB backend
Træfik can be configured to use Amazon DynamoDB as a backend configuration:
```toml
################################################################
# DynamoDB configuration backend
################################################################
# Enable DynamoDB configuration backend
#
# Optional
#
[dynamodb]
# DyanmoDB Table Name
#
# Optional
#
TableName = "traefik"
# Enable watch DynamoDB changes
#
# Optional
#
Watch = true
# Polling interval (in seconds)
#
# Optional
#
RefreshSeconds = 15
# Region to use when connecting to AWS
#
# Required
#
# Region = "us-west-1"
# AccessKeyID to use when connecting to AWS
#
# Optional
#
# AccessKeyID = "abc"
# SecretAccessKey to use when connecting to AWS
#
# Optional
#
# SecretAccessKey = "123"
# Endpoint of local dynamodb instance for testing
#
# Optional
#
# Endpoint = "http://localhost:8080"
```
Items in the `dynamodb` table must have three attributes:
- `id` : string
- The id is the primary key.
- `name` : string
- The name is used as the name of the frontend or backend.
- `frontend` or `backend` : map
- This attribute's structure matches exactly the structure of a Frontend or Backend type in traefik. See `types/types.go` for details. The presence or absence of this attribute determines its type. So an item should never have both a `frontend` and a `backend` attribute.

View File

@@ -1,7 +1,7 @@
# Clustering / High Availability
# Clustering / High Availability (beta)
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.
This guide explains how tu use Træfik in high availability mode.
In order to deploy and configure multiple Træfik instances, without copying the same configuration file on each instance, we will use a distributed Key-Value store.
## Prerequisites
@@ -9,11 +9,12 @@ 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.
We created a special Træfik command to help configuring your Key Value store from a Træfik 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
## Deploy a Træfik 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.
Once your Træfik configuration is uploaded on your KV store, you can start each Træfik instance.
A Træfik cluster is based on a master/slave model.
When starting, Træfik will elect a master. If this instance fails, another master will be automatically elected.

View File

@@ -1,11 +1,11 @@
# Examples
You will find here some configuration examples of Træfɪk.
You will find here some configuration examples of Træfik.
## HTTP only
```
```toml
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
@@ -14,7 +14,7 @@ defaultEntryPoints = ["http"]
## HTTP + HTTPS (with SNI)
```
```toml
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
@@ -33,7 +33,7 @@ Note that we can either give path to certificate file or directly the file conte
## HTTP redirect on HTTPS
```
```toml
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
@@ -50,7 +50,7 @@ defaultEntryPoints = ["http", "https"]
## Let's Encrypt support
```
```toml
[entryPoints]
[entryPoints.https]
address = ":443"
@@ -80,7 +80,7 @@ entryPoint = "https"
## Override entrypoints in frontends
```
```toml
[frontends]
[frontends.frontend1]
backend = "backend2"
@@ -107,11 +107,34 @@ With two user/pass:
Passwords are encoded in MD5: you can use htpasswd to generate those ones.
```
```toml
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
```toml
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"]
```
## Override the Traefik HTTP server IdleTimeout and/or throttle configurations from re-loading too quickly
```toml
IdleTimeout = "360s"
ProvidersThrottleDuration = "5s"
```

View File

@@ -1,6 +1,6 @@
# Kubernetes Ingress Controller
This guide explains how to use Træfɪk as an Ingress controller in a Kubernetes cluster.
This guide explains how to use Træfik 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)
@@ -12,14 +12,76 @@ on your machine, as it is the quickest way to get a local Kubernetes cluster set
2. The `kubectl` binary should be [installed on your workstation](http://kubernetes.io/docs/getting-started-guides/minikube/#download-kubectl).
## Deploy Træfɪk
### Role Based Access Control configuration (Kubernetes 1.6+ only)
We are going to deploy Træfɪk with a
Kubernetes introduces [Role Based Access Control (RBAC)](https://kubernetes.io/docs/admin/authorization/rbac/) in 1.6+ to allow fine-grained control
of Kubernetes resources and api.
If your cluster is configured with RBAC, you may need to authorize Traefik to use
kubernetes API using ClusterRole and ClusterRoleBinding resources:
_Note: your cluster may have suitable ClusterRoles already setup, but the following should work everywhere_
```yaml
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
rules:
- apiGroups:
- ""
resources:
- pods
- services
- endpoints
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: kube-system
```
[examples/k8s/traefik-rbac.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/traefik-rbac.yaml)
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-rbac.yaml
```
## Deploy Træfik using a Deployment object
We are going to deploy Træfik 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
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
namespace: kube-system
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
@@ -37,11 +99,11 @@ spec:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
version: v1.0.0
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
containers:
- image: traefik:v1.0.0
- image: traefik
name: traefik-ingress-lb
resources:
limits:
@@ -60,14 +122,14 @@ spec:
```
[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.
> notice that we binding port 80 on the Træfik container to port 80 on the host.
> With a multi node cluster we might expose Træfik with a NodePort or LoadBalancer service
> and run more than 1 replica of Træfik for high availability.
To deploy Træfɪk to your cluster start by submitting the deployment to the cluster with `kubectl`:
To deploy Træfik to your cluster start by submitting the deployment to the cluster with `kubectl`:
```sh
kubectl apply -f examples/k8s/traefik.yaml
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik.yaml
```
### Check the deployment
@@ -76,7 +138,7 @@ Now lets check if our deployment was successful.
Start by listing the pods in the `kube-system` namespace:
```sh
```shell
$kubectl --namespace=kube-system get pods
NAME READY STATUS RESTARTS AGE
@@ -86,26 +148,38 @@ 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 kubenetes to pull
the Træfɪk image and start the container._
a pod, and it is now running. _It might take a few moments for kubernetes to pull
the Træfik 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.
You should now be able to access Træfik 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.
> We expect to see a 404 response here as we haven't yet given Træfik any configuration.
## Deploy Træfik using Helm Chart
Instead of installing Træfik via a Deployment object, you can also use the Træfik Helm chart.
Install Træfik chart by:
```sh
helm install stable/traefik
```
For more information, check out [the doc](https://github.com/kubernetes/charts/tree/master/stable/traefik).
## 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).
[Træfik Web UI](https://github.com/containous/traefik#web-ui).
```yaml
apiVersion: v1
@@ -115,7 +189,7 @@ metadata:
namespace: kube-system
spec:
selector:
k8s-app: traefik-ingress-lb
k8s-app: traefik-ingress-lb
ports:
- port: 80
targetPort: 8080
@@ -125,6 +199,8 @@ kind: Ingress
metadata:
name: traefik-web-ui
namespace: kube-system
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: traefik-ui.local
@@ -136,22 +212,22 @@ spec:
```
[examples/k8s/ui.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/ui.yaml)
```sh
kubectl apply -f examples/k8s/ui.yaml
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/ui.yaml
```
Now lets setup an entry in our /etc/hosts file to route `traefik-ui.local`
to our cluster.
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`
```
```shell
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.
We should now be able to visit [traefik-ui.local](http://traefik-ui.local) in the browser and view the Træfik Web UI.
## Name based routing
@@ -263,8 +339,8 @@ spec:
```
[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
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-deployments.yaml
```
Next we need to setup a service for each of the cheese pods.
@@ -301,6 +377,8 @@ apiVersion: v1
kind: Service
metadata:
name: wensleydale
annotations:
traefik.backend.circuitbreaker: "NetworkErrorRatio() > 0.5"
spec:
ports:
- name: http
@@ -310,10 +388,15 @@ spec:
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
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-services.yaml
```
Now we can submit an ingress for the cheese websites.
@@ -323,6 +406,8 @@ apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cheese
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: stilton.local
@@ -351,18 +436,18 @@ spec:
> Notice that we list each hostname, and add a backend service.
```sh
kubectl apply -f examples/k8s/cheese-ingress.yaml
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-ingress.yaml
```
Now visit the [Træfɪk dashboard](http://traefik-ui.local/) and you should
Now visit the [Træfik 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
```shell
echo "$(minikube ip) stilton.local cheddar.local wensleydale.local" | sudo tee -a /etc/hosts
```
@@ -385,6 +470,7 @@ kind: Ingress
metadata:
name: cheeses
annotations:
kubernetes.io/ingress.class: traefik
traefik.frontend.rule.type: pathprefixstrip
spec:
rules:
@@ -406,15 +492,15 @@ spec:
```
[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
> Notice that we are configuring Træfik 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
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheeses-ingress.yaml
```
```sh
```shell
echo "$(minikube ip) cheeses.local" | sudo tee -a /etc/hosts
```
@@ -423,3 +509,72 @@ 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/)
## Disable passing the Host header
By default Træfik will pass the incoming Host header on to the upstream resource.
There are times however where you may not want this to be the case.
For example if your service is of the ExternalName type.
### Disable entirely
Add the following to your toml config:
```toml
disablePassHostHeaders = true
```
### Disable per ingress
To disable passing the Host header per ingress resource set the `traefik.frontend.passHostHeader`
annotation on your ingress to `false`.
Here is an example ingress definition:
```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example
annotations:
kubernetes.io/ingress.class: traefik
traefik.frontend.passHostHeader: "false"
spec:
rules:
- host: example.com
http:
paths:
- path: /static
backend:
serviceName: static
servicePort: https
```
And an example service definition:
```yaml
apiVersion: v1
kind: Service
metadata:
name: static
spec:
ports:
- name: https
port: 443
type: ExternalName
externalName: static.otherdomain.com
```
If you were to visit example.com/static the request would then be passed onto
static.otherdomain.com/static and static.otherdomain.com would receive the
request with the Host header being static.otherdomain.com.
Note: The per ingress annotation overides whatever the global value is set to.
So you could set `disablePassHostHeaders` to `true` in your toml file and then enable passing
the host header per ingress if you wanted.
## Excluding an ingress from Træfik
You can control which ingress Træfik cares about by using the `kubernetes.io/ingress.class` annotation.
By default if the annotation is not set at all Træfik will include the ingress.
If the annotation is set to anything other than traefik or a blank string Træfik will ignore it.
![](http://i.giphy.com/ujUdrdpX7Ok5W.gif)

View File

@@ -3,9 +3,9 @@
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.
This section explains how to launch Træfik using a configuration loaded from a Key-value store.
Træfɪk supports several Key-value stores:
Træfik supports several Key-value stores:
- [Consul](https://consul.io)
- [etcd](https://coreos.com/etcd/)
@@ -19,12 +19,12 @@ 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.
The Træfik 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
```yaml
consul:
image: progrium/consul
command: -server -bootstrap -log-level debug -ui-dir /ui
@@ -54,11 +54,11 @@ whoami4:
## 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).
We should now fill the store with the Træfik 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.
Fortunately, Træfik allows automation of this process using the `storeconfig` subcommand.
Please refer to the [store Træfik 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 :
@@ -112,21 +112,21 @@ And there, the same global configuration in the Key-value Store (using `prefix =
| `/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`.
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
## Launch Træfik
We will now launch Træfɪk in a container.
We use CLI flags to setup the connection between Træfɪk and Consul.
We will now launch Træfik in a container.
We use CLI flags to setup the connection between Træfik 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
```yaml
traefik:
image: traefik
command: --consul --consul.endpoint=127.0.0.1:8500
@@ -142,7 +142,7 @@ NB : Be careful to give the correct IP address and port in the flag `--consul.en
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 :
Then, we have to provide CA, Cert and Key to Træfik using `consul` flags :
- `--consul.tls`
- `--consul.tls.ca=path/to/the/file`
@@ -161,9 +161,9 @@ Note that we can either give directly directly the file content itself (instead
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.
Following our example, we will provide backends/frontends rules to Træfik.
Note that this section is independent of the way Træfɪk got its static configuration.
Note that this section is independent of the way Træfik 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
@@ -259,13 +259,13 @@ And there, the same dynamic configuration in a KV Store (using `prefix = "traefi
## Atomic configuration changes
Træfɪk can watch the backends/frontends configuration changes and generate its configuration automatically.
Træfik 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.
Note that only backends/frontends rules are dynamic, the rest of the Træfik 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.
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æfik to read an intermediate configuration state despite judicious use of the `--providersThrottleDuration` flag. To solve this problem, Træfik supports a special key called `/traefik/alias`. If set, Træfik 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).
Given the key structure below, Træfik will use the `http://172.17.0.2:80` as its only backend (frontend keys have been omitted for brevity).
| Key | Value |
|-------------------------------------------------------------------------|-----------------------------|
@@ -297,24 +297,24 @@ Once the `/traefik/alias` key is updated, the new `/traefik_configurations/2` co
| `/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`.
Note that Træfik *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).
Don't forget to [setup the connection between Træfik and Key-value store](/user-guide/kv-config/#launch-trfk).
The static Træfik configuration in a key-value store can be automatically created and updated, using the [`storeconfig` subcommand](/basics/#commands).
```bash
$ traefik storeconfig [flags] ...
$ 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.
Træfik 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:
```
```toml
[acme]
email = "test@traefik.io"
storage = "traefik/acme/account" # the key where to store your certificates in the KV store
@@ -323,6 +323,7 @@ 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!
![](http://i.giphy.com/ujUdrdpX7Ok5W.gif)

View File

@@ -0,0 +1,96 @@
# Marathon
This guide explains how to integrate Marathon and operate the cluster in a reliable way from Traefik's standpoint.
# Host detection
Marathon offers multiple ways to run (Docker-containerized) applications, the most popular ones being
- BRIDGE-networked containers with dynamic high ports exposed
- HOST-networked containers with host machine ports
- containers with dedicated IP addresses ([IP-per-task](https://mesosphere.github.io/marathon/docs/ip-per-task.html)).
Traefik tries to detect the configured mode and route traffic to the right IP addresses. It is possible to force using task hosts with the `forceTaskHostname` option.
Given the complexity of the subject, it is possible that the heuristic fails. Apart from filing an issue and waiting for the feature request / bug report to get addressed, one workaround for such situations is to customize the Marathon template file to the individual needs. (Note that this does _not_ require rebuilding Traefik but only to point the `filename` configuration parameter to a customized version of the `marathon.tmpl` file on Traefik startup.)
# Port detection
Traefik also attempts to determine the right port (which is a [non-trivial matter in Marathon](https://mesosphere.github.io/marathon/docs/ports.html)). Following is the order by which Traefik tries to identify the port (the first one that yields a positive result will be used):
1. A arbitrary port specified through the `traefik.port` label.
1. The task port (possibly indexed through the `traefik.portIndex` label, otherwise the first one).
1. The port from the application's `portDefinitions` field (possibly indexed through the `traefik.portIndex` label, otherwise the first one).
1. The port from the application's `ipAddressPerTask` field (possibly indexed through the `traefik.portIndex` label, otherwise the first one).
# Achieving high availability
## Scenarios
There are three scenarios where the availability of a Marathon application could be impaired along with the risk of losing or failing requests:
- During the startup phase when Traefik already routes requests to the backend even though it has not completed its bootstrapping process yet.
- During the shutdown phase when Traefik still routes requests to the backend while the backend is already terminating.
- During a failure of the application when Traefik has not yet identified the backend as being erroneous.
The first two scenarios are common with every rolling upgrade of an application (i.e., a new version release or configuration update).
The following sub-sections describe how to resolve or mitigate each scenario.
### Startup
In general, it is possible to define [readiness checks](https://mesosphere.github.io/marathon/docs/readiness-checks.html) (available since Marathon version 1.1) per application and have Marathon take these into account during the startup phase. The idea is that each application provides an HTTP endpoint that Marathon queries periodically during an ongoing deployment in order to mark the associated readiness check result as successful if and only if the endpoint returns a response within the configured HTTP code range. As long as the check keeps failing, Marathon will not proceed with the deployment (within the configured upgrade stategy bounds).
Unfortunately, Traefik does not respect the result of the readiness check yet. Support is expected to land in a not-too-distant future release of Traefik, however, as being tracked by [issue 1559](https://github.com/containous/traefik/issues/1559).
A current mitigation strategy is to enable [retries](http://docs.traefik.io/toml/#retry-configuration) and make sure that a sufficient number of healthy application tasks exist so that one retry will likely hit one of those. Apart from its probabilistic nature, the workaround comes at the price of increased latency.
### Shutdown
It is possible to install a [termination handler](https://mesosphere.github.io/marathon/docs/health-checks.html) (available since Marathon version 1.3) with each application whose responsibility it is to delay the shutdown process long enough until the backend has been taken out of load-balancing rotation with reasonable confidence (i.e., Traefik has received an update from the Marathon event bus, recomputes the available Marathon backends, and applies the new configuration). Specifically, each termination handler should install a signal handler listening for a SIGTERM signal and implement the following steps on signal reception:
1. Disable Keep-Alive HTTP connections.
1. Keep accepting HTTP requests for a certain period of time.
1. Stop accepting new connections.
1. Finish serving any in-flight requests.
1. Shut down.
Traefik already ignores Marathon tasks whose state does not match `TASK_RUNNING`; since terminating tasks transition into the `TASK_KILLING` and eventually `TASK_KILLED` state, there is nothing further that needs to be done on Traefik's end.
How long HTTP requests should continue to be accepted in step 2 depends on how long Traefik needs to receive and process the Marathon configuration update. Under regular operational conditions, it should be on the order of seconds, with 10 seconds possibly being a good default value.
Again, configuring Traefik to do retries (as discussed in the previous section) can serve as a decent workaround strategy. Paired with termination handlers, they would cover for those cases where either the termination sequence or Traefik cannot complete their part of the orchestration process in time.
### Failure
A failing application always happens unexpectedly, and hence, it is very difficult or even impossible to rule out the adversal effects categorically. Failure reasons vary broadly and could stretch from unacceptable slowness, a task crash, or a network split.
There are two mitigaton efforts:
1. Configure [Marathon health checks](https://mesosphere.github.io/marathon/docs/health-checks.html) on each application.
1. Configure Traefik health checks (possibly via the `traefik.backend.healthcheck.*` labels) and make sure they probe with proper frequency.
The Marathon health check makes sure that applications once deemed dysfunctional are being rescheduled to different slaves. However, they might take a while to get triggered and the follow-up processes to complete. For that reason, the Treafik health check provides an additional check that responds more rapidly and does not require a configuration reload to happen. Additionally, it protects from cases that the Marathon health check may not be able to cover, such as a network split.
## (Non-)Alternatives
There are a few alternatives of varying quality that are frequently asked for. The remaining section is going to explore them along with a benefit/cost trade-off.
### Reusing Marathon health checks
It may seem obvious to reuse the Marathon health checks as a signal to Traefik whether an application should be taken into load-balancing rotation or not.
Apart from the increased latency a failing health check may have, a major problem with this is is that Marathon does not persist the health check results. Consequently, if a master re-election occurs in the Marathon clusters, all health check results will revert to the _unknown_ state, effectively causing all applications inside the cluster to become unavailable and leading to a complete cluster failure. Re-elections do not only happen during regular maintenance work (often requiring rolling upgrades of the Marathon nodes) but also when the Marathon leader fails spontaneously). As such, there is no way to handle this situation deterministically.
Finally, Marathon health checks are not mandatory (the default is to use the task state as reported by Mesos), so requiring them for Traefik would raise the entry barrier for Marathon users.
Traefik used to use the health check results but moved away from it as [users reported the dramatic consequences](https://github.com/containous/traefik/issues/653).
### Draining
Another common approach is to let a proxy drain backends that are supposed to shut down. That is, once a backend is supposed to shut down, Traefik would stop forwarding requests.
On the plus side, this would not require any modifications to the application in question. However, implementing this fully within Traefik seems like a non-trivial undertaking. Additionally, the approach is less flexible compared to a custom termination handler since only the latter allows for the implementation of custom termination sequences that go beyond simple request draining (e.g., persisting a snapshot state to disk prior to terminating).
The feature is currently not implemented; a request for draining in general is at [issue 41](https://github.com/containous/traefik/issues/41).

View File

@@ -2,9 +2,9 @@
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.
how to deploy Træfik on it.
The cluster constist of:
The cluster consists of:
- 3 servers
- 1 manager
@@ -19,10 +19,10 @@ The cluster constist of:
## Cluster provisioning
First, let's create all the nodes required. It's a shorter version of
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
```shell
docker-machine create -d virtualbox manager
docker-machine create -d virtualbox worker1
docker-machine create -d virtualbox worker2
@@ -34,7 +34,7 @@ Then, let's setup the cluster, in order :
2. get the token for other host to join
3. on both workers, join the cluster with the token
```sh
```shell
docker-machine ssh manager "docker swarm init \
--listen-addr $(docker-machine ip manager) \
--advertise-addr $(docker-machine ip manager)"
@@ -47,6 +47,7 @@ docker-machine ssh worker1 "docker swarm join \
--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) \
@@ -56,7 +57,7 @@ docker-machine ssh worker2 "docker swarm join \
Let's validate the cluster is up and running.
```sh
```shell
docker-machine ssh manager docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
2a770ov9vixeadep674265u1n worker1 Ready Active
@@ -66,7 +67,7 @@ esbhhy6vnqv90xomjaomdgy46 worker2 Ready Active
Finally, let's create a network for Træfik to use.
```sh
```shell
docker-machine ssh manager "docker network create --driver=overlay traefik-net"
```
@@ -78,7 +79,7 @@ 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.
```
```shell
docker-machine ssh manager "docker service create \
--name traefik \
--constraint=node.role==manager \
@@ -103,7 +104,7 @@ Let's explain this command:
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 underlined container) to the `traefik-net` network.
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
@@ -114,22 +115,27 @@ 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
```shell
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
```shell
docker-machine ssh manager "docker service ls"
ID NAME REPLICAS IMAGE COMMAND
ab046gpaqtln whoami0 1/1 emilevauge/whoami
@@ -137,9 +143,9 @@ 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
## Access to your apps through Træfik
```sh
```shell
curl -H Host:whoami0.traefik http://$(docker-machine ip manager)
Hostname: 8147a7746e7a
IP: 127.0.0.1
@@ -180,7 +186,7 @@ X-Forwarded-Server: 8fbc39271b4c
Note that as Træfik is published, you can access it from any machine
and not only the manager.
```sh
```shell
curl -H Host:whoami0.traefik http://$(docker-machine ip worker1)
Hostname: 8147a7746e7a
IP: 127.0.0.1
@@ -218,6 +224,82 @@ X-Forwarded-Proto: http
X-Forwarded-Server: 8fbc39271b4c
```
## Scale both services
```shell
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:
```shell
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æfik 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.
```shell
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.
```shell
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)

View File

@@ -1,6 +1,6 @@
# 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.
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æfik on it.
The cluster consists of:
- 2 servers
@@ -21,13 +21,13 @@ We first follow [this guide](https://docs.docker.com/engine/userguide/networking
This machine is the service registry of our cluster.
```sh
```shell
docker-machine create -d virtualbox mh-keystore
```
Then we install the service registry [Consul](https://consul.io) on this machine:
```sh
```shell
eval "$(docker-machine env mh-keystore)"
docker run -d \
-p "8500:8500" \
@@ -39,7 +39,7 @@ docker run -d \
This machine is a swarm master and a swarm agent on it.
```sh
```shell
docker-machine create -d virtualbox \
--swarm --swarm-master \
--swarm-discovery="consul://$(docker-machine ip mh-keystore):8500" \
@@ -52,7 +52,7 @@ docker-machine create -d virtualbox \
This machine have a swarm agent on it.
```sh
```shell
docker-machine create -d virtualbox \
--swarm \
--swarm-discovery="consul://$(docker-machine ip mh-keystore):8500" \
@@ -65,16 +65,16 @@ docker-machine create -d virtualbox \
Create the overlay network on the swarm master:
```sh
```shell
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æfik
Deploy Træfɪk:
Deploy Træfik:
```sh
```shell
docker $(docker-machine config mhs-demo0) run \
-d \
-p 80:80 -p 8080:8080 \
@@ -110,7 +110,7 @@ Let's explain this command:
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
```shell
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
@@ -118,7 +118,7 @@ docker run -d --name=whoami1 --net=my-net --env="constraint:node==mhs-demo1" emi
Check that everything is started:
```sh
```shell
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
@@ -126,9 +126,9 @@ ba2c21488299 emilevauge/whoami "/whoamI" 8 seconds ago
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
## Access to your apps through Træfik
```sh
```shell
curl -H Host:whoami0.traefik http://$(docker-machine ip mhs-demo0)
Hostname: 8147a7746e7a
IP: 127.0.0.1
@@ -167,4 +167,3 @@ X-Forwarded-Server: 8fbc39271b4c
```
![](http://i.giphy.com/ujUdrdpX7Ok5W.gif)

View File

@@ -1,12 +1,11 @@
kubelet:
image: gcr.io/google_containers/hyperkube-amd64:v1.2.2
image: gcr.io/google_containers/hyperkube-amd64:v1.5.2
privileged: true
pid: host
net : host
volumes:
- /:/rootfs:ro
- /sys:/sys:ro
- /sys:/sys:rw
- /var/lib/docker/:/var/lib/docker:rw
- /var/lib/kubelet/:/var/lib/kubelet:rw
- /var/lib/kubelet/:/var/lib/kubelet:rw,shared
- /var/run:/var/run:rw
command: ['/hyperkube', 'kubelet', '--containerized', '--hostname-override=127.0.0.1', '--address=0.0.0.0', '--api-servers=http://localhost:8080', '--config=/etc/kubernetes/manifests', '--allow-privileged=true', '--v=2']
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,7 @@
traefik:
image: traefik
command: --web --rancher --rancher.domain=rancher.localhost --rancher.endpoint=http://example.com --rancher.accesskey=XXXXXXX --rancher.secretkey=YYYYYY --logLevel=DEBUG
ports:
- "80:80"
- "443:443"
- "8080:8080"

View File

@@ -0,0 +1,37 @@
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
rules:
- apiGroups:
- ""
resources:
- pods
- services
- endpoints
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: kube-system

View File

@@ -1,5 +1,11 @@
---
apiVersion: v1
kind: Deployment
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
namespace: kube-system
---
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
name: traefik-ingress-controller
@@ -7,21 +13,17 @@ metadata:
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
version: v1.1.0
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
hostNetwork: true
containers:
- image: traefik:v1.1.0
- image: traefik
name: traefik-ingress-lb
resources:
limits:
@@ -35,7 +37,11 @@ spec:
containerPort: 80
hostPort: 80
- name: admin
containerPort: 8080
containerPort: 8081
securityContext:
privileged: true
args:
- -d
- --web
- --web.address=:8081
- --kubernetes

View File

@@ -10,7 +10,7 @@ spec:
ports:
- name: web
port: 80
targetPort: 8080
targetPort: 8081
---
apiVersion: extensions/v1beta1
kind: Ingress

634
glide.lock generated
View File

@@ -1,108 +1,148 @@
hash: 1bbeb842ee639ccc6e2edf8cc13fc2759cb96e3d839a1aec7b7f6af4fb89c8e1
updated: 2016-11-09T19:24:00.762904389+01:00
hash: e59e8244152a823cd3633fb09cdd583c4e5be78d7b50fb7047ba6b6a9ed5e8ec
updated: 2017-05-19T23:30:19.890844996+02:00
imports:
- name: cloud.google.com/go
version: 2e6a95edb1071d750f6d7db777bf66cd2997af6c
subpackages:
- compute/metadata
- internal
- name: github.com/abbot/go-http-auth
version: cb4372376e1e00e9f6ab9ec142e029302c9e7140
version: d45c47bedec736d172957bd394786b76626fa8ac
- name: github.com/ArthurHlt/go-eureka-client
version: 9d0a49cbd39aa3634ae1977e9f519a262b10adaf
subpackages:
- eureka
- name: github.com/ArthurHlt/gominlog
version: 72eebf980f467d3ab3a8b4ddf660f664911ce519
- 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/dynamodb
- service/dynamodb/dynamodbattribute
- service/dynamodb/dynamodbiface
- service/dynamodbattribute
- service/ec2
- service/ecs
- service/route53
- service/sts
- name: github.com/Azure/azure-sdk-for-go
version: 088007b3b08cc02b27f2eadfdcd870958460ce7e
subpackages:
- arm/dns
- name: github.com/Azure/go-autorest
version: a2fdd780c9a50455cecd249b00bdc3eb73a78e31
subpackages:
- autorest
- autorest/azure
- autorest/date
- autorest/to
- name: github.com/beorn7/perks
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
subpackages:
- quantile
- name: github.com/blang/semver
version: 31b736133b98f26d5e078ec9eb591666edfd091f
- name: github.com/boltdb/bolt
version: f4c032d907f61f08dba2d719c58f108a1abb8e81
version: e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd
- name: github.com/BurntSushi/toml
version: 99064174e013895bbd9b025c31100bd1d9b590ca
version: b26d9c308763d68093482582cea63d69be07a0f0
- name: github.com/BurntSushi/ty
version: 6add9cd6ad42d389d6ead1dde60b4ad71e46fd74
subpackages:
- fun
- name: github.com/cenk/backoff
version: 8edc80b07f38c27352fb186d971c628a6c32552b
version: 5d150e7eec023ce7a124856b37c68e54b4050ac7
- name: github.com/codahale/hdrhistogram
version: f8ad88b59a584afeee9d334eff879b104439117b
version: 9208b142303c12d8899bae836fd524ac9338b4fd
- name: github.com/codegangsta/cli
version: 1efa31f08b9333f1bd4882d61f9d668a70cd902e
version: bf4a526f48af7badd25d2cb02d587e1b01be3b50
- name: github.com/codegangsta/negroni
version: 3f7ce7b928e14ff890b067e5bbbc80af73690a9c
version: c0db5feaa33826cd5117930c8f4ee5c0f565eec6
- name: github.com/containous/flaeg
version: a731c034dda967333efce5f8d276aeff11f8ff87
version: b5d2dc5878df07c2d74413348186982e7b865871
- name: github.com/containous/mux
version: a819b77bba13f0c0cbe36e437bc2e948411b3996
- name: github.com/containous/staert
version: 1e26a71803e428fd933f5f9c8e50a26878f53147
- name: github.com/coreos/etcd
version: 1c9e0a0e33051fed6c05c141e6fcbfe5c7f2a899
version: c400d05d0aa73e21e431c16145e558d624098018
subpackages:
- Godeps/_workspace/src/github.com/coreos/go-systemd/journal
- Godeps/_workspace/src/github.com/coreos/pkg/capnslog
- Godeps/_workspace/src/github.com/ugorji/go/codec
- Godeps/_workspace/src/golang.org/x/net/context
- client
- pkg/fileutil
- pkg/pathutil
- pkg/types
- version
- name: github.com/coreos/go-oidc
version: 5644a2f50e2d2d5ba0b474bc5bc55fea1925936d
subpackages:
- http
- jose
- key
- oauth2
- oidc
- name: github.com/coreos/go-systemd
version: 43e4800a6165b4e02bb2a36673c54b230d6f7b26
version: 48702e0da86bd25e76cfef347e2adeb434a0d0a6
subpackages:
- daemon
- name: github.com/coreos/pkg
version: fa29b1d70f0beaddd4c7021607cc3c3be8ce94b8
subpackages:
- health
- httputil
- timeutil
- name: github.com/davecgh/go-spew
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9
subpackages:
- spew
- name: github.com/docker/distribution
version: 99cb7c0946d2f5a38015443e515dc916295064d7
- name: github.com/decker502/dnspod-go
version: 68650ee11e182e30773781d391c66a0c80ccf9f2
- name: github.com/dgrijalva/jwt-go
version: d2709f9f1f31ebcda9651b03077758c1f3a0018c
- name: github.com/dnsimple/dnsimple-go
version: 5a5b427618a76f9eed5ede0f3e6306fbd9311d2e
subpackages:
- dnsimple
- name: github.com/docker/distribution
version: 325b0804fef3a66309d962357aac3c2ce3f4d329
subpackages:
- context
- digest
- reference
- registry/api/errcode
- registry/api/v2
- registry/client
- registry/client/auth
- registry/client/transport
- registry/storage/cache
- registry/storage/cache/memory
- uuid
- name: github.com/docker/docker
version: 534753663161334baba06f13b8efa4cad22b5bc5
version: 49bf474f9ed7ce7143a59d1964ff7b7fd9b52178
subpackages:
- api/types/backend
- builder
- builder/dockerignore
- cliconfig
- cliconfig/configfile
- daemon/graphdriver
- image
- image/v1
- layer
- namesgenerator
- opts
- pkg/archive
- pkg/chrootarchive
- pkg/fileutils
- pkg/gitutils
- pkg/homedir
- pkg/httputils
- pkg/idtools
- pkg/ioutils
- pkg/jsonlog
- pkg/jsonmessage
- pkg/longpath
- pkg/mflag
- pkg/mount
- pkg/namesgenerator
- 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
- reference
- registry
- runconfig/opts
- name: github.com/docker/engine-api
version: 62043eb79d581a32ea849645277023c550732e52
version: 3d1601b9d2436a70b0dfc045a23f6503d19195df
subpackages:
- client
- client/transport
@@ -120,34 +160,17 @@ imports:
- types/time
- types/versions
- name: github.com/docker/go-connections
version: 988efe982fdecb46f01d53465878ff1f2ff411ce
version: 990a1a1a70b0da4c4cb70e117971a4f0babfbf1a
subpackages:
- nat
- sockets
- tlsconfig
- name: github.com/docker/go-units
version: f2145db703495b2e525c59662db69a7344b00bb8
version: 0dadbb0345b35ec7ef35e228dabb8de89a65bf52
- name: github.com/docker/leadership
version: 0a913e2d71a12fd14a028452435cb71ac8d82cb6
- 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/docker/libkv
version: 3fce6a0f26e07da3eac45796a8e255547a47a750
version: 1d8431073ae03cdaedb198a89722f3aab6d418ef
subpackages:
- store
- store/boltdb
@@ -156,54 +179,116 @@ imports:
- 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: 9a6736ed45b44bf3835afeebb3034b57ed329f3e
version: 30f82fa23fd844bd5bb1e5f216db87fd77b5eb43
- name: github.com/emicklei/go-restful
version: 892402ba11a2e2fd5e1295dd633481f27365f14d
subpackages:
- log
- swagger
- name: github.com/fatih/color
version: 9131ab34cf20d2f6d83fdc67168a5430d1c7dc23
- name: github.com/gambol99/go-marathon
version: a558128c87724cd7430060ef5aedf39f83937f55
- name: github.com/go-check/check
version: 4f90aeace3a26ad7021961c297b22c42160c7b25
version: 15ea23e360abb8b25071e677aed344f31838e403
- name: github.com/ghodss/yaml
version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee
- name: github.com/go-ini/ini
version: e7fea39b01aea8d5671f6858f0532f56e8bff3a5
- name: github.com/go-kit/kit
version: f66b0e13579bfc5a48b9e2a94b1209c107ea1f41
subpackages:
- metrics
- metrics/internal/lv
- metrics/prometheus
- name: github.com/go-openapi/jsonpointer
version: 46af16f9f7b149af66e5d1bd010e3574dc06de98
- name: github.com/go-openapi/jsonreference
version: 13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272
- name: github.com/go-openapi/spec
version: 6aced65f8501fe1217321abf0749d354824ba2ff
- name: github.com/go-openapi/swag
version: 1d0bd113de87027671077d3c71eb3ac5d7dbba72
- name: github.com/gogo/protobuf
version: 99cb9b23110011cc45571c901ecae6f6f5e65cd3
version: 909568be09de550ed094403c2bf8a261b5bb730a
subpackages:
- proto
- sortkeys
- name: github.com/golang/glog
version: fca8c8854093a154ff1eb580aae10276ad6b1b5f
- name: github.com/golang/protobuf
version: 2bba0603135d7d7f5cb73b2125beeda19c09f4ef
subpackages:
- proto
- name: github.com/google/go-github
version: 55263f30529cb06f5b478efc333390b791cfe3b1
version: 6896997c7c9fe603fb9d2e8e92303bb18481e60a
subpackages:
- github
- name: github.com/google/go-querystring
version: 9235644dd9e52eeae6fa48efd539fdc351a0af53
version: 53e6ce116135b80d037921a7fdd5138cf32d7a8a
subpackages:
- query
- name: github.com/google/gofuzz
version: bbcb9da2d746f8bdbd6a936686a0a6067ada0ec5
- name: github.com/googleapis/gax-go
version: 9af46dd5a1713e8b5cd71106287eba3cefdde50b
- name: github.com/gorilla/context
version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42
- name: github.com/gorilla/websocket
version: a91eba7f97777409bc2c443f5534d41dd20c5720
- name: github.com/hashicorp/consul
version: d8e2fb7dd594163e25a89bc52c1a4613f5c5bfb8
version: 3f92cc70e8163df866873c16c6d89889b5c95fc4
subpackages:
- api
- name: github.com/hashicorp/go-cleanhttp
version: ad28ea4487f05916463e2423a55166280e8254b5
version: 3573b8b52aa7b37b9358d966a898feb387f62437
- name: github.com/hashicorp/go-version
version: e96d3840402619007766590ecea8dd7af1292276
version: 03c5bf6be031b6dd45afec16b1cf94fc8938bc77
- name: github.com/hashicorp/serf
version: b03bf85930b2349eb04b97c8fac437495296e3e7
version: 19f2c401e122352c047a84d6584dd51e2fb8fcc4
subpackages:
- coordinate
- name: github.com/jarcoal/httpmock
version: 145b10d659265440f062c31ea15326166bae56ee
- name: github.com/libkermit/compose
version: cadc5a3b83a15790174bd7fbc75ea2529785e772
- name: github.com/JamesClonk/vultr
version: 0f156dd232bc4ebf8a32ba83fec57c0e4c9db69f
subpackages:
- check
- name: github.com/libkermit/docker
version: 55e3595409924fcfbb850811e5a7cdbe8960a0b7
- name: github.com/mailgun/manners
version: a585afd9d65c0e05f6c003f921e71ebc05074f4f
- 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/timetools
version: fd192d755b00c968d312d23f521eb0cdc6f66bd0
- name: github.com/mailru/easyjson
version: d5b7844b561a7bc640052f1b935f7b800330d7e0
subpackages:
- buffer
- jlexer
- jwriter
- name: github.com/mattn/go-colorable
version: 5411d3eea5978e6cdc258b30de592b60df6aba96
repo: https://github.com/mattn/go-colorable
- name: github.com/mattn/go-isatty
version: 57fdcb988a5c543893cc61bce354a6e24ab70022
repo: https://github.com/mattn/go-isatty
- name: github.com/mattn/go-shellwords
version: 525bedee691b5a8df547cb5cf9f86b7fb1883e24
version: 02e3cf038dcea8290e44424da473dd12be796a8a
- name: github.com/matttproud/golang_protobuf_extensions
version: c12348ce28de40eed0136aa2b644d0ee0650e56c
subpackages:
- pbutil
- name: github.com/mesos/mesos-go
version: 068d5470506e3780189fe607af40892814197c5e
subpackages:
@@ -227,64 +312,104 @@ imports:
- records/state
- util
- name: github.com/Microsoft/go-winio
version: ce2922f643c8fd76b46cadc7f404a06282678b34
version: fff283ad5116362ca252298cfc9b95828956d85d
- name: github.com/miekg/dns
version: 5d001d020961ae1c184f9f8152fdc73810481677
version: 8060d9f51305bbe024b99679454e62f552cd0b0b
- name: github.com/mitchellh/mapstructure
version: f3009df150dadf309fdee4a54ed65c124afad715
- name: github.com/moul/http2curl
version: b1479103caacaa39319f75e7f57fc545287fca0d
version: 53818660ed4955e899c0bcafa97299a388bd7c8e
- name: github.com/mvdan/xurls
version: db96455566f05ffe42bd6ac671f05eeb1152b45d
- name: github.com/NYTimes/gziphandler
version: f6438dbf4a82c56684964b03956aa727b0d7816b
version: 22d4470af89e09998fc16b35029df973932df4ae
- name: github.com/ogier/pflag
version: 45c278ab3607870051a2ea9040bb85fcb8557481
- name: github.com/opencontainers/runc
version: 02f8fa7863dd3f82909a73e2061897828460d52f
version: 50401b5b4c2e01e4f1372b73a021742deeaf4e2d
subpackages:
- libcontainer/user
- name: github.com/parnurzeal/gorequest
version: e30af16d4e485943aab0b0885ad6bdbb8c0d3dc7
- name: github.com/ovh/go-ovh
version: d2207178e10e4527e8f222fd8707982df8c3af17
subpackages:
- ovh
- name: github.com/pborman/uuid
version: ca53cad383cad2479bbba7f7a1a05797ec1386e4
- name: github.com/pkg/errors
version: ff09b135c25aae272398c51a07235b90a75aa4f0
- name: github.com/pmezard/go-difflib
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
subpackages:
- difflib
- name: github.com/prometheus/client_golang
version: 08fd2e12372a66e68e30523c7642e0cbc3e4fbde
subpackages:
- prometheus
- prometheus/promhttp
- name: github.com/prometheus/client_model
version: 6f3806018612930941127f2a7c6c453ba2c527d2
subpackages:
- go
- name: github.com/prometheus/common
version: 49fee292b27bfff7f354ee0f64e1bc4850462edf
subpackages:
- expfmt
- internal/bitbucket.org/ww/goautoneg
- model
- name: github.com/prometheus/procfs
version: a1dba9ce8baed984a2495b658c82687f8157b98f
subpackages:
- xfs
- name: github.com/PuerkitoBio/purell
version: 8a290539e2e8629dbc4e6bad948158f790ec31f4
- name: github.com/PuerkitoBio/urlesc
version: 5bd2802263f21d8788851d5305584c82a5c75d7e
- name: github.com/pyr/egoscale
version: 987e683a7552f34ee586217d1cc8507d52e80ab9
subpackages:
- src/egoscale
- name: github.com/rancher/go-rancher
version: 5b8f6cc26b355ba03d7611fce3844155b7baf05b
subpackages:
- client
- name: github.com/ryanuber/go-glob
version: 572520ed46dbddaed19ea3d9541bdd0494163693
version: 256dc444b735e061061cf46c809487313d5b0065
- name: github.com/samuel/go-zookeeper
version: 87e1bca4477a3cc767ca71be023ced183d74e538
version: 1d7be4effb13d2d908342d349d71a284a7542693
subpackages:
- zk
- name: github.com/satori/go.uuid
version: 879c5887cd475cd7864858769793b2ceb0d44feb
- name: github.com/Sirupsen/logrus
version: 3ec0642a7fb6488f65b06f9040adc67e3990296a
version: 10f801ebc38b33738c9d17d50860f484a0988ff5
- name: github.com/spf13/pflag
version: 5ccb023bc27df288a957c5e994cd44fd19619465
- name: github.com/streamrail/concurrent-map
version: 8bf1e9bacbf65b10c81d0f4314cf2b1ebef728b5
- name: github.com/stretchr/objx
version: cbeaeb16a013161a98496fad62933b1d21786672
- name: github.com/stretchr/testify
version: 976c720a22c8eb4eb6a0b4348ad85ad12491a506
version: 4d4bfba8f1d1027c4fdbe371823030df51419987
subpackages:
- assert
- mock
- require
- 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: b94837a2404ab90efe9289e77a70694c355739cb
version: ea9cd21fa0bc41ee4bdd50ac7ed8cbc7ea2ed960
subpackages:
- codec
- name: github.com/unrolled/render
version: 526faf80cd4b305bb8134abea8d20d5ced74faa6
- name: github.com/urfave/negroni
version: e0e50f7dc431c043cb33f91b09c3419d48b7cff5
version: 50716a0a853771bb36bfce61a45cdefdb98c2e6e
- name: github.com/vdemeester/docker-events
version: be74d4929ec1ad118df54349fda4b0cba60f849b
- name: github.com/vdemeester/shakers
version: 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
- name: github.com/vulcand/oxy
version: fcc76b52eb8568540a020b7a99e854d9d752b364
version: f88530866c561d24a6b5aac49f76d6351b788b9f
repo: https://github.com/containous/oxy.git
vcs: git
subpackages:
@@ -300,68 +425,249 @@ imports:
- name: github.com/vulcand/route
version: cb89d787ddbb1c5849a7ac9f79004c1fd12a4a32
- name: github.com/vulcand/vulcand
version: bed092e10989250b48bdb6aa3b0557b207f05c80
version: 42492a3a85e294bdbdd1bcabb8c12769a81ea284
subpackages:
- conntracker
- plugin
- plugin/rewrite
- router
- name: github.com/xenolf/lego
version: b2fad6198110326662e9e356a97199078a4a775c
version: 5dfe609afb1ebe9da97c9846d97a55415e5a5ccd
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: d81fdb778bf2c40a91b24519d60cdc5767318829
version: 4ed45ec682102c643324fae5dff8dab085b6c300
subpackages:
- bcrypt
- blowfish
- ocsp
- name: golang.org/x/net
version: b400c2eff1badec7022a8c8f5bea058b6315eed7
version: 242b6b35177ec3909636b6cf6a47e8c2c6324b5d
subpackages:
- context
- context/ctxhttp
- http2
- http2/hpack
- idna
- internal/timeseries
- lex/httplex
- proxy
- publicsuffix
- trace
- name: golang.org/x/oauth2
version: 7fdf09982454086d5570c7db3e11f360194830ca
subpackages:
- google
- internal
- jws
- jwt
- name: golang.org/x/sys
version: 62bee037599929a6e9146f29d10dd5208c43507d
version: 8d1157a435470616f975ff9bb013bea8d0962067
subpackages:
- unix
- windows
- name: golang.org/x/text
version: 2910a502d2bf9e43193af9d68ca516529614eed3
subpackages:
- cases
- internal/tag
- language
- runes
- secure/bidirule
- secure/precis
- transform
- unicode/bidi
- unicode/norm
- width
- name: google.golang.org/api
version: 9bf6e6e569ff057f75d9604a46c52928f17d2b54
subpackages:
- dns/v1
- gensupport
- googleapi
- googleapi/internal/uritemplates
- name: google.golang.org/appengine
version: 4f7eeb5305a4ba1966344836ba4af9996b7b4e05
subpackages:
- internal
- internal/app_identity
- internal/base
- internal/datastore
- internal/log
- internal/modules
- internal/remote_api
- internal/urlfetch
- urlfetch
- name: google.golang.org/grpc
version: cdee119ee21e61eef7093a41ba148fa83585e143
subpackages:
- codes
- credentials
- grpclog
- internal
- keepalive
- metadata
- naming
- peer
- stats
- tap
- transport
- name: gopkg.in/fsnotify.v1
version: 944cff21b3baf3ced9a880365682152ba577d348
version: 629574ca2a5df945712d3079857300b5e4da0236
- name: gopkg.in/inf.v0
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
- name: gopkg.in/ini.v1
version: e7fea39b01aea8d5671f6858f0532f56e8bff3a5
- name: gopkg.in/mgo.v2
version: 22287bab4379e1fbf6002fb4eb769888f3fb224c
version: 3f83fa5005286a7fe593b055f0d7771a7dce4655
subpackages:
- bson
- internal/json
- name: gopkg.in/ns1/ns1-go.v2
version: 2abc76c60bf88ba33b15d1d87a13f624d8dff956
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: aa2e30fdd1fe9dd3394119af66451ae790d50e0d
subpackages:
- cipher
- json
testImports:
- name: github.com/Azure/go-ansiterm
version: fa152c58bc15761d0200cb75fe958b89a9d4888e
- name: gopkg.in/yaml.v2
version: 53feefa2559fb8dfa8d81baad31be332c97d6c77
- name: k8s.io/client-go
version: e121606b0d09b2e1c467183ee46217fa85a6b672
subpackages:
- winterm
- name: github.com/cloudfoundry-incubator/candiedyaml
version: 99c3df83b51532e3615f851d8c2dbb638f5313bf
- name: github.com/flynn/go-shlex
version: 3f9db97f856818214da2e1057f8ad84803971cff
- name: github.com/gorilla/mux
version: 9fa818a44c2bf1396a17f9d5a3c0f6dd39d2ff8e
- name: github.com/libkermit/docker-check
version: cbe0ef03b3d23070eac4d00ba8828f2cc7f7e5a3
- name: github.com/spf13/pflag
version: 5644820622454e71517561946e3d94b9f9db6842
- name: github.com/vbatts/tar-split
version: bd4c5d64c3e9297f410025a3b1bd0c58f659e721
subpackages:
- archive/tar
- tar/asm
- tar/storage
- name: github.com/xeipuuv/gojsonpointer
version: e0fe6f68307607d540ed8eac07a342c33fa1b54a
- name: github.com/xeipuuv/gojsonreference
version: e02fc20de94c78484cd5ffb007f8af96be030a45
- name: github.com/xeipuuv/gojsonschema
version: 00f9fafb54d2244d291b86ab63d12c38bd5c3886
- discovery
- kubernetes
- kubernetes/typed/apps/v1beta1
- kubernetes/typed/authentication/v1beta1
- kubernetes/typed/authorization/v1beta1
- kubernetes/typed/autoscaling/v1
- kubernetes/typed/batch/v1
- kubernetes/typed/batch/v2alpha1
- kubernetes/typed/certificates/v1alpha1
- kubernetes/typed/core/v1
- kubernetes/typed/extensions/v1beta1
- kubernetes/typed/policy/v1beta1
- kubernetes/typed/rbac/v1alpha1
- kubernetes/typed/storage/v1beta1
- pkg/api
- pkg/api/errors
- pkg/api/install
- pkg/api/meta
- pkg/api/meta/metatypes
- pkg/api/resource
- pkg/api/unversioned
- pkg/api/v1
- pkg/api/validation/path
- pkg/apimachinery
- pkg/apimachinery/announced
- pkg/apimachinery/registered
- pkg/apis/apps
- pkg/apis/apps/install
- pkg/apis/apps/v1beta1
- pkg/apis/authentication
- pkg/apis/authentication/install
- pkg/apis/authentication/v1beta1
- pkg/apis/authorization
- pkg/apis/authorization/install
- pkg/apis/authorization/v1beta1
- pkg/apis/autoscaling
- pkg/apis/autoscaling/install
- pkg/apis/autoscaling/v1
- pkg/apis/batch
- pkg/apis/batch/install
- pkg/apis/batch/v1
- pkg/apis/batch/v2alpha1
- pkg/apis/certificates
- pkg/apis/certificates/install
- pkg/apis/certificates/v1alpha1
- pkg/apis/extensions
- pkg/apis/extensions/install
- pkg/apis/extensions/v1beta1
- pkg/apis/policy
- pkg/apis/policy/install
- pkg/apis/policy/v1beta1
- pkg/apis/rbac
- pkg/apis/rbac/install
- pkg/apis/rbac/v1alpha1
- pkg/apis/storage
- pkg/apis/storage/install
- pkg/apis/storage/v1beta1
- pkg/auth/user
- pkg/conversion
- pkg/conversion/queryparams
- pkg/fields
- pkg/genericapiserver/openapi/common
- pkg/labels
- pkg/runtime
- pkg/runtime/serializer
- pkg/runtime/serializer/json
- pkg/runtime/serializer/protobuf
- pkg/runtime/serializer/recognizer
- pkg/runtime/serializer/streaming
- pkg/runtime/serializer/versioning
- pkg/selection
- pkg/third_party/forked/golang/reflect
- pkg/third_party/forked/golang/template
- pkg/types
- pkg/util
- pkg/util/cert
- pkg/util/clock
- pkg/util/diff
- pkg/util/errors
- pkg/util/flowcontrol
- pkg/util/framer
- pkg/util/integer
- pkg/util/intstr
- pkg/util/json
- pkg/util/jsonpath
- pkg/util/labels
- pkg/util/net
- pkg/util/parsers
- pkg/util/rand
- pkg/util/runtime
- pkg/util/sets
- pkg/util/uuid
- pkg/util/validation
- pkg/util/validation/field
- pkg/util/wait
- pkg/util/yaml
- pkg/version
- pkg/watch
- pkg/watch/versioned
- plugin/pkg/client/auth
- plugin/pkg/client/auth/gcp
- plugin/pkg/client/auth/oidc
- rest
- tools/cache
- tools/clientcmd/api
- tools/metrics
- transport
testImports: []

View File

@@ -6,11 +6,9 @@ import:
- fun
- package: github.com/Sirupsen/logrus
- package: github.com/cenk/backoff
- package: github.com/urfave/negroni
- package: github.com/containous/flaeg
version: a731c034dda967333efce5f8d276aeff11f8ff87
- package: github.com/vulcand/oxy
version: fcc76b52eb8568540a020b7a99e854d9d752b364
version: f88530866c561d24a6b5aac49f76d6351b788b9f
repo: https://github.com/containous/oxy.git
vcs: git
subpackages:
@@ -23,16 +21,19 @@ import:
- package: github.com/containous/staert
version: 1e26a71803e428fd933f5f9c8e50a26878f53147
- package: github.com/docker/engine-api
version: 62043eb79d581a32ea849645277023c550732e52
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
@@ -41,46 +42,35 @@ import:
- store/etcd
- store/zookeeper
- package: github.com/elazarl/go-bindata-assetfs
- package: github.com/gambol99/go-marathon
version: a558128c87724cd7430060ef5aedf39f83937f55
- package: github.com/containous/mux
- package: github.com/hashicorp/consul
subpackages:
- api
- package: github.com/mailgun/manners
- package: github.com/parnurzeal/gorequest
- package: github.com/streamrail/concurrent-map
- package: github.com/stretchr/testify
subpackages:
- assert
- mock
- require
- 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: b2fad6198110326662e9e356a97199078a4a775c
version: 5dfe609afb1ebe9da97c9846d97a55415e5a5ccd
subpackages:
- acme
- package: golang.org/x/net
subpackages:
- context
- package: gopkg.in/fsnotify.v1
- package: github.com/libkermit/compose
version: cadc5a3b83a15790174bd7fbc75ea2529785e772
- package: github.com/libkermit/docker
version: 55e3595409924fcfbb850811e5a7cdbe8960a0b7
- package: github.com/docker/docker
version: 534753663161334baba06f13b8efa4cad22b5bc5
version: v1.13.0
subpackages:
- namesgenerator
- package: github.com/go-check/check
- package: github.com/docker/libcompose
version: d1876c1d68527a49c0aac22a0b161acc7296b740
- package: github.com/mattn/go-shellwords
- package: github.com/vdemeester/shakers
- package: github.com/ryanuber/go-glob
- package: github.com/mesos/mesos-go
subpackages:
@@ -89,24 +79,74 @@ import:
- upid
- mesosutil
- detector
- package: github.com/jarcoal/httpmock
- 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/tv42/zbase32
- package: github.com/abbot/go-http-auth
- package: github.com/miekg/dns
version: 5d001d020961ae1c184f9f8152fdc73810481677
- package: github.com/NYTimes/gziphandler
- package: github.com/docker/leadership
- package: github.com/satori/go.uuid
version: ^1.1.0
- package: github.com/mitchellh/mapstructure
version: f3009df150dadf309fdee4a54ed65c124afad715
- package: k8s.io/client-go
version: v2.0.0
- package: github.com/gambol99/go-marathon
version: d672c6fbb499596869d95146a26e7d0746c06c54
- package: github.com/ArthurHlt/go-eureka-client
subpackages:
- eureka
- package: github.com/coreos/go-systemd
version: v12
version: v14
subpackages:
- daemon
- package: github.com/google/go-github
- package: github.com/hashicorp/go-version
- 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/sys
version: 8d1157a435470616f975ff9bb013bea8d0962067
- 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/dynamodb
- service/dynamodb/dynamodbiface
- service/dynamodbattribute
- service/ec2
- service/ecs
- package: cloud.google.com/go
version: v0.7.0
subpackages:
- compute/metadata
- package: github.com/gogo/protobuf
version: v0.3
subpackages:
- proto
- package: github.com/rancher/go-rancher
version: 5b8f6cc26b355ba03d7611fce3844155b7baf05b
- package: golang.org/x/oauth2/google
version: 7fdf09982454086d5570c7db3e11f360194830ca
- package: github.com/googleapis/gax-go
version: 9af46dd5a1713e8b5cd71106287eba3cefdde50b
- package: google.golang.org/grpc
version: v1.2.0

139
healthcheck/healthcheck.go Normal file
View File

@@ -0,0 +1,139 @@
package healthcheck
import (
"context"
"fmt"
"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 returns the health check which is guaranteed to be a singleton.
func GetHealthCheck() *HealthCheck {
once.Do(func() {
singleton = newHealthCheck()
})
return singleton
}
// Options are the public health check options.
type Options struct {
Path string
Interval time.Duration
LB LoadBalancer
}
func (opt Options) String() string {
return fmt.Sprintf("[Path: %s Interval: %s]", opt.Path, opt.Interval)
}
// BackendHealthCheck HealthCheck configuration for a backend
type BackendHealthCheck struct {
Options
disabledURLs []*url.URL
requestTimeout time.Duration
}
//HealthCheck struct
type HealthCheck struct {
Backends map[string]*BackendHealthCheck
cancel context.CancelFunc
}
// LoadBalancer includes functionality for load-balancing management.
type LoadBalancer interface {
RemoveServer(u *url.URL) error
UpsertServer(u *url.URL, options ...roundrobin.ServerOption) error
Servers() []*url.URL
}
func newHealthCheck() *HealthCheck {
return &HealthCheck{
Backends: make(map[string]*BackendHealthCheck),
}
}
// NewBackendHealthCheck Instantiate a new BackendHealthCheck
func NewBackendHealthCheck(options Options) *BackendHealthCheck {
return &BackendHealthCheck{
Options: options,
requestTimeout: 5 * time.Second,
}
}
//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
for backendID, backend := range hc.Backends {
currentBackendID := backendID
currentBackend := backend
safe.Go(func() {
hc.execute(ctx, currentBackendID, currentBackend)
})
}
}
func (hc *HealthCheck) execute(ctx context.Context, backendID string, backend *BackendHealthCheck) {
log.Debugf("Initial healthcheck for currentBackend %s ", backendID)
checkBackend(backend)
ticker := time.NewTicker(backend.Interval)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
log.Debugf("Stopping all current Healthcheck goroutines")
return
case <-ticker.C:
log.Debugf("Refreshing healthcheck for currentBackend %s ", backendID)
checkBackend(backend)
}
}
}
func checkBackend(currentBackend *BackendHealthCheck) {
enabledURLs := currentBackend.LB.Servers()
var newDisabledURLs []*url.URL
for _, url := range currentBackend.disabledURLs {
if checkHealth(url, currentBackend) {
log.Debugf("HealthCheck is up [%s]: Upsert in server list", url.String())
currentBackend.LB.UpsertServer(url, roundrobin.Weight(1))
} else {
log.Warnf("HealthCheck is still failing [%s]", url.String())
newDisabledURLs = append(newDisabledURLs, url)
}
}
currentBackend.disabledURLs = newDisabledURLs
for _, url := range enabledURLs {
if !checkHealth(url, currentBackend) {
log.Warnf("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, backend *BackendHealthCheck) bool {
client := http.Client{
Timeout: backend.requestTimeout,
}
resp, err := client.Get(serverURL.String() + backend.Path)
if err == nil {
defer resp.Body.Close()
}
return err == nil && resp.StatusCode == 200
}

View File

@@ -0,0 +1,202 @@
package healthcheck
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"sync"
"testing"
"time"
"github.com/vulcand/oxy/roundrobin"
)
const healthCheckInterval = 100 * time.Millisecond
type testLoadBalancer struct {
// RWMutex needed due to parallel test execution: Both the system-under-test
// and the test assertions reference the counters.
*sync.RWMutex
numRemovedServers int
numUpsertedServers int
servers []*url.URL
}
func (lb *testLoadBalancer) RemoveServer(u *url.URL) error {
lb.Lock()
defer lb.Unlock()
lb.numRemovedServers++
lb.removeServer(u)
return nil
}
func (lb *testLoadBalancer) UpsertServer(u *url.URL, options ...roundrobin.ServerOption) error {
lb.Lock()
defer lb.Unlock()
lb.numUpsertedServers++
lb.servers = append(lb.servers, u)
return nil
}
func (lb *testLoadBalancer) Servers() []*url.URL {
return lb.servers
}
func (lb *testLoadBalancer) removeServer(u *url.URL) {
var i int
var serverURL *url.URL
for i, serverURL = range lb.servers {
if *serverURL == *u {
break
}
}
lb.servers = append(lb.servers[:i], lb.servers[i+1:]...)
}
type testHandler struct {
done func()
healthSequence []bool
}
func newTestServer(done func(), healthSequence []bool) *httptest.Server {
handler := &testHandler{
done: done,
healthSequence: healthSequence,
}
return httptest.NewServer(handler)
}
// ServeHTTP returns 200 or 503 HTTP response codes depending on whether the
// current request is marked as healthy or not.
// It calls the given 'done' function once all request health indicators have
// been depleted.
func (th *testHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if len(th.healthSequence) == 0 {
panic("received unexpected request")
}
healthy := th.healthSequence[0]
if healthy {
w.WriteHeader(http.StatusOK)
} else {
w.WriteHeader(http.StatusServiceUnavailable)
}
th.healthSequence = th.healthSequence[1:]
if len(th.healthSequence) == 0 {
th.done()
}
}
func TestSetBackendsConfiguration(t *testing.T) {
tests := []struct {
desc string
startHealthy bool
healthSequence []bool
wantNumRemovedServers int
wantNumUpsertedServers int
}{
{
desc: "healthy server staying healthy",
startHealthy: true,
healthSequence: []bool{true},
wantNumRemovedServers: 0,
wantNumUpsertedServers: 0,
},
{
desc: "healthy server becoming sick",
startHealthy: true,
healthSequence: []bool{false},
wantNumRemovedServers: 1,
wantNumUpsertedServers: 0,
},
{
desc: "sick server becoming healthy",
startHealthy: false,
healthSequence: []bool{true},
wantNumRemovedServers: 0,
wantNumUpsertedServers: 1,
},
{
desc: "sick server staying sick",
startHealthy: false,
healthSequence: []bool{false},
wantNumRemovedServers: 0,
wantNumUpsertedServers: 0,
},
{
desc: "healthy server toggling to sick and back to healthy",
startHealthy: true,
healthSequence: []bool{false, true},
wantNumRemovedServers: 1,
wantNumUpsertedServers: 1,
},
}
for _, test := range tests {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
// The context is passed to the health check and canonically cancelled by
// the test server once all expected requests have been received.
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
ts := newTestServer(cancel, test.healthSequence)
defer ts.Close()
lb := &testLoadBalancer{RWMutex: &sync.RWMutex{}}
backend := NewBackendHealthCheck(Options{
Path: "/path",
Interval: healthCheckInterval,
LB: lb,
})
serverURL := MustParseURL(ts.URL)
if test.startHealthy {
lb.servers = append(lb.servers, serverURL)
} else {
backend.disabledURLs = append(backend.disabledURLs, serverURL)
}
healthCheck := HealthCheck{
Backends: make(map[string]*BackendHealthCheck),
}
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
healthCheck.execute(ctx, "id", backend)
wg.Done()
}()
// Make test timeout dependent on number of expected requests, health
// check interval, and a safety margin.
timeout := time.Duration(len(test.healthSequence)*int(healthCheckInterval) + 500)
select {
case <-time.After(timeout):
t.Fatal("test did not complete in time")
case <-ctx.Done():
wg.Wait()
}
lb.Lock()
defer lb.Unlock()
if lb.numRemovedServers != test.wantNumRemovedServers {
t.Errorf("got %d removed servers, wanted %d", lb.numRemovedServers, test.wantNumRemovedServers)
}
if lb.numUpsertedServers != test.wantNumUpsertedServers {
t.Errorf("got %d upserted servers, wanted %d", lb.numUpsertedServers, test.wantNumUpsertedServers)
}
})
}
}
func MustParseURL(rawurl string) *url.URL {
u, err := url.Parse(rawurl)
if err != nil {
panic(fmt.Sprintf("failed to parse URL '%s': %s", rawurl, err))
}
return u
}

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

@@ -26,7 +26,7 @@ func (s *SimpleSuite) TestInvalidConfigShouldFail(c *check.C) {
defer cmd.Process.Kill()
output := b.Bytes()
c.Assert(string(output), checker.Contains, "Near line 0 (last key parsed ''): Bare keys cannot contain '{'")
c.Assert(string(output), checker.Contains, "Near line 0 (last key parsed ''): bare keys cannot contain '{'")
}
func (s *SimpleSuite) TestSimpleDefaultConfig(c *check.C) {
@@ -70,7 +70,7 @@ func (s *SimpleSuite) TestDefaultEntryPoints(c *check.C) {
defer cmd.Process.Kill()
output := b.Bytes()
c.Assert(string(output), checker.Contains, "\\\"DefaultEntryPoints\\\":[\\\"http\\\"]")
c.Assert(string(output), checker.Contains, "\"DefaultEntryPoints\":[\"http\"]")
}
func (s *SimpleSuite) TestPrintHelp(c *check.C) {

View File

@@ -1,26 +1,25 @@
package main
import (
"context"
"errors"
"io/ioutil"
"net/http"
"os"
"os/exec"
"strings"
"sync"
"time"
"github.com/containous/staert"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/integration/utils"
"github.com/containous/traefik/provider"
"github.com/docker/libkv"
"github.com/docker/libkv/store"
"github.com/docker/libkv/store/consul"
"github.com/go-check/check"
"golang.org/x/net/context"
"errors"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/integration/utils"
"github.com/containous/traefik/provider"
checker "github.com/vdemeester/shakers"
"io/ioutil"
"os"
"strings"
"sync"
)
// Consul test suites (using libcompose)

View File

@@ -110,7 +110,7 @@ func (s *DockerSuite) TestDefaultDockerContainers(c *check.C) {
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", name)
req.Host = fmt.Sprintf("%s.docker.localhost", strings.Replace(name, "_", "-", -1))
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)

View File

@@ -0,0 +1,181 @@
package main
import (
"errors"
"io/ioutil"
"net/http"
"os"
"os/exec"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
"github.com/containous/traefik/integration/utils"
"github.com/containous/traefik/types"
"github.com/go-check/check"
checker "github.com/vdemeester/shakers"
)
type DynamoDBSuite struct {
BaseSuite
}
type DynamoDBItem struct {
ID string `dynamodbav:"id"`
Name string `dynamodbav:"name"`
}
type DynamoDBBackendItem struct {
DynamoDBItem
Backend types.Backend `dynamodbav:"backend"`
}
type DynamoDBFrontendItem struct {
DynamoDBItem
Frontend types.Frontend `dynamodbav:"frontend"`
}
func (s *DynamoDBSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "dynamodb")
s.composeProject.Start(c)
dynamoURL := "http://" + s.composeProject.Container(c, "dynamo").NetworkSettings.IPAddress + ":8000"
config := &aws.Config{
Region: aws.String("us-east-1"),
Credentials: credentials.NewStaticCredentials("id", "secret", ""),
Endpoint: aws.String(dynamoURL),
}
var sess *session.Session
err := utils.Try(60*time.Second, func() error {
_, err := session.NewSession(config)
if err != nil {
return err
}
sess = session.New(config)
return nil
})
svc := dynamodb.New(sess)
// create dynamodb table
params := &dynamodb.CreateTableInput{
AttributeDefinitions: []*dynamodb.AttributeDefinition{
{
AttributeName: aws.String("id"),
AttributeType: aws.String("S"),
},
},
KeySchema: []*dynamodb.KeySchemaElement{
{
AttributeName: aws.String("id"),
KeyType: aws.String("HASH"),
},
},
ProvisionedThroughput: &dynamodb.ProvisionedThroughput{
ReadCapacityUnits: aws.Int64(1),
WriteCapacityUnits: aws.Int64(1),
},
TableName: aws.String("traefik"),
}
_, err = svc.CreateTable(params)
if err != nil {
c.Error(err)
return
}
// load config into dynamodb
whoami1 := "http://" + s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80"
whoami2 := "http://" + s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress + ":80"
whoami3 := "http://" + s.composeProject.Container(c, "whoami3").NetworkSettings.IPAddress + ":80"
backend := DynamoDBBackendItem{
Backend: types.Backend{
Servers: map[string]types.Server{
"whoami1": {
URL: whoami1,
},
"whoami2": {
URL: whoami2,
},
"whoami3": {
URL: whoami3,
},
},
},
DynamoDBItem: DynamoDBItem{
ID: "whoami_backend",
Name: "whoami",
},
}
frontend := DynamoDBFrontendItem{
Frontend: types.Frontend{
EntryPoints: []string{
"http",
},
Backend: "whoami",
Routes: map[string]types.Route{
"hostRule": {
Rule: "Host:test.traefik.io",
},
},
},
DynamoDBItem: DynamoDBItem{
ID: "whoami_frontend",
Name: "whoami",
},
}
backendAttributeValue, err := dynamodbattribute.MarshalMap(backend)
c.Assert(err, checker.IsNil)
frontendAttributeValue, err := dynamodbattribute.MarshalMap(frontend)
c.Assert(err, checker.IsNil)
putParams := &dynamodb.PutItemInput{
Item: backendAttributeValue,
TableName: aws.String("traefik"),
}
_, err = svc.PutItem(putParams)
c.Assert(err, checker.IsNil)
putParams = &dynamodb.PutItemInput{
Item: frontendAttributeValue,
TableName: aws.String("traefik"),
}
_, err = svc.PutItem(putParams)
c.Assert(err, checker.IsNil)
}
func (s *DynamoDBSuite) TestSimpleConfiguration(c *check.C) {
dynamoURL := "http://" + s.composeProject.Container(c, "dynamo").NetworkSettings.IPAddress + ":8000"
file := s.adaptFile(c, "fixtures/dynamodb/simple.toml", struct{ DynamoURL string }{dynamoURL})
defer os.Remove(file)
cmd := exec.Command(traefikBinary, "--configFile="+file)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
err = utils.TryRequest("http://127.0.0.1:8081/api/providers", 120*time.Second, func(res *http.Response) error {
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
if !strings.Contains(string(body), "Host:test.traefik.io") {
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:8080", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.traefik.io"
response, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(response.StatusCode, checker.Equals, 200)
}
func (s *DynamoDBSuite) TearDownSuite(c *check.C) {
if s.composeProject != nil {
s.composeProject.Stop(c)
}
}

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

@@ -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

@@ -0,0 +1,16 @@
defaultEntryPoints = ["http"]
logLevel = "DEBUG"
[entryPoints]
[entryPoints.http]
address = ":8080"
[dynamodb]
AccessKeyID = "key"
SecretAccessKey = "secret"
Endpoint = "{{.DynamoURL}}"
Region = "us-east-1"
[web]
address = ":8081"

View File

@@ -0,0 +1,14 @@
defaultEntryPoints = ["http"]
logLevel = "DEBUG"
[entryPoints]
[entryPoints.http]
address = ":8000"
[eureka]
endpoint = "http://{{.EurekaHost}}:8761/eureka"
delay = "1s"
[web]
address = ":8080"

View File

@@ -0,0 +1,27 @@
defaultEntryPoints = ["http"]
logLevel = "DEBUG"
[entryPoints]
[entryPoints.http]
address = ":8000"
[web]
address = ":8080"
[file]
[backends]
[backends.backend1]
[backends.backend1.healthcheck]
path = "/health"
interval = "1s"
[backends.backend1.servers.server1]
url = "http://{{.Server1}}:80"
[backends.backend1.servers.server2]
url = "http://{{.Server2}}:80"
[frontends]
[frontends.frontend1]
backend = "backend1"
[frontends.frontend1.routes.test_1]
rule = "Host:test.localhost"

295
integration/glide.lock generated Normal file
View File

@@ -0,0 +1,295 @@
hash: c53f57a45247b08a91f127ece494d49f1b7fee8c5f75be87ab12e27aa92d065f
updated: 2016-11-17T16:23:56.727970904Z
imports:
- name: github.com/cenk/backoff
version: 8edc80b07f38c27352fb186d971c628a6c32552b
testImports:
- name: github.com/ArthurHlt/go-eureka-client
version: ba361cd0f9f571b4e871421423d2f02f5689c3d2
subpackages:
- eureka
- name: github.com/ArthurHlt/gominlog
version: 068c01ce147ad68fca25ef3fa29ae5395ae273ab
- name: github.com/Azure/go-ansiterm
version: fa152c58bc15761d0200cb75fe958b89a9d4888e
subpackages:
- winterm
- name: github.com/boltdb/bolt
version: f4c032d907f61f08dba2d719c58f108a1abb8e81
- name: github.com/BurntSushi/toml
version: 99064174e013895bbd9b025c31100bd1d9b590ca
- name: github.com/BurntSushi/ty
version: 6add9cd6ad42d389d6ead1dde60b4ad71e46fd74
subpackages:
- fun
- name: github.com/cloudfoundry-incubator/candiedyaml
version: 99c3df83b51532e3615f851d8c2dbb638f5313bf
- name: github.com/containous/flaeg
version: a731c034dda967333efce5f8d276aeff11f8ff87
- name: github.com/containous/staert
version: 92329254783dc01174f03302d51d7cf2c9ff84cf
- name: github.com/containous/traefik
version: 15732269da23c35524bf7cabea5857e4c5f63881
subpackages:
- autogen
- cluster
- job
- log
- provider
- provider/k8s
- safe
- types
- version
- 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/daviddengcn/go-colortext
version: 3b18c8575a432453d41fdafb340099fff5bba2f7
- name: github.com/docker/distribution
version: 99cb7c0946d2f5a38015443e515dc916295064d7
subpackages:
- context
- digest
- reference
- registry/api/errcode
- registry/api/v2
- registry/client
- registry/client/auth
- registry/client/transport
- registry/storage/cache
- registry/storage/cache/memory
- uuid
- name: github.com/docker/docker
version: 534753663161334baba06f13b8efa4cad22b5bc5
subpackages:
- api/types/backend
- builder
- builder/dockerignore
- cliconfig
- cliconfig/configfile
- daemon/graphdriver
- image
- image/v1
- layer
- opts
- pkg/archive
- pkg/chrootarchive
- pkg/fileutils
- pkg/gitutils
- pkg/homedir
- pkg/httputils
- pkg/idtools
- pkg/ioutils
- pkg/jsonlog
- pkg/jsonmessage
- pkg/longpath
- pkg/mflag
- pkg/mount
- pkg/namesgenerator
- 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
- reference
- registry
- runconfig/opts
- name: github.com/docker/engine-api
version: 62043eb79d581a32ea849645277023c550732e52
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: 988efe982fdecb46f01d53465878ff1f2ff411ce
subpackages:
- nat
- sockets
- tlsconfig
- name: github.com/docker/go-units
version: f2145db703495b2e525c59662db69a7344b00bb8
- name: github.com/docker/leadership
version: 0a913e2d71a12fd14a028452435cb71ac8d82cb6
- 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/docker/libkv
version: 3fce6a0f26e07da3eac45796a8e255547a47a750
subpackages:
- store
- store/boltdb
- store/consul
- store/etcd
- store/zookeeper
- name: github.com/donovanhide/eventsource
version: fd1de70867126402be23c306e1ce32828455d85b
- name: github.com/flynn/go-shlex
version: 3f9db97f856818214da2e1057f8ad84803971cff
- name: github.com/gambol99/go-marathon
version: a558128c87724cd7430060ef5aedf39f83937f55
- name: github.com/go-check/check
version: 11d3bc7aa68e238947792f30573146a3231fc0f1
- name: github.com/gogo/protobuf
version: 43ab7f0ec7b6d072e0368bd537ffefe74ed30198
subpackages:
- proto
- name: github.com/golang/glog
version: fca8c8854093a154ff1eb580aae10276ad6b1b5f
- name: github.com/google/go-querystring
version: 9235644dd9e52eeae6fa48efd539fdc351a0af53
subpackages:
- query
- name: github.com/gorilla/context
version: 14f550f51af52180c2eefed15e5fd18d63c0a64a
- name: github.com/gorilla/mux
version: e444e69cbd2e2e3e0749a2f3c717cec491552bbf
- name: github.com/hashicorp/consul
version: d8e2fb7dd594163e25a89bc52c1a4613f5c5bfb8
subpackages:
- api
- name: github.com/hashicorp/go-cleanhttp
version: ad28ea4487f05916463e2423a55166280e8254b5
- name: github.com/hashicorp/serf
version: 598c54895cc5a7b1a24a398d635e8c0ea0959870
subpackages:
- coordinate
- 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/mattn/go-shellwords
version: 525bedee691b5a8df547cb5cf9f86b7fb1883e24
- name: github.com/mesos/mesos-go
version: 068d5470506e3780189fe607af40892814197c5e
subpackages:
- detector
- detector/zoo
- 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: 5d001d020961ae1c184f9f8152fdc73810481677
- name: github.com/mitchellh/mapstructure
version: ca63d7c062ee3c9f34db231e352b60012b4fd0c1
- name: github.com/moul/http2curl
version: b1479103caacaa39319f75e7f57fc545287fca0d
- name: github.com/ogier/pflag
version: 45c278ab3607870051a2ea9040bb85fcb8557481
- name: github.com/opencontainers/runc
version: ba1568de399395774ad84c2ace65937814c542ed
subpackages:
- libcontainer/user
- name: github.com/parnurzeal/gorequest
version: e30af16d4e485943aab0b0885ad6bdbb8c0d3dc7
- name: github.com/ryanuber/go-glob
version: 572520ed46dbddaed19ea3d9541bdd0494163693
- name: github.com/samuel/go-zookeeper
version: 87e1bca4477a3cc767ca71be023ced183d74e538
subpackages:
- zk
- name: github.com/satori/go.uuid
version: 879c5887cd475cd7864858769793b2ceb0d44feb
- name: github.com/Sirupsen/logrus
version: 3ec0642a7fb6488f65b06f9040adc67e3990296a
- name: github.com/spf13/pflag
version: 5644820622454e71517561946e3d94b9f9db6842
- name: github.com/stretchr/objx
version: cbeaeb16a013161a98496fad62933b1d21786672
- name: github.com/stretchr/testify
version: b8dc1cecf15bdaf1988d9e87aa7cd98d899a06d6
subpackages:
- assert
- mock
- name: github.com/tv42/zbase32
version: 03389da7e0bf9844767f82690f4d68fc097a1306
- name: github.com/vbatts/tar-split
version: bd4c5d64c3e9297f410025a3b1bd0c58f659e721
subpackages:
- archive/tar
- tar/asm
- tar/storage
- name: github.com/vdemeester/docker-events
version: be74d4929ec1ad118df54349fda4b0cba60f849b
- 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/net
version: db8e4de5b2d6653f66aea53094624468caad15d2
subpackages:
- context
- proxy
- publicsuffix
- name: golang.org/x/sys
version: 9c60d1c508f5134d1ca726b4641db998f2523357
subpackages:
- unix
- windows
- name: gopkg.in/fsnotify.v1
version: 944cff21b3baf3ced9a880365682152ba577d348

33
integration/glide.yaml Normal file
View File

@@ -0,0 +1,33 @@
package: github.com/containous/traefik/integration
import:
- package: github.com/cenk/backoff
testImport:
- package: github.com/containous/staert
version: 92329254783dc01174f03302d51d7cf2c9ff84cf
- package: github.com/docker/docker
version: 534753663161334baba06f13b8efa4cad22b5bc5
subpackages:
- pkg/namesgenerator
- package: github.com/docker/libkv
subpackages:
- store
- store/consul
- store/etcd
- package: github.com/go-check/check
- package: github.com/hashicorp/consul
subpackages:
- api
- package: github.com/libkermit/compose
version: cadc5a3b83a15790174bd7fbc75ea2529785e772
subpackages:
- check
- package: github.com/libkermit/docker
version: 55e3595409924fcfbb850811e5a7cdbe8960a0b7
- package: github.com/libkermit/docker-check
- package: github.com/mattn/go-shellwords
- package: github.com/vdemeester/shakers
- package: golang.org/x/net
subpackages:
- context
- package: github.com/spf13/pflag
version: 5644820622454e71517561946e3d94b9f9db6842

View File

@@ -0,0 +1,91 @@
package main
import (
"bytes"
"errors"
"io/ioutil"
"net/http"
"os"
"os/exec"
"strings"
"time"
"github.com/containous/traefik/integration/utils"
"github.com/go-check/check"
checker "github.com/vdemeester/shakers"
)
// HealthCheck test suites (using libcompose)
type HealthCheckSuite struct{ BaseSuite }
func (s *HealthCheckSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "healthcheck")
s.composeProject.Start(c)
}
func (s *HealthCheckSuite) TestSimpleConfiguration(c *check.C) {
whoami1Host := s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress
whoami2Host := s.composeProject.Container(c, "whoami2").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/healthcheck/simple.toml", struct {
Server1 string
Server2 string
}{whoami1Host, whoami2Host})
defer os.Remove(file)
cmd := exec.Command(traefikBinary, "--configFile="+file)
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:test.localhost") {
return errors.New("Incorrect traefik config: " + string(body))
}
return nil
})
c.Assert(err, checker.IsNil)
client := &http.Client{}
req, err := http.NewRequest("GET", "http://127.0.0.1:8000/health", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.localhost"
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 200)
resp, err = client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 200)
healthReq, err := http.NewRequest("POST", "http://"+whoami1Host+"/health", bytes.NewBuffer([]byte("500")))
c.Assert(err, checker.IsNil)
_, err = client.Do(healthReq)
c.Assert(err, checker.IsNil)
time.Sleep(time.Second * 3)
resp, err = client.Do(req)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, 200)
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

@@ -4,6 +4,7 @@ package main
import (
"fmt"
"io/ioutil"
"net"
"os"
"os/exec"
"path/filepath"
@@ -26,6 +27,7 @@ func init() {
check.Suite(&AccessLogSuite{})
check.Suite(&HTTPSSuite{})
check.Suite(&FileSuite{})
check.Suite(&HealthCheckSuite{})
check.Suite(&DockerSuite{})
check.Suite(&ConsulSuite{})
check.Suite(&ConsulCatalogSuite{})
@@ -33,6 +35,9 @@ func init() {
check.Suite(&MarathonSuite{})
check.Suite(&ConstraintSuite{})
check.Suite(&MesosSuite{})
check.Suite(&EurekaSuite{})
check.Suite(&AcmeSuite{})
check.Suite(&DynamoDBSuite{})
}
var traefikBinary = "../dist/traefik"
@@ -51,6 +56,18 @@ func (s *BaseSuite) TearDownSuite(c *check.C) {
func (s *BaseSuite) createComposeProject(c *check.C, name string) {
projectName := fmt.Sprintf("integration-test-%s", name)
composeFile := fmt.Sprintf("resources/compose/%s.yml", name)
addrs, err := net.InterfaceAddrs()
c.Assert(err, checker.IsNil)
for _, addr := range addrs {
ip, _, err := net.ParseCIDR(addr.String())
c.Assert(err, checker.IsNil)
if !ip.IsLoopback() && ip.To4() != nil {
os.Setenv("DOCKER_HOST_IP", ip.String())
break
}
}
s.composeProject = compose.CreateProject(c, projectName, composeFile)
}

View File

@@ -0,0 +1,44 @@
boulder:
image: containous/boulder:release
environment:
FAKE_DNS: ${DOCKER_HOST_IP}
PKCS11_PROXY_SOCKET: tcp://boulder-hsm:5657
extra_hosts:
- le.wtf:127.0.0.1
- boulder:127.0.0.1
ports:
- 4000:4000 # ACME
- 4002:4002 # OCSP
- 4003:4003 # OCSP
- 4500:4500 # ct-test-srv
- 8000:8000 # debug ports
- 8001:8001
- 8002:8002
- 8003:8003
- 8004:8004
- 8055:8055 # dns-test-srv updates
- 9380:9380 # mail-test-srv
- 9381:9381 # mail-test-srv
links:
- bhsm:boulder-hsm
- bmysql:boulder-mysql
- brabbitmq:boulder-rabbitmq
bhsm:
# To minimize the fetching of various layers this should match
# the FROM image and tag in boulder/Dockerfile
image: letsencrypt/boulder-tools:2016-11-02
environment:
PKCS11_DAEMON_SOCKET: tcp://0.0.0.0:5657
command: /usr/local/bin/pkcs11-daemon /usr/lib/softhsm/libsofthsm.so
expose:
- 5657
bmysql:
image: mariadb:10.1
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
log_driver: none
brabbitmq:
image: rabbitmq:3-alpine
environment:
RABBITMQ_NODE_IP_ADDRESS: "0.0.0.0"

View File

@@ -12,6 +12,6 @@ consul:
- "8302"
- "8302/udp"
nginx:
image: nginx
image: nginx:alpine
ports:
- "8881:80"

View File

@@ -12,6 +12,6 @@ consul:
- "8302"
- "8302/udp"
nginx:
image: nginx
image: nginx:alpine
ports:
- "8881:80"

View File

@@ -0,0 +1,16 @@
dynamo:
image: deangiberson/aws-dynamodb-local
command: -sharedDb
ports:
- "8000:8000"
expose:
- "8000"
whoami1:
image: emilevauge/whoami
whoami2:
image: emilevauge/whoami
whoami3:
image: emilevauge/whoami

View File

@@ -0,0 +1,5 @@
eureka:
image: springcloud/eureka
whoami1:
image: emilevauge/whoami

View File

@@ -1,20 +1,20 @@
nginx1:
image: nginx
image: nginx:alpine
ports:
- "8881:80"
nginx2:
image: nginx
image: nginx:alpine
ports:
- "8882:80"
nginx3:
image: nginx
image: nginx:alpine
ports:
- "8883:80"
nginx4:
image: nginx
image: nginx:alpine
ports:
- "8884:80"
nginx5:
image: nginx
image: nginx:alpine
ports:
- "8885:80"

View File

@@ -0,0 +1,5 @@
whoami1:
image: emilevauge/whoami
whoami2:
image: emilevauge/whoami

View File

@@ -0,0 +1,357 @@
package eureka
import (
"crypto/tls"
"crypto/x509"
"encoding/json"
"errors"
"io"
"io/ioutil"
"net"
"net/http"
"net/url"
"os"
"path"
"time"
"strings"
)
const (
defaultBufferSize = 10
UP = "UP"
DOWN = "DOWN"
STARTING = "STARTING"
)
type Config struct {
CertFile string `json:"certFile"`
KeyFile string `json:"keyFile"`
CaCertFile []string `json:"caCertFiles"`
DialTimeout time.Duration `json:"timeout"`
Consistency string `json:"consistency"`
}
type Client struct {
Config Config `json:"config"`
Cluster *Cluster `json:"cluster"`
httpClient *http.Client
persistence io.Writer
cURLch chan string
// CheckRetry can be used to control the policy for failed requests
// and modify the cluster if needed.
// The client calls it before sending requests again, and
// stops retrying if CheckRetry returns some error. The cases that
// this function needs to handle include no response and unexpected
// http status code of response.
// If CheckRetry is nil, client will call the default one
// `DefaultCheckRetry`.
// Argument cluster is the eureka.Cluster object that these requests have been made on.
// Argument numReqs is the number of http.Requests that have been made so far.
// Argument lastResp is the http.Responses from the last request.
// Argument err is the reason of the failure.
CheckRetry func(cluster *Cluster, numReqs int,
lastResp http.Response, err error) error
}
// NewClient create a basic client that is configured to be used
// with the given machine list.
func NewClient(machines []string) *Client {
config := Config{
// default timeout is one second
DialTimeout: time.Second,
}
client := &Client{
Cluster: NewCluster(machines),
Config: config,
}
client.initHTTPClient()
return client
}
// NewTLSClient create a basic client with TLS configuration
func NewTLSClient(machines []string, cert string, key string, caCerts []string) (*Client, error) {
// overwrite the default machine to use https
if len(machines) == 0 {
machines = []string{"https://127.0.0.1:4001"}
}
config := Config{
// default timeout is one second
DialTimeout: time.Second,
CertFile: cert,
KeyFile: key,
CaCertFile: make([]string, 0),
}
client := &Client{
Cluster: NewCluster(machines),
Config: config,
}
err := client.initHTTPSClient(cert, key)
if err != nil {
return nil, err
}
for _, caCert := range caCerts {
if err := client.AddRootCA(caCert); err != nil {
return nil, err
}
}
return client, nil
}
// NewClientFromFile creates a client from a given file path.
// The given file is expected to use the JSON format.
func NewClientFromFile(fpath string) (*Client, error) {
fi, err := os.Open(fpath)
if err != nil {
return nil, err
}
defer func() {
if err := fi.Close(); err != nil {
panic(err)
}
}()
return NewClientFromReader(fi)
}
// NewClientFromReader creates a Client configured from a given reader.
// The configuration is expected to use the JSON format.
func NewClientFromReader(reader io.Reader) (*Client, error) {
c := new(Client)
b, err := ioutil.ReadAll(reader)
if err != nil {
return nil, err
}
err = json.Unmarshal(b, c)
if err != nil {
return nil, err
}
if c.Config.CertFile == "" {
c.initHTTPClient()
} else {
err = c.initHTTPSClient(c.Config.CertFile, c.Config.KeyFile)
}
if err != nil {
return nil, err
}
for _, caCert := range c.Config.CaCertFile {
if err := c.AddRootCA(caCert); err != nil {
return nil, err
}
}
return c, nil
}
// Override the Client's HTTP Transport object
func (c *Client) SetTransport(tr *http.Transport) {
c.httpClient.Transport = tr
}
// initHTTPClient initializes a HTTP client for eureka client
func (c *Client) initHTTPClient() {
tr := &http.Transport{
Dial: c.dial,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
c.httpClient = &http.Client{Transport: tr}
}
// initHTTPClient initializes a HTTPS client for eureka client
func (c *Client) initHTTPSClient(cert, key string) error {
if cert == "" || key == "" {
return errors.New("Require both cert and key path")
}
tlsCert, err := tls.LoadX509KeyPair(cert, key)
if err != nil {
return err
}
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{tlsCert},
InsecureSkipVerify: true,
}
tr := &http.Transport{
TLSClientConfig: tlsConfig,
Dial: c.dial,
}
c.httpClient = &http.Client{Transport: tr}
return nil
}
// Sets the DialTimeout value
func (c *Client) SetDialTimeout(d time.Duration) {
c.Config.DialTimeout = d
}
// AddRootCA adds a root CA cert for the eureka client
func (c *Client) AddRootCA(caCert string) error {
if c.httpClient == nil {
return errors.New("Client has not been initialized yet!")
}
certBytes, err := ioutil.ReadFile(caCert)
if err != nil {
return err
}
tr, ok := c.httpClient.Transport.(*http.Transport)
if !ok {
panic("AddRootCA(): Transport type assert should not fail")
}
if tr.TLSClientConfig.RootCAs == nil {
caCertPool := x509.NewCertPool()
ok = caCertPool.AppendCertsFromPEM(certBytes)
if ok {
tr.TLSClientConfig.RootCAs = caCertPool
}
tr.TLSClientConfig.InsecureSkipVerify = false
} else {
ok = tr.TLSClientConfig.RootCAs.AppendCertsFromPEM(certBytes)
}
if !ok {
err = errors.New("Unable to load caCert")
}
c.Config.CaCertFile = append(c.Config.CaCertFile, caCert)
return err
}
// SetCluster updates cluster information using the given machine list.
func (c *Client) SetCluster(machines []string) bool {
success := c.internalSyncCluster(machines)
return success
}
func (c *Client) GetCluster() []string {
return c.Cluster.Machines
}
// SyncCluster updates the cluster information using the internal machine list.
func (c *Client) SyncCluster() bool {
return c.internalSyncCluster(c.Cluster.Machines)
}
// internalSyncCluster syncs cluster information using the given machine list.
func (c *Client) internalSyncCluster(machines []string) bool {
for _, machine := range machines {
httpPath := c.createHttpPath(machine, "machines")
resp, err := c.httpClient.Get(httpPath)
if err != nil {
// try another machine in the cluster
continue
} else {
b, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
// try another machine in the cluster
continue
}
// update Machines List
c.Cluster.updateFromStr(string(b))
// update leader
// the first one in the machine list is the leader
c.Cluster.switchLeader(0)
logger.Debug("sync.machines " + strings.Join(c.Cluster.Machines, ", "))
return true
}
}
return false
}
// createHttpPath creates a complete HTTP URL.
// serverName should contain both the host name and a port number, if any.
func (c *Client) createHttpPath(serverName string, _path string) string {
u, err := url.Parse(serverName)
if err != nil {
panic(err)
}
u.Path = path.Join(u.Path, _path)
if u.Scheme == "" {
u.Scheme = "http"
}
return u.String()
}
// dial attempts to open a TCP connection to the provided address, explicitly
// enabling keep-alives with a one-second interval.
func (c *Client) dial(network, addr string) (net.Conn, error) {
conn, err := net.DialTimeout(network, addr, c.Config.DialTimeout)
if err != nil {
return nil, err
}
tcpConn, ok := conn.(*net.TCPConn)
if !ok {
return nil, errors.New("Failed type-assertion of net.Conn as *net.TCPConn")
}
// Keep TCP alive to check whether or not the remote machine is down
if err = tcpConn.SetKeepAlive(true); err != nil {
return nil, err
}
if err = tcpConn.SetKeepAlivePeriod(time.Second); err != nil {
return nil, err
}
return tcpConn, nil
}
// MarshalJSON implements the Marshaller interface
// as defined by the standard JSON package.
func (c *Client) MarshalJSON() ([]byte, error) {
b, err := json.Marshal(struct {
Config Config `json:"config"`
Cluster *Cluster `json:"cluster"`
}{
Config: c.Config,
Cluster: c.Cluster,
})
if err != nil {
return nil, err
}
return b, nil
}
// UnmarshalJSON implements the Unmarshaller interface
// as defined by the standard JSON package.
func (c *Client) UnmarshalJSON(b []byte) error {
temp := struct {
Config Config `json:"config"`
Cluster *Cluster `json:"cluster"`
}{}
err := json.Unmarshal(b, &temp)
if err != nil {
return err
}
c.Cluster = temp.Cluster
c.Config = temp.Config
return nil
}

View File

@@ -0,0 +1,51 @@
package eureka
import (
"net/url"
"strings"
)
type Cluster struct {
Leader string `json:"leader"`
Machines []string `json:"machines"`
}
func NewCluster(machines []string) *Cluster {
// if an empty slice was sent in then just assume HTTP 4001 on localhost
if len(machines) == 0 {
machines = []string{"http://127.0.0.1:4001"}
}
// default leader and machines
return &Cluster{
Leader: machines[0],
Machines: machines,
}
}
// switchLeader switch the current leader to machines[num]
func (cl *Cluster) switchLeader(num int) {
logger.Debug("switch.leader[from %v to %v]",
cl.Leader, cl.Machines[num])
cl.Leader = cl.Machines[num]
}
func (cl *Cluster) updateFromStr(machines string) {
cl.Machines = strings.Split(machines, ", ")
}
func (cl *Cluster) updateLeader(leader string) {
logger.Debug("update.leader[%s,%s]", cl.Leader, leader)
cl.Leader = leader
}
func (cl *Cluster) updateLeaderFromURL(u *url.URL) {
var leader string
if u.Scheme == "" {
leader = "http://" + u.Host
} else {
leader = u.Scheme + "://" + u.Host
}
cl.updateLeader(leader)
}

View File

@@ -0,0 +1,21 @@
package eureka
import (
"github.com/ArthurHlt/gominlog"
"log"
)
var logger *gominlog.MinLog
func GetLogger() *log.Logger {
return logger.GetLogger()
}
func SetLogger(loggerLog *log.Logger) {
logger.SetLogger(loggerLog)
}
func init() {
// Default logger uses the go default log.
logger = gominlog.NewClassicMinLogWithPackageName("go-eureka-client")
}

View File

@@ -0,0 +1,10 @@
package eureka
import "strings"
func (c *Client) UnregisterInstance(appId, instanceId string) error {
values := []string{"apps", appId, instanceId}
path := strings.Join(values, "/")
_, err := c.Delete(path)
return err
}

View File

@@ -0,0 +1,48 @@
package eureka
import (
"encoding/json"
"fmt"
)
const (
ErrCodeEurekaNotReachable = 501
)
var (
errorMap = map[int]string{
ErrCodeEurekaNotReachable: "All the given peers are not reachable",
}
)
type EurekaError struct {
ErrorCode int `json:"errorCode"`
Message string `json:"message"`
Cause string `json:"cause,omitempty"`
Index uint64 `json:"index"`
}
func (e EurekaError) Error() string {
return fmt.Sprintf("%v: %v (%v) [%v]", e.ErrorCode, e.Message, e.Cause, e.Index)
}
func newError(errorCode int, cause string, index uint64) *EurekaError {
return &EurekaError{
ErrorCode: errorCode,
Message: errorMap[errorCode],
Cause: cause,
Index: index,
}
}
func handleError(b []byte) error {
eurekaErr := new(EurekaError)
err := json.Unmarshal(b, eurekaErr)
if err != nil {
logger.Warning("cannot unmarshal eureka error: %v", err)
return err
}
return eurekaErr
}

View File

@@ -0,0 +1,38 @@
package eureka
import (
"encoding/xml"
"strings"
)
func (c *Client) GetApplications() (*Applications, error) {
response, err := c.Get("apps");
if err != nil {
return nil, err
}
var applications *Applications = new(Applications)
err = xml.Unmarshal(response.Body, applications)
return applications, err
}
func (c *Client) GetApplication(appId string) (*Application, error) {
values := []string{"apps", appId}
path := strings.Join(values, "/")
response, err := c.Get(path);
if err != nil {
return nil, err
}
var application *Application = new(Application)
err = xml.Unmarshal(response.Body, application)
return application, err
}
func (c *Client) GetInstance(appId, instanceId string) (*InstanceInfo, error) {
values := []string{"apps", appId, instanceId}
path := strings.Join(values, "/")
response, err := c.Get(path);
if err != nil {
return nil, err
}
var instance *InstanceInfo = new(InstanceInfo)
err = xml.Unmarshal(response.Body, instance)
return instance, err
}

View File

@@ -0,0 +1,95 @@
package eureka
import (
"encoding/xml"
"encoding/json"
"regexp"
)
type MetaData struct {
Map map[string]string
Class string
}
type Vraw struct {
Content []byte `xml:",innerxml"`
Class string `xml:"class,attr" json:"@class"`
}
func (s *MetaData) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
var attributes []xml.Attr = make([]xml.Attr, 0)
if s.Class != "" {
attributes = append(attributes, xml.Attr{
Name: xml.Name{
Local: "class",
},
Value: s.Class,
})
}
start.Attr = attributes
tokens := []xml.Token{start}
for key, value := range s.Map {
t := xml.StartElement{Name: xml.Name{"", key}}
tokens = append(tokens, t, xml.CharData(value), xml.EndElement{t.Name})
}
tokens = append(tokens, xml.EndElement{
Name: start.Name,
})
for _, t := range tokens {
err := e.EncodeToken(t)
if err != nil {
return err
}
}
// flush to ensure tokens are written
err := e.Flush()
if err != nil {
return err
}
return nil
}
func (s *MetaData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
s.Map = make(map[string]string)
vraw := &Vraw{}
d.DecodeElement(vraw, &start)
dataInString := string(vraw.Content)
regex, err := regexp.Compile("\\s*<([^<>]+)>([^<>]+)</[^<>]+>\\s*")
if err != nil {
return err
}
subMatches := regex.FindAllStringSubmatch(dataInString, -1)
for _, subMatch := range subMatches {
s.Map[subMatch[1]] = subMatch[2]
}
s.Class = vraw.Class
return nil
}
func (s *MetaData) MarshalJSON() ([]byte, error) {
mapIt := make(map[string]string)
for key, value := range s.Map {
mapIt[key] = value
}
if s.Class != "" {
mapIt["@class"] = s.Class
}
return json.Marshal(mapIt)
}
func (s *MetaData) UnmarshalJSON(data []byte) error {
dataUnmarshal := make(map[string]string)
err := json.Unmarshal(data, dataUnmarshal)
s.Map = dataUnmarshal
if val, ok := s.Map["@class"]; ok {
s.Class = val
delete(s.Map, "@class")
}
return err
}

View File

@@ -0,0 +1,21 @@
package eureka
import (
"encoding/json"
"strings"
)
func (c *Client) RegisterInstance(appId string, instanceInfo *InstanceInfo) error {
values := []string{"apps", appId}
path := strings.Join(values, "/")
instance := &Instance{
Instance: instanceInfo,
}
body, err := json.Marshal(instance)
if err != nil {
return err
}
_, err = c.Post(path, body)
return err
}

View File

@@ -0,0 +1,10 @@
package eureka
import "strings"
func (c *Client) SendHeartbeat(appId, instanceId string) error {
values := []string{"apps", appId, instanceId}
path := strings.Join(values, "/")
_, err := c.Put(path, nil)
return err
}

View File

@@ -0,0 +1,437 @@
package eureka
import (
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
"math/rand"
"net/http"
"net/url"
"sync"
"time"
"strconv"
)
// Errors introduced by handling requests
var (
ErrRequestCancelled = errors.New("sending request is cancelled")
)
type RawRequest struct {
method string
relativePath string
body []byte
cancel <-chan bool
}
type Applications struct {
VersionsDelta int `xml:"versions__delta"`
AppsHashcode string `xml:"apps__hashcode"`
Applications []Application `xml:"application,omitempty"`
}
type Application struct {
Name string `xml:"name"`
Instances []InstanceInfo `xml:"instance"`
}
type Instance struct {
Instance *InstanceInfo `xml:"instance" json:"instance"`
}
type Port struct {
Port int `xml:",chardata" json:"$"`
Enabled bool `xml:"enabled,attr" json:"@enabled"`
}
type InstanceInfo struct {
HostName string `xml:"hostName" json:"hostName"`
HomePageUrl string `xml:"homePageUrl,omitempty" json:"homePageUrl,omitempty"`
StatusPageUrl string `xml:"statusPageUrl" json:"statusPageUrl"`
HealthCheckUrl string `xml:"healthCheckUrl,omitempty" json:"healthCheckUrl,omitempty"`
App string `xml:"app" json:"app"`
IpAddr string `xml:"ipAddr" json:"ipAddr"`
VipAddress string `xml:"vipAddress" json:"vipAddress"`
secureVipAddress string `xml:"secureVipAddress,omitempty" json:"secureVipAddress,omitempty"`
Status string `xml:"status" json:"status"`
Port *Port `xml:"port,omitempty" json:"port,omitempty"`
SecurePort *Port `xml:"securePort,omitempty" json:"securePort,omitempty"`
DataCenterInfo *DataCenterInfo `xml:"dataCenterInfo" json:"dataCenterInfo"`
LeaseInfo *LeaseInfo `xml:"leaseInfo,omitempty" json:"leaseInfo,omitempty"`
Metadata *MetaData `xml:"metadata,omitempty" json:"metadata,omitempty"`
IsCoordinatingDiscoveryServer bool `xml:"isCoordinatingDiscoveryServer,omitempty" json:"isCoordinatingDiscoveryServer,omitempty"`
LastUpdatedTimestamp int `xml:"lastUpdatedTimestamp,omitempty" json:"lastUpdatedTimestamp,omitempty"`
LastDirtyTimestamp int `xml:"lastDirtyTimestamp,omitempty" json:"lastDirtyTimestamp,omitempty"`
ActionType string `xml:"actionType,omitempty" json:"actionType,omitempty"`
Overriddenstatus string `xml:"overriddenstatus,omitempty" json:"overriddenstatus,omitempty"`
CountryId int `xml:"countryId,omitempty" json:"countryId,omitempty"`
}
type DataCenterInfo struct {
Name string `xml:"name" json:"name"`
Class string `xml:"class,attr" json:"@class"`
Metadata DataCenterMetadata `xml:"metadata,omitempty" json:"metadata,omitempty"`
}
type DataCenterMetadata struct {
AmiLaunchIndex string `xml:"ami-launch-index,omitempty" json:"ami-launch-index,omitempty"`
LocalHostname string `xml:"local-hostname,omitempty" json:"local-hostname,omitempty"`
AvailabilityZone string `xml:"availability-zone,omitempty" json:"availability-zone,omitempty"`
InstanceId string `xml:"instance-id,omitempty" json:"instance-id,omitempty"`
PublicIpv4 string `xml:"public-ipv4,omitempty" json:"public-ipv4,omitempty"`
PublicHostname string `xml:"public-hostname,omitempty" json:"public-hostname,omitempty"`
AmiManifestPath string `xml:"ami-manifest-path,omitempty" json:"ami-manifest-path,omitempty"`
LocalIpv4 string `xml:"local-ipv4,omitempty" json:"local-ipv4,omitempty"`
Hostname string `xml:"hostname,omitempty" json:"hostname,omitempty"`
AmiId string `xml:"ami-id,omitempty" json:"ami-id,omitempty"`
InstanceType string `xml:"instance-type,omitempty" json:"instance-type,omitempty"`
}
type LeaseInfo struct {
EvictionDurationInSecs uint `xml:"evictionDurationInSecs,omitempty" json:"evictionDurationInSecs,omitempty"`
RenewalIntervalInSecs int `xml:"renewalIntervalInSecs,omitempty" json:"renewalIntervalInSecs,omitempty"`
DurationInSecs int `xml:"durationInSecs,omitempty" json:"durationInSecs,omitempty"`
RegistrationTimestamp int `xml:"registrationTimestamp,omitempty" json:"registrationTimestamp,omitempty"`
LastRenewalTimestamp int `xml:"lastRenewalTimestamp,omitempty" json:"lastRenewalTimestamp,omitempty"`
EvictionTimestamp int `xml:"evictionTimestamp,omitempty" json:"evictionTimestamp,omitempty"`
ServiceUpTimestamp int `xml:"serviceUpTimestamp,omitempty" json:"serviceUpTimestamp,omitempty"`
}
func NewRawRequest(method, relativePath string, body []byte, cancel <-chan bool) *RawRequest {
return &RawRequest{
method: method,
relativePath: relativePath,
body: body,
cancel: cancel,
}
}
func NewInstanceInfo(hostName, app, ip string, port int, ttl uint, isSsl bool) *InstanceInfo {
dataCenterInfo := &DataCenterInfo{
Name: "MyOwn",
}
leaseInfo := &LeaseInfo{
EvictionDurationInSecs: ttl,
}
instanceInfo := &InstanceInfo{
HostName: hostName,
App: app,
IpAddr: ip,
Status: UP,
DataCenterInfo: dataCenterInfo,
LeaseInfo: leaseInfo,
Metadata: nil,
}
stringPort := ""
if (port != 80 && port != 443) {
stringPort = ":" + strconv.Itoa(port)
}
var protocol string = "http"
if (isSsl) {
protocol = "https"
instanceInfo.secureVipAddress = protocol + "://" + hostName + stringPort
instanceInfo.SecurePort = &Port{
Port: port,
Enabled: true,
}
}else {
instanceInfo.VipAddress = protocol + "://" + hostName + stringPort
instanceInfo.Port = &Port{
Port: port,
Enabled: true,
}
}
instanceInfo.StatusPageUrl = protocol + "://" + hostName + stringPort + "/info"
return instanceInfo
}
// getCancelable issues a cancelable GET request
func (c *Client) getCancelable(endpoint string,
cancel <-chan bool) (*RawResponse, error) {
logger.Debug("get %s [%s]", endpoint, c.Cluster.Leader)
p := endpoint
req := NewRawRequest("GET", p, nil, cancel)
resp, err := c.SendRequest(req)
if err != nil {
return nil, err
}
return resp, nil
}
// get issues a GET request
func (c *Client) Get(endpoint string) (*RawResponse, error) {
return c.getCancelable(endpoint, nil)
}
// put issues a PUT request
func (c *Client) Put(endpoint string, body []byte) (*RawResponse, error) {
logger.Debug("put %s, %s, [%s]", endpoint, body, c.Cluster.Leader)
p := endpoint
req := NewRawRequest("PUT", p, body, nil)
resp, err := c.SendRequest(req)
if err != nil {
return nil, err
}
return resp, nil
}
// post issues a POST request
func (c *Client) Post(endpoint string, body []byte) (*RawResponse, error) {
logger.Debug("post %s, %s, [%s]", endpoint, body, c.Cluster.Leader)
p := endpoint
req := NewRawRequest("POST", p, body, nil)
resp, err := c.SendRequest(req)
if err != nil {
return nil, err
}
return resp, nil
}
// delete issues a DELETE request
func (c *Client) Delete(endpoint string) (*RawResponse, error) {
logger.Debug("delete %s [%s]", endpoint, c.Cluster.Leader)
p := endpoint
req := NewRawRequest("DELETE", p, nil, nil)
resp, err := c.SendRequest(req)
if err != nil {
return nil, err
}
return resp, nil
}
func (c *Client) SendRequest(rr *RawRequest) (*RawResponse, error) {
var req *http.Request
var resp *http.Response
var httpPath string
var err error
var respBody []byte
var numReqs = 1
checkRetry := c.CheckRetry
if checkRetry == nil {
checkRetry = DefaultCheckRetry
}
cancelled := make(chan bool, 1)
reqLock := new(sync.Mutex)
if rr.cancel != nil {
cancelRoutine := make(chan bool)
defer close(cancelRoutine)
go func() {
select {
case <-rr.cancel:
cancelled <- true
logger.Debug("send.request is cancelled")
case <-cancelRoutine:
return
}
// Repeat canceling request until this thread is stopped
// because we have no idea about whether it succeeds.
for {
reqLock.Lock()
c.httpClient.Transport.(*http.Transport).CancelRequest(req)
reqLock.Unlock()
select {
case <-time.After(100 * time.Millisecond):
case <-cancelRoutine:
return
}
}
}()
}
// If we connect to a follower and consistency is required, retry until
// we connect to a leader
sleep := 25 * time.Millisecond
maxSleep := time.Second
for attempt := 0;; attempt++ {
if attempt > 0 {
select {
case <-cancelled:
return nil, ErrRequestCancelled
case <-time.After(sleep):
sleep = sleep * 2
if sleep > maxSleep {
sleep = maxSleep
}
}
}
logger.Debug("Connecting to eureka: attempt %d for %s", attempt + 1, rr.relativePath)
httpPath = c.getHttpPath(false, rr.relativePath)
logger.Debug("send.request.to %s | method %s", httpPath, rr.method)
req, err := func() (*http.Request, error) {
reqLock.Lock()
defer reqLock.Unlock()
if req, err = http.NewRequest(rr.method, httpPath, bytes.NewReader(rr.body)); err != nil {
return nil, err
}
req.Header.Set("Content-Type",
"application/json")
return req, nil
}()
if err != nil {
return nil, err
}
resp, err = c.httpClient.Do(req)
defer func() {
if resp != nil {
resp.Body.Close()
}
}()
// If the request was cancelled, return ErrRequestCancelled directly
select {
case <-cancelled:
return nil, ErrRequestCancelled
default:
}
numReqs++
// network error, change a machine!
if err != nil {
logger.Error("network error: %v", err.Error())
lastResp := http.Response{}
if checkErr := checkRetry(c.Cluster, numReqs, lastResp, err); checkErr != nil {
return nil, checkErr
}
c.Cluster.switchLeader(attempt % len(c.Cluster.Machines))
continue
}
// if there is no error, it should receive response
logger.Debug("recv.response.from "+httpPath)
if validHttpStatusCode[resp.StatusCode] {
// try to read byte code and break the loop
respBody, err = ioutil.ReadAll(resp.Body)
if err == nil {
logger.Debug("recv.success "+ httpPath)
break
}
// ReadAll error may be caused due to cancel request
select {
case <-cancelled:
return nil, ErrRequestCancelled
default:
}
if err == io.ErrUnexpectedEOF {
// underlying connection was closed prematurely, probably by timeout
// TODO: empty body or unexpectedEOF can cause http.Transport to get hosed;
// this allows the client to detect that and take evasive action. Need
// to revisit once code.google.com/p/go/issues/detail?id=8648 gets fixed.
respBody = []byte{}
break
}
}
// if resp is TemporaryRedirect, set the new leader and retry
if resp.StatusCode == http.StatusTemporaryRedirect {
u, err := resp.Location()
if err != nil {
logger.Warning("%v", err)
} else {
// Update cluster leader based on redirect location
// because it should point to the leader address
c.Cluster.updateLeaderFromURL(u)
logger.Debug("recv.response.relocate "+ u.String())
}
resp.Body.Close()
continue
}
if checkErr := checkRetry(c.Cluster, numReqs, *resp,
errors.New("Unexpected HTTP status code")); checkErr != nil {
return nil, checkErr
}
resp.Body.Close()
}
r := &RawResponse{
StatusCode: resp.StatusCode,
Body: respBody,
Header: resp.Header,
}
return r, nil
}
// DefaultCheckRetry defines the retrying behaviour for bad HTTP requests
// If we have retried 2 * machine number, stop retrying.
// If status code is InternalServerError, sleep for 200ms.
func DefaultCheckRetry(cluster *Cluster, numReqs int, lastResp http.Response,
err error) error {
if numReqs >= 2 * len(cluster.Machines) {
return newError(ErrCodeEurekaNotReachable,
"Tried to connect to each peer twice and failed", 0)
}
code := lastResp.StatusCode
if code == http.StatusInternalServerError {
time.Sleep(time.Millisecond * 200)
}
logger.Warning("bad response status code %d", code)
return nil
}
func (c *Client) getHttpPath(random bool, s ...string) string {
var machine string
if random {
machine = c.Cluster.Machines[rand.Intn(len(c.Cluster.Machines))]
} else {
machine = c.Cluster.Leader
}
fullPath := machine
for _, seg := range s {
fullPath += "/" + seg
}
return fullPath
}
// buildValues builds a url.Values map according to the given value and ttl
func buildValues(value string, ttl uint64) url.Values {
v := url.Values{}
if value != "" {
v.Set("value", value)
}
if ttl > 0 {
v.Set("ttl", fmt.Sprintf("%v", ttl))
}
return v
}

View File

@@ -0,0 +1,21 @@
package eureka
import "net/http"
type RawResponse struct {
StatusCode int
Body []byte
Header http.Header
}
var (
validHttpStatusCode = map[int]bool{
http.StatusNoContent: true,
http.StatusCreated: true,
http.StatusOK: true,
http.StatusBadRequest: true,
http.StatusNotFound: true,
http.StatusPreconditionFailed: true,
http.StatusForbidden: true,
}
)

View File

@@ -0,0 +1,3 @@
package eureka
const version = "v2"

View File

@@ -0,0 +1,23 @@
The MIT License (MIT)
Copyright (c) 2015 Arthur Halet
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The Software should rather be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
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.

View File

@@ -0,0 +1,185 @@
package gominlog
import (
"log"
"os"
"fmt"
"runtime"
"github.com/daviddengcn/go-colortext"
"regexp"
"strings"
"io"
)
type Level int
const (
Loff = Level(^uint(0) >> 1)
Lsevere = Level(1000)
Lerror = Level(900)
Lwarning = Level(800)
Linfo = Level(700)
Ldebug = Level(600)
Lall = Level(-Loff - 1)
)
type MinLog struct {
log *log.Logger
level Level
packageName string
isColorized bool
}
func NewClassicMinLog() *MinLog {
minLog := &MinLog{}
logWriter := os.Stdout
flags := log.Lshortfile | log.Ldate | log.Ltime
minLog.log = log.New(logWriter, "", flags)
minLog.isColorized = true
minLog.packageName = ""
minLog.level = Lall
return minLog
}
func NewClassicMinLogWithPackageName(packageName string) *MinLog {
minLog := NewClassicMinLog()
minLog.SetPackageName(packageName)
return minLog
}
func NewMinLog(appName string, level Level, withColor bool, flag int) *MinLog {
minLog := &MinLog{}
logWriter := os.Stdout
minLog.log = log.New(logWriter, "", flag)
minLog.isColorized = withColor
minLog.packageName = appName
minLog.level = level
return minLog
}
func NewMinLogWithLogger(packageName string, level Level, withColor bool, logger *log.Logger) *MinLog {
minLog := &MinLog{}
minLog.log = logger
minLog.isColorized = withColor
minLog.packageName = packageName
minLog.level = level
return minLog
}
func (this *MinLog) GetLevel() Level {
return Level(this.level)
}
func (this *MinLog) SetWriter(writer io.Writer) {
this.log.SetOutput(writer)
}
func (this *MinLog) SetLevel(level Level) {
this.level = level
}
func (this *MinLog) SetPackageName(newPackageName string) {
this.packageName = newPackageName
}
func (this *MinLog) GetPackageName() string {
return this.packageName
}
func (this *MinLog) SetLogger(l *log.Logger) {
this.log = l
}
func (this *MinLog) WithColor(isColorized bool) {
this.isColorized = isColorized
}
func (this *MinLog) IsColorized() bool {
return this.isColorized
}
func (this *MinLog) GetLogger() *log.Logger {
return this.log
}
func (this *MinLog) logMessage(typeLog string, colorFg ct.Color, colorBg ct.Color, args ...interface{}) {
var text string
msg := ""
flags := this.log.Flags()
if (log.Lshortfile | flags) == flags {
msg += this.trace()
this.log.SetFlags(flags - log.Lshortfile)
}
text, ok := args[0].(string);
if !ok {
panic("Firt argument should be a string")
}
if len(args) > 1 {
newArgs := args[1:]
msg += typeLog + ": " + fmt.Sprintf(text, newArgs...)
}else {
msg += typeLog + ": " + text
}
this.writeMsgInLogger(msg, colorFg, colorBg)
this.log.SetFlags(flags)
}
func (this *MinLog) writeMsgInLogger(msg string, colorFg ct.Color, colorBg ct.Color) {
if this.isColorized && colorFg > 0 {
ct.Foreground(colorFg, false)
}
if this.isColorized && colorBg > 0 {
ct.ChangeColor(colorFg, false, colorBg, false)
}
this.log.Print(msg)
if this.isColorized {
ct.ResetColor()
}
}
func (this *MinLog) Error(args ...interface{}) {
if this.level > Lerror {
return
}
this.logMessage("ERROR", ct.Red, 0, args...)
}
func (this *MinLog) Severe(args ...interface{}) {
if this.level > Lsevere {
return
}
this.logMessage("SEVERE", ct.Red, ct.Yellow, args...)
}
func (this *MinLog) Debug(args ...interface{}) {
if this.level > Ldebug {
return
}
this.logMessage("DEBUG", ct.Blue, 0, args...)
}
func (this *MinLog) Info(args ...interface{}) {
if this.level > Linfo {
return
}
this.logMessage("INFO", ct.Cyan, 0, args...)
}
func (this *MinLog) Warning(args ...interface{}) {
if this.level > Lwarning {
return
}
this.logMessage("WARNING", ct.Yellow, 0, args...)
}
func (this *MinLog) trace() string {
var shortFile string
pc := make([]uintptr, 10)
runtime.Callers(2, pc)
f := runtime.FuncForPC(pc[2])
file, line := f.FileLine(pc[2])
if this.packageName == "" {
execFileSplit := strings.Split(os.Args[0], "/")
this.packageName = execFileSplit[len(execFileSplit) - 1]
}
regex, err := regexp.Compile(regexp.QuoteMeta(this.packageName) + "/(.*)")
if err != nil {
panic(err)
}
subMatch := regex.FindStringSubmatch(file)
if len(subMatch) < 2 {
fileSplit := strings.Split(file, "/")
shortFile = fileSplit[len(fileSplit) - 1]
}else {
shortFile = subMatch[1]
}
return fmt.Sprintf("/%s/%s:%d ", this.packageName, shortFile, line)
}

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Microsoft Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
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.

View File

@@ -0,0 +1,188 @@
package ansiterm
const LogEnv = "DEBUG_TERMINAL"
// ANSI constants
// References:
// -- http://www.ecma-international.org/publications/standards/Ecma-048.htm
// -- http://man7.org/linux/man-pages/man4/console_codes.4.html
// -- http://manpages.ubuntu.com/manpages/intrepid/man4/console_codes.4.html
// -- http://en.wikipedia.org/wiki/ANSI_escape_code
// -- http://vt100.net/emu/dec_ansi_parser
// -- http://vt100.net/emu/vt500_parser.svg
// -- http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
// -- http://www.inwap.com/pdp10/ansicode.txt
const (
// ECMA-48 Set Graphics Rendition
// Note:
// -- Constants leading with an underscore (e.g., _ANSI_xxx) are unsupported or reserved
// -- Fonts could possibly be supported via SetCurrentConsoleFontEx
// -- Windows does not expose the per-window cursor (i.e., caret) blink times
ANSI_SGR_RESET = 0
ANSI_SGR_BOLD = 1
ANSI_SGR_DIM = 2
_ANSI_SGR_ITALIC = 3
ANSI_SGR_UNDERLINE = 4
_ANSI_SGR_BLINKSLOW = 5
_ANSI_SGR_BLINKFAST = 6
ANSI_SGR_REVERSE = 7
_ANSI_SGR_INVISIBLE = 8
_ANSI_SGR_LINETHROUGH = 9
_ANSI_SGR_FONT_00 = 10
_ANSI_SGR_FONT_01 = 11
_ANSI_SGR_FONT_02 = 12
_ANSI_SGR_FONT_03 = 13
_ANSI_SGR_FONT_04 = 14
_ANSI_SGR_FONT_05 = 15
_ANSI_SGR_FONT_06 = 16
_ANSI_SGR_FONT_07 = 17
_ANSI_SGR_FONT_08 = 18
_ANSI_SGR_FONT_09 = 19
_ANSI_SGR_FONT_10 = 20
_ANSI_SGR_DOUBLEUNDERLINE = 21
ANSI_SGR_BOLD_DIM_OFF = 22
_ANSI_SGR_ITALIC_OFF = 23
ANSI_SGR_UNDERLINE_OFF = 24
_ANSI_SGR_BLINK_OFF = 25
_ANSI_SGR_RESERVED_00 = 26
ANSI_SGR_REVERSE_OFF = 27
_ANSI_SGR_INVISIBLE_OFF = 28
_ANSI_SGR_LINETHROUGH_OFF = 29
ANSI_SGR_FOREGROUND_BLACK = 30
ANSI_SGR_FOREGROUND_RED = 31
ANSI_SGR_FOREGROUND_GREEN = 32
ANSI_SGR_FOREGROUND_YELLOW = 33
ANSI_SGR_FOREGROUND_BLUE = 34
ANSI_SGR_FOREGROUND_MAGENTA = 35
ANSI_SGR_FOREGROUND_CYAN = 36
ANSI_SGR_FOREGROUND_WHITE = 37
_ANSI_SGR_RESERVED_01 = 38
ANSI_SGR_FOREGROUND_DEFAULT = 39
ANSI_SGR_BACKGROUND_BLACK = 40
ANSI_SGR_BACKGROUND_RED = 41
ANSI_SGR_BACKGROUND_GREEN = 42
ANSI_SGR_BACKGROUND_YELLOW = 43
ANSI_SGR_BACKGROUND_BLUE = 44
ANSI_SGR_BACKGROUND_MAGENTA = 45
ANSI_SGR_BACKGROUND_CYAN = 46
ANSI_SGR_BACKGROUND_WHITE = 47
_ANSI_SGR_RESERVED_02 = 48
ANSI_SGR_BACKGROUND_DEFAULT = 49
// 50 - 65: Unsupported
ANSI_MAX_CMD_LENGTH = 4096
MAX_INPUT_EVENTS = 128
DEFAULT_WIDTH = 80
DEFAULT_HEIGHT = 24
ANSI_BEL = 0x07
ANSI_BACKSPACE = 0x08
ANSI_TAB = 0x09
ANSI_LINE_FEED = 0x0A
ANSI_VERTICAL_TAB = 0x0B
ANSI_FORM_FEED = 0x0C
ANSI_CARRIAGE_RETURN = 0x0D
ANSI_ESCAPE_PRIMARY = 0x1B
ANSI_ESCAPE_SECONDARY = 0x5B
ANSI_OSC_STRING_ENTRY = 0x5D
ANSI_COMMAND_FIRST = 0x40
ANSI_COMMAND_LAST = 0x7E
DCS_ENTRY = 0x90
CSI_ENTRY = 0x9B
OSC_STRING = 0x9D
ANSI_PARAMETER_SEP = ";"
ANSI_CMD_G0 = '('
ANSI_CMD_G1 = ')'
ANSI_CMD_G2 = '*'
ANSI_CMD_G3 = '+'
ANSI_CMD_DECPNM = '>'
ANSI_CMD_DECPAM = '='
ANSI_CMD_OSC = ']'
ANSI_CMD_STR_TERM = '\\'
KEY_CONTROL_PARAM_2 = ";2"
KEY_CONTROL_PARAM_3 = ";3"
KEY_CONTROL_PARAM_4 = ";4"
KEY_CONTROL_PARAM_5 = ";5"
KEY_CONTROL_PARAM_6 = ";6"
KEY_CONTROL_PARAM_7 = ";7"
KEY_CONTROL_PARAM_8 = ";8"
KEY_ESC_CSI = "\x1B["
KEY_ESC_N = "\x1BN"
KEY_ESC_O = "\x1BO"
FILL_CHARACTER = ' '
)
func getByteRange(start byte, end byte) []byte {
bytes := make([]byte, 0, 32)
for i := start; i <= end; i++ {
bytes = append(bytes, byte(i))
}
return bytes
}
var toGroundBytes = getToGroundBytes()
var executors = getExecuteBytes()
// SPACE 20+A0 hex Always and everywhere a blank space
// Intermediate 20-2F hex !"#$%&'()*+,-./
var intermeds = getByteRange(0x20, 0x2F)
// Parameters 30-3F hex 0123456789:;<=>?
// CSI Parameters 30-39, 3B hex 0123456789;
var csiParams = getByteRange(0x30, 0x3F)
var csiCollectables = append(getByteRange(0x30, 0x39), getByteRange(0x3B, 0x3F)...)
// Uppercase 40-5F hex @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
var upperCase = getByteRange(0x40, 0x5F)
// Lowercase 60-7E hex `abcdefghijlkmnopqrstuvwxyz{|}~
var lowerCase = getByteRange(0x60, 0x7E)
// Alphabetics 40-7E hex (all of upper and lower case)
var alphabetics = append(upperCase, lowerCase...)
var printables = getByteRange(0x20, 0x7F)
var escapeIntermediateToGroundBytes = getByteRange(0x30, 0x7E)
var escapeToGroundBytes = getEscapeToGroundBytes()
// See http://www.vt100.net/emu/vt500_parser.png for description of the complex
// byte ranges below
func getEscapeToGroundBytes() []byte {
escapeToGroundBytes := getByteRange(0x30, 0x4F)
escapeToGroundBytes = append(escapeToGroundBytes, getByteRange(0x51, 0x57)...)
escapeToGroundBytes = append(escapeToGroundBytes, 0x59)
escapeToGroundBytes = append(escapeToGroundBytes, 0x5A)
escapeToGroundBytes = append(escapeToGroundBytes, 0x5C)
escapeToGroundBytes = append(escapeToGroundBytes, getByteRange(0x60, 0x7E)...)
return escapeToGroundBytes
}
func getExecuteBytes() []byte {
executeBytes := getByteRange(0x00, 0x17)
executeBytes = append(executeBytes, 0x19)
executeBytes = append(executeBytes, getByteRange(0x1C, 0x1F)...)
return executeBytes
}
func getToGroundBytes() []byte {
groundBytes := []byte{0x18}
groundBytes = append(groundBytes, 0x1A)
groundBytes = append(groundBytes, getByteRange(0x80, 0x8F)...)
groundBytes = append(groundBytes, getByteRange(0x91, 0x97)...)
groundBytes = append(groundBytes, 0x99)
groundBytes = append(groundBytes, 0x9A)
groundBytes = append(groundBytes, 0x9C)
return groundBytes
}
// Delete 7F hex Always and everywhere ignored
// C1 Control 80-9F hex 32 additional control characters
// G1 Displayable A1-FE hex 94 additional displayable characters
// Special A0+FF hex Same as SPACE and DELETE

View File

@@ -0,0 +1,7 @@
package ansiterm
type ansiContext struct {
currentChar byte
paramBuffer []byte
interBuffer []byte
}

View File

@@ -0,0 +1,49 @@
package ansiterm
type csiEntryState struct {
baseState
}
func (csiState csiEntryState) Handle(b byte) (s state, e error) {
logger.Infof("CsiEntry::Handle %#x", b)
nextState, err := csiState.baseState.Handle(b)
if nextState != nil || err != nil {
return nextState, err
}
switch {
case sliceContains(alphabetics, b):
return csiState.parser.ground, nil
case sliceContains(csiCollectables, b):
return csiState.parser.csiParam, nil
case sliceContains(executors, b):
return csiState, csiState.parser.execute()
}
return csiState, nil
}
func (csiState csiEntryState) Transition(s state) error {
logger.Infof("CsiEntry::Transition %s --> %s", csiState.Name(), s.Name())
csiState.baseState.Transition(s)
switch s {
case csiState.parser.ground:
return csiState.parser.csiDispatch()
case csiState.parser.csiParam:
switch {
case sliceContains(csiParams, csiState.parser.context.currentChar):
csiState.parser.collectParam()
case sliceContains(intermeds, csiState.parser.context.currentChar):
csiState.parser.collectInter()
}
}
return nil
}
func (csiState csiEntryState) Enter() error {
csiState.parser.clear()
return nil
}

View File

@@ -0,0 +1,38 @@
package ansiterm
type csiParamState struct {
baseState
}
func (csiState csiParamState) Handle(b byte) (s state, e error) {
logger.Infof("CsiParam::Handle %#x", b)
nextState, err := csiState.baseState.Handle(b)
if nextState != nil || err != nil {
return nextState, err
}
switch {
case sliceContains(alphabetics, b):
return csiState.parser.ground, nil
case sliceContains(csiCollectables, b):
csiState.parser.collectParam()
return csiState, nil
case sliceContains(executors, b):
return csiState, csiState.parser.execute()
}
return csiState, nil
}
func (csiState csiParamState) Transition(s state) error {
logger.Infof("CsiParam::Transition %s --> %s", csiState.Name(), s.Name())
csiState.baseState.Transition(s)
switch s {
case csiState.parser.ground:
return csiState.parser.csiDispatch()
}
return nil
}

View File

@@ -0,0 +1,36 @@
package ansiterm
type escapeIntermediateState struct {
baseState
}
func (escState escapeIntermediateState) Handle(b byte) (s state, e error) {
logger.Infof("escapeIntermediateState::Handle %#x", b)
nextState, err := escState.baseState.Handle(b)
if nextState != nil || err != nil {
return nextState, err
}
switch {
case sliceContains(intermeds, b):
return escState, escState.parser.collectInter()
case sliceContains(executors, b):
return escState, escState.parser.execute()
case sliceContains(escapeIntermediateToGroundBytes, b):
return escState.parser.ground, nil
}
return escState, nil
}
func (escState escapeIntermediateState) Transition(s state) error {
logger.Infof("escapeIntermediateState::Transition %s --> %s", escState.Name(), s.Name())
escState.baseState.Transition(s)
switch s {
case escState.parser.ground:
return escState.parser.escDispatch()
}
return nil
}

View File

@@ -0,0 +1,47 @@
package ansiterm
type escapeState struct {
baseState
}
func (escState escapeState) Handle(b byte) (s state, e error) {
logger.Infof("escapeState::Handle %#x", b)
nextState, err := escState.baseState.Handle(b)
if nextState != nil || err != nil {
return nextState, err
}
switch {
case b == ANSI_ESCAPE_SECONDARY:
return escState.parser.csiEntry, nil
case b == ANSI_OSC_STRING_ENTRY:
return escState.parser.oscString, nil
case sliceContains(executors, b):
return escState, escState.parser.execute()
case sliceContains(escapeToGroundBytes, b):
return escState.parser.ground, nil
case sliceContains(intermeds, b):
return escState.parser.escapeIntermediate, nil
}
return escState, nil
}
func (escState escapeState) Transition(s state) error {
logger.Infof("Escape::Transition %s --> %s", escState.Name(), s.Name())
escState.baseState.Transition(s)
switch s {
case escState.parser.ground:
return escState.parser.escDispatch()
case escState.parser.escapeIntermediate:
return escState.parser.collectInter()
}
return nil
}
func (escState escapeState) Enter() error {
escState.parser.clear()
return nil
}

View File

@@ -0,0 +1,90 @@
package ansiterm
type AnsiEventHandler interface {
// Print
Print(b byte) error
// Execute C0 commands
Execute(b byte) error
// CUrsor Up
CUU(int) error
// CUrsor Down
CUD(int) error
// CUrsor Forward
CUF(int) error
// CUrsor Backward
CUB(int) error
// Cursor to Next Line
CNL(int) error
// Cursor to Previous Line
CPL(int) error
// Cursor Horizontal position Absolute
CHA(int) error
// Vertical line Position Absolute
VPA(int) error
// CUrsor Position
CUP(int, int) error
// Horizontal and Vertical Position (depends on PUM)
HVP(int, int) error
// Text Cursor Enable Mode
DECTCEM(bool) error
// Origin Mode
DECOM(bool) error
// 132 Column Mode
DECCOLM(bool) error
// Erase in Display
ED(int) error
// Erase in Line
EL(int) error
// Insert Line
IL(int) error
// Delete Line
DL(int) error
// Insert Character
ICH(int) error
// Delete Character
DCH(int) error
// Set Graphics Rendition
SGR([]int) error
// Pan Down
SU(int) error
// Pan Up
SD(int) error
// Device Attributes
DA([]string) error
// Set Top and Bottom Margins
DECSTBM(int, int) error
// Index
IND() error
// Reverse Index
RI() error
// Flush updates from previous commands
Flush() error
}

View File

@@ -0,0 +1,24 @@
package ansiterm
type groundState struct {
baseState
}
func (gs groundState) Handle(b byte) (s state, e error) {
gs.parser.context.currentChar = b
nextState, err := gs.baseState.Handle(b)
if nextState != nil || err != nil {
return nextState, err
}
switch {
case sliceContains(printables, b):
return gs, gs.parser.print()
case sliceContains(executors, b):
return gs, gs.parser.execute()
}
return gs, nil
}

View File

@@ -0,0 +1,31 @@
package ansiterm
type oscStringState struct {
baseState
}
func (oscState oscStringState) Handle(b byte) (s state, e error) {
logger.Infof("OscString::Handle %#x", b)
nextState, err := oscState.baseState.Handle(b)
if nextState != nil || err != nil {
return nextState, err
}
switch {
case isOscStringTerminator(b):
return oscState.parser.ground, nil
}
return oscState, nil
}
// See below for OSC string terminators for linux
// http://man7.org/linux/man-pages/man4/console_codes.4.html
func isOscStringTerminator(b byte) bool {
if b == ANSI_BEL || b == 0x5C {
return true
}
return false
}

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