1
0
mirror of https://github.com/containous/traefik.git synced 2025-10-11 03:33:18 +03:00

Compare commits

..

16 Commits
v1.3.5 ... v1.1

Author SHA1 Message Date
mmatur
a467eb6244 fix: docs build trusted host 2024-05-16 21:10:13 +02:00
mmatur
faae17839d fix: docs build alpine version 2024-05-16 16:27:43 +02:00
mmatur
00315d3d55 feat: add dockerfile for documentation 2021-10-05 10:30:33 +02:00
Michael
146a1016a8 [doc] fix version in requirements.txt
To be able to generate versionned documentation
2018-01-19 15:44:58 +01:00
Emile Vauge
ca9822cc5f Merge pull request #974 from containous/prepare-release-v1.1.2
Prepare release v1.1.2
2016-12-15 11:13:30 +01:00
Emile Vauge
71980c9785 Prepare release v1.1.2 2016-12-15 10:41:51 +01:00
Emile Vauge
a3a9edc3c6 Merge pull request #972 from containous/fix-duplicate-acme-certs
Fix duplicate acme certificates
2016-12-15 10:35:00 +01:00
Emile Vauge
67b25550c0 Fix duplicate acme certificates 2016-12-14 18:10:10 +01:00
Emile Vauge
fa62ccb0c2 Merge pull request #944 from containous/add-operation-recover
Add operation recover
2016-12-13 16:55:04 +01:00
Emile Vauge
f5bfe681c2 Fix panic in k8s loadIngresses
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-12-13 10:48:28 +01:00
Emile Vauge
19417d8af5 Add Operation with recover 2016-12-13 10:48:28 +01:00
Emile Vauge
59b3a392f2 Merge pull request #956 from containous/fix-leadership-panic
Fix leadership panic
2016-12-13 10:39:59 +01:00
Emile Vauge
25bab338c1 Manage acme cert in infinit channels
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-12-11 21:44:23 +01:00
Emile Vauge
3f6993f0a0 Fix safe panic 2016-12-09 14:26:33 +01:00
Emile Vauge
70f39c3326 Merge pull request #947 from containous/fix-redirect-regex
Fix redirect regex
2016-12-09 10:43:26 +01:00
Emile Vauge
81560827c6 Fix redirect regex
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-12-08 15:40:22 +01:00
5242 changed files with 4800 additions and 1848251 deletions

View File

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

1
.gitattributes vendored Normal file
View File

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

View File

