Merge pull request #1208 from containous/merge-v1.2.0-rc2-master

Merge v1.2.0 rc2 master
This commit is contained in:
Emile Vauge 2017-03-06 18:37:03 +01:00 committed by GitHub
commit 7d83027954
23 changed files with 752 additions and 68 deletions

View file

@ -9,7 +9,7 @@ env:
- 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= - 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 - REPO: $TRAVIS_REPO_SLUG
- VERSION: $TRAVIS_TAG - VERSION: $TRAVIS_TAG
- CODENAME: camembert - CODENAME: morbier
matrix: matrix:
fast_finish: true fast_finish: true

View file

@ -1,5 +1,151 @@
# Change Log # Change Log
## [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) ## [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) [Full Changelog](https://github.com/containous/traefik/compare/v1.1.1...v1.1.2)

View file

@ -239,6 +239,20 @@ For example:
[backends.backend1.loadbalancer] [backends.backend1.loadbalancer]
sticky = true sticky = true
``` ```
Healthcheck URL can be configured with a relative URL for `healthcheck.URL`.
Interval between healthcheck can be configured by using `healthcheck.interval`
(default: 30s)
For example:
```toml
[backends]
[backends.backend1]
[backends.backend1.healthcheck]
URL = "/health"
interval = "10s"
```
## Servers ## 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). Servers are simply defined using a `URL`. You can also apply a custom `weight` to each server (this will be used by load-balancing).

View file