@@ -2,7 +2,7 @@
### Building
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.
You need either [Docker](https://github.com/docker/docker) and `make` (Method 1), or `go` and `glide` (Method 2) in order to build traefik.
#### Method 1: Using `Docker` and `Makefile`
@@ -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.7
Step 0 : FROM golang:1.5
---> 8c6473912976
Step 1 : RUN go get github.com/Masterminds/glide
[...]
@@ -26,14 +26,15 @@ $ ls dist/
traefik*
```
#### Method 2: Using `go`
#### Method 2: Using `go` and `glide`
###### Setting up your `go` environment
- 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)
- 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)
- This will allow your `GOPATH` and `PATH` variable to be set to `~/go` via:
```bash
```
$ export GOPATH=~/go
$ export PATH=$PATH:$GOPATH/bin
```
@@ -42,33 +43,27 @@ 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 `glide` and `glide-vc` for dependency management
###### Setting up your `glide` environment
- 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`
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.
The idea behind `glide` is the following :
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:
- 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`.
```bash
# 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 )
$ glide install
# 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}}" \
./cmd/traefik
-output="dist/traefik_{{.OS}}-{{.Arch}}"
# run other commands like tests
```
@@ -95,7 +90,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
@@ -111,7 +106,7 @@ TESTFLAGS="-check.f MyTestSuite.*Test" make test-integration
More: https://labix.org/gocheck
##### Method 2: `go`
##### Method 2: `go` and `glide`
- Tests can be run from the cloned directory, by `$ go test ./...` which should return `ok` similar to:
```
@@ -124,7 +119,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
@@ -133,13 +128,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

View File

@@ -1,58 +0,0 @@
<!--
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)
```

View File

@@ -1,23 +0,0 @@
<!--
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
View File

@@ -1,26 +0,0 @@
#!/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
View File

@@ -1,27 +0,0 @@
#!/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
View File

@@ -1,36 +0,0 @@
#!/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,13 +1,15 @@
/dist
/autogen/gen.go
gen.go
.idea
.intellij
*.iml
/traefik
/traefik.toml
/static/
traefik
traefik.toml
*.test
vendor/
static/
.vscode/
/site/
site/
*.log
*.exe
.DS_Store

View File

@@ -1,11 +0,0 @@
#!/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-ce=${DOCKER_VERSION}*
docker version
pip install --user -r requirements.txt
make pull-images
ci_retry make validate

View File

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

View File

@@ -1,39 +0,0 @@
#!/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'
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,58 +1,34 @@
sudo: required
dist: trusty
services:
- docker
branches:
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: raclette
- N_MAKE_JOBS: 2
- 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
script:
- 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-ce=${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
- make test-unit
- make test-integration
- make crossbinary
- make image
after_success:
- make deploy
- make deploy-pr

View File

@@ -1,532 +1,5 @@
# Change Log
## [v1.3.5](https://github.com/containous/traefik/tree/v1.3.5) (2017-08-01)
[All Commits](https://github.com/containous/traefik/compare/v1.3.4...v1.3.5)
**Bug fixes:**
- **[websocket]** Oxy with fixes on websocket + integration tests ([#1905](https://github.com/containous/traefik/pull/1905) by [Juliens](https://github.com/Juliens))
## [v1.3.4](https://github.com/containous/traefik/tree/v1.3.4) (2017-07-27)
[All Commits](https://github.com/containous/traefik/compare/v1.3.3...v1.3.4)
**Bug fixes:**
- **[middleware]** Double compression. ([#1863](https://github.com/containous/traefik/pull/1863) by [ldez](https://github.com/ldez))
- **[middleware]** Fix replace path rule ([#1859](https://github.com/containous/traefik/pull/1859) by [dedalusj](https://github.com/dedalusj))
- **[websocket]** New oxy with gorilla for websocket with integration tests ([#1896](https://github.com/containous/traefik/pull/1896) by [Juliens](https://github.com/Juliens))
## [v1.3.3](https://github.com/containous/traefik/tree/v1.3.3) (2017-07-06)
[All Commits](https://github.com/containous/traefik/compare/v1.3.2...v1.3.3)
**Bug fixes:**
- **[k8s]** Undo the Secrets controller sync wait. ([#1828](https://github.com/containous/traefik/pull/1828) by [timoreimann](https://github.com/timoreimann))
- **[k8s]** Tell glog to log everything into STDERR. ([#1817](https://github.com/containous/traefik/pull/1817) by [timoreimann](https://github.com/timoreimann))
## [v1.3.2](https://github.com/containous/traefik/tree/v1.3.2) (2017-06-29)
[All Commits](https://github.com/containous/traefik/compare/v1.3.1...v1.3.2)
**Bug fixes:**
- **[acme]** Add provided certificate checking before LE certificate generation with OnHostRule option ([#1772](https://github.com/containous/traefik/pull/1772) by [nmengin](https://github.com/nmengin))
- **[k8s]** Fix race on closing event channel. ([#1798](https://github.com/containous/traefik/pull/1798) by [timoreimann](https://github.com/timoreimann))
- **[marathon]** Upgrade go-marathon to dd6cbd4. ([#1800](https://github.com/containous/traefik/pull/1800) by [timoreimann](https://github.com/timoreimann))
- **[oxy,websocket]** Problem with keepalive when switching protocol failed ([#1782](https://github.com/containous/traefik/pull/1782) by [ldez](https://github.com/ldez))
- **[oxy]** Fix proxying of unannounced trailers ([#1805](https://github.com/containous/traefik/pull/1805) by [ldez](https://github.com/ldez))
## [v1.3.1](https://github.com/containous/traefik/tree/v1.3.1) (2017-06-16)
[All Commits](https://github.com/containous/traefik/compare/v1.3.0...v1.3.1)
**Enhancements:**
- **[logs,eureka,marathon]** Minor logs changes ([#1749](https://github.com/containous/traefik/pull/1749) by [ldez](https://github.com/ldez))
**Bug fixes:**
- **[k8s]** Use correct type when watching for k8s secrets ([#1700](https://github.com/containous/traefik/pull/1700) by [kekoav](https://github.com/kekoav))
- **[middleware]** fix: Double compression. ([#1714](https://github.com/containous/traefik/pull/1714) by [ldez](https://github.com/ldez))
- **[webui]** Don&#39;t fail when backend or frontend are empty. ([#1757](https://github.com/containous/traefik/pull/1757) by [ldez](https://github.com/ldez))
**Documentation:**
- **[k8s]** Fix capitalization of PathPrefixStrip in kubernetes doc ([#1695](https://github.com/containous/traefik/pull/1695) by [Miouge1](https://github.com/Miouge1))
## [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)
@@ -1182,4 +655,4 @@
\* *This Change Log was automatically generated by [gcg](https://github.com/ldez/gcg)*
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*

View File

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

View File

@@ -6,25 +6,21 @@ TRAEFIK_ENVS := \
-e TESTFLAGS \
-e VERBOSE \
-e VERSION \
-e CODENAME \
-e TESTDIRS
-e CODENAME
SRCS = $(shell git ls-files '*.go' | grep -v '^vendor/' | grep -v '^integration/vendor/')
SRCS = $(shell git ls-files '*.go' | grep -v '^external/')
BIND_DIR := "dist"
TRAEFIK_MOUNT := -v "$(CURDIR)/$(BIND_DIR):/go/src/github.com/containous/traefik/$(BIND_DIR)"
GIT_BRANCH := $(subst heads/,,$(shell git rev-parse --abbrev-ref HEAD 2>/dev/null))
GIT_BRANCH := $(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_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)
DOCKER_RUN_TRAEFIK := docker run $(INTEGRATION_OPTS) -it $(TRAEFIK_ENVS) $(TRAEFIK_MOUNT) "$(TRAEFIK_DEV_IMAGE)"
print-%: ; @echo $*=$($*)
@@ -39,24 +35,6 @@ 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
@@ -64,10 +42,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 binary test-integration
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate test-integration
validate: build ## validate gofmt, golint and go vet
$(DOCKER_RUN_TRAEFIK) ./script/make.sh validate-glide validate-gofmt validate-govet validate-golint validate-misspell validate-vendor
$(DOCKER_RUN_TRAEFIK) ./script/make.sh validate-gofmt validate-govet validate-golint
build: dist
docker build $(DOCKER_BUILD_ARGS) -t "$(TRAEFIK_DEV_IMAGE)" -f build.Dockerfile .
@@ -81,7 +59,7 @@ build-no-cache: dist
shell: build ## start a shell inside the build env
$(DOCKER_RUN_TRAEFIK) /bin/bash
image: binary ## build a docker traefik image
image: build ## build a docker traefik image
docker build -t $(TRAEFIK_IMAGE) .
dist:
@@ -105,10 +83,11 @@ lint:
fmt:
gofmt -s -l -w $(SRCS)
pull-images:
for f in $(shell find ./integration/resources/compose/ -type f); do \
docker-compose -f $$f pull; \
done
deploy:
./script/deploy.sh
deploy-pr:
./script/deploy-pr.sh
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æfik" title="Træfik" />
<img src="docs/img/traefik.logo.png" alt="Træfɪk" title="Træfɪk" />
</p>
[![Build Status](https://travis-ci.org/containous/traefik.svg?branch=master)](https://travis-ci.org/containous/traefik)
[![Docs](https://img.shields.io/badge/docs-current-brightgreen.svg)](https://docs.traefik.io)
[![Go Report Card](https://goreportcard.com/badge/containous/traefik)](http://goreportcard.com/report/containous/traefik)
[![Go Report Card](https://goreportcard.com/badge/kubernetes/helm)](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æ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.
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.
## 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æfik.
Here enters Træfɪk.
![Architecture](docs/img/architecture.png)
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.
Træfɪk can listen to your service registry/orchestrator API, and knows each time a microservice is added, removed, killed or upgraded, and can generate its configuration automatically.
Routes to your services will be created instantly.
Run it and forget it!
@@ -64,21 +64,21 @@ Run it and forget it!
## Quickstart
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.
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.
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æfik features and see some demos with Kubernetes.
You will learn fundamental Træfɪk features and see some demos with Kubernetes.
[![Traefik ContainerCamp UK](http://img.youtube.com/vi/aFtpIShV60I/0.jpg)](https://www.youtube.com/watch?v=aFtpIShV60I)
Here is a talk (in French) given by [Emile Vauge](https://github.com/emilevauge) at the [Devoxx France 2016](http://www.devoxx.fr) conference.
You will learn fundamental Træfik features and see some demos with Docker, Mesos/Marathon and Let's Encrypt.
You will learn fundamental Træfɪk features and see some demos with Docker, Mesos/Marathon and Let's Encrypt.
[![Traefik Devoxx France](http://img.youtube.com/vi/QvAz9mVx5TI/0.jpg)](http://www.youtube.com/watch?v=QvAz9mVx5TI)
## Web UI
You can access the simple HTML frontend of Træfik.
You can access to a simple HTML frontend of Træfik.
![Web UI Providers](docs/img/web.frontend.png)
![Web UI Health](docs/img/traefik-health.png)
@@ -88,6 +88,7 @@ You can access the 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
@@ -127,6 +128,33 @@ 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)
@@ -135,13 +163,7 @@ If you prefer commercial support, please contact [containo.us](https://containo.
- 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).
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/).
Kudos to [Peka](http://peka.byethost11.com/photoblog/) for his awesome work on the logo ![logo](docs/img/traefik.icon.png)

View File

@@ -7,14 +7,13 @@ 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
@@ -133,7 +132,7 @@ func (dc *DomainsCertificates) removeDuplicates() {
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())
log.Warnf("Remove duplicate cert: %+v, exipration :%s", dc.Certs[i2].Domains, dc.Certs[i2].tlsCert.Leaf.NotAfter.String())
dc.Certs = append(dc.Certs[:i2], dc.Certs[i2+1:]...)
i2--
}
@@ -235,7 +234,7 @@ func (dc *DomainsCertificate) needRenew() bool {
// If there's an error, we assume the cert is broken, and needs update
return true
}
// <= 30 days left, renew certificate
// <= 7 days left, renew certificate
if crt.NotAfter.Before(time.Now().Add(time.Duration(24 * 30 * time.Hour))) {
return true
}

View File

@@ -1,17 +1,9 @@
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"
@@ -21,12 +13,12 @@ import (
"github.com/containous/traefik/types"
"github.com/eapache/channels"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/providers/dns"
)
var (
// OSCPMustStaple enables OSCP stapling as from https://github.com/xenolf/lego/issues/270
OSCPMustStaple = false
"golang.org/x/net/context"
"io/ioutil"
fmtlog "log"
"os"
"strings"
"time"
)
// ACME allows to connect to lets encrypt and retrieve certs
@@ -39,16 +31,12 @@ 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
@@ -93,11 +81,7 @@ type Domain struct {
}
func (a *ACME) init() error {
if a.ACMELogging {
acme.Logger = fmtlog.New(os.Stderr, "legolog: ", fmtlog.LstdFlags)
} else {
acme.Logger = fmtlog.New(ioutil.Discard, "", 0)
}
acme.Logger = fmtlog.New(ioutil.Discard, "", 0)
// no certificates in TLS config, so we add a default one
cert, err := generateDefaultCertificate()
if err != nil {
@@ -125,7 +109,6 @@ 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()
@@ -245,7 +228,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}
@@ -328,11 +311,6 @@ 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)
if providedCertificate := a.getProvidedCertificate([]string{domain}); providedCertificate != nil {
return providedCertificate, nil
}
if challengeCert, ok := a.challengeProvider.getCertificate(domain); ok {
log.Debugf("ACME got challenge %s", domain)
return challengeCert, nil
@@ -401,7 +379,7 @@ func (a *ACME) renewCertificates() {
CertStableURL: certificateResource.Certificate.CertStableURL,
PrivateKey: certificateResource.Certificate.PrivateKey,
Certificate: certificateResource.Certificate.Certificate,
}, true, OSCPMustStaple)
}, true)
if err != nil {
log.Errorf("Error renewing certificate: %v", err)
continue
@@ -435,20 +413,6 @@ func (a *ACME) renewCertificates() {
}
}
func dnsOverrideDelay(delay int) error {
var err error
if delay > 0 {
log.Debugf("Delaying %d seconds rather than validating DNS propagation", delay)
acme.PreCheckDNS = func(_, _ string) (bool, error) {
time.Sleep(time.Duration(delay) * time.Second)
return true, nil
}
} else if delay < 0 {
err = fmt.Errorf("Invalid negative DelayDontCheckDNS: %d", delay)
}
return err
}
func (a *ACME) buildACMEClient(account *Account) (*acme.Client, error) {
log.Debugf("Building ACME client...")
caServer := "https://acme-v01.api.letsencrypt.org/directory"
@@ -459,28 +423,8 @@ func (a *ACME) buildACMEClient(account *Account) (*acme.Client, error) {
if err != nil {
return nil, err
}
if len(a.DNSProvider) > 0 {
log.Debugf("Using DNS Challenge provider: %s", a.DNSProvider)
err = dnsOverrideDelay(a.DelayDontCheckDNS)
if err != nil {
return nil, err
}
var provider acme.ChallengeProvider
provider, err = dns.NewDNSChallengeProviderByName(a.DNSProvider)
if err != nil {
return nil, err
}
client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.TLSSNI01})
err = client.SetChallengeProvider(acme.DNS01, provider)
} else {
client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.DNS01})
err = client.SetChallengeProvider(acme.TLSSNI01, a.challengeProvider)
}
client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.DNS01})
err = client.SetChallengeProvider(acme.TLSSNI01, a.challengeProvider)
if err != nil {
return nil, err
}
@@ -517,20 +461,8 @@ func (a *ACME) loadCertificateOnDemand(clientHello *tls.ClientHelloInfo) (*tls.C
// LoadCertificateForDomains loads certificates from ACME for given domains
func (a *ACME) LoadCertificateForDomains(domains []string) {
a.jobs.In() <- func() {
log.Debugf("LoadCertificateForDomains %v...", domains)
if len(domains) == 0 {
// no domain
return
}
log.Debugf("LoadCertificateForDomains %s...", domains)
domains = fun.Map(types.CanonicalDomain, domains).([]string)
// Check provided certificates
if a.getProvidedCertificate(domains) != nil {
return
}
operation := func() error {
if a.client == nil {
return fmt.Errorf("ACME client still not built")
@@ -549,7 +481,11 @@ func (a *ACME) LoadCertificateForDomains(domains []string) {
}
account := a.store.Get().(*Account)
var domain Domain
if len(domains) > 1 {
if len(domains) == 0 {
// no domain
return
} else if len(domains) > 1 {
domain = Domain{Main: domains[0], SANs: domains[1:]}
} else {
domain = Domain{Main: domains[0]}
@@ -583,34 +519,11 @@ func (a *ACME) LoadCertificateForDomains(domains []string) {
}
}
// Get provided certificate which check a domains list (Main and SANs)
func (a *ACME) getProvidedCertificate(domains []string) *tls.Certificate {
// Use regex to test for provided certs that might have been added into TLSConfig
providedCertMatch := false
log.Debugf("Look for provided certificate to validate %s...", domains)
for k := range a.TLSConfig.NameToCertificate {
selector := "^" + strings.Replace(k, "*.", "[^\\.]*\\.?", -1) + "$"
for _, domainToCheck := range domains {
providedCertMatch, _ = regexp.MatchString(selector, domainToCheck)
if !providedCertMatch {
break
}
}
if providedCertMatch {
log.Debugf("Got provided certificate for domains %s", domains)
return a.TLSConfig.NameToCertificate[k]
}
}
log.Debugf("No provided certificate found for domains %s, get ACME certificate.", domains)
return nil
}
func (a *ACME) getDomainsCertificates(domains []string) (*Certificate, error) {
domains = fun.Map(types.CanonicalDomain, domains).([]string)
log.Debugf("Loading ACME certificates %s...", domains)
bundle := true
certificate, failures := a.client.ObtainCertificate(domains, bundle, nil, OSCPMustStaple)
certificate, failures := a.client.ObtainCertificate(domains, bundle, nil)
if len(failures) > 0 {
log.Error(failures)
return nil, fmt.Errorf("Cannot obtain certificates %s+v", failures)

View File

@@ -1,17 +1,10 @@
package acme
import (
"crypto/tls"
"encoding/base64"
"net/http"
"net/http/httptest"
"reflect"
"sync"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/xenolf/lego/acme"
)
func TestDomainsSet(t *testing.T) {
@@ -212,85 +205,7 @@ func TestRemoveDuplicates(t *testing.T) {
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)
t.Errorf("Unkown 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.")
}
}
func TestAcme_getProvidedCertificate(t *testing.T) {
mm := make(map[string]*tls.Certificate)
mm["*.containo.us"] = &tls.Certificate{}
mm["traefik.acme.io"] = &tls.Certificate{}
a := ACME{TLSConfig: &tls.Config{NameToCertificate: mm}}
domains := []string{"traefik.containo.us", "trae.containo.us"}
certificate := a.getProvidedCertificate(domains)
assert.NotNil(t, certificate)
domains = []string{"traefik.acme.io", "trae.acme.io"}
certificate = a.getProvidedCertificate(domains)
assert.Nil(t, certificate)
}

View File

@@ -2,16 +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)

View File

@@ -3,12 +3,10 @@ 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)
@@ -39,17 +37,7 @@ func (s *LocalStore) Load() (cluster.Object, error) {
s.storageLock.Lock()
defer s.storageLock.Unlock()
account := &Account{}
err := checkPermissions(s.file)
if err != nil {
return nil, err
}
f, err := os.Open(s.file)
if err != nil {
return nil, err
}
defer f.Close()
file, err := ioutil.ReadAll(f)
file, err := ioutil.ReadFile(s.file)
if err != nil {
return nil, err
}

View File

@@ -1,25 +0,0 @@
// +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

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

View File

@@ -1,35 +1,25 @@
FROM golang:1.8
FROM golang:1.7
# 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/... \
RUN go get github.com/Masterminds/glide \
&& go get github.com/jteeuwen/go-bindata/... \
&& go get github.com/golang/lint/golint \
&& go get github.com/kisielk/errcheck \
&& go get github.com/client9/misspell/cmd/misspell \
&& go get github.com/mattfarina/glide-hash \
&& go get github.com/sgotti/glide-vc
&& go get github.com/kisielk/errcheck
# Which docker version to test on
ARG DOCKER_VERSION=17.03.1
# Which glide version to test on
ARG GLIDE_VERSION=v0.12.3
# Download glide
RUN mkdir -p /usr/local/bin \
&& curl -fL https://github.com/Masterminds/glide/releases/download/${GLIDE_VERSION}/glide-${GLIDE_VERSION}-linux-amd64.tar.gz \
| tar -xzC /usr/local/bin --transform 's#^.+/##x'
ARG DOCKER_VERSION=1.10.1
# Download docker
RUN mkdir -p /usr/local/bin \
&& curl -fL https://get.docker.com/builds/Linux/x86_64/docker-${DOCKER_VERSION}-ce.tgz \
| tar -xzC /usr/local/bin --transform 's#^.+/##x'
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
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

36
circle.yml Normal file
View File

@@ -0,0 +1,36 @@
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,12 +1,8 @@
package cluster
import (
"context"
"encoding/json"
"fmt"
"sync"
"time"
"github.com/cenk/backoff"
"github.com/containous/staert"
"github.com/containous/traefik/job"
@@ -14,6 +10,9 @@ import (
"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
@@ -250,6 +249,6 @@ func (s *datastoreTransaction) Commit(object Object) error {
}
s.dirty = true
log.Debugf("Transaction committed %s", s.id)
log.Debugf("Transaction commited %s", s.id)
return nil
}

View File

@@ -1,14 +1,13 @@
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

View File

@@ -1,152 +0,0 @@
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)
}

View File

@@ -1,313 +0,0 @@
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
}

View File

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

@@ -25,10 +25,11 @@ type TraefikConfiguration struct {
type GlobalConfiguration struct {
GraceTimeOut int64 `short:"g" description:"Duration to give active requests a chance to finish during hot-reload"`
Debug bool `short:"d" description:"Enable debug mode"`
CheckNewVersion bool `description:"Periodically check if a new version has been released"`
AccessLogsFile string `description:"Access logs file"`
TraefikLogsFile string `description:"Traefik logs file"`
LogLevel string `short:"l" description:"Log level"`
EntryPoints EntryPoints `description:"Entrypoints definition using format: --entryPoints='Name:http Address::8000 Redirect.EntryPoint:https' --entryPoints='Name:https Address::4442 TLS:tests/traefik.crt,tests/traefik.key'"`
EntryPoints EntryPoints `description:"Entrypoints definition using format: --entryPoints='Name:http Address::8000 Redirect.EntryPoint:https' --entryPoints='Name:https Address::4442 TLS:tests/traefik.crt,tests/traefik.key;prod/traefik.crt,prod/traefik.key'"`
Cluster *types.Cluster `description:"Enable clustering"`
Constraints types.Constraints `description:"Filter services by constraint, matching with service tags"`
ACME *acme.ACME `description:"Enable ACME (Let's Encrypt): automatic SSL"`
@@ -48,7 +49,6 @@ type GlobalConfiguration struct {
Boltdb *provider.BoltDb `description:"Enable Boltdb backend"`
Kubernetes *provider.Kubernetes `description:"Enable Kubernetes backend"`
Mesos *provider.Mesos `description:"Enable Mesos backend"`
Eureka *provider.Eureka `description:"Enable Eureka backend"`
}
// DefaultEntryPoints holds default entry points
@@ -264,21 +264,28 @@ func (certs *Certificates) String() string {
if len(*certs) == 0 {
return ""
}
return (*certs)[0].CertFile + "," + (*certs)[0].KeyFile
var result []string
for _, certificate := range *certs {
result = append(result, certificate.CertFile+","+certificate.KeyFile)
}
return strings.Join(result, ";")
}
// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func (certs *Certificates) Set(value string) error {
files := strings.Split(value, ",")
if len(files) != 2 {
return errors.New("Bad certificates format: " + value)
certificates := strings.Split(value, ";")
for _, certificate := range certificates {
files := strings.Split(certificate, ",")
if len(files) != 2 {
return errors.New("Bad certificates format: " + value)
}
*certs = append(*certs, Certificate{
CertFile: files[0],
KeyFile: files[1],
})
}
*certs = append(*certs, Certificate{
CertFile: files[0],
KeyFile: files[1],
})
return nil
}
@@ -316,64 +323,60 @@ func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration {
// default Web
var defaultWeb WebProvider
defaultWeb.Address = ":8080"
defaultWeb.Statistics = &types.Statistics{
RecentErrors: 10,
}
// default Marathon
var defaultMarathon provider.Marathon
defaultMarathon.Watch = true
defaultMarathon.Endpoint = "http://127.0.0.1:8080"
defaultMarathon.ExposedByDefault = true
defaultMarathon.Constraints = []types.Constraint{}
defaultMarathon.DialerTimeout = 60
defaultMarathon.Constraints = types.Constraints{}
// default Consul
var defaultConsul provider.Consul
defaultConsul.Watch = true
defaultConsul.Endpoint = "127.0.0.1:8500"
defaultConsul.Prefix = "traefik"
defaultConsul.Constraints = []types.Constraint{}
defaultConsul.Constraints = types.Constraints{}
// default ConsulCatalog
var defaultConsulCatalog provider.ConsulCatalog
defaultConsulCatalog.Endpoint = "127.0.0.1:8500"
defaultConsulCatalog.Constraints = []types.Constraint{}
defaultConsulCatalog.Constraints = types.Constraints{}
// default Etcd
var defaultEtcd provider.Etcd
defaultEtcd.Watch = true
defaultEtcd.Endpoint = "127.0.0.1:2379"
defaultEtcd.Prefix = "/traefik"
defaultEtcd.Constraints = []types.Constraint{}
defaultEtcd.Constraints = types.Constraints{}
//default Zookeeper
var defaultZookeeper provider.Zookepper
defaultZookeeper.Watch = true
defaultZookeeper.Endpoint = "127.0.0.1:2181"
defaultZookeeper.Prefix = "/traefik"
defaultZookeeper.Constraints = []types.Constraint{}
defaultZookeeper.Constraints = types.Constraints{}
//default Boltdb
var defaultBoltDb provider.BoltDb
defaultBoltDb.Watch = true
defaultBoltDb.Endpoint = "127.0.0.1:4001"
defaultBoltDb.Prefix = "/traefik"
defaultBoltDb.Constraints = []types.Constraint{}
defaultBoltDb.Constraints = types.Constraints{}
//default Kubernetes
var defaultKubernetes provider.Kubernetes
defaultKubernetes.Watch = true
defaultKubernetes.Endpoint = ""
defaultKubernetes.LabelSelector = ""
defaultKubernetes.Constraints = []types.Constraint{}
defaultKubernetes.Constraints = types.Constraints{}
// default Mesos
var defaultMesos provider.Mesos
defaultMesos.Watch = true
defaultMesos.Endpoint = "http://127.0.0.1:5050"
defaultMesos.ExposedByDefault = true
defaultMesos.Constraints = []types.Constraint{}
defaultMesos.Constraints = types.Constraints{}
defaultConfiguration := GlobalConfiguration{
Docker: &defaultDocker,
@@ -403,10 +406,11 @@ func NewTraefikConfiguration() *TraefikConfiguration {
TraefikLogsFile: "",
LogLevel: "ERROR",
EntryPoints: map[string]*EntryPoint{},
Constraints: []types.Constraint{},
Constraints: types.Constraints{},
DefaultEntryPoints: []string{},
ProvidersThrottleDuration: time.Duration(2 * time.Second),
MaxIdleConnsPerHost: 200,
CheckNewVersion: true,
},
ConfigFile: "",
}

View File

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

10
docs.Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM alpine:3.7
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/bin
COPY requirements.txt /mkdocs/
WORKDIR /mkdocs
VOLUME /mkdocs
RUN apk --no-cache --no-progress add py-pip \
&& pip install --trusted-host pypi.python.org --user -r requirements.txt

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æfik and have an overview of its internal architecture:
Let's zoom on Træfɪk and have an overview of its internal architecture:
![Architecture](img/internal.png)
- Incoming requests end on [entrypoints](#entrypoints), as the name suggests, they are the network entry points into Træfik (listening port, SSL, traffic redirection...).
- Incoming requests end on [entrypoints](#entrypoints), as the name suggests, they are the network entry points into Træfɪk (listening port, SSL, traffic redirection...).
- Traffic is then forwarded to a matching [frontend](#frontends). A frontend defines routes from [entrypoints](#entrypoints) to [backends](#backends).
Routes are created using requests fields (`Host`, `Path`, `Headers`...) and can match or not a request.
- The [frontend](#frontends) will then send the request to a [backend](#backends). A backend can be composed by one or more [servers](#servers), and by a load-balancing strategy.
@@ -26,7 +26,7 @@ Routes are created using requests fields (`Host`, `Path`, `Headers`...) and can
## Entrypoints
Entrypoints are the network entry points into Træfik.
Entrypoints are the network entry points into Træfɪk.
They can be defined using:
- a port (80, 443...)
@@ -73,62 +73,23 @@ And here is another example with client certificate authentication:
## Frontends
A frontend consists of a set of rules that determine how incoming requests are forwarded from an entrypoint to a backend.
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:
Rules may be classified in one of two groups: Modifiers and matchers.
- `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.
### 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 use multiple rules by separating them by `;`
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
@@ -143,7 +104,7 @@ Here is an example of frontends definition:
priority = 10
entrypoints = ["https"] # overrides defaultEntryPoints
[frontends.frontend2.routes.test_1]
rule = "HostRegexp:localhost,{subdomain:[a-z]+}.localhost"
rule = "Host:localhost,{subdomain:[a-z]+}.localhost"
[frontends.frontend3]
backend = "backend2"
[frontends.frontend3.routes.test_1]
@@ -161,55 +122,36 @@ 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):
@@ -217,20 +159,20 @@ By default, routes will be sorted (in descending order) using rules length (to a
You can customize priority by frontend:
```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"
```
[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`).
@@ -238,16 +180,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 are supported:
Various methods of load-balancing is supported:
- `wrr`: Weighted Round Robin
- `drr`: Dynamic Round Robin: increases weights on servers that perform better than others. It also rolls back to original weights if the servers have changed.
A circuit breaker can also be applied to a backend, preventing high loads on failing servers.
Initial state is Standby. CB observes the statistics and does not modify the request.
In case the condition matches, CB enters Tripped state, where it responds with predefined code or redirects to another frontend.
In case if condition matches, CB enters Tripped state, where it responds with predefines code or redirects to another frontend.
Once Tripped timer expires, CB enters Recovering state and resets all stats.
In case the condition does not match and recovery timer expires, CB enters Standby state.
In case if the condition does not match and recovery timer expires, CB enters Standby state.
It can be configured using:
@@ -291,26 +233,6 @@ 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).
@@ -346,17 +268,17 @@ Here is an example of backends and servers definition:
# Configuration
Træfik's configuration has two parts:
Træfɪk's configuration has two parts:
- 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).
- 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).
## Static Træfik configuration
## Static Træfɪk configuration
The static configuration is the global configuration which is setting up connections to configuration backends and entrypoints.
The static configuration is the global configuration which setting up connections to configuration backends and entrypoints.
Træfik can be configured using many configuration sources with the following precedence order.
Træfɪk can be configured using many configuration sources with the following precedence order.
Each item takes precedence over the item below it:
- [Key-value Store](/basics/#key-value-stores)
@@ -364,11 +286,11 @@ Each item takes precedence over the item below it:
- [Configuration file](/basics/#configuration-file)
- Default
It means that arguments override configuration file, and Key-value Store overrides arguments.
It means that arguments overrides configuration file, and Key-value Store overrides arguments.
### Configuration file
By default, Træfik will try to find a `traefik.toml` in the following places:
By default, Træfɪk will try to find a `traefik.toml` in the following places:
- `/etc/traefik/`
- `$HOME/.traefik/`
@@ -394,7 +316,7 @@ Note that all default values will be displayed as well.
### Key-value stores
Træfik supports several Key-value stores:
Træfɪk supports several Key-value stores:
- [Consul](https://consul.io)
- [etcd](https://coreos.com/etcd/)
@@ -403,7 +325,7 @@ Træfik 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æfik configuration
## Dynamic Træfɪk configuration
The dynamic configuration concerns :
@@ -411,9 +333,9 @@ The dynamic configuration concerns :
- [Backends](/basics/#backends)
- [Servers](/basics/#servers)
Træfik can hot-reload those rules which could be provided by [multiple configuration backends](/toml/#configuration-backends).
Træfɪk can hot-reload those rules which could be provided by [multiple configuration backends](/toml/#configuration-backends).
We only need to enable `watch` option to make Træfik watch configuration backend changes and generate its configuration automatically.
We only need to enable `watch` option to make Træfɪk watch configuration backend changes and generate its configuration automatically.
Routes to services will be created and updated instantly at any changes.
Please refer to the [configuration backends](/toml/#configuration-backends) section to get documentation on it.
@@ -422,19 +344,19 @@ Please refer to the [configuration backends](/toml/#configuration-backends) sect
Usage: `traefik [command] [--flag=flag_argument]`
List of Træfik available commands with description :                                                             
List of Træfɪk available commands with description :                                                             
- `version` : Print version 
- `storeconfig` : Store the static traefik configuration into a Key-value stores. Please refer to the [Store Træfik 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æfɪk configuration](/user-guide/kv-config/#store-trfk-configuration) section to get documentation on it.
Each command may have related flags.
All those related flags will be displayed with :
```bash
$ traefik [command] --help
$ traefik [command] --help
```
Note that each command is described at the beginning of the help section:
Note that each command is described at the begining 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: 52 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View File

@@ -1,5 +1,5 @@
<p align="center">
<img src="img/traefik.logo.png" alt="Træfik" title="Træfik" />
<img src="img/traefik.logo.png" alt="Træfɪk" title="Træfɪk" />
</p>
[![Build Status](https://travis-ci.org/containous/traefik.svg?branch=master)](https://travis-ci.org/containous/traefik)
@@ -10,8 +10,8 @@
[![Twitter](https://img.shields.io/twitter/follow/traefikproxy.svg?style=social)](https://twitter.com/intent/follow?screen_name=traefikproxy)
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.
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.
## 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æfik.
Here enters Træfɪk.
![Architecture](img/architecture.png)
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.
Træfɪk can listen to your service registry/orchestrator API, and knows each time a microservice is added, removed, killed or upgraded, and can generate its configuration automatically.
Routes to your services will be created instantly.
Run it and forget it!
## Quickstart
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.
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.
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æfik features and see some demos with Kubernetes.
You will learn fundamental Træfɪk features and see some demos with Kubernetes.
[![Traefik ContainerCamp UK](http://img.youtube.com/vi/aFtpIShV60I/0.jpg)](https://www.youtube.com/watch?v=aFtpIShV60I)
Here is a talk (in French) given by [Emile Vauge](https://github.com/emilevauge) at the [Devoxx France 2016](http://www.devoxx.fr) conference.
You will learn fundamental Træfik features and see some demos with Docker, Mesos/Marathon and Let's Encrypt.
You will learn fundamental Træfɪk features and see some demos with Docker, Mesos/Marathon and Let's Encrypt.
[![Traefik Devoxx France](http://img.youtube.com/vi/QvAz9mVx5TI/0.jpg)](http://www.youtube.com/watch?v=QvAz9mVx5TI)
@@ -70,65 +70,41 @@ docker run -d -p 8080:8080 -p 80:80 -v $PWD/traefik.toml:/etc/traefik/traefik.to
## Test it
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`:
You can test Træfɪk easily using [Docker compose](https://docs.docker.com/compose), with this `docker-compose.yml` file:
```yaml
version: '2'
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
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
whoami1:
image: emilevauge/whoami
labels:
- "traefik.backend=whoami"
- "traefik.frontend.rule=Host:whoami.docker.localhost"
networks:
webgateway:
driver: bridge
whoami2:
image: emilevauge/whoami
labels:
- "traefik.backend=whoami"
- "traefik.frontend.rule=Host:whoami.docker.localhost"
```
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 it:
```
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 services `test_whoami_1` and `test_whoami_2`:
Finally, test load-balancing between the two servers `whoami1` and `whoami2`:
```shell
```bash
$ curl -H Host:whoami.docker.localhost http://127.0.0.1
Hostname: ef194d07634a
IP: 127.0.0.1

View File

@@ -9,15 +9,13 @@
# Global configuration
################################################################
# 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.
# Timeout in seconds.
# Duration to give active requests a chance to finish during hot-reloads
#
# Optional
# Default: "10s"
# Default: 10
#
# graceTimeOut = "10s"
# graceTimeOut = 10
# Enable debug mode
#
@@ -58,32 +56,17 @@
# 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: "2s"
# Default: "2"
#
# ProvidersThrottleDuration = "2s"
# ProvidersThrottleDuration = "5"
# 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.
# 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.
#
# Optional
# 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
# Default: http.DefaultMaxIdleConnsPerHost
#
# MaxIdleConnsPerHost = 200
@@ -105,9 +88,9 @@
### Constraints
In a micro-service architecture, with a central service discovery, setting constraints limits Træfik scope to a smaller number of routes.
In a micro-service architecture, with a central service discovery, setting constraints limits Træfɪk scope to a smaller number of routes.
Træfik filters services according to service attributes/tags set in your configuration backends.
Træfɪk filters services according to service attributes/tags set in your configuration backends.
Supported backends:
@@ -117,13 +100,12 @@ Supported backends:
- Zookeeper
- Etcd
- Consul Catalog
- Rancher
Supported filters:
- `tag`
- ```tag```
```toml
```
# Constraints definition
#
# Optional
@@ -209,24 +191,20 @@ 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]
@@ -270,27 +248,6 @@ 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
@@ -325,50 +282,13 @@ email = "test@traefik.io"
#
storage = "acme.json" # or "traefik/acme/account" if using KV store
# Entrypoint to proxy acme challenge/apply certificates to.
# Entrypoint to proxy acme challenge 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
@@ -421,7 +341,7 @@ entryPoint = "https"
## File backend
Like any other reverse proxy, Træfik can be configured with a file. You have two choices:
Like any other reverse proxy, Træfɪk can be configured with a file. You have two choices:
- simply add your configuration at the end of the global configuration file `traefik.toml`:
@@ -555,7 +475,7 @@ filename = "rules.toml"
rule = "Path:/test"
```
If you want Træfik to watch file changes automatically, just add:
If you want Træfɪk to watch file changes automatically, just add:
```toml
[file]
@@ -571,12 +491,6 @@ To enable it:
[web]
address = ":8080"
# Set the root path for webui and API
#
# Optional
#
# path = "/mypath"
#
# SSL certificate and key used
#
# Optional
@@ -589,28 +503,17 @@ 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
@@ -620,7 +523,7 @@ address = ":8080"
- `/ping`: `GET` simple endpoint to check for Træfik process liveness.
```shell
```sh
$ curl -sv "http://localhost:8080/ping"
* Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
@@ -640,14 +543,14 @@ OK
- `/health`: `GET` json metrics
```shell
```sh
$ curl -s "http://localhost:8080/health" | jq .
{
// Træfik PID
// Træfɪk PID
"pid": 2458,
// Træfik server uptime (formated time)
// Træfɪk server uptime (formated time)
"uptime": "39m6.885931127s",
// Træfik server uptime in seconds
// Træfɪk server uptime in seconds
"uptime_sec": 2346.885931127,
// current server date
"time": "2015-10-07 18:32:24.362238909 +0200 CEST",
@@ -657,7 +560,7 @@ $ curl -s "http://localhost:8080/health" | jq .
"status_code_count": {
"502": 1
},
// count HTTP response status code since Træfik started
// count HTTP response status code since Træfɪk started
"total_status_code_count": {
"200": 7,
"404": 21,
@@ -674,32 +577,13 @@ $ 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,
// 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"
}
]
"average_response_time_sec": 0.8648016000000001
}
```
- `/api`: `GET` configuration for all providers
```shell
```sh
$ curl -s "http://localhost:8080/api" | jq .
{
"file": {
@@ -771,15 +655,10 @@ $ 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æfik can be configured to use Docker as a backend configuration:
Træfɪk can be configured to use Docker as a backend configuration:
```toml
################################################################
@@ -818,7 +697,6 @@ 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
@@ -851,40 +729,27 @@ swarmmode = false
Labels can be used on containers to override default behaviour:
- `traefik.backend=foo`: give the name `backend-foo` to the generated backend for this container.
- `traefik.backend=foo`: assign the container to `foo` backend
- `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æ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.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.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
- `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.
- `traefik.docker.network`: Set the docker network to use for connections to this 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>`
NB: when running inside a container, Træfɪk will need network access through `docker network connect <network> <traefik-container>`
## Marathon backend
Træfik can be configured to use Marathon as a backend configuration:
Træfɪk can be configured to use Marathon as a backend configuration:
```toml
@@ -927,7 +792,7 @@ domain = "marathon.localhost"
# Expose Marathon apps by default in traefik
#
# Optional
# Default: true
# Default: false
#
# exposedByDefault = true
@@ -960,9 +825,6 @@ 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
@@ -970,37 +832,6 @@ 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:
@@ -1011,13 +842,11 @@ 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æfik
- `traefik.enable=false`: disable this application in Træfɪk
- `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
@@ -1026,7 +855,7 @@ Labels can be used on containers to override default behaviour:
## Mesos generic backend
Træfik can be configured to use Mesos as a backend configuration:
Træfɪk can be configured to use Mesos as a backend configuration:
```toml
@@ -1085,14 +914,12 @@ domain = "mesos.localhost"
# Zookeeper timeout (in seconds)
#
# Optional
# Default: 30
#
# ZkDetectionTimeout = 30
# Polling interval (in seconds)
#
# Optional
# Default: 30
#
# RefreshSeconds = 30
@@ -1105,15 +932,14 @@ domain = "mesos.localhost"
# HTTP Timeout (in seconds)
#
# Optional
# Default: 30
#
# StateTimeoutSecond = "30"
# StateTimeoutSecond = "host"
```
## Kubernetes Ingress backend
Træfik can be configured to use Kubernetes Ingress as a backend configuration:
Træfɪk can be configured to use Kubernetes Ingress as a backend configuration:
```toml
################################################################
@@ -1127,46 +953,17 @@ Træfik 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
# the environment variables KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT
# to construct the endpoint.
# When deployed as a replication controller in Kubernetes,
# Traefik will use env variable KUBERNETES_SERVICE_HOST
# and KUBERNETES_SERVICE_PORT_HTTPS as 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
#
# 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
# Optional
#
# endpoint = "http://localhost:8080"
# Bearer token used for the Kubernetes client configuration.
# namespaces = ["default","production"]
#
# 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"
#
@@ -1176,36 +973,11 @@ 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æfik can be configured to use Consul as a backend configuration:
Træfɪk can be configured to use Consul as a backend configuration:
```toml
################################################################
@@ -1257,7 +1029,7 @@ Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-val
## Consul catalog backend
Træfik can be configured to use service discovery catalog of Consul as a backend configuration:
Træfɪk can be configured to use service discovery catalog of Consul as a backend configuration:
```toml
################################################################
@@ -1294,7 +1066,7 @@ used in consul.
Additional settings can be defined using Consul Catalog tags:
- `traefik.enable=false`: disable this container in Træfik
- `traefik.enable=false`: disable this container in Træfɪk
- `traefik.protocol=https`: override the default `http` protocol
- `traefik.backend.weight=10`: assign this weight to the container
- `traefik.backend.circuitbreaker=NetworkErrorRatio() > 0.5`
@@ -1308,7 +1080,7 @@ Additional settings can be defined using Consul Catalog tags:
## Etcd backend
Træfik can be configured to use Etcd as a backend configuration:
Træfɪk can be configured to use Etcd as a backend configuration:
```toml
################################################################
@@ -1345,13 +1117,6 @@ prefix = "/traefik"
#
# filename = "etcd.tmpl"
# Use etcd user/pass authentication
#
# Optional
#
# username = foo
# password = bar
# Enable etcd TLS connection
#
# Optional
@@ -1368,7 +1133,7 @@ Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-val
## Zookeeper backend
Træfik can be configured to use Zookeeper as a backend configuration:
Træfɪk can be configured to use Zookeeper as a backend configuration:
```toml
################################################################
@@ -1397,7 +1162,7 @@ watch = true
#
# Optional
#
prefix = "traefik"
prefix = "/traefik"
# Override default configuration template. For advanced users :)
#
@@ -1410,7 +1175,7 @@ Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-val
## BoltDB backend
Træfik can be configured to use BoltDB as a backend configuration:
Træfɪk can be configured to use BoltDB as a backend configuration:
```toml
################################################################
@@ -1448,297 +1213,4 @@ 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 (beta)
# Clustering / High Availability
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.
This guide explains how tu use Træfɪk in high availability mode.
In order to deploy and configure multiple Træfɪk instances, without copying the same configuration file on each instance, we will use a distributed Key-Value store.
## Prerequisites
@@ -9,12 +9,11 @@ You will need a working KV store cluster.
## File configuration to KV store migration
We created a special Træfik command to help configuring your Key Value store from a Træfik TOML configuration file.
We created a special Træfɪk command to help configuring your Key Value store from a Træfɪk TOML configuration file.
Please refer to [this section](/user-guide/kv-config/#store-configuration-in-key-value-store) to get more details.
## Deploy a Træfik cluster
## Deploy a Træfɪk cluster
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.
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.

View File

@@ -1,11 +1,11 @@
# Examples
You will find here some configuration examples of Træfik.
You will find here some configuration examples of Træfɪk.
## 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,34 +107,11 @@ 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æfik as an Ingress controller in a Kubernetes cluster.
This guide explains how to use Træfɪk as an Ingress controller in a Kubernetes cluster.
If you are not familiar with Ingresses in Kubernetes you might want to read the [Kubernetes user guide](http://kubernetes.io/docs/user-guide/ingress/)
The config files used in this guide can be found in the [examples directory](https://github.com/containous/traefik/tree/master/examples/k8s)
@@ -12,76 +12,14 @@ 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).
### Role Based Access Control configuration (Kubernetes 1.6+ only)
## Deploy Træfɪk
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
We are going to deploy Træfɪk with a
[Deployment](http://kubernetes.io/docs/user-guide/deployments/), as this will
allow you to easily roll out config changes or update the image.
```yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
namespace: kube-system
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
@@ -99,11 +37,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
- image: traefik:v1.0.0
name: traefik-ingress-lb
resources:
limits:
@@ -122,14 +60,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æ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.
> notice that we binding port 80 on the Træfɪk container to port 80 on the host.
> With a multi node cluster we might expose Træfɪk with a NodePort or LoadBalancer service
> and run more than 1 replica of Træfɪk for high availability.
To deploy Træfik to your cluster start by submitting the deployment to the cluster with `kubectl`:
To deploy Træfɪk to your cluster start by submitting the deployment to the cluster with `kubectl`:
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik.yaml
```sh
kubectl apply -f examples/k8s/traefik.yaml
```
### Check the deployment
@@ -138,7 +76,7 @@ Now lets check if our deployment was successful.
Start by listing the pods in the `kube-system` namespace:
```shell
```sh
$kubectl --namespace=kube-system get pods
NAME READY STATUS RESTARTS AGE
@@ -148,38 +86,26 @@ traefik-ingress-controller-678226159-eqseo 1/1 Running 0 7m
```
You should see that after submitting the Deployment to Kubernetes it has launched
a pod, and it is now running. _It might take a few moments for kubernetes to pull
the Træfik image and start the container._
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._
> 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æfik on port 80 of your minikube instance.
You should now be able to access Træfɪk on port 80 of your minikube instance.
```sh
curl $(minikube ip)
404 page not found
```
> We expect to see a 404 response here as we haven't yet given Træ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).
> We expect to see a 404 response here as we haven't yet given Træfɪk any configuration.
## Submitting An Ingress to the cluster.
Lets start by creating a Service and an Ingress that will expose the
[Træfik Web UI](https://github.com/containous/traefik#web-ui).
[Træfɪk Web UI](https://github.com/containous/traefik#web-ui).
```yaml
apiVersion: v1
@@ -189,7 +115,7 @@ metadata:
namespace: kube-system
spec:
selector:
k8s-app: traefik-ingress-lb
k8s-app: traefik-ingress-lb
ports:
- port: 80
targetPort: 8080
@@ -199,8 +125,6 @@ kind: Ingress
metadata:
name: traefik-web-ui
namespace: kube-system
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: traefik-ui.local
@@ -212,22 +136,22 @@ spec:
```
[examples/k8s/ui.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/ui.yaml)
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/ui.yaml
```sh
kubectl apply -f examples/k8s/ui.yaml
```
Now lets setup an entry in our /etc/hosts file to route `traefik-ui.local`
to our cluster.
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æfik Web UI.
We should now be able to visit [traefik-ui.local](http://traefik-ui.local) in the browser and view the Træfɪk Web UI.
## Name based routing
@@ -339,8 +263,8 @@ spec:
```
[examples/k8s/cheese-deployments.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/cheese-deployments.yaml)
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-deployments.yaml
```sh
kubectl apply -f examples/k8s/cheese-deployments.yaml
```
Next we need to setup a service for each of the cheese pods.
@@ -377,8 +301,6 @@ apiVersion: v1
kind: Service
metadata:
name: wensleydale
annotations:
traefik.backend.circuitbreaker: "NetworkErrorRatio() > 0.5"
spec:
ports:
- name: http
@@ -388,15 +310,10 @@ 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)
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-services.yaml
```sh
kubectl apply -f examples/k8s/cheese-services.yaml
```
Now we can submit an ingress for the cheese websites.
@@ -406,8 +323,6 @@ apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cheese
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: stilton.local
@@ -436,18 +351,18 @@ spec:
> Notice that we list each hostname, and add a backend service.
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-ingress.yaml
```sh
kubectl apply -f examples/k8s/cheese-ingress.yaml
```
Now visit the [Træfik dashboard](http://traefik-ui.local/) and you should
Now visit the [Træfɪk dashboard](http://traefik-ui.local/) and you should
see a frontend for each host. Along with a backend listing for each service
with a Server set up for each pod.
If you edit your `/etc/hosts` again you should be able to access the cheese
websites in your browser.
```shell
```sh
echo "$(minikube ip) stilton.local cheddar.local wensleydale.local" | sudo tee -a /etc/hosts
```
@@ -470,8 +385,7 @@ kind: Ingress
metadata:
name: cheeses
annotations:
kubernetes.io/ingress.class: traefik
traefik.frontend.rule.type: PathPrefixStrip
traefik.frontend.rule.type: pathprefixstrip
spec:
rules:
- host: cheeses.local
@@ -492,15 +406,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æfik to strip the prefix from the url path
> Notice that we are configuring Træfɪk to strip the prefix from the url path
> with the `traefik.frontend.rule.type` annotation so that we can use
> the containers from the previous example without modification.
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheeses-ingress.yaml
```sh
kubectl apply -f examples/k8s/cheeses-ingress.yaml
```
```shell
```sh
echo "$(minikube ip) cheeses.local" | sudo tee -a /etc/hosts
```
@@ -509,72 +423,3 @@ 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æfik using a configuration loaded from a Key-value store.
This section explains how to launch Træfɪk using a configuration loaded from a Key-value store.
Træfik supports several Key-value stores:
Træfɪk 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æfik global configuration will be getted from a [Consul](https://consul.io) store.
The Træfɪk global configuration will be getted from a [Consul](https://consul.io) store.
First we have to launch Consul in a container.
The [docker-compose file](https://docs.docker.com/compose/compose-file/) allows us to launch Consul and four instances of the trivial app [emilevauge/whoamI](https://github.com/emilevauge/whoamI) :
```yaml
```yml
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æfik global configuration, as we do with a [TOML file configuration](/toml).
We should now fill the store with the Træfɪk global configuration, as we do with a [TOML file configuration](/toml).
To do that, we can send the Key-value pairs via [curl commands](https://www.consul.io/intro/getting-started/kv.html) or via the [Web UI](https://www.consul.io/intro/getting-started/ui.html).
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.
Hopefully, Træfɪk allows automation of this process using the `storeconfig` subcommand.
Please refer to the [store Træfɪk configuration](/user-guide/kv-config/#store-configuration-in-key-value-store) section to get documentation on it.
Here is the toml configuration we would like to store in the Key-value Store :
@@ -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æfik
## Launch Træfɪk
We will now launch Træfik in a container.
We use CLI flags to setup the connection between Træfik and Consul.
We will now launch Træfɪk in a container.
We use CLI flags to setup the connection between Træfɪk and Consul.
All the rest of the global configuration is stored in Consul.
Here is the [docker-compose file](https://docs.docker.com/compose/compose-file/) :
```yaml
```yml
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æfik using `consul` flags :
Then, we have to provide CA, Cert and Key to Træfɪk using `consul` flags :
- `--consul.tls`
- `--consul.tls.ca=path/to/the/file`
@@ -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æfik.
Following our example, we will provide backends/frontends rules to Træfɪk.
Note that this section is independent of the way Træfik got its static configuration.
Note that this section is independent of the way Træfɪk got its static configuration.
It means that the static configuration can either come from the same Key-value store or from any other sources.
## Key-value storage structure
@@ -259,13 +259,13 @@ And there, the same dynamic configuration in a KV Store (using `prefix = "traefi
## Atomic configuration changes
Træfik can watch the backends/frontends configuration changes and generate its configuration automatically.
Træfɪk can watch the backends/frontends configuration changes and generate its configuration automatically.
Note that only backends/frontends rules are dynamic, the rest of the Træfik configuration stay static.
Note that only backends/frontends rules are dynamic, the rest of the Træfɪk configuration stay static.
The [Etcd](https://github.com/coreos/etcd/issues/860) and [Consul](https://github.com/hashicorp/consul/issues/886) backends do not support updating multiple keys atomically. As a result, it may be possible for Træ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.
The [Etcd](https://github.com/coreos/etcd/issues/860) and [Consul](https://github.com/hashicorp/consul/issues/886) backends do not support updating multiple keys atomically. As a result, it may be possible for Træfɪk to read an intermediate configuration state despite judicious use of the `--providersThrottleDuration` flag. To solve this problem, Træfɪk supports a special key called `/traefik/alias`. If set, Træfɪk use the value as an alternative key prefix.
Given the key structure below, Træfik 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æfɪk 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æfik *will not watch for key changes in the `/traefik_configurations` prefix*. It will only watch for changes in the `/traefik/alias`.
Note that Træfɪk *will not watch for key changes in the `/traefik_configurations` prefix*. It will only watch for changes in the `/traefik/alias`.
Further, if the `/traefik/alias` key is set, all other configuration with `/traefik/backends` or `/traefik/frontends` prefix are ignored.
# Store configuration in Key-value store
Don't forget to [setup the connection between Træ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).
Don't forget to [setup the connection between Træfɪk and Key-value store](/user-guide/kv-config/#launch-trfk).
The static Træfɪk configuration in a key-value store can be automatically created and updated, using the [`storeconfig` subcommand](/basics/#commands).
```bash
$ traefik storeconfig [flags] ...
$ 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æfik will not start but the [static configuration](/basics/#static-trfk-configuration) will be uploaded into the Key-value store.
Træfɪk will not start but the [static configuration](/basics/#static-trfk-configuration) will be uploaded into the Key-value store.
If you configured ACME (Let's Encrypt), your registration account and your certificates will also be uploaded.
To upload your ACME certificates to the KV store, get your traefik TOML file and add the new `storage` option in the `acme` section:
```toml
```
[acme]
email = "test@traefik.io"
storage = "traefik/acme/account" # the key where to store your certificates in the KV store
@@ -323,7 +323,6 @@ 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

@@ -1,96 +0,0 @@
# 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æfik on it.
how to deploy Træfɪk on it.
The cluster consists of:
The cluster constist of:
- 3 servers
- 1 manager
@@ -19,10 +19,10 @@ The cluster consists of:
## Cluster provisioning
First, let's create all the required nodes. It's a shorter version of
First, let's create all the nodes required. It's a shorter version of
the [swarm tutorial](https://docs.docker.com/engine/swarm/swarm-tutorial/).
```shell
```sh
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
```shell
```sh
docker-machine ssh manager "docker swarm init \
--listen-addr $(docker-machine ip manager) \
--advertise-addr $(docker-machine ip manager)"
@@ -47,7 +47,6 @@ 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) \
@@ -57,7 +56,7 @@ docker-machine ssh worker2 "docker swarm join \
Let's validate the cluster is up and running.
```shell
```sh
docker-machine ssh manager docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
2a770ov9vixeadep674265u1n worker1 Ready Active
@@ -67,7 +66,7 @@ esbhhy6vnqv90xomjaomdgy46 worker2 Ready Active
Finally, let's create a network for Træfik to use.
```shell
```sh
docker-machine ssh manager "docker network create --driver=overlay traefik-net"
```
@@ -79,7 +78,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 \
@@ -104,7 +103,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 underlying container) to the `traefik-net` network.
the underlined 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
@@ -115,27 +114,22 @@ 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.
```shell
```sh
docker-machine ssh manager "docker service create \
--name whoami0 \
--label traefik.port=80 \
--network traefik-net \
emilevauge/whoami"
docker-machine ssh manager "docker service create \
--name whoami1 \
--label traefik.port=80 \
--network traefik-net \
--label traefik.backend.loadbalancer.sticky=true \
emilevauge/whoami"
```
Note that we set whoami1 to use sticky sessions (`--label traefik.backend.loadbalancer.sticky=true`). We'll demonstrate that later.
If using `docker stack deploy`, there is [a specific way that the labels must be defined in the docker-compose file](https://github.com/containous/traefik/issues/994#issuecomment-269095109).
Check that everything is scheduled and started:
```shell
```sh
docker-machine ssh manager "docker service ls"
ID NAME REPLICAS IMAGE COMMAND
ab046gpaqtln whoami0 1/1 emilevauge/whoami
@@ -143,9 +137,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æfik
## Access to your apps through Træfɪk
```shell
```sh
curl -H Host:whoami0.traefik http://$(docker-machine ip manager)
Hostname: 8147a7746e7a
IP: 127.0.0.1
@@ -186,7 +180,7 @@ X-Forwarded-Server: 8fbc39271b4c
Note that as Træfik is published, you can access it from any machine
and not only the manager.
```shell
```sh
curl -H Host:whoami0.traefik http://$(docker-machine ip worker1)
Hostname: 8147a7746e7a
IP: 127.0.0.1
@@ -224,82 +218,6 @@ 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æfik 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æfɪk 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.
```shell
```sh
docker-machine create -d virtualbox mh-keystore
```
Then we install the service registry [Consul](https://consul.io) on this machine:
```shell
```sh
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.
```shell
```sh
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.
```shell
```sh
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:
```shell
```sh
eval $(docker-machine env --swarm mhs-demo0)
docker network create --driver overlay --subnet=10.0.9.0/24 my-net
```
## Deploy Træfik
## Deploy Træfɪk
Deploy Træfik:
Deploy Træfɪk:
```shell
```sh
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`:
```shell
```sh
eval $(docker-machine env --swarm mhs-demo0)
docker run -d --name=whoami0 --net=my-net --env="constraint:node==mhs-demo0" emilevauge/whoami
docker run -d --name=whoami1 --net=my-net --env="constraint:node==mhs-demo1" emilevauge/whoami
@@ -118,7 +118,7 @@ docker run -d --name=whoami1 --net=my-net --env="constraint:node==mhs-demo1" emi
Check that everything is started:
```shell
```sh
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ba2c21488299 emilevauge/whoami "/whoamI" 8 seconds ago Up 9 seconds 80/tcp mhs-demo1/whoami1
@@ -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æfik
## Access to your apps through Træfɪk
```shell
```sh
curl -H Host:whoami0.traefik http://$(docker-machine ip mhs-demo0)
Hostname: 8147a7746e7a
IP: 127.0.0.1
@@ -167,3 +167,4 @@ X-Forwarded-Server: 8fbc39271b4c
```
![](http://i.giphy.com/ujUdrdpX7Ok5W.gif)

View File

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

View File

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

@@ -3,7 +3,7 @@ kind: Ingress
metadata:
name: cheeses
annotations:
traefik.frontend.rule.type: PathPrefixStrip
traefik.frontend.rule.type: pathprefixstrip
spec:
rules:
- host: cheeses.local

View File

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

View File

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

632
glide.lock generated
View File

@@ -1,148 +1,108 @@
hash: eddc889b1c0fc19ad91d886268e46ebdf85cd9e376e78b96b0d6661cc5842aca
updated: 2017-06-29T16:47:14.848940186+02:00
hash: fa6c0ac899b3c9296d83f1d4110186b339101b800b241e08cdcd2e3d49270562
updated: 2016-12-09T13:43:16.816754682+01:00
imports:
- name: cloud.google.com/go
version: 2e6a95edb1071d750f6d7db777bf66cd2997af6c
subpackages:
- compute/metadata
- internal
- name: github.com/abbot/go-http-auth
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
version: cb4372376e1e00e9f6ab9ec142e029302c9e7140
- name: github.com/boltdb/bolt
version: e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd
version: f4c032d907f61f08dba2d719c58f108a1abb8e81
- name: github.com/BurntSushi/toml
version: b26d9c308763d68093482582cea63d69be07a0f0
version: 99064174e013895bbd9b025c31100bd1d9b590ca
- name: github.com/BurntSushi/ty
version: 6add9cd6ad42d389d6ead1dde60b4ad71e46fd74
subpackages:
- fun
- name: github.com/cenk/backoff
version: 5d150e7eec023ce7a124856b37c68e54b4050ac7
version: 8edc80b07f38c27352fb186d971c628a6c32552b
- name: github.com/codahale/hdrhistogram
version: 9208b142303c12d8899bae836fd524ac9338b4fd
version: f8ad88b59a584afeee9d334eff879b104439117b
- name: github.com/codegangsta/cli
version: bf4a526f48af7badd25d2cb02d587e1b01be3b50
version: 1efa31f08b9333f1bd4882d61f9d668a70cd902e
- name: github.com/codegangsta/negroni
version: c0db5feaa33826cd5117930c8f4ee5c0f565eec6
version: 3f7ce7b928e14ff890b067e5bbbc80af73690a9c
- name: github.com/containous/flaeg
version: b5d2dc5878df07c2d74413348186982e7b865871
version: a731c034dda967333efce5f8d276aeff11f8ff87
- name: github.com/containous/mux
version: a819b77bba13f0c0cbe36e437bc2e948411b3996
- name: github.com/containous/staert
version: 1e26a71803e428fd933f5f9c8e50a26878f53147
- name: github.com/coreos/etcd
version: c400d05d0aa73e21e431c16145e558d624098018
version: 1c9e0a0e33051fed6c05c141e6fcbfe5c7f2a899
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: 48702e0da86bd25e76cfef347e2adeb434a0d0a6
version: 43e4800a6165b4e02bb2a36673c54b230d6f7b26
subpackages:
- daemon
- name: github.com/coreos/pkg
version: fa29b1d70f0beaddd4c7021607cc3c3be8ce94b8
subpackages:
- health
- httputil
- timeutil
- name: github.com/davecgh/go-spew
version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
subpackages:
- spew
- 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
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: 49bf474f9ed7ce7143a59d1964ff7b7fd9b52178
version: 534753663161334baba06f13b8efa4cad22b5bc5
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: 3d1601b9d2436a70b0dfc045a23f6503d19195df
version: 62043eb79d581a32ea849645277023c550732e52
subpackages:
- client
- client/transport
@@ -160,17 +120,34 @@ imports:
- types/time
- types/versions
- name: github.com/docker/go-connections
version: 990a1a1a70b0da4c4cb70e117971a4f0babfbf1a
version: 988efe982fdecb46f01d53465878ff1f2ff411ce
subpackages:
- nat
- sockets
- tlsconfig
- name: github.com/docker/go-units
version: 0dadbb0345b35ec7ef35e228dabb8de89a65bf52
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: 1d8431073ae03cdaedb198a89722f3aab6d418ef
version: 3fce6a0f26e07da3eac45796a8e255547a47a750
subpackages:
- store
- store/boltdb
@@ -178,117 +155,59 @@ imports:
- store/etcd
- store/zookeeper
- name: github.com/donovanhide/eventsource
version: 441a03aa37b3329bbb79f43de81914ea18724718
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: 30f82fa23fd844bd5bb1e5f216db87fd77b5eb43
- name: github.com/emicklei/go-restful
version: 892402ba11a2e2fd5e1295dd633481f27365f14d
subpackages:
- log
- swagger
- name: github.com/fatih/color
version: 9131ab34cf20d2f6d83fdc67168a5430d1c7dc23
version: 9a6736ed45b44bf3835afeebb3034b57ed329f3e
- name: github.com/gambol99/go-marathon
version: dd6cbd4c2d71294a19fb89158f2a00d427f174ab
- 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
version: a558128c87724cd7430060ef5aedf39f83937f55
- name: github.com/go-check/check
version: 4f90aeace3a26ad7021961c297b22c42160c7b25
- name: github.com/gogo/protobuf
version: 909568be09de550ed094403c2bf8a261b5bb730a
version: 99cb9b23110011cc45571c901ecae6f6f5e65cd3
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: 6896997c7c9fe603fb9d2e8e92303bb18481e60a
version: 55263f30529cb06f5b478efc333390b791cfe3b1
subpackages:
- github
- name: github.com/google/go-querystring
version: 53e6ce116135b80d037921a7fdd5138cf32d7a8a
version: 9235644dd9e52eeae6fa48efd539fdc351a0af53
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: a69d9f6de432e2c6b296a947d8a5ee88f68522cf
- name: github.com/hashicorp/consul
version: 3f92cc70e8163df866873c16c6d89889b5c95fc4
version: d8e2fb7dd594163e25a89bc52c1a4613f5c5bfb8
subpackages:
- api
- name: github.com/hashicorp/go-cleanhttp
version: 3573b8b52aa7b37b9358d966a898feb387f62437
version: ad28ea4487f05916463e2423a55166280e8254b5
- name: github.com/hashicorp/go-version
version: 03c5bf6be031b6dd45afec16b1cf94fc8938bc77
version: e96d3840402619007766590ecea8dd7af1292276
- name: github.com/hashicorp/serf
version: 19f2c401e122352c047a84d6584dd51e2fb8fcc4
version: b03bf85930b2349eb04b97c8fac437495296e3e7
subpackages:
- coordinate
- name: github.com/JamesClonk/vultr
version: 0f156dd232bc4ebf8a32ba83fec57c0e4c9db69f
- name: github.com/jarcoal/httpmock
version: 145b10d659265440f062c31ea15326166bae56ee
- name: github.com/libkermit/compose
version: cadc5a3b83a15790174bd7fbc75ea2529785e772
subpackages:
- lib
- name: github.com/jmespath/go-jmespath
version: bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d
- name: github.com/jonboulle/clockwork
version: 72f9bd7c4e0c2a40055ab3d0f09654f730cce982
- name: github.com/juju/ratelimit
version: 77ed1c8a01217656d2080ad51981f6e99adaa177
- check
- name: github.com/libkermit/docker
version: 55e3595409924fcfbb850811e5a7cdbe8960a0b7
- name: github.com/mailgun/manners
version: a585afd9d65c0e05f6c003f921e71ebc05074f4f
- 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: 02e3cf038dcea8290e44424da473dd12be796a8a
- name: github.com/matttproud/golang_protobuf_extensions
version: c12348ce28de40eed0136aa2b644d0ee0650e56c
subpackages:
- pbutil
version: 525bedee691b5a8df547cb5cf9f86b7fb1883e24
- name: github.com/mesos/mesos-go
version: 068d5470506e3780189fe607af40892814197c5e
subpackages:
@@ -312,106 +231,64 @@ imports:
- records/state
- util
- name: github.com/Microsoft/go-winio
version: fff283ad5116362ca252298cfc9b95828956d85d
version: ce2922f643c8fd76b46cadc7f404a06282678b34
- name: github.com/miekg/dns
version: 8060d9f51305bbe024b99679454e62f552cd0b0b
version: 5d001d020961ae1c184f9f8152fdc73810481677
- name: github.com/mitchellh/mapstructure
version: 53818660ed4955e899c0bcafa97299a388bd7c8e
- name: github.com/mvdan/xurls
version: db96455566f05ffe42bd6ac671f05eeb1152b45d
version: f3009df150dadf309fdee4a54ed65c124afad715
- name: github.com/moul/http2curl
version: b1479103caacaa39319f75e7f57fc545287fca0d
- name: github.com/NYTimes/gziphandler
version: 316adfc72ed3b0157975917adf62ba2dc31842ce
repo: https://github.com/containous/gziphandler.git
vcs: git
version: f6438dbf4a82c56684964b03956aa727b0d7816b
- name: github.com/ogier/pflag
version: 45c278ab3607870051a2ea9040bb85fcb8557481
- name: github.com/opencontainers/runc
version: 50401b5b4c2e01e4f1372b73a021742deeaf4e2d
version: 02f8fa7863dd3f82909a73e2061897828460d52f
subpackages:
- libcontainer/user
- 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/parnurzeal/gorequest
version: e30af16d4e485943aab0b0885ad6bdbb8c0d3dc7
- 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: 256dc444b735e061061cf46c809487313d5b0065
version: 572520ed46dbddaed19ea3d9541bdd0494163693
- name: github.com/samuel/go-zookeeper
version: 1d7be4effb13d2d908342d349d71a284a7542693
version: 87e1bca4477a3cc767ca71be023ced183d74e538
subpackages:
- zk
- name: github.com/satori/go.uuid
version: 879c5887cd475cd7864858769793b2ceb0d44feb
- name: github.com/Sirupsen/logrus
version: 10f801ebc38b33738c9d17d50860f484a0988ff5
- name: github.com/spf13/pflag
version: 5ccb023bc27df288a957c5e994cd44fd19619465
version: 3ec0642a7fb6488f65b06f9040adc67e3990296a
- name: github.com/streamrail/concurrent-map
version: 8bf1e9bacbf65b10c81d0f4314cf2b1ebef728b5
- name: github.com/stretchr/objx
version: cbeaeb16a013161a98496fad62933b1d21786672
- name: github.com/stretchr/testify
version: 4d4bfba8f1d1027c4fdbe371823030df51419987
version: 976c720a22c8eb4eb6a0b4348ad85ad12491a506
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: ea9cd21fa0bc41ee4bdd50ac7ed8cbc7ea2ed960
version: b94837a2404ab90efe9289e77a70694c355739cb
subpackages:
- codec
- name: github.com/unrolled/render
version: 50716a0a853771bb36bfce61a45cdefdb98c2e6e
version: 526faf80cd4b305bb8134abea8d20d5ced74faa6
- name: github.com/urfave/negroni
version: e0e50f7dc431c043cb33f91b09c3419d48b7cff5
- name: github.com/vdemeester/docker-events
version: be74d4929ec1ad118df54349fda4b0cba60f849b
- name: github.com/vdemeester/shakers
version: 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
- name: github.com/vulcand/oxy
version: 05a57556d820dc5c56721ebdefbafc15f36fac98
version: fcc76b52eb8568540a020b7a99e854d9d752b364
repo: https://github.com/containous/oxy.git
vcs: git
subpackages:
@@ -427,249 +304,68 @@ imports:
- name: github.com/vulcand/route
version: cb89d787ddbb1c5849a7ac9f79004c1fd12a4a32
- name: github.com/vulcand/vulcand
version: 42492a3a85e294bdbdd1bcabb8c12769a81ea284
version: bed092e10989250b48bdb6aa3b0557b207f05c80
subpackages:
- conntracker
- plugin
- plugin/rewrite
- router
- name: github.com/xenolf/lego
version: 5dfe609afb1ebe9da97c9846d97a55415e5a5ccd
version: b2fad6198110326662e9e356a97199078a4a775c
subpackages:
- acme
- providers/dns
- providers/dns/auroradns
- providers/dns/azure
- providers/dns/cloudflare
- providers/dns/digitalocean
- providers/dns/dnsimple
- providers/dns/dnsmadeeasy
- providers/dns/dnspod
- providers/dns/dyn
- providers/dns/exoscale
- providers/dns/gandi
- providers/dns/googlecloud
- providers/dns/linode
- providers/dns/namecheap
- providers/dns/ns1
- providers/dns/ovh
- providers/dns/pdns
- providers/dns/rackspace
- providers/dns/rfc2136
- providers/dns/route53
- providers/dns/vultr
- name: golang.org/x/crypto
version: 4ed45ec682102c643324fae5dff8dab085b6c300
version: d81fdb778bf2c40a91b24519d60cdc5767318829
subpackages:
- bcrypt
- blowfish
- ocsp
- name: golang.org/x/net
version: 242b6b35177ec3909636b6cf6a47e8c2c6324b5d
version: b400c2eff1badec7022a8c8f5bea058b6315eed7
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: 8d1157a435470616f975ff9bb013bea8d0962067
version: 62bee037599929a6e9146f29d10dd5208c43507d
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: 629574ca2a5df945712d3079857300b5e4da0236
- name: gopkg.in/inf.v0
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
- name: gopkg.in/ini.v1
version: e7fea39b01aea8d5671f6858f0532f56e8bff3a5
version: 944cff21b3baf3ced9a880365682152ba577d348
- name: gopkg.in/mgo.v2
version: 3f83fa5005286a7fe593b055f0d7771a7dce4655
version: 22287bab4379e1fbf6002fb4eb769888f3fb224c
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
- name: gopkg.in/yaml.v2
version: 53feefa2559fb8dfa8d81baad31be332c97d6c77
- name: k8s.io/client-go
version: e121606b0d09b2e1c467183ee46217fa85a6b672
testImports:
- name: github.com/Azure/go-ansiterm
version: fa152c58bc15761d0200cb75fe958b89a9d4888e
subpackages:
- 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: []
- 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

View File

@@ -6,9 +6,11 @@ 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: 05a57556d820dc5c56721ebdefbafc15f36fac98
version: fcc76b52eb8568540a020b7a99e854d9d752b364
repo: https://github.com/containous/oxy.git
vcs: git
subpackages:
@@ -21,19 +23,16 @@ import:
- package: github.com/containous/staert
version: 1e26a71803e428fd933f5f9c8e50a26878f53147
- package: github.com/docker/engine-api
version: v0.4.0
version: 62043eb79d581a32ea849645277023c550732e52
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
@@ -42,35 +41,46 @@ 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: 5dfe609afb1ebe9da97c9846d97a55415e5a5ccd
version: b2fad6198110326662e9e356a97199078a4a775c
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: v1.13.0
version: 534753663161334baba06f13b8efa4cad22b5bc5
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:
@@ -79,76 +89,25 @@ import:
- upid
- mesosutil
- detector
- package: github.com/miekg/dns
version: 8060d9f51305bbe024b99679454e62f552cd0b0b
- package: github.com/jarcoal/httpmock
- 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
repo: https://github.com/containous/gziphandler.git
vcs: git
- package: github.com/docker/leadership
- package: github.com/satori/go.uuid
version: ^1.1.0
- package: k8s.io/client-go
version: v2.0.0
- package: github.com/gambol99/go-marathon
version: dd6cbd4c2d71294a19fb89158f2a00d427f174ab
- package: github.com/ArthurHlt/go-eureka-client
subpackages:
- eureka
- package: github.com/mitchellh/mapstructure
version: f3009df150dadf309fdee4a54ed65c124afad715
- package: github.com/coreos/go-systemd
version: v14
version: v12
subpackages:
- daemon
- package: github.com/google/go-github
- package: github.com/hashicorp/go-version
- package: github.com/mvdan/xurls
- package: github.com/go-kit/kit
version: v0.3.0
subpackages:
- metrics
- package: github.com/eapache/channels
version: v1.1.0
- package: golang.org/x/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
- package: github.com/eapache/channels

View File

@@ -1,139 +0,0 @@
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

@@ -1,202 +0,0 @@
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
}

View File

@@ -1,160 +0,0 @@
package main
import (
"crypto/tls"
"errors"
"net/http"
"os"
"os/exec"
"time"
"github.com/containous/traefik/integration/utils"
"github.com/go-check/check"
checker "github.com/vdemeester/shakers"
)
// ACME test suites (using libcompose)
type AcmeSuite struct {
BaseSuite
boulderIP string
}
// Acme tests configuration
type AcmeTestCase struct {
onDemand bool
traefikConfFilePath string
domainToCheck string
}
// Domain to check
const acmeDomain = "traefik.acme.wtf"
// Wildcard domain to chekc
const wildcardDomain = "*.acme.wtf"
func (s *AcmeSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "boulder")
s.composeProject.Start(c)
s.boulderIP = s.composeProject.Container(c, "boulder").NetworkSettings.IPAddress
// wait for boulder
err := utils.Try(120*time.Second, func() error {
resp, err := http.Get("http://" + s.boulderIP + ":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)
}
}
// Test OnDemand option with none provided certificate
func (s *AcmeSuite) TestOnDemandRetrieveAcmeCertificate(c *check.C) {
aTestCase := AcmeTestCase{
traefikConfFilePath: "fixtures/acme/acme.toml",
onDemand: true,
domainToCheck: acmeDomain}
s.retrieveAcmeCertificate(c, aTestCase)
}
// Test OnHostRule option with none provided certificate
func (s *AcmeSuite) TestOnHostRuleRetrieveAcmeCertificate(c *check.C) {
aTestCase := AcmeTestCase{
traefikConfFilePath: "fixtures/acme/acme.toml",
onDemand: false,
domainToCheck: acmeDomain}
s.retrieveAcmeCertificate(c, aTestCase)
}
// Test OnDemand option with a wildcard provided certificate
func (s *AcmeSuite) TestOnDemandRetrieveAcmeCertificateWithWildcard(c *check.C) {
aTestCase := AcmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_provided.toml",
onDemand: true,
domainToCheck: wildcardDomain}
s.retrieveAcmeCertificate(c, aTestCase)
}
// Test onHostRule option with a wildcard provided certificate
func (s *AcmeSuite) TestOnHostRuleRetrieveAcmeCertificateWithWildcard(c *check.C) {
aTestCase := AcmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_provided.toml",
onDemand: false,
domainToCheck: wildcardDomain}
s.retrieveAcmeCertificate(c, aTestCase)
}
// Doing an HTTPS request and test the response certificate
func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, a AcmeTestCase) {
file := s.adaptFile(c, a.traefikConfFilePath, struct {
BoulderHost string
OnDemand, OnHostRule bool
}{s.boulderIP, a.onDemand, !a.onDemand})
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: acmeDomain,
},
}
client = &http.Client{Transport: tr}
req, _ := http.NewRequest("GET", "https://127.0.0.1:5001/", nil)
req.Host = acmeDomain
req.Header.Set("Host", acmeDomain)
req.Header.Set("Accept", "*/*")
var resp *http.Response
// Retry to send a Request which uses the LE generated certificate
err = utils.Try(60*time.Second, func() error {
resp, err = client.Do(req)
// /!\ If connection is not closed, SSLHandshake will only be done during the first trial /!\
req.Close = true
if err != nil {
return err
} else if resp.TLS.PeerCertificates[0].Subject.CommonName != a.domainToCheck {
return errors.New("Domain " + resp.TLS.PeerCertificates[0].Subject.CommonName + " found in place of " + a.domainToCheck)
}
return nil
})
c.Assert(err, checker.IsNil)
// Check Domain into response certificate
c.Assert(resp.TLS.PeerCertificates[0].Subject.CommonName, checker.Equals, a.domainToCheck)
// 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,25 +1,26 @@
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", strings.Replace(name, "_", "-", -1))
req.Host = fmt.Sprintf("%s.docker.localhost", name)
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)

View File

@@ -1,181 +0,0 @@
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)
}
}

View File

@@ -1,111 +0,0 @@
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

@@ -1,37 +0,0 @@
# How to generate the self-signed wildcard certificate
```bash
#!/usr/bin/env bash
# Specify where we will install
# the wildcard certificate
SSL_DIR="./ssl"
# Set the wildcarded domain
# we want to use
DOMAIN="*.acme.wtf"
# A blank passphrase
PASSPHRASE=""
# Set our CSR variables
SUBJ="
C=FR
ST=MP
O=
localityName=Toulouse
commonName=$DOMAIN
organizationalUnitName=Traefik
emailAddress=
"
# Create our SSL directory
# in case it doesn't exist
sudo mkdir -p "$SSL_DIR"
# Generate our Private Key, CSR and Certificate
sudo openssl genrsa -out "$SSL_DIR/wildcard.key" 2048
sudo openssl req -new -subj "$(echo -n "$SUBJ" | tr "\n" "/")" -key "$SSL_DIR/wildcard.key" -out "$SSL_DIR/wildcard.csr" -passin pass:$PASSPHRASE
sudo openssl x509 -req -days 3650 -in "$SSL_DIR/wildcard.csr" -signkey "$SSL_DIR/wildcard.key" -out "$SSL_DIR/wildcard.crt"
sudo rm -f "$SSL_DIR/wildcard.csr"
```

View File

@@ -1,33 +0,0 @@
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 = {{.OnDemand}}
OnHostRule = {{.OnHostRule}}
caServer = "http://{{.BoulderHost}}:4000/directory"
[file]
[backends]
[backends.backend]
[backends.backend.servers.server1]
url = "http://127.0.0.1:9010"
[frontends]
[frontends.frontend]
backend = "backend"
[frontends.frontend.routes.test]
rule = "Host:traefik.acme.wtf"

View File

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

View File

@@ -1,19 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDJDCCAgwCCQCS90TE7NuTqzANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJG
UjELMAkGA1UECAwCTVAxETAPBgNVBAcMCFRvdWxvdXNlMRMwEQYDVQQDDAoqLmFj
bWUud3RmMRAwDgYDVQQLDAdUcmFlZmlrMB4XDTE3MDYyMzE0NTE0MVoXDTI3MDYy
MTE0NTE0MVowVDELMAkGA1UEBhMCRlIxCzAJBgNVBAgMAk1QMREwDwYDVQQHDAhU
b3Vsb3VzZTETMBEGA1UEAwwKKi5hY21lLnd0ZjEQMA4GA1UECwwHVHJhZWZpazCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAODqsVCLhauFZPhPXqZDIKST
wqoJST+jO5O/WmA7oC4S6JlecRoNsHAXyddd3cQW3yZqB0ryOHrMOpMX0PPXf3jS
OOXoXA6xsq+RXlR4hDrBkOrj/LR/g62Eiuj2JVO2uy6tKJIetSB/Wzl6OgRkY/um
EXIc7zQS81/QKg+pg7Z4AYJht5J88nOFHJ3RspUMaH1vJ6LhH3MOUkgFj+I1OiqX
Tnkd7EDWbkYxAJa0xI2qbmY5VYv8dsIUN+IlPFDtBt87Fc2qv5dQkOz11FDYxWnz
+kxX6+MESLBaTvJjXvG+bzTfh9xCExFQFiN+Us0JuLX8HKQ4MqWL2IiVLsko2osC
AwEAATANBgkqhkiG9w0BAQsFAAOCAQEAl2jTX2yzUpiufrJ6WtZjKIAH8GF817hS
dWvt2eyLrBPvllMUj8zqCE5uNVUDVuXQvOhOyx+3zZzfcgfYqbTD8G8amNWcSiRA
vonoOn1p1pW2OonSi32h3qv5i4gCyh/6cBneYi03lkQ7uLCsJK9+dXTAvoKL6s23
IXhZGS0Qkvs4vkORA2MX9tyJdyfCCaCx3GpPCGkKrKJ8ePTEvq1ZE2xdhERnV5pz
L1PRY2QthXXVjMz7AXw0gkHvAbtrKVKR1Tv4ZK34bFBh/kyGAjkcn0zdeFKITqTF
tCoXWEArmiRqGuXwbqU3mEA9Cv6aMM+0YX89K2InhOnBU80OWs0uMQ==
-----END CERTIFICATE-----

View File

@@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA4OqxUIuFq4Vk+E9epkMgpJPCqglJP6M7k79aYDugLhLomV5x
Gg2wcBfJ113dxBbfJmoHSvI4esw6kxfQ89d/eNI45ehcDrGyr5FeVHiEOsGQ6uP8
tH+DrYSK6PYlU7a7Lq0okh61IH9bOXo6BGRj+6YRchzvNBLzX9AqD6mDtngBgmG3
knzyc4UcndGylQxofW8nouEfcw5SSAWP4jU6KpdOeR3sQNZuRjEAlrTEjapuZjlV
i/x2whQ34iU8UO0G3zsVzaq/l1CQ7PXUUNjFafP6TFfr4wRIsFpO8mNe8b5vNN+H
3EITEVAWI35SzQm4tfwcpDgypYvYiJUuySjaiwIDAQABAoIBAQCs9Ex9v4x+pQlL
2NzTxXLom6dp0dI92WwK5W696Zv3UhsDNRiMDFLNH73amxfZnizjAU2yWCkOZNX2
Hq5TlDc11ZJjWRbRRdw+He8HzdUAybCCr+a3dgbv+6hGFGIHydCOyCEWm/50ivq/
bDoI/pnT/ZQUyCM5TAlSeGSfvp7GRHi9v3HOl85H1Pn2Dvyk9gj4y3BIFrKuv8fJ
o6aEzlfgWGROCzshU2m8fB9P0B4hWDlJsc1D01sW60zhjLo9+XoWznmw5mczz7sc
S5sdDh47rSJsNRuFd7YDjeLzJWPqLrKVB5nn6nRbvrnBqhfsknkO4VIXhmEMSs1u
RMYOJ9ShAoGBAPinA6ktIeez1t5IsfxGwbCeZzFI1suZqZeX6ezNKaMpeykyAPuh
CqN7H+a4NCKsinsgHJowU98ckHeAsQ22s7R8dFZhyxEXkcBawY2soK29eq2aJHnY
lqKOwjOA7wgElRHwLkNFniQ5lKFPMly8a9NVAqg+Th/J3uR+7wE2t+b1AoGBAOeQ
H/vVkdaNB2ovnCxMh+OfxpcjkfF6KnD2jpn/TKsbR5BtnrtyRLc5+qt52D0CEgSy
qU3zrsZebShej3OIBPrEwIcPN+LezaxnLMf9RXdOde+wWrQLWLkShJaSTwSoGqZB
fcO0/sc1lzhGxm++ByP5mWbHr/VM9IdTQQH5Bct/AoGBAMhmOrIXeNL4Az2FU0Vi
dWp2T+7NqKfRAXj264Z5V4xzuxpZfadPhHZ7nhth7Erhyn4vRD4UoxQXPmvB4XCP
Bkh5YX3ZNUNiPorL2mDnd1xvcLcHm0xEfisnaWb/DCbnIomhjHeVXT4O1jYn0Qwi
o7hgNFMKXAaMuUJo9xGAWzkdAoGASxC4nY2tOiz7k1udt+qTPqHj4cjhHbOpoHb8
4UUWmH0+ZL50b3Vqey8raH0WMSjDqIw2QBPXu2yO3EBTJnOYkaZIdz/isQPjDplf
tfEPnM5tgubbcHQhLdWn75u8S9km0nB2kYPR98gSnmarGzwx2mKmbOAc1Vs+BcRi
VX5hd4cCgYAubBq0VsFT0KVU3Rva3dgPR1K5bp4r4hE5cGXm4HvLiOgv995CwPy1
27eONF9GN7hvjI6C17jA1Gyx5sN0QrsMv/1BZqiGaragMOPXFD+tVecWuKH4lZQi
VbKTOWHlGkrDCpiYWpfetQAjouj+0c6d+wigcoC8e5dwxBPI2f3rGw==
-----END RSA PRIVATE KEY-----

View File

@@ -1,16 +0,0 @@
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

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

View File

@@ -1,27 +0,0 @@
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"

View File

@@ -1,24 +0,0 @@
defaultEntryPoints = ["http"]
logLevel = "DEBUG"
[entryPoints]
[entryPoints.http]
address = ":8000"
[web]
address = ":8080"
[file]
[backends]
[backends.backend1]
[backends.backend1.servers.server1]
url = "{{ .WebsocketServer }}"
[frontends]
[frontends.frontend1]
backend = "backend1"
[frontends.frontend1.routes.test_1]
rule = "Path:/ws"

296
integration/glide.lock generated
View File

@@ -1,296 +0,0 @@
hash: afc00e3aa064550eed7ff6a98b4eced543fe41e84894f1ac0ec25adf06354ec7
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
- websocket
- name: golang.org/x/sys
version: 9c60d1c508f5134d1ca726b4641db998f2523357
subpackages:
- unix
- windows
- name: gopkg.in/fsnotify.v1
version: 944cff21b3baf3ced9a880365682152ba577d348

View File

@@ -1,34 +0,0 @@
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
- websocket
- package: github.com/spf13/pflag
version: 5644820622454e71517561946e3d94b9f9db6842

View File

@@ -1,91 +0,0 @@
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,7 +4,6 @@ package main
import (
"fmt"
"io/ioutil"
"net"
"os"
"os/exec"
"path/filepath"
@@ -14,8 +13,6 @@ import (
"github.com/containous/traefik/integration/utils"
"github.com/go-check/check"
"bytes"
compose "github.com/libkermit/compose/check"
checker "github.com/vdemeester/shakers"
)
@@ -29,7 +26,6 @@ func init() {
check.Suite(&AccessLogSuite{})
check.Suite(&HTTPSSuite{})
check.Suite(&FileSuite{})
check.Suite(&HealthCheckSuite{})
check.Suite(&DockerSuite{})
check.Suite(&ConsulSuite{})
check.Suite(&ConsulCatalogSuite{})
@@ -37,10 +33,6 @@ func init() {
check.Suite(&MarathonSuite{})
check.Suite(&ConstraintSuite{})
check.Suite(&MesosSuite{})
check.Suite(&EurekaSuite{})
check.Suite(&AcmeSuite{})
check.Suite(&DynamoDBSuite{})
check.Suite(&WebsocketSuite{})
}
var traefikBinary = "../dist/traefik"
@@ -59,33 +51,9 @@ 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)
}
func withConfigFile(file string) string {
return "--configFile=" + file
}
func (s *BaseSuite) cmdTraefik(args ...string) (*exec.Cmd, *bytes.Buffer) {
cmd := exec.Command(traefikBinary, args...)
var out bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &out
return cmd, &out
}
func (s *BaseSuite) traefikCmd(c *check.C, args ...string) (*exec.Cmd, string) {
cmd, out, err := utils.RunCommand(traefikBinary, args...)
c.Assert(err, checker.IsNil, check.Commentf("Fail to run %s with %v", traefikBinary, args))

View File

@@ -1,44 +0,0 @@
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:alpine
image: nginx
ports:
- "8881:80"

View File

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

View File

@@ -1,16 +0,0 @@
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

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

View File

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

View File

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

View File

@@ -1,357 +0,0 @@
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

@@ -1,51 +0,0 @@
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

@@ -1,21 +0,0 @@
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

@@ -1,10 +0,0 @@
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

@@ -1,48 +0,0 @@
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

@@ -1,38 +0,0 @@
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

@@ -1,95 +0,0 @@
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

@@ -1,21 +0,0 @@
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

@@ -1,10 +0,0 @@
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

@@ -1,437 +0,0 @@
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

@@ -1,21 +0,0 @@
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

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

View File

@@ -1,23 +0,0 @@
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

@@ -1,185 +0,0 @@
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

@@ -1,21 +0,0 @@
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

@@ -1,188 +0,0 @@
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

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