@ -1423,3 +1423,102 @@ Labels can be used on task containers to override default behaviour:
- `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend. - `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend.
- `traefik.frontend.priority=10`: override default frontend priority - `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.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æfɪk 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æfɪk 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
# Expose Rancher services by default in traefik
#
# Optional
# Default: true
#
ExposedByDefault = false
# Endpoint to use when connecting to Rancher
#
# Optional
# Endpoint = "http://rancherserver.example.com"
# AccessKey to use when connecting to Rancher
#
# Optional
# AccessKey = "XXXXXXXXX"
# SecretKey to use when connecting to Rancher
#
# Optional
# SecretKey = "XXXXXXXXXXX"
```
If you're deploying traefik as a service within rancher, you can alternatively set these labels on the service to let it only fetch data of its current environment. The settings `endpoint`, `accesskey` and `secretkey` can be omitted then.
- `io.rancher.container.create_agent=true`
- `io.rancher.container.agent.role=environment`
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æ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`.

View file

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

6
glide.lock generated
View file

@ -1,5 +1,5 @@
hash: b2ac93355c3f551a75216a800337cee9321f6c9a04a18ab1fa8d8152e89b7595 hash: f2a0b9af55c8312762e4148bd876e5bd2451c240b407fbb6d4a5dbc56bf46c05
updated: 2017-02-20T16:04:18.834166585+01:00 updated: 2017-03-03T10:21:14.720631882+01:00
imports: imports:
- name: bitbucket.org/ww/goautoneg - name: bitbucket.org/ww/goautoneg
version: 75cd24fc2f2c2a2088577d12123ddee5f54e0675 version: 75cd24fc2f2c2a2088577d12123ddee5f54e0675
@ -444,7 +444,7 @@ imports:
- assert - assert
- mock - mock
- name: github.com/thoas/stats - name: github.com/thoas/stats
version: 79b768ff1780f4e5b0ed132e192bfeefe9f85a9c version: 152b5d051953fdb6e45f14b6826962aadc032324
- name: github.com/timewasted/linode - name: github.com/timewasted/linode
version: 37e84520dcf74488f67654f9c775b9752c232dc1 version: 37e84520dcf74488f67654f9c775b9752c232dc1
subpackages: subpackages:

View file

@ -53,6 +53,7 @@ import:
subpackages: subpackages:
- mock - mock
- package: github.com/thoas/stats - package: github.com/thoas/stats
version: 152b5d051953fdb6e45f14b6826962aadc032324
- package: github.com/unrolled/render - package: github.com/unrolled/render
- package: github.com/vdemeester/docker-events - package: github.com/vdemeester/docker-events
version: be74d4929ec1ad118df54349fda4b0cba60f849b version: be74d4929ec1ad118df54349fda4b0cba60f849b

View file

@ -26,6 +26,7 @@ func GetHealthCheck() *HealthCheck {
// BackendHealthCheck HealthCheck configuration for a backend // BackendHealthCheck HealthCheck configuration for a backend
type BackendHealthCheck struct { type BackendHealthCheck struct {
URL string URL string
Interval time.Duration
DisabledURLs []*url.URL DisabledURLs []*url.URL
lb loadBalancer lb loadBalancer
} }
@ -49,8 +50,8 @@ func newHealthCheck() *HealthCheck {
} }
// NewBackendHealthCheck Instantiate a new BackendHealthCheck // NewBackendHealthCheck Instantiate a new BackendHealthCheck
func NewBackendHealthCheck(URL string, lb loadBalancer) *BackendHealthCheck { func NewBackendHealthCheck(URL string, interval time.Duration, lb loadBalancer) *BackendHealthCheck {
return &BackendHealthCheck{URL, nil, lb} return &BackendHealthCheck{URL, interval, nil, lb}
} }
//SetBackendsConfiguration set backends configuration //SetBackendsConfiguration set backends configuration
@ -70,7 +71,7 @@ func (hc *HealthCheck) execute(ctx context.Context) {
currentBackendID := backendID currentBackendID := backendID
safe.Go(func() { safe.Go(func() {
for { for {
ticker := time.NewTicker(time.Second * 30) ticker := time.NewTicker(currentBackend.Interval)
select { select {
case <-ctx.Done(): case <-ctx.Done():
log.Debugf("Stopping all current Healthcheck goroutines") log.Debugf("Stopping all current Healthcheck goroutines")

View file

@ -0,0 +1,27 @@
defaultEntryPoints = ["http"]
logLevel = "DEBUG"
[entryPoints]
[entryPoints.http]
address = ":8000"
[web]
address = ":8080"
[file]
[backends]
[backends.backend1]
[backends.backend1.healthcheck]
url = "/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

@ -0,0 +1,91 @@
package main
import (
"bytes"
"errors"
"io/ioutil"
"net/http"
"os"
"os/exec"
"strings"
"time"
"github.com/containous/traefik/integration/utils"
"github.com/go-check/check"
checker "github.com/vdemeester/shakers"
)
// HealchCheck test suites (using libcompose)
type HealchCheckSuite struct{ BaseSuite }
func (s *HealchCheckSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "healthcheck")
s.composeProject.Start(c)
}
func (s *HealchCheckSuite) 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

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

View file

@ -626,11 +626,12 @@ func (provider *Docker) listServices(ctx context.Context, dockerClient client.AP
for _, service := range serviceList { for _, service := range serviceList {
dockerData := parseService(service, networkMap) dockerData := parseService(service, networkMap)
useSwarmLB, _ := strconv.ParseBool(provider.getIsBackendLBSwarm(dockerData)) useSwarmLB, _ := strconv.ParseBool(provider.getIsBackendLBSwarm(dockerData))
isGlobalSvc := service.Spec.Mode.Global != nil
if useSwarmLB { if useSwarmLB {
dockerDataList = append(dockerDataList, dockerData) dockerDataList = append(dockerDataList, dockerData)
} else { } else {
dockerDataListTasks, err = listTasks(ctx, dockerClient, service.ID, dockerData, networkMap) dockerDataListTasks, err = listTasks(ctx, dockerClient, service.ID, dockerData, networkMap, isGlobalSvc)
for _, dockerDataTask := range dockerDataListTasks { for _, dockerDataTask := range dockerDataListTasks {
dockerDataList = append(dockerDataList, dockerDataTask) dockerDataList = append(dockerDataList, dockerDataTask)
@ -675,9 +676,10 @@ func parseService(service swarmtypes.Service, networkMap map[string]*dockertypes
} }
func listTasks(ctx context.Context, dockerClient client.APIClient, serviceID string, func listTasks(ctx context.Context, dockerClient client.APIClient, serviceID string,
serviceDockerData dockerData, networkMap map[string]*dockertypes.NetworkResource) ([]dockerData, error) { serviceDockerData dockerData, networkMap map[string]*dockertypes.NetworkResource, isGlobalSvc bool) ([]dockerData, error) {
serviceIDFilter := filters.NewArgs() serviceIDFilter := filters.NewArgs()
serviceIDFilter.Add("service", serviceID) serviceIDFilter.Add("service", serviceID)
serviceIDFilter.Add("desired-state", "running")
taskList, err := dockerClient.TaskList(ctx, dockertypes.TaskListOptions{Filter: serviceIDFilter}) taskList, err := dockerClient.TaskList(ctx, dockertypes.TaskListOptions{Filter: serviceIDFilter})
if err != nil { if err != nil {
@ -686,13 +688,13 @@ func listTasks(ctx context.Context, dockerClient client.APIClient, serviceID str
var dockerDataList []dockerData var dockerDataList []dockerData
for _, task := range taskList { for _, task := range taskList {
dockerData := parseTasks(task, serviceDockerData, networkMap) dockerData := parseTasks(task, serviceDockerData, networkMap, isGlobalSvc)
dockerDataList = append(dockerDataList, dockerData) dockerDataList = append(dockerDataList, dockerData)
} }
return dockerDataList, err return dockerDataList, err
} }
func parseTasks(task swarmtypes.Task, serviceDockerData dockerData, networkMap map[string]*dockertypes.NetworkResource) dockerData { func parseTasks(task swarmtypes.Task, serviceDockerData dockerData, networkMap map[string]*dockertypes.NetworkResource, isGlobalSvc bool) dockerData {
dockerData := dockerData{ dockerData := dockerData{
ServiceName: serviceDockerData.Name, ServiceName: serviceDockerData.Name,
Name: serviceDockerData.Name + "." + strconv.Itoa(task.Slot), Name: serviceDockerData.Name + "." + strconv.Itoa(task.Slot),
@ -700,6 +702,10 @@ func parseTasks(task swarmtypes.Task, serviceDockerData dockerData, networkMap m
NetworkSettings: networkSettings{}, NetworkSettings: networkSettings{},
} }
if isGlobalSvc == true {
dockerData.Name = serviceDockerData.Name + "." + task.ID
}
if task.NetworksAttachments != nil { if task.NetworksAttachments != nil {
dockerData.NetworkSettings.Networks = make(map[string]*networkData) dockerData.NetworkSettings.Networks = make(map[string]*networkData)
for _, virtualIP := range task.NetworksAttachments { for _, virtualIP := range task.NetworksAttachments {

View file

@ -2184,3 +2184,90 @@ func TestSwarmLoadDockerConfig(t *testing.T) {
} }
} }
} }
func TestSwarmTaskParsing(t *testing.T) {
cases := []struct {
service swarm.Service
tasks []swarm.Task
isGlobalSvc bool
expectedNames map[string]string
networks map[string]*docker.NetworkResource
}{
{
service: swarm.Service{
Spec: swarm.ServiceSpec{
Annotations: swarm.Annotations{
Name: "container",
},
},
},
tasks: []swarm.Task{
{
ID: "id1",
Slot: 1,
},
{
ID: "id2",
Slot: 2,
},
{
ID: "id3",
Slot: 3,
},
},
isGlobalSvc: false,
expectedNames: map[string]string{
"id1": "container.1",
"id2": "container.2",
"id3": "container.3",
},
networks: map[string]*docker.NetworkResource{
"1": {
Name: "foo",
},
},
},
{
service: swarm.Service{
Spec: swarm.ServiceSpec{
Annotations: swarm.Annotations{
Name: "container",
},
},
},
tasks: []swarm.Task{
{
ID: "id1",
},
{
ID: "id2",
},
{
ID: "id3",
},
},
isGlobalSvc: true,
expectedNames: map[string]string{
"id1": "container.id1",
"id2": "container.id2",
"id3": "container.id3",
},
networks: map[string]*docker.NetworkResource{
"1": {
Name: "foo",
},
},
},
}
for _, e := range cases {
dockerData := parseService(e.service, e.networks)
for _, task := range e.tasks {
taskDockerData := parseTasks(task, dockerData, map[string]*docker.NetworkResource{}, e.isGlobalSvc)
if !reflect.DeepEqual(taskDockerData.Name, e.expectedNames[task.ID]) {
t.Fatalf("expect %v, got %v", e.expectedNames[task.ID], taskDockerData.Name)
}
}
}
}

View file

@ -275,37 +275,48 @@ func (provider *ECS) listInstances(ctx context.Context, client *awsClient) ([]ec
} }
func (provider *ECS) lookupEc2Instances(ctx context.Context, client *awsClient, containerArns []*string) ([]*ec2.Instance, error) { func (provider *ECS) lookupEc2Instances(ctx context.Context, client *awsClient, containerArns []*string) ([]*ec2.Instance, error) {
req, containerResp := client.ecs.DescribeContainerInstancesRequest(&ecs.DescribeContainerInstancesInput{
ContainerInstances: containerArns,
Cluster: &provider.Cluster,
})
if err := wrapAws(ctx, req); err != nil {
return nil, err
}
order := make(map[string]int) order := make(map[string]int)
instanceIds := make([]*string, len(containerArns))
instances := make([]*ec2.Instance, len(containerArns))
for i, arn := range containerArns { for i, arn := range containerArns {
order[*arn] = i order[*arn] = i
} }
instanceIds := make([]*string, len(containerArns)) req, _ := client.ecs.DescribeContainerInstancesRequest(&ecs.DescribeContainerInstancesInput{
for i, container := range containerResp.ContainerInstances { ContainerInstances: containerArns,
order[*container.Ec2InstanceId] = order[*container.ContainerInstanceArn] Cluster: &provider.Cluster,
instanceIds[i] = container.Ec2InstanceId })
for ; req != nil; req = req.NextPage() {
if err := wrapAws(ctx, req); err != nil {
return nil, err
}
containerResp := req.Data.(*ecs.DescribeContainerInstancesOutput)
for i, container := range containerResp.ContainerInstances {
order[*container.Ec2InstanceId] = order[*container.ContainerInstanceArn]
instanceIds[i] = container.Ec2InstanceId
}
} }
req, instancesResp := client.ec2.DescribeInstancesRequest(&ec2.DescribeInstancesInput{ req, _ = client.ec2.DescribeInstancesRequest(&ec2.DescribeInstancesInput{
InstanceIds: instanceIds, InstanceIds: instanceIds,
}) })
if err := wrapAws(ctx, req); err != nil { for ; req != nil; req = req.NextPage() {
return nil, err if err := wrapAws(ctx, req); err != nil {
} return nil, err
}
instances := make([]*ec2.Instance, len(containerArns)) instancesResp := req.Data.(*ec2.DescribeInstancesOutput)
for _, r := range instancesResp.Reservations { for _, r := range instancesResp.Reservations {
instances[order[*r.Instances[0].InstanceId]] = r.Instances[0] for _, i := range r.Instances {
if i.InstanceId != nil {
instances[order[*i.InstanceId]] = i
}
}
}
} }
return instances, nil return instances, nil
} }
@ -340,6 +351,23 @@ func (provider *ECS) filterInstance(i ecsInstance) bool {
return false return false
} }
if i.machine == nil ||
i.machine.State == nil ||
i.machine.State.Name == nil {
log.Debugf("Filtering ecs instance in an missing ec2 information %s (%s)", i.Name, i.ID)
return false
}
if *i.machine.State.Name != ec2.InstanceStateNameRunning {
log.Debugf("Filtering ecs instance in an incorrect state %s (%s) (state = %s)", i.Name, i.ID, *i.machine.State.Name)
return false
}
if i.machine.PrivateIpAddress == nil {
log.Debugf("Filtering ecs instance without an ip address %s (%s)", i.Name, i.ID)
return false
}
label := i.label("traefik.enable") label := i.label("traefik.enable")
enabled := provider.ExposedByDefault && label != "false" || label == "true" enabled := provider.ExposedByDefault && label != "false" || label == "true"
if !enabled { if !enabled {

View file

@ -37,6 +37,9 @@ func makeEcsInstance(containerDef *ecs.ContainerDefinition) ecsInstance {
containerDefinition: containerDef, containerDefinition: containerDef,
machine: &ec2.Instance{ machine: &ec2.Instance{
PrivateIpAddress: aws.String("10.0.0.0"), PrivateIpAddress: aws.String("10.0.0.0"),
State: &ec2.InstanceState{
Name: aws.String(ec2.InstanceStateNameRunning),
},
}, },
} }
} }
@ -70,10 +73,10 @@ func TestEcsProtocol(t *testing.T) {
}, },
} }
for _, c := range cases { for i, c := range cases {
value := c.instanceInfo.Protocol() value := c.instanceInfo.Protocol()
if value != c.expected { if value != c.expected {
t.Fatalf("Should have been %s, got %s", c.expected, value) t.Fatalf("Should have been %v, got %v (case %d)", c.expected, value, i)
} }
} }
} }
@ -89,10 +92,10 @@ func TestEcsHost(t *testing.T) {
}, },
} }
for _, c := range cases { for i, c := range cases {
value := c.instanceInfo.Host() value := c.instanceInfo.Host()
if value != c.expected { if value != c.expected {
t.Fatalf("Should have been %s, got %s", c.expected, value) t.Fatalf("Should have been %v, got %v (case %d)", c.expected, value, i)
} }
} }
} }
@ -108,10 +111,10 @@ func TestEcsPort(t *testing.T) {
}, },
} }
for _, c := range cases { for i, c := range cases {
value := c.instanceInfo.Port() value := c.instanceInfo.Port()
if value != c.expected { if value != c.expected {
t.Fatalf("Should have been %s, got %s", c.expected, value) t.Fatalf("Should have been %v, got %v (case %d)", c.expected, value, i)
} }
} }
} }
@ -133,10 +136,10 @@ func TestEcsWeight(t *testing.T) {
}, },
} }
for _, c := range cases { for i, c := range cases {
value := c.instanceInfo.Weight() value := c.instanceInfo.Weight()
if value != c.expected { if value != c.expected {
t.Fatalf("Should have been %s, got %s", c.expected, value) t.Fatalf("Should have been %v, got %v (case %d)", c.expected, value, i)
} }
} }
} }
@ -158,10 +161,10 @@ func TestEcsPassHostHeader(t *testing.T) {
}, },
} }
for _, c := range cases { for i, c := range cases {
value := c.instanceInfo.PassHostHeader() value := c.instanceInfo.PassHostHeader()
if value != c.expected { if value != c.expected {
t.Fatalf("Should have been %s, got %s", c.expected, value) t.Fatalf("Should have been %v, got %v (case %d)", c.expected, value, i)
} }
} }
} }
@ -183,10 +186,10 @@ func TestEcsPriority(t *testing.T) {
}, },
} }
for _, c := range cases { for i, c := range cases {
value := c.instanceInfo.Priority() value := c.instanceInfo.Priority()
if value != c.expected { if value != c.expected {
t.Fatalf("Should have been %s, got %s", c.expected, value) t.Fatalf("Should have been %v, got %v (case %d)", c.expected, value, i)
} }
} }
} }
@ -214,10 +217,94 @@ func TestEcsEntryPoints(t *testing.T) {
}, },
} }
for _, c := range cases { for i, c := range cases {
value := c.instanceInfo.EntryPoints() value := c.instanceInfo.EntryPoints()
if !reflect.DeepEqual(value, c.expected) { if !reflect.DeepEqual(value, c.expected) {
t.Fatalf("Should have been %s, got %s", c.expected, value) t.Fatalf("Should have been %v, got %v (case %d)", c.expected, value, i)
}
}
}
func TestFilterInstance(t *testing.T) {
nilPrivateIP := simpleEcsInstance(map[string]*string{})
nilPrivateIP.machine.PrivateIpAddress = nil
nilMachine := simpleEcsInstance(map[string]*string{})
nilMachine.machine = nil
nilMachineState := simpleEcsInstance(map[string]*string{})
nilMachineState.machine.State = nil
nilMachineStateName := simpleEcsInstance(map[string]*string{})
nilMachineStateName.machine.State.Name = nil
invalidMachineState := simpleEcsInstance(map[string]*string{})
invalidMachineState.machine.State.Name = aws.String(ec2.InstanceStateNameStopped)
cases := []struct {
expected bool
exposedByDefault bool
instanceInfo ecsInstance
}{
{
expected: true,
exposedByDefault: true,
instanceInfo: simpleEcsInstance(map[string]*string{}),
},
{
expected: false,
exposedByDefault: false,
instanceInfo: simpleEcsInstance(map[string]*string{}),
},
{
expected: false,
exposedByDefault: true,
instanceInfo: simpleEcsInstance(map[string]*string{
"traefik.enable": aws.String("false"),
}),
},
{
expected: true,
exposedByDefault: false,
instanceInfo: simpleEcsInstance(map[string]*string{
"traefik.enable": aws.String("true"),
}),
},
{
expected: false,
exposedByDefault: true,
instanceInfo: nilPrivateIP,
},
{
expected: false,
exposedByDefault: true,
instanceInfo: nilMachine,
},
{
expected: false,
exposedByDefault: true,
instanceInfo: nilMachineState,
},
{
expected: false,
exposedByDefault: true,
instanceInfo: nilMachineStateName,
},
{
expected: false,
exposedByDefault: true,
instanceInfo: invalidMachineState,
},
}
for i, c := range cases {
provider := &ECS{
ExposedByDefault: c.exposedByDefault,
}
value := provider.filterInstance(c.instanceInfo)
if value != c.expected {
t.Fatalf("Should have been %v, got %v (case %d)", c.expected, value, i)
} }
} }
} }

View file

@ -264,9 +264,6 @@ func (provider *Marathon) taskFilter(task marathon.Task, applications *marathon.
return false return false
} }
} }
} else {
log.Debugf("Filtering marathon task %s with defined healthcheck as no healthcheck has run yet", task.AppID)
return false
} }
} }
return true return true

View file

@ -629,7 +629,7 @@ func TestMarathonTaskFilter(t *testing.T) {
}, },
}, },
}, },
expected: false, expected: true,
exposedByDefault: true, exposedByDefault: true,
}, },
{ {

View file

@ -4,6 +4,13 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"math"
"os"
"strconv"
"strings"
"text/template"
"time"
"github.com/BurntSushi/ty/fun" "github.com/BurntSushi/ty/fun"
"github.com/cenk/backoff" "github.com/cenk/backoff"
"github.com/containous/traefik/job" "github.com/containous/traefik/job"
@ -11,11 +18,6 @@ import (
"github.com/containous/traefik/safe" "github.com/containous/traefik/safe"
"github.com/containous/traefik/types" "github.com/containous/traefik/types"
rancher "github.com/rancher/go-rancher/client" rancher "github.com/rancher/go-rancher/client"
"math"
"strconv"
"strings"
"text/template"
"time"
) )
const ( const (
@ -72,7 +74,7 @@ func (provider *Rancher) getFrontendRule(service rancherData) string {
if label, err := getServiceLabel(service, "traefik.frontend.rule"); err == nil { if label, err := getServiceLabel(service, "traefik.frontend.rule"); err == nil {
return label return label
} }
return "Host:" + strings.ToLower(strings.Replace(service.Name, "/", "_", -1)) + "." + provider.Domain return "Host:" + strings.ToLower(strings.Replace(service.Name, "/", ".", -1)) + "." + provider.Domain
} }
func (provider *Rancher) getFrontendName(service rancherData) string { func (provider *Rancher) getFrontendName(service rancherData) string {
@ -193,13 +195,26 @@ func getServiceLabel(service rancherData, label string) (string, error) {
} }
func (provider *Rancher) createClient() (*rancher.RancherClient, error) { func (provider *Rancher) createClient() (*rancher.RancherClient, error) {
rancherURL := getenv("CATTLE_URL", provider.Endpoint)
accessKey := getenv("CATTLE_ACCESS_KEY", provider.AccessKey)
secretKey := getenv("CATTLE_SECRET_KEY", provider.SecretKey)
return rancher.NewRancherClient(&rancher.ClientOpts{ return rancher.NewRancherClient(&rancher.ClientOpts{
Url: provider.Endpoint, Url: rancherURL,
AccessKey: provider.AccessKey, AccessKey: accessKey,
SecretKey: provider.SecretKey, SecretKey: secretKey,
}) })
} }
func getenv(key, fallback string) string {
value := os.Getenv(key)
if len(value) == 0 {
return fallback
}
return value
}
// Provide allows the provider to provide configurations to traefik // Provide allows the provider to provide configurations to traefik
// using the given configuration channel. // using the given configuration channel.
func (provider *Rancher) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { func (provider *Rancher) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
@ -207,6 +222,12 @@ func (provider *Rancher) Provide(configurationChan chan<- types.ConfigMessage, p
safe.Go(func() { safe.Go(func() {
operation := func() error { operation := func() error {
rancherClient, err := provider.createClient() rancherClient, err := provider.createClient()
if err != nil {
log.Errorf("Failed to create a client for rancher, error: %s", err)
return err
}
ctx := context.Background() ctx := context.Background()
var environments = listRancherEnvironments(rancherClient) var environments = listRancherEnvironments(rancherClient)
var services = listRancherServices(rancherClient) var services = listRancherServices(rancherClient)
@ -214,11 +235,6 @@ func (provider *Rancher) Provide(configurationChan chan<- types.ConfigMessage, p
var rancherData = parseRancherData(environments, services, container) var rancherData = parseRancherData(environments, services, container)
if err != nil {
log.Errorf("Failed to create a client for rancher, error: %s", err)
return err
}
configuration := provider.loadRancherConfig(rancherData) configuration := provider.loadRancherConfig(rancherData)
configurationChan <- types.ConfigMessage{ configurationChan <- types.ConfigMessage{
ProviderName: "rancher", ProviderName: "rancher",

View file

@ -87,6 +87,12 @@ func TestRancherGetFrontendRule(t *testing.T) {
}, },
expected: "Host:foo.rancher.localhost", expected: "Host:foo.rancher.localhost",
}, },
{
service: rancherData{
Name: "foo/bar",
},
expected: "Host:foo.bar.rancher.localhost",
},
{ {
service: rancherData{ service: rancherData{
Name: "test-service", Name: "test-service",
@ -388,7 +394,7 @@ func TestRancherLoadRancherConfig(t *testing.T) {
{ {
services: []rancherData{ services: []rancherData{
{ {
Name: "test-service", Name: "test/service",
Labels: map[string]string{ Labels: map[string]string{
"traefik.port": "80", "traefik.port": "80",
}, },
@ -405,7 +411,7 @@ func TestRancherLoadRancherConfig(t *testing.T) {
Routes: map[string]types.Route{ Routes: map[string]types.Route{
"route-frontend-Host-test-service-rancher-localhost": { "route-frontend-Host-test-service-rancher-localhost": {
Rule: "Host:test-service.rancher.localhost", Rule: "Host:test.service.rancher.localhost",
}, },
}, },
}, },

View file

@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
set -e set -e
if [ -n "$TRAVIS_TAG" ] && [ "$DOCKER_VERSION" = "1.10.1" ]; then if [ -n "$TRAVIS_TAG" ] && [ "$DOCKER_VERSION" = "1.10.3" ]; then
echo "Deploying..." echo "Deploying..."
else else
echo "Skipping deploy" echo "Skipping deploy"

View file

@ -658,7 +658,15 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo
continue frontend continue frontend
} }
if configuration.Backends[frontend.Backend].HealthCheck != nil { if configuration.Backends[frontend.Backend].HealthCheck != nil {
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(configuration.Backends[frontend.Backend].HealthCheck.URL, rebalancer) var interval time.Duration
if configuration.Backends[frontend.Backend].HealthCheck.Interval != "" {
interval, err = time.ParseDuration(configuration.Backends[frontend.Backend].HealthCheck.Interval)
if err != nil {
log.Errorf("Wrong healthcheck interval: %s", err)
interval = time.Second * 30
}
}
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(configuration.Backends[frontend.Backend].HealthCheck.URL, interval, rebalancer)
} }
} }
case types.Wrr: case types.Wrr:
@ -684,7 +692,15 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo
} }
} }
if configuration.Backends[frontend.Backend].HealthCheck != nil { if configuration.Backends[frontend.Backend].HealthCheck != nil {
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(configuration.Backends[frontend.Backend].HealthCheck.URL, rr) var interval time.Duration
if configuration.Backends[frontend.Backend].HealthCheck.Interval != "" {
interval, err = time.ParseDuration(configuration.Backends[frontend.Backend].HealthCheck.Interval)
if err != nil {
log.Errorf("Wrong healthcheck interval: %s", err)
interval = time.Second * 30
}
}
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(configuration.Backends[frontend.Backend].HealthCheck.URL, interval, rr)
} }
} }
maxConns := configuration.Backends[frontend.Backend].MaxConn maxConns := configuration.Backends[frontend.Backend].MaxConn

View file

@ -935,6 +935,52 @@
# #
# filename = "ecs.tmpl" # filename = "ecs.tmpl"
################################################################
# 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
# Expose Rancher services by default in traefik
#
# Optional
# Default: true
#
ExposedByDefault = false
# Endpoint to use when connecting to Rancher
#
# Optional
# Endpoint = "http://rancherserver.example.com"
# AccessKey to use when connecting to Rancher
#
# Optional
# AccessKey = "XXXXXXXXX"
# SecretKey to use when connecting to Rancher
#
# Optional
# SecretKey = "XXXXXXXXXXX"
################################################################ ################################################################
# Sample rules # Sample rules

View file

@ -39,7 +39,8 @@ type CircuitBreaker struct {
// HealthCheck holds HealthCheck configuration // HealthCheck holds HealthCheck configuration
type HealthCheck struct { type HealthCheck struct {
URL string `json:"url,omitempty"` URL string `json:"url,omitempty"`
Interval string `json:"interval,omitempty"`
} }
// Server holds server configuration. // Server holds server configuration.