Compare commits

...

33 Commits

Author SHA1 Message Date
Emile Vauge
fe1b982d13 Merge pull request #856 from containous/prepare-release-v1.1.0
Changelog v1.1.0
2016-11-17 22:41:11 +01:00
Emile Vauge
221ae2427b changelog v1.1.0 2016-11-17 22:07:15 +01:00
Emile Vauge
29f780863b Merge pull request #845 from containous/fix-kubernetes-watch-leak
Fix Kubernetes watch leak
2016-11-17 18:54:12 +01:00
Emile Vauge
8aaca8e55c Update docs with errm talk 2016-11-17 17:37:06 +01:00
Emile Vauge
2dda3d2feb Fix Kubernetes watch leak
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-11-17 17:37:06 +01:00
Emile Vauge
22ebaedb45 Merge pull request #855 from containous/fix-path-case-sensitive-v1.1
Fix path case sensitive v1.1
2016-11-17 17:36:40 +01:00
Steven Bower
7065f00443 Fixes #851 (#852) 2016-11-17 15:40:25 +01:00
Emile Vauge
801e0f9ef7 Merge pull request #849 from containous/fix-golint-1.1
Fix golint in v1.1
2016-11-16 12:26:56 +01:00
Ed Robinson
ac20ddfc6c Fix golint
recent additions to golint mean that a number of files cause the
build to start failing if they are edited (we only run against changed
files)

This fixes all the errors in the repo so things don't unexpectedly start
failing for people making PRs
2016-11-16 11:52:15 +01:00
Vincent Demeester
f6576cce27 Merge pull request #842 from guilhem/version-cross-binary
Pass Version, Codename and Date to crosscompiled
2016-11-14 17:35:58 +01:00
Guilhem Lettron
d3b48cdd22 Pass Version, Codename and Date to crosscompiled
Copy variables from ./script/binary
2016-11-14 16:41:30 +01:00
Emile Vauge
c26b36cf4f Merge pull request #820 from trecloux/check_http2
Check that we serve HTTP/2
2016-11-14 09:38:31 +01:00
Thomas Recloux
3095da64d7 Check that we provide HTTP/2 2016-11-14 09:10:47 +01:00
Vincent Demeester
07f961ecba Merge pull request #829 from SantoDE/fix-webui-dashboard
Add Nvd3 Dependency to fix UI / Dashboard
2016-11-13 11:47:22 +01:00
Manuel Laufenberg
3db6e185e0 Add Nvd3 Dependency to fix UI / Dashboard 2016-11-11 21:50:59 +01:00
Emile Vauge
4430befe90 Merge pull request #823 from containous/fix-mkdoc-theme
Fix mkdoc theme
2016-11-10 12:20:46 +01:00
Emile Vauge
1c4eb4322b Fix changelog 2016-11-10 11:15:42 +01:00
Emile Vauge
3f3fa61a51 Fix mkdocs theme 2016-11-10 11:12:54 +01:00
Emile Vauge
ddf24039e8 Merge pull request #822 from containous/prepare-release-v1.1.0-rc4
Prepare release v1.1.0 rc4
2016-11-10 10:40:36 +01:00
Emile Vauge
5b6a5f8aa9 Changelog v1.1.0-rc4 2016-11-09 22:00:10 +01:00
Emile Vauge
3e6d2391f7 Add dtomcej, SantoDE remove samber from maintainers 2016-11-09 21:59:58 +01:00
Emile Vauge
664ee9d82f Merge pull request #814 from containous/fix-acme-renew
Fix multiple issues
2016-11-09 21:47:13 +01:00
Emile Vauge
c9cc3c9895 Fix contraint store/read from KV
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-11-09 21:08:37 +01:00
Emile Vauge
00c7e5c72b Ensure HTTP/2 enabled 2016-11-09 17:56:41 +01:00
Emile Vauge
558b31f4d9 Fix oxy version 2016-11-08 10:34:39 +01:00
Emile Vauge
174a5e7f13 Fix ACME renew 2016-11-07 21:51:23 +01:00
Emile Vauge
c821f191b0 Merge pull request #783 from containous/add-version-check
Fix ACME renew & add version check
2016-11-03 14:14:06 +01:00
Emile Vauge
3322e564fd Add version check
Signed-off-by: Emile Vauge <emile@vauge.com>
2016-11-03 11:30:00 +01:00
Emile Vauge
7bf5d557c1 Fix acme renew 2016-11-03 11:30:00 +01:00
Vincent Demeester
0c1e06199c Merge pull request #782 from guilhem/defaultToIndex1
Use first port by default
2016-11-02 14:34:42 -07:00
Guilhem Lettron
85a20b9a39 Use first index for ports 2016-11-02 17:31:27 +01:00
Guilhem Lettron
5641af437e Use first port by default
If no information is given, use first index of ports
2016-10-28 11:59:24 +02:00
Guilhem Lettron
1c8d3ded3d Add name to some case to help debug 2016-10-28 11:59:24 +02:00
41 changed files with 528 additions and 135 deletions

View File

@@ -20,6 +20,7 @@ install:
- docker version - docker version
- pip install --user mkdocs - pip install --user mkdocs
- pip install --user pymdown-extensions - pip install --user pymdown-extensions
- pip install --user mkdocs-bootswatch
before_script: before_script:
- make validate - make validate
- make binary - make binary

View File

@@ -1,5 +1,238 @@
# Change Log # Change Log
## [v1.1.0](https://github.com/containous/traefik/tree/v1.1.0) (2016-11-17)
[Full Changelog](https://github.com/containous/traefik/compare/v1.0.0...v1.1.0)
**Implemented enhancements:**
- Support healthcheck if present for docker [\#666](https://github.com/containous/traefik/issues/666)
- Standard unit for traefik latency in access log [\#559](https://github.com/containous/traefik/issues/559)
- \[CI\] wiredep marked as unmaintained [\#550](https://github.com/containous/traefik/issues/550)
- Feature Request: Enable Health checks to containers. [\#540](https://github.com/containous/traefik/issues/540)
- Feature Request: SSL Cipher Selection [\#535](https://github.com/containous/traefik/issues/535)
- Error with -consulcatalog and missing load balance method on 1.0.0 [\#524](https://github.com/containous/traefik/issues/524)
- Running Traefik with Docker 1.12 Swarm Mode [\#504](https://github.com/containous/traefik/issues/504)
- Kubernetes provider: should allow the master url to be override [\#501](https://github.com/containous/traefik/issues/501)
- \[FRONTEND\]\[LE\] Pre-generate SSL certificates for "Host:" rules [\#483](https://github.com/containous/traefik/issues/483)
- Frontend Rule evolution [\#437](https://github.com/containous/traefik/issues/437)
- Add a Changelog [\#388](https://github.com/containous/traefik/issues/388)
- Add label matching for kubernetes ingests [\#363](https://github.com/containous/traefik/issues/363)
- Acme in HA Traefik Scenario [\#348](https://github.com/containous/traefik/issues/348)
- HTTP Basic Auth support [\#77](https://github.com/containous/traefik/issues/77)
- Session affinity / stickiness / persistence [\#5](https://github.com/containous/traefik/issues/5)
**Fixed bugs:**
- 1.1.0-rc4 dashboard UX not displaying [\#828](https://github.com/containous/traefik/issues/828)
- Traefik stopped serving on upgrade to v1.1.0-rc3 [\#807](https://github.com/containous/traefik/issues/807)
- cannot access webui/dashboard [\#796](https://github.com/containous/traefik/issues/796)
- Traefik cannot read constraints from KV [\#794](https://github.com/containous/traefik/issues/794)
- HTTP2 - configuration [\#790](https://github.com/containous/traefik/issues/790)
- Cannot provide multiple certificates using flag [\#757](https://github.com/containous/traefik/issues/757)
- Allow multiple certificates on a single entrypoint when trying to use TLS? [\#747](https://github.com/containous/traefik/issues/747)
- traefik \* Users: unsupported type: slice [\#743](https://github.com/containous/traefik/issues/743)
- \[Docker swarm mode\] The traefik.docker.network seems to have no effect [\#719](https://github.com/containous/traefik/issues/719)
- traefik hangs - stops handling requests [\#662](https://github.com/containous/traefik/issues/662)
- Add long jobs in exponential backoff providers [\#626](https://github.com/containous/traefik/issues/626)
- Tip of tree crashes on invalid pointer on Marathon provider [\#624](https://github.com/containous/traefik/issues/624)
- ACME: revoke certificate on agreement update [\#579](https://github.com/containous/traefik/issues/579)
- WebUI: Providers tabs disappeared [\#577](https://github.com/containous/traefik/issues/577)
- traefik version command contains incorrect information when building from master branch [\#569](https://github.com/containous/traefik/issues/569)
- Case sensitive domain names breaks routing [\#562](https://github.com/containous/traefik/issues/562)
- Flag --etcd.endpoint default [\#508](https://github.com/containous/traefik/issues/508)
- Conditional ACME on demand generation [\#505](https://github.com/containous/traefik/issues/505)
- Important delay with streams \(Mozilla EventSource\) [\#503](https://github.com/containous/traefik/issues/503)
- Traefik crashing [\#458](https://github.com/containous/traefik/issues/458)
- traefik.toml constraints error: `Expected map but found 'string'.` [\#451](https://github.com/containous/traefik/issues/451)
- Multiple path separators in the url path causing redirect [\#167](https://github.com/containous/traefik/issues/167)
**Closed issues:**
- All path rules require paths to be lowercase [\#851](https://github.com/containous/traefik/issues/851)
- The UI stops working after a time and have to restart the service. [\#840](https://github.com/containous/traefik/issues/840)
- Incorrect Dashboard page returned [\#831](https://github.com/containous/traefik/issues/831)
- LoadBalancing doesn't work in single node Swarm-mode [\#815](https://github.com/containous/traefik/issues/815)
- cannot connect to docker daemon [\#813](https://github.com/containous/traefik/issues/813)
- Let's encrypt configuration not working [\#805](https://github.com/containous/traefik/issues/805)
- Multiple subdomains for Marathon backend. [\#785](https://github.com/containous/traefik/issues/785)
- traefik-1.1.0-rc1: build error [\#781](https://github.com/containous/traefik/issues/781)
- dependencies installation error [\#755](https://github.com/containous/traefik/issues/755)
- k8s provider w/ acme? [\#752](https://github.com/containous/traefik/issues/752)
- Swarm Docs - How to use a FQDN [\#744](https://github.com/containous/traefik/issues/744)
- Documented ProvidersThrottleDuration value is invalid [\#741](https://github.com/containous/traefik/issues/741)
- Sensible configuration for consulCatalog [\#737](https://github.com/containous/traefik/issues/737)
- Traefik ignoring container listening in more than one TCP port [\#734](https://github.com/containous/traefik/issues/734)
- Loadbalaning issues with traefik and Docker Swarm cluster [\#730](https://github.com/containous/traefik/issues/730)
- issues with marathon app ids containing a dot [\#726](https://github.com/containous/traefik/issues/726)
- Error when using HA acme in kubernetes with etcd [\#725](https://github.com/containous/traefik/issues/725)
- \[Docker swarm mode\] No round robin when using service [\#718](https://github.com/containous/traefik/issues/718)
- Dose it support docker swarm mode [\#712](https://github.com/containous/traefik/issues/712)
- Kubernetes - Undefined backend [\#710](https://github.com/containous/traefik/issues/710)
- How Routing traffic depending on path not domain in docker [\#706](https://github.com/containous/traefik/issues/706)
- Constraints on Consul Catalogue not working as expected [\#703](https://github.com/containous/traefik/issues/703)
- Global InsecureSkipVerify does not work [\#700](https://github.com/containous/traefik/issues/700)
- Traefik crashes when using Consul catalog [\#699](https://github.com/containous/traefik/issues/699)
- \[documentation/feature\] Consul/etcd support atomic multiple key changes now [\#698](https://github.com/containous/traefik/issues/698)
- How to configure which network to use when starting traefik binary? [\#694](https://github.com/containous/traefik/issues/694)
- How to get multiple host headers working for docker labels? [\#692](https://github.com/containous/traefik/issues/692)
- Requests with URL-encoded characters are not forwarded correctly [\#684](https://github.com/containous/traefik/issues/684)
- File Watcher for rules does not work [\#683](https://github.com/containous/traefik/issues/683)
- Issue with global InsecureSkipVerify = true and self signed certificates [\#667](https://github.com/containous/traefik/issues/667)
- Docker exposedbydefault = false didn't work [\#663](https://github.com/containous/traefik/issues/663)
- swarm documentation needs update [\#656](https://github.com/containous/traefik/issues/656)
- \[ACME\] Auto SAN Detection [\#655](https://github.com/containous/traefik/issues/655)
- Fronting a domain with DNS A-record round-robin & ACME [\#654](https://github.com/containous/traefik/issues/654)
- Overriding toml configuration with environment variables [\#650](https://github.com/containous/traefik/issues/650)
- marathon provider exposedByDefault = false [\#647](https://github.com/containous/traefik/issues/647)
- Add status URL for service up checks [\#642](https://github.com/containous/traefik/issues/642)
- acme's storage file, containing private key, is word readable [\#638](https://github.com/containous/traefik/issues/638)
- wildcard domain with exclusions [\#633](https://github.com/containous/traefik/issues/633)
- Enable evenly distribution among backend [\#631](https://github.com/containous/traefik/issues/631)
- Traefik sporadically failing when proxying requests [\#615](https://github.com/containous/traefik/issues/615)
- TCP Proxy [\#608](https://github.com/containous/traefik/issues/608)
- How to use in Windows? [\#605](https://github.com/containous/traefik/issues/605)
- `ClientCAFiles` ignored [\#604](https://github.com/containous/traefik/issues/604)
- Let`s Encrypt enable in etcd [\#600](https://github.com/containous/traefik/issues/600)
- Support HTTP Basic Auth [\#599](https://github.com/containous/traefik/issues/599)
- Consul KV seem broken [\#587](https://github.com/containous/traefik/issues/587)
- HTTPS entryPoint not working [\#574](https://github.com/containous/traefik/issues/574)
- Traefik stuck when used as frontend for a streaming API [\#560](https://github.com/containous/traefik/issues/560)
- Exclude some frontends in consul catalog [\#555](https://github.com/containous/traefik/issues/555)
- Update docs with new Mesos provider [\#548](https://github.com/containous/traefik/issues/548)
- Can I use Traefik without a domain name? [\#539](https://github.com/containous/traefik/issues/539)
- docker run syntax in swarm example has changed [\#528](https://github.com/containous/traefik/issues/528)
- Priortities in 1.0.0 not behaving [\#506](https://github.com/containous/traefik/issues/506)
- Route by path [\#500](https://github.com/containous/traefik/issues/500)
- Secure WebSockets [\#467](https://github.com/containous/traefik/issues/467)
- Container IP Lost [\#375](https://github.com/containous/traefik/issues/375)
- Multiple routes support with Docker or Marathon labels [\#118](https://github.com/containous/traefik/issues/118)
**Merged pull requests:**
- Fix path case sensitive v1.1 [\#855](https://github.com/containous/traefik/pull/855) ([emilevauge](https://github.com/emilevauge))
- Fix golint in v1.1 [\#849](https://github.com/containous/traefik/pull/849) ([emilevauge](https://github.com/emilevauge))
- Fix Kubernetes watch leak [\#845](https://github.com/containous/traefik/pull/845) ([emilevauge](https://github.com/emilevauge))
- Pass Version, Codename and Date to crosscompiled [\#842](https://github.com/containous/traefik/pull/842) ([guilhem](https://github.com/guilhem))
- Add Nvd3 Dependency to fix UI / Dashboard [\#829](https://github.com/containous/traefik/pull/829) ([SantoDE](https://github.com/SantoDE))
- Fix mkdoc theme [\#823](https://github.com/containous/traefik/pull/823) ([emilevauge](https://github.com/emilevauge))
- Prepare release v1.1.0 rc4 [\#822](https://github.com/containous/traefik/pull/822) ([emilevauge](https://github.com/emilevauge))
- Check that we serve HTTP/2 [\#820](https://github.com/containous/traefik/pull/820) ([trecloux](https://github.com/trecloux))
- Fix multiple issues [\#814](https://github.com/containous/traefik/pull/814) ([emilevauge](https://github.com/emilevauge))
- Fix ACME renew & add version check [\#783](https://github.com/containous/traefik/pull/783) ([emilevauge](https://github.com/emilevauge))
- Use first port by default [\#782](https://github.com/containous/traefik/pull/782) ([guilhem](https://github.com/guilhem))
- Prepare release v1.1.0-rc3 [\#779](https://github.com/containous/traefik/pull/779) ([emilevauge](https://github.com/emilevauge))
- Fix ResponseRecorder Flush [\#776](https://github.com/containous/traefik/pull/776) ([emilevauge](https://github.com/emilevauge))
- Use sdnotify for systemd [\#768](https://github.com/containous/traefik/pull/768) ([guilhem](https://github.com/guilhem))
- Fix providers throttle duration doc [\#760](https://github.com/containous/traefik/pull/760) ([emilevauge](https://github.com/emilevauge))
- Fix mapstructure issue with anonymous slice [\#759](https://github.com/containous/traefik/pull/759) ([emilevauge](https://github.com/emilevauge))
- Fix multiple certificates using flag [\#758](https://github.com/containous/traefik/pull/758) ([emilevauge](https://github.com/emilevauge))
- Really fix deploy ghr... [\#748](https://github.com/containous/traefik/pull/748) ([emilevauge](https://github.com/emilevauge))
- Fixes deploy ghr [\#742](https://github.com/containous/traefik/pull/742) ([emilevauge](https://github.com/emilevauge))
- prepare v1.1.0-rc2 [\#740](https://github.com/containous/traefik/pull/740) ([emilevauge](https://github.com/emilevauge))
- Fix case sensitive host [\#733](https://github.com/containous/traefik/pull/733) ([emilevauge](https://github.com/emilevauge))
- Update Kubernetes examples [\#731](https://github.com/containous/traefik/pull/731) ([Starefossen](https://github.com/Starefossen))
- fIx marathon template with dots in ID [\#728](https://github.com/containous/traefik/pull/728) ([emilevauge](https://github.com/emilevauge))
- Fix networkMap construction in ListServices [\#724](https://github.com/containous/traefik/pull/724) ([vincentlepot](https://github.com/vincentlepot))
- Add basic compatibility with marathon-lb [\#720](https://github.com/containous/traefik/pull/720) ([guilhem](https://github.com/guilhem))
- Add Ed's video at ContainerCamp [\#717](https://github.com/containous/traefik/pull/717) ([emilevauge](https://github.com/emilevauge))
- Add documentation for Træfik on docker swarm mode [\#715](https://github.com/containous/traefik/pull/715) ([vdemeester](https://github.com/vdemeester))
- Remove duplicated link to Kubernetes.io in README.md [\#713](https://github.com/containous/traefik/pull/713) ([oscerd](https://github.com/oscerd))
- Show current version in web UI [\#709](https://github.com/containous/traefik/pull/709) ([vhf](https://github.com/vhf))
- Add support for docker healthcheck 👼 [\#708](https://github.com/containous/traefik/pull/708) ([vdemeester](https://github.com/vdemeester))
- Fix syntax in Swarm example. Resolves \#528 [\#707](https://github.com/containous/traefik/pull/707) ([billglover](https://github.com/billglover))
- Add HTTP compression [\#702](https://github.com/containous/traefik/pull/702) ([tuier](https://github.com/tuier))
- Carry PR 446 - Add sticky session support \(round two!\) [\#701](https://github.com/containous/traefik/pull/701) ([emilevauge](https://github.com/emilevauge))
- Remove unused endpoint when using constraints with Marathon provider [\#697](https://github.com/containous/traefik/pull/697) ([tuier](https://github.com/tuier))
- Replace imagelayers.io with microbadger [\#696](https://github.com/containous/traefik/pull/696) ([solidnerd](https://github.com/solidnerd))
- Selectable TLS Versions [\#690](https://github.com/containous/traefik/pull/690) ([dtomcej](https://github.com/dtomcej))
- Carry pr 439 [\#689](https://github.com/containous/traefik/pull/689) ([emilevauge](https://github.com/emilevauge))
- Disable gorilla/mux URL cleaning to prevent sending redirect [\#688](https://github.com/containous/traefik/pull/688) ([ydubreuil](https://github.com/ydubreuil))
- Some fixes [\#687](https://github.com/containous/traefik/pull/687) ([emilevauge](https://github.com/emilevauge))
- feat\(constraints\): Supports constraints for Marathon provider [\#686](https://github.com/containous/traefik/pull/686) ([tuier](https://github.com/tuier))
- Update docs to improve contribution setup [\#685](https://github.com/containous/traefik/pull/685) ([dtomcej](https://github.com/dtomcej))
- Add basic auth support for web backend [\#677](https://github.com/containous/traefik/pull/677) ([SantoDE](https://github.com/SantoDE))
- Document accepted values for logLevel. [\#676](https://github.com/containous/traefik/pull/676) ([jimmycuadra](https://github.com/jimmycuadra))
- If Marathon doesn't have healthcheck, assume it's ok [\#665](https://github.com/containous/traefik/pull/665) ([gomes](https://github.com/gomes))
- ACME: renew certificates 30 days before expiry [\#660](https://github.com/containous/traefik/pull/660) ([JayH5](https://github.com/JayH5))
- Update broken link and add a comment to sample config file [\#658](https://github.com/containous/traefik/pull/658) ([Yggdrasil](https://github.com/Yggdrasil))
- Add possibility to use BindPort IPAddress 👼 [\#657](https://github.com/containous/traefik/pull/657) ([vdemeester](https://github.com/vdemeester))
- Update marathon [\#648](https://github.com/containous/traefik/pull/648) ([emilevauge](https://github.com/emilevauge))
- Add backend features to docker [\#646](https://github.com/containous/traefik/pull/646) ([jangie](https://github.com/jangie))
- enable consul catalog to use maxconn [\#645](https://github.com/containous/traefik/pull/645) ([jangie](https://github.com/jangie))
- Adopt the Code Of Coduct from http://contributor-covenant.org [\#641](https://github.com/containous/traefik/pull/641) ([errm](https://github.com/errm))
- Use secure mode 600 instead of 644 for acme.json [\#639](https://github.com/containous/traefik/pull/639) ([discordianfish](https://github.com/discordianfish))
- docker clarification, fix dead urls, misc typos [\#637](https://github.com/containous/traefik/pull/637) ([djalal](https://github.com/djalal))
- add PING handler to dashboard API [\#630](https://github.com/containous/traefik/pull/630) ([jangie](https://github.com/jangie))
- Migrate to JobBackOff [\#628](https://github.com/containous/traefik/pull/628) ([emilevauge](https://github.com/emilevauge))
- Add long job exponential backoff [\#627](https://github.com/containous/traefik/pull/627) ([emilevauge](https://github.com/emilevauge))
- HA acme support [\#625](https://github.com/containous/traefik/pull/625) ([emilevauge](https://github.com/emilevauge))
- Bump go v1.7 [\#620](https://github.com/containous/traefik/pull/620) ([emilevauge](https://github.com/emilevauge))
- Make duration logging consistent [\#619](https://github.com/containous/traefik/pull/619) ([jangie](https://github.com/jangie))
- fix for nil clientTLS causing issue [\#617](https://github.com/containous/traefik/pull/617) ([jangie](https://github.com/jangie))
- Add ability for marathon provider to set maxconn values, loadbalancer algorithm, and circuit breaker expression [\#616](https://github.com/containous/traefik/pull/616) ([jangie](https://github.com/jangie))
- Make systemd unit installable [\#613](https://github.com/containous/traefik/pull/613) ([keis](https://github.com/keis))
- Merge v1.0.2 master [\#610](https://github.com/containous/traefik/pull/610) ([emilevauge](https://github.com/emilevauge))
- update staert and flaeg [\#609](https://github.com/containous/traefik/pull/609) ([cocap10](https://github.com/cocap10))
- \#504 Initial support for Docker 1.12 Swarm Mode [\#602](https://github.com/containous/traefik/pull/602) ([diegofernandes](https://github.com/diegofernandes))
- Add Host cert ACME generation [\#601](https://github.com/containous/traefik/pull/601) ([emilevauge](https://github.com/emilevauge))
- Fixed binary script so traefik version command doesn't just print default values [\#598](https://github.com/containous/traefik/pull/598) ([keiths-osc](https://github.com/keiths-osc))
- Name servers after thier pods [\#596](https://github.com/containous/traefik/pull/596) ([errm](https://github.com/errm))
- Fix Consul prefix [\#589](https://github.com/containous/traefik/pull/589) ([jippi](https://github.com/jippi))
- Prioritize kubernetes routes by path length [\#588](https://github.com/containous/traefik/pull/588) ([philk](https://github.com/philk))
- beautify help [\#580](https://github.com/containous/traefik/pull/580) ([cocap10](https://github.com/cocap10))
- Upgrade directives name since we use angular-ui-bootstrap [\#578](https://github.com/containous/traefik/pull/578) ([micaelmbagira](https://github.com/micaelmbagira))
- Fix basic docs for configuration of multiple rules [\#576](https://github.com/containous/traefik/pull/576) ([ajaegle](https://github.com/ajaegle))
- Fix k8s watch [\#573](https://github.com/containous/traefik/pull/573) ([errm](https://github.com/errm))
- Add requirements.txt for netlify [\#567](https://github.com/containous/traefik/pull/567) ([emilevauge](https://github.com/emilevauge))
- Merge v1.0.1 master [\#565](https://github.com/containous/traefik/pull/565) ([emilevauge](https://github.com/emilevauge))
- Move webui to FountainJS with Webpack [\#558](https://github.com/containous/traefik/pull/558) ([micaelmbagira](https://github.com/micaelmbagira))
- Add global InsecureSkipVerify option to disable certificate checking [\#557](https://github.com/containous/traefik/pull/557) ([stuart-c](https://github.com/stuart-c))
- Move version.go in its own package… [\#553](https://github.com/containous/traefik/pull/553) ([vdemeester](https://github.com/vdemeester))
- Upgrade libkermit and dependencies [\#552](https://github.com/containous/traefik/pull/552) ([vdemeester](https://github.com/vdemeester))
- Add command storeconfig [\#551](https://github.com/containous/traefik/pull/551) ([cocap10](https://github.com/cocap10))
- Add basic/digest auth [\#547](https://github.com/containous/traefik/pull/547) ([emilevauge](https://github.com/emilevauge))
- Bump node to 6 for webui [\#546](https://github.com/containous/traefik/pull/546) ([vdemeester](https://github.com/vdemeester))
- Bump golang to 1.6.3 [\#545](https://github.com/containous/traefik/pull/545) ([vdemeester](https://github.com/vdemeester))
- Fix typos [\#538](https://github.com/containous/traefik/pull/538) ([jimt](https://github.com/jimt))
- Kubernetes user-guide [\#519](https://github.com/containous/traefik/pull/519) ([errm](https://github.com/errm))
- Implement Kubernetes Selectors, minor kube endpoint fix [\#516](https://github.com/containous/traefik/pull/516) ([pnegahdar](https://github.com/pnegahdar))
- Carry \#358 : Option to disable expose of all docker containers [\#514](https://github.com/containous/traefik/pull/514) ([vdemeester](https://github.com/vdemeester))
- Remove traefik.frontend.value support in docker… [\#510](https://github.com/containous/traefik/pull/510) ([vdemeester](https://github.com/vdemeester))
- Use KvStores as global config sources [\#481](https://github.com/containous/traefik/pull/481) ([cocap10](https://github.com/cocap10))
- Add endpoint option to authenticate by client tls cert. [\#461](https://github.com/containous/traefik/pull/461) ([andersbetner](https://github.com/andersbetner))
- add mesos provider inspired by mesos-dns & marathon provider [\#353](https://github.com/containous/traefik/pull/353) ([skydjol](https://github.com/skydjol))
## [v1.1.0-rc4](https://github.com/containous/traefik/tree/v1.1.0-rc4) (2016-11-10)
[Full Changelog](https://github.com/containous/traefik/compare/v1.1.0-rc3...v1.1.0-rc4)
**Implemented enhancements:**
- Feature Request: Enable Health checks to containers. [\#540](https://github.com/containous/traefik/issues/540)
**Fixed bugs:**
- Traefik stopped serving on upgrade to v1.1.0-rc3 [\#807](https://github.com/containous/traefik/issues/807)
- Traefik cannot read constraints from KV [\#794](https://github.com/containous/traefik/issues/794)
- HTTP2 - configuration [\#790](https://github.com/containous/traefik/issues/790)
- Allow multiple certificates on a single entrypoint when trying to use TLS? [\#747](https://github.com/containous/traefik/issues/747)
**Closed issues:**
- LoadBalancing doesn't work in single node Swarm-mode [\#815](https://github.com/containous/traefik/issues/815)
- cannot connect to docker daemon [\#813](https://github.com/containous/traefik/issues/813)
- Let's encrypt configuration not working [\#805](https://github.com/containous/traefik/issues/805)
- Question: Wildcard Host for Kubernetes Ingress [\#792](https://github.com/containous/traefik/issues/792)
- Multiple subdomains for Marathon backend. [\#785](https://github.com/containous/traefik/issues/785)
- traefik-1.1.0-rc1: build error [\#781](https://github.com/containous/traefik/issues/781)
- Multiple routes support with Docker or Marathon labels [\#118](https://github.com/containous/traefik/issues/118)
**Merged pull requests:**
- Prepare release v1.1.0 rc4 [\#822](https://github.com/containous/traefik/pull/822) ([emilevauge](https://github.com/emilevauge))
- Fix multiple issues [\#814](https://github.com/containous/traefik/pull/814) ([emilevauge](https://github.com/emilevauge))
- Fix ACME renew & add version check [\#783](https://github.com/containous/traefik/pull/783) ([emilevauge](https://github.com/emilevauge))
- Use first port by default [\#782](https://github.com/containous/traefik/pull/782) ([guilhem](https://github.com/guilhem))
## [v1.1.0-rc3](https://github.com/containous/traefik/tree/v1.1.0-rc3) (2016-10-26) ## [v1.1.0-rc3](https://github.com/containous/traefik/tree/v1.1.0-rc3) (2016-10-26)
[Full Changelog](https://github.com/containous/traefik/compare/v1.1.0-rc2...v1.1.0-rc3) [Full Changelog](https://github.com/containous/traefik/compare/v1.1.0-rc2...v1.1.0-rc3)

View File

@@ -52,7 +52,7 @@ Run it and forget it!
- Circuit breakers on backends - Circuit breakers on backends
- Round Robin, rebalancer load-balancers - Round Robin, rebalancer load-balancers
- Rest Metrics - Rest Metrics
- [Tiny](https://imagelayers.io/?images=traefik) [official](https://hub.docker.com/r/_/traefik/) docker image included - [Tiny](https://microbadger.com/images/traefik) [official](https://hub.docker.com/r/_/traefik/) docker image included
- SSL backends support - SSL backends support
- SSL frontend support (with SNI) - SSL frontend support (with SNI)
- Clean AngularJS Web UI - Clean AngularJS Web UI
@@ -159,9 +159,10 @@ Founded in 2014, Asteris creates next-generation infrastructure software for the
- Emile Vauge [@emilevauge](https://github.com/emilevauge) - Emile Vauge [@emilevauge](https://github.com/emilevauge)
- Vincent Demeester [@vdemeester](https://github.com/vdemeester) - Vincent Demeester [@vdemeester](https://github.com/vdemeester)
- Samuel Berthe [@samber](https://github.com/samber)
- Russell Clare [@Russell-IO](https://github.com/Russell-IO) - Russell Clare [@Russell-IO](https://github.com/Russell-IO)
- Ed Robinson [@errm](https://github.com/errm) - Ed Robinson [@errm](https://github.com/errm)
- Daniel Tomcej [@dtomcej](https://github.com/dtomcej)
- Manuel Laufenberg [@SantoDE](https://github.com/SantoDE)
## Credits ## Credits

View File

@@ -119,11 +119,12 @@ func (a *ACME) CreateClusterConfig(leadership *cluster.Leadership, tlsConfig *tl
} }
datastore, err := cluster.NewDataStore( datastore, err := cluster.NewDataStore(
leadership.Pool.Ctx(),
staert.KvSource{ staert.KvSource{
Store: leadership.Store, Store: leadership.Store,
Prefix: a.Storage, Prefix: a.Storage,
}, },
leadership.Pool.Ctx(), &Account{}, &Account{},
listener) listener)
if err != nil { if err != nil {
return err return err
@@ -136,12 +137,14 @@ func (a *ACME) CreateClusterConfig(leadership *cluster.Leadership, tlsConfig *tl
leadership.Pool.AddGoCtx(func(ctx context.Context) { leadership.Pool.AddGoCtx(func(ctx context.Context) {
log.Infof("Starting ACME renew job...") log.Infof("Starting ACME renew job...")
defer log.Infof("Stopped ACME renew job...") defer log.Infof("Stopped ACME renew job...")
select { for {
case <-ctx.Done(): select {
return case <-ctx.Done():
case <-ticker.C: return
if err := a.renewCertificates(); err != nil { case <-ticker.C:
log.Errorf("Error renewing ACME certificate: %s", err.Error()) if err := a.renewCertificates(); err != nil {
log.Errorf("Error renewing ACME certificate: %s", err.Error())
}
} }
} }
}) })
@@ -251,7 +254,6 @@ func (a *ACME) CreateLocalConfig(tlsConfig *tls.Config, checkOnDemandDomain func
needRegister = true needRegister = true
} }
log.Infof("buildACMEClient...")
a.client, err = a.buildACMEClient(account) a.client, err = a.buildACMEClient(account)
if err != nil { if err != nil {
return err return err
@@ -269,7 +271,7 @@ func (a *ACME) CreateLocalConfig(tlsConfig *tls.Config, checkOnDemandDomain func
// The client has a URL to the current Let's Encrypt Subscriber // The client has a URL to the current Let's Encrypt Subscriber
// Agreement. The user will need to agree to it. // Agreement. The user will need to agree to it.
log.Infof("AgreeToTOS...") log.Debugf("AgreeToTOS...")
err = a.client.AgreeToTOS() err = a.client.AgreeToTOS()
if err != nil { if err != nil {
// Let's Encrypt Subscriber Agreement renew ? // Let's Encrypt Subscriber Agreement renew ?
@@ -373,11 +375,6 @@ func (a *ACME) renewCertificates() error {
account := a.store.Get().(*Account) account := a.store.Get().(*Account)
for _, certificateResource := range account.DomainsCertificate.Certs { for _, certificateResource := range account.DomainsCertificate.Certs {
if certificateResource.needRenew() { if certificateResource.needRenew() {
transaction, object, err := a.store.Begin()
if err != nil {
return err
}
account = object.(*Account)
log.Debugf("Renewing certificate %+v", certificateResource.Domains) log.Debugf("Renewing certificate %+v", certificateResource.Domains)
renewedCert, err := a.client.RenewCertificate(acme.CertificateResource{ renewedCert, err := a.client.RenewCertificate(acme.CertificateResource{
Domain: certificateResource.Certificate.Domain, Domain: certificateResource.Certificate.Domain,
@@ -398,6 +395,11 @@ func (a *ACME) renewCertificates() error {
PrivateKey: renewedCert.PrivateKey, PrivateKey: renewedCert.PrivateKey,
Certificate: renewedCert.Certificate, Certificate: renewedCert.Certificate,
} }
transaction, object, err := a.store.Begin()
if err != nil {
return err
}
account = object.(*Account)
err = account.DomainsCertificate.renewCertificates(renewedACMECert, certificateResource.Domains) err = account.DomainsCertificate.renewCertificates(renewedACMECert, certificateResource.Domains)
if err != nil { if err != nil {
log.Errorf("Error renewing certificate: %v", err) log.Errorf("Error renewing certificate: %v", err)

View File

@@ -68,7 +68,7 @@ func (t *localTransaction) Commit(object cluster.Object) error {
t.LocalStore.account = object.(*Account) t.LocalStore.account = object.(*Account)
defer t.storageLock.Unlock() defer t.storageLock.Unlock()
if t.dirty { if t.dirty {
return fmt.Errorf("Transaction already used. Please begin a new one.") return fmt.Errorf("transaction already used, please begin a new one")
} }
// write account to file // write account to file

View File

@@ -56,7 +56,7 @@ type Datastore struct {
} }
// NewDataStore creates a Datastore // NewDataStore creates a Datastore
func NewDataStore(kvSource staert.KvSource, ctx context.Context, object Object, listener Listener) (*Datastore, error) { func NewDataStore(ctx context.Context, kvSource staert.KvSource, object Object, listener Listener) (*Datastore, error) {
datastore := Datastore{ datastore := Datastore{
kv: kvSource, kv: kvSource,
ctx: ctx, ctx: ctx,
@@ -230,7 +230,7 @@ func (s *datastoreTransaction) Commit(object Object) error {
s.localLock.Lock() s.localLock.Lock()
defer s.localLock.Unlock() defer s.localLock.Unlock()
if s.dirty { if s.dirty {
return fmt.Errorf("Transaction already used. Please begin a new one.") return fmt.Errorf("transaction already used, please begin a new one")
} }
s.Datastore.meta.object = object s.Datastore.meta.object = object
err := s.Datastore.meta.Marshall() err := s.Datastore.meta.Marshall()

View File

@@ -39,7 +39,7 @@ func (l *Leadership) Participate(pool *safe.Pool) {
defer log.Debugf("Node %s no more running for election", l.Cluster.Node) defer log.Debugf("Node %s no more running for election", l.Cluster.Node)
backOff := backoff.NewExponentialBackOff() backOff := backoff.NewExponentialBackOff()
operation := func() error { operation := func() error {
return l.run(l.candidate, ctx) return l.run(ctx, l.candidate)
} }
notify := func(err error, time time.Duration) { notify := func(err error, time time.Duration) {
@@ -63,7 +63,7 @@ func (l *Leadership) Resign() {
log.Infof("Node %s resigned", l.Cluster.Node) log.Infof("Node %s resigned", l.Cluster.Node)
} }
func (l *Leadership) run(candidate *leadership.Candidate, ctx context.Context) error { func (l *Leadership) run(ctx context.Context, candidate *leadership.Candidate) error {
electedCh, errCh := candidate.RunForElection() electedCh, errCh := candidate.RunForElection()
for { for {
select { select {

View File

@@ -25,6 +25,7 @@ type TraefikConfiguration struct {
type GlobalConfiguration struct { type GlobalConfiguration struct {
GraceTimeOut int64 `short:"g" description:"Duration to give active requests a chance to finish during hot-reload"` 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"` 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"` AccessLogsFile string `description:"Access logs file"`
TraefikLogsFile string `description:"Traefik logs file"` TraefikLogsFile string `description:"Traefik logs file"`
LogLevel string `short:"l" description:"Log level"` LogLevel string `short:"l" description:"Log level"`
@@ -233,10 +234,10 @@ func (certs *Certificates) CreateTLSConfig() (*tls.Config, error) {
if errKey == nil { if errKey == nil {
isAPath = true isAPath = true
} else { } else {
return nil, fmt.Errorf("Bad TLS Certificate KeyFile format. Expected a path.") return nil, fmt.Errorf("bad TLS Certificate KeyFile format, expected a path")
} }
} else if errKey == nil { } else if errKey == nil {
return nil, fmt.Errorf("Bad TLS Certificate KeyFile format. Expected a path.") return nil, fmt.Errorf("bad TLS Certificate KeyFile format, expected a path")
} }
cert := tls.Certificate{} cert := tls.Certificate{}
@@ -328,54 +329,54 @@ func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration {
defaultMarathon.Watch = true defaultMarathon.Watch = true
defaultMarathon.Endpoint = "http://127.0.0.1:8080" defaultMarathon.Endpoint = "http://127.0.0.1:8080"
defaultMarathon.ExposedByDefault = true defaultMarathon.ExposedByDefault = true
defaultMarathon.Constraints = []types.Constraint{} defaultMarathon.Constraints = types.Constraints{}
// default Consul // default Consul
var defaultConsul provider.Consul var defaultConsul provider.Consul
defaultConsul.Watch = true defaultConsul.Watch = true
defaultConsul.Endpoint = "127.0.0.1:8500" defaultConsul.Endpoint = "127.0.0.1:8500"
defaultConsul.Prefix = "traefik" defaultConsul.Prefix = "traefik"
defaultConsul.Constraints = []types.Constraint{} defaultConsul.Constraints = types.Constraints{}
// default ConsulCatalog // default ConsulCatalog
var defaultConsulCatalog provider.ConsulCatalog var defaultConsulCatalog provider.ConsulCatalog
defaultConsulCatalog.Endpoint = "127.0.0.1:8500" defaultConsulCatalog.Endpoint = "127.0.0.1:8500"
defaultConsulCatalog.Constraints = []types.Constraint{} defaultConsulCatalog.Constraints = types.Constraints{}
// default Etcd // default Etcd
var defaultEtcd provider.Etcd var defaultEtcd provider.Etcd
defaultEtcd.Watch = true defaultEtcd.Watch = true
defaultEtcd.Endpoint = "127.0.0.1:2379" defaultEtcd.Endpoint = "127.0.0.1:2379"
defaultEtcd.Prefix = "/traefik" defaultEtcd.Prefix = "/traefik"
defaultEtcd.Constraints = []types.Constraint{} defaultEtcd.Constraints = types.Constraints{}
//default Zookeeper //default Zookeeper
var defaultZookeeper provider.Zookepper var defaultZookeeper provider.Zookepper
defaultZookeeper.Watch = true defaultZookeeper.Watch = true
defaultZookeeper.Endpoint = "127.0.0.1:2181" defaultZookeeper.Endpoint = "127.0.0.1:2181"
defaultZookeeper.Prefix = "/traefik" defaultZookeeper.Prefix = "/traefik"
defaultZookeeper.Constraints = []types.Constraint{} defaultZookeeper.Constraints = types.Constraints{}
//default Boltdb //default Boltdb
var defaultBoltDb provider.BoltDb var defaultBoltDb provider.BoltDb
defaultBoltDb.Watch = true defaultBoltDb.Watch = true
defaultBoltDb.Endpoint = "127.0.0.1:4001" defaultBoltDb.Endpoint = "127.0.0.1:4001"
defaultBoltDb.Prefix = "/traefik" defaultBoltDb.Prefix = "/traefik"
defaultBoltDb.Constraints = []types.Constraint{} defaultBoltDb.Constraints = types.Constraints{}
//default Kubernetes //default Kubernetes
var defaultKubernetes provider.Kubernetes var defaultKubernetes provider.Kubernetes
defaultKubernetes.Watch = true defaultKubernetes.Watch = true
defaultKubernetes.Endpoint = "" defaultKubernetes.Endpoint = ""
defaultKubernetes.LabelSelector = "" defaultKubernetes.LabelSelector = ""
defaultKubernetes.Constraints = []types.Constraint{} defaultKubernetes.Constraints = types.Constraints{}
// default Mesos // default Mesos
var defaultMesos provider.Mesos var defaultMesos provider.Mesos
defaultMesos.Watch = true defaultMesos.Watch = true
defaultMesos.Endpoint = "http://127.0.0.1:5050" defaultMesos.Endpoint = "http://127.0.0.1:5050"
defaultMesos.ExposedByDefault = true defaultMesos.ExposedByDefault = true
defaultMesos.Constraints = []types.Constraint{} defaultMesos.Constraints = types.Constraints{}
defaultConfiguration := GlobalConfiguration{ defaultConfiguration := GlobalConfiguration{
Docker: &defaultDocker, Docker: &defaultDocker,
@@ -405,10 +406,11 @@ func NewTraefikConfiguration() *TraefikConfiguration {
TraefikLogsFile: "", TraefikLogsFile: "",
LogLevel: "ERROR", LogLevel: "ERROR",
EntryPoints: map[string]*EntryPoint{}, EntryPoints: map[string]*EntryPoint{},
Constraints: []types.Constraint{}, Constraints: types.Constraints{},
DefaultEntryPoints: []string{}, DefaultEntryPoints: []string{},
ProvidersThrottleDuration: time.Duration(2 * time.Second), ProvidersThrottleDuration: time.Duration(2 * time.Second),
MaxIdleConnsPerHost: 200, MaxIdleConnsPerHost: 200,
CheckNewVersion: true,
}, },
ConfigFile: "", ConfigFile: "",
} }

View File

@@ -40,10 +40,15 @@ Run it and forget it!
You can have a quick look at Træfɪk in this [Katacoda tutorial](https://www.katacoda.com/courses/traefik/deploy-load-balancer) that shows how to load balance requests between multiple Docker containers. You can have a quick look at Træ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 (in french) given by [Emile Vauge](https://github.com/emilevauge) at the [Devoxx France 2016](http://www.devoxx.fr) conference. Here is a talk given by [Ed Robinson](https://github.com/errm) at the [ContainerCamp UK](https://container.camp) conference.
You will learn fundamental Træfɪk features and see some demos with Docker, Mesos/Marathon and Lets'Encrypt. You will learn fundamental Træfɪk features and see some demos with Kubernetes.
[![Traefik Devoxx France](https://img.youtube.com/vi/QvAz9mVx5TI/0.jpg)](https://www.youtube.com/watch?v=QvAz9mVx5TI) [![Traefik ContainerCamp UK](http://img.youtube.com/vi/aFtpIShV60I/0.jpg)](https://www.youtube.com/watch?v=aFtpIShV60I)
Here is a talk (in French) given by [Emile Vauge](https://github.com/emilevauge) at the [Devoxx France 2016](http://www.devoxx.fr) conference.
You will learn fundamental Træfɪk features and see some demos with Docker, Mesos/Marathon and Let's Encrypt.
[![Traefik Devoxx France](http://img.youtube.com/vi/QvAz9mVx5TI/0.jpg)](http://www.youtube.com/watch?v=QvAz9mVx5TI)
## Get it ## Get it

View File

@@ -9,6 +9,28 @@
# Global configuration # Global configuration
################################################################ ################################################################
# Timeout in seconds.
# Duration to give active requests a chance to finish during hot-reloads
#
# Optional
# Default: 10
#
# graceTimeOut = 10
# Enable debug mode
#
# Optional
# Default: false
#
# debug = true
# Periodically check if a new version has been released
#
# Optional
# Default: true
#
# checkNewVersion = false
# Traefik logs file # Traefik logs file
# If not defined, logs to stdout # If not defined, logs to stdout
# #

16
glide.lock generated
View File

@@ -1,5 +1,5 @@
hash: 45d9abd00276bba5aaeb92cd5f2464e404bba3cf90f37aa538d4866041626327 hash: 1bbeb842ee639ccc6e2edf8cc13fc2759cb96e3d839a1aec7b7f6af4fb89c8e1
updated: 2016-10-26T14:26:07.740582437+02:00 updated: 2016-11-09T19:24:00.762904389+01:00
imports: imports:
- name: github.com/abbot/go-http-auth - name: github.com/abbot/go-http-auth
version: cb4372376e1e00e9f6ab9ec142e029302c9e7140 version: cb4372376e1e00e9f6ab9ec142e029302c9e7140
@@ -24,7 +24,7 @@ imports:
- name: github.com/containous/mux - name: github.com/containous/mux
version: a819b77bba13f0c0cbe36e437bc2e948411b3996 version: a819b77bba13f0c0cbe36e437bc2e948411b3996
- name: github.com/containous/staert - name: github.com/containous/staert
version: 92329254783dc01174f03302d51d7cf2c9ff84cf version: 1e26a71803e428fd933f5f9c8e50a26878f53147
- name: github.com/coreos/etcd - name: github.com/coreos/etcd
version: 1c9e0a0e33051fed6c05c141e6fcbfe5c7f2a899 version: 1c9e0a0e33051fed6c05c141e6fcbfe5c7f2a899
subpackages: subpackages:
@@ -168,6 +168,10 @@ imports:
- proto - proto
- name: github.com/golang/glog - name: github.com/golang/glog
version: fca8c8854093a154ff1eb580aae10276ad6b1b5f version: fca8c8854093a154ff1eb580aae10276ad6b1b5f
- name: github.com/google/go-github
version: 55263f30529cb06f5b478efc333390b791cfe3b1
subpackages:
- github
- name: github.com/google/go-querystring - name: github.com/google/go-querystring
version: 9235644dd9e52eeae6fa48efd539fdc351a0af53 version: 9235644dd9e52eeae6fa48efd539fdc351a0af53
subpackages: subpackages:
@@ -180,6 +184,8 @@ imports:
- api - api
- name: github.com/hashicorp/go-cleanhttp - name: github.com/hashicorp/go-cleanhttp
version: ad28ea4487f05916463e2423a55166280e8254b5 version: ad28ea4487f05916463e2423a55166280e8254b5
- name: github.com/hashicorp/go-version
version: e96d3840402619007766590ecea8dd7af1292276
- name: github.com/hashicorp/serf - name: github.com/hashicorp/serf
version: b03bf85930b2349eb04b97c8fac437495296e3e7 version: b03bf85930b2349eb04b97c8fac437495296e3e7
subpackages: subpackages:
@@ -271,12 +277,14 @@ imports:
- codec - codec
- name: github.com/unrolled/render - name: github.com/unrolled/render
version: 526faf80cd4b305bb8134abea8d20d5ced74faa6 version: 526faf80cd4b305bb8134abea8d20d5ced74faa6
- name: github.com/urfave/negroni
version: e0e50f7dc431c043cb33f91b09c3419d48b7cff5
- name: github.com/vdemeester/docker-events - name: github.com/vdemeester/docker-events
version: be74d4929ec1ad118df54349fda4b0cba60f849b version: be74d4929ec1ad118df54349fda4b0cba60f849b
- name: github.com/vdemeester/shakers - name: github.com/vdemeester/shakers
version: 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3 version: 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
- name: github.com/vulcand/oxy - name: github.com/vulcand/oxy
version: 4298f24d572dc554eb984f2ffdf6bdd54d4bd613 version: fcc76b52eb8568540a020b7a99e854d9d752b364
repo: https://github.com/containous/oxy.git repo: https://github.com/containous/oxy.git
vcs: git vcs: git
subpackages: subpackages:

View File

@@ -6,11 +6,11 @@ import:
- fun - fun
- package: github.com/Sirupsen/logrus - package: github.com/Sirupsen/logrus
- package: github.com/cenk/backoff - package: github.com/cenk/backoff
- package: github.com/codegangsta/negroni - package: github.com/urfave/negroni
- package: github.com/containous/flaeg - package: github.com/containous/flaeg
version: a731c034dda967333efce5f8d276aeff11f8ff87 version: a731c034dda967333efce5f8d276aeff11f8ff87
- package: github.com/vulcand/oxy - package: github.com/vulcand/oxy
version: 4298f24d572dc554eb984f2ffdf6bdd54d4bd613 version: fcc76b52eb8568540a020b7a99e854d9d752b364
repo: https://github.com/containous/oxy.git repo: https://github.com/containous/oxy.git
vcs: git vcs: git
subpackages: subpackages:
@@ -21,7 +21,7 @@ import:
- stream - stream
- utils - utils
- package: github.com/containous/staert - package: github.com/containous/staert
version: 92329254783dc01174f03302d51d7cf2c9ff84cf version: 1e26a71803e428fd933f5f9c8e50a26878f53147
- package: github.com/docker/engine-api - package: github.com/docker/engine-api
version: 62043eb79d581a32ea849645277023c550732e52 version: 62043eb79d581a32ea849645277023c550732e52
subpackages: subpackages:
@@ -107,4 +107,6 @@ import:
- package: github.com/coreos/go-systemd - package: github.com/coreos/go-systemd
version: v12 version: v12
subpackages: subpackages:
- daemon - daemon
- package: github.com/google/go-github
- package: github.com/hashicorp/go-version

View File

@@ -446,9 +446,9 @@ func (s *ConsulSuite) TestDatastore(c *check.C) {
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
ctx := context.Background() ctx := context.Background()
datastore1, err := cluster.NewDataStore(*kvSource, ctx, &TestStruct{}, nil) datastore1, err := cluster.NewDataStore(ctx, *kvSource, &TestStruct{}, nil)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
datastore2, err := cluster.NewDataStore(*kvSource, ctx, &TestStruct{}, nil) datastore2, err := cluster.NewDataStore(ctx, *kvSource, &TestStruct{}, nil)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
setter1, _, err := datastore1.Begin() setter1, _, err := datastore1.Begin()

View File

@@ -30,6 +30,7 @@ func (s *HTTPSSuite) TestWithSNIConfigHandshake(c *check.C) {
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
InsecureSkipVerify: true, InsecureSkipVerify: true,
ServerName: "snitest.com", ServerName: "snitest.com",
NextProtos: []string{"h2", "http/1.1"},
} }
conn, err := tls.Dial("tcp", "127.0.0.1:4443", tlsConfig) conn, err := tls.Dial("tcp", "127.0.0.1:4443", tlsConfig)
c.Assert(err, checker.IsNil, check.Commentf("failed to connect to server")) c.Assert(err, checker.IsNil, check.Commentf("failed to connect to server"))
@@ -41,6 +42,9 @@ func (s *HTTPSSuite) TestWithSNIConfigHandshake(c *check.C) {
cs := conn.ConnectionState() cs := conn.ConnectionState()
err = cs.PeerCertificates[0].VerifyHostname("snitest.com") err = cs.PeerCertificates[0].VerifyHostname("snitest.com")
c.Assert(err, checker.IsNil, check.Commentf("certificate did not match SNI servername")) c.Assert(err, checker.IsNil, check.Commentf("certificate did not match SNI servername"))
proto := conn.ConnectionState().NegotiatedProtocol
c.Assert(proto, checker.Equals, "h2")
} }
// TestWithSNIConfigRoute involves a client sending HTTPS requests with // TestWithSNIConfigRoute involves a client sending HTTPS requests with

View File

@@ -17,7 +17,7 @@ type BoltDb struct {
// 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 *BoltDb) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { func (provider *BoltDb) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
store, err := provider.CreateStore() store, err := provider.CreateStore()
if err != nil { if err != nil {
return fmt.Errorf("Failed to Connect to KV store: %v", err) return fmt.Errorf("Failed to Connect to KV store: %v", err)

View File

@@ -17,7 +17,7 @@ type Consul struct {
// 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 *Consul) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { func (provider *Consul) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
store, err := provider.CreateStore() store, err := provider.CreateStore()
if err != nil { if err != nil {
return fmt.Errorf("Failed to Connect to KV store: %v", err) return fmt.Errorf("Failed to Connect to KV store: %v", err)

View File

@@ -317,7 +317,7 @@ func (provider *ConsulCatalog) watch(configurationChan chan<- types.ConfigMessag
// 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 *ConsulCatalog) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { func (provider *ConsulCatalog) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
config := api.DefaultConfig() config := api.DefaultConfig()
config.Address = provider.Endpoint config.Address = provider.Endpoint
client, err := api.NewClient(config) client, err := api.NewClient(config)

View File

@@ -114,7 +114,7 @@ func (provider *Docker) createClient() (client.APIClient, error) {
// 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 *Docker) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { func (provider *Docker) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
provider.Constraints = append(provider.Constraints, constraints...) provider.Constraints = append(provider.Constraints, constraints...)
// TODO register this routine in pool, and watch for stop channel // TODO register this routine in pool, and watch for stop channel
safe.Go(func() { safe.Go(func() {
@@ -364,10 +364,6 @@ func (provider *Docker) containerFilter(container dockerData) bool {
log.Debugf("Filtering container without port and no traefik.port label %s", container.Name) log.Debugf("Filtering container without port and no traefik.port label %s", container.Name)
return false return false
} }
if len(container.NetworkSettings.Ports) > 1 && err != nil {
log.Debugf("Filtering container with more than 1 port and no traefik.port label %s", container.Name)
return false
}
if !isContainerEnabled(container, provider.ExposedByDefault) { if !isContainerEnabled(container, provider.ExposedByDefault) {
log.Debugf("Filtering disabled container %s", container.Name) log.Debugf("Filtering disabled container %s", container.Name)

View File

@@ -390,6 +390,27 @@ func TestDockerGetPort(t *testing.T) {
}, },
expected: "8080", expected: "8080",
}, },
{
container: docker.ContainerJSON{
ContainerJSONBase: &docker.ContainerJSONBase{
Name: "test-multi-ports",
},
Config: &container.Config{
Labels: map[string]string{
"traefik.port": "8080",
},
},
NetworkSettings: &docker.NetworkSettings{
NetworkSettingsBase: docker.NetworkSettingsBase{
Ports: nat.PortMap{
"8080/tcp": {},
"80/tcp": {},
},
},
},
},
expected: "8080",
},
} }
for _, e := range containers { for _, e := range containers {
@@ -735,7 +756,7 @@ func TestDockerTraefikFilter(t *testing.T) {
{ {
container: docker.ContainerJSON{ container: docker.ContainerJSON{
ContainerJSONBase: &docker.ContainerJSONBase{ ContainerJSONBase: &docker.ContainerJSONBase{
Name: "container", Name: "container-multi-ports",
}, },
Config: &container.Config{}, Config: &container.Config{},
NetworkSettings: &docker.NetworkSettings{ NetworkSettings: &docker.NetworkSettings{
@@ -748,7 +769,7 @@ func TestDockerTraefikFilter(t *testing.T) {
}, },
}, },
exposedByDefault: true, exposedByDefault: true,
expected: false, expected: true,
}, },
{ {
container: docker.ContainerJSON{ container: docker.ContainerJSON{

View File

@@ -17,7 +17,7 @@ type Etcd struct {
// 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 *Etcd) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { func (provider *Etcd) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
store, err := provider.CreateStore() store, err := provider.CreateStore()
if err != nil { if err != nil {
return fmt.Errorf("Failed to Connect to KV store: %v", err) return fmt.Errorf("Failed to Connect to KV store: %v", err)

View File

@@ -21,7 +21,7 @@ type File struct {
// 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 *File) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, _ []types.Constraint) error { func (provider *File) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
watcher, err := fsnotify.NewWatcher() watcher, err := fsnotify.NewWatcher()
if err != nil { if err != nil {
log.Error("Error creating file watcher", err) log.Error("Error creating file watcher", err)

View File

@@ -1,6 +1,7 @@
package k8s package k8s
import ( import (
"context"
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"encoding/json" "encoding/json"
@@ -141,20 +142,20 @@ func (c *clientImpl) WatchEndpoints(stopCh <-chan bool) (chan interface{}, chan
// WatchAll returns events in the cluster // WatchAll returns events in the cluster
func (c *clientImpl) WatchAll(labelSelector string, stopCh <-chan bool) (chan interface{}, chan error, error) { func (c *clientImpl) WatchAll(labelSelector string, stopCh <-chan bool) (chan interface{}, chan error, error) {
watchCh := make(chan interface{}, 10) watchCh := make(chan interface{}, 100)
errCh := make(chan error, 10) errCh := make(chan error, 100)
stopIngresses := make(chan bool) stopIngresses := make(chan bool, 10)
chanIngresses, chanIngressesErr, err := c.WatchIngresses(labelSelector, stopIngresses) chanIngresses, chanIngressesErr, err := c.WatchIngresses(labelSelector, stopIngresses)
if err != nil { if err != nil {
return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err) return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err)
} }
stopServices := make(chan bool) stopServices := make(chan bool, 10)
chanServices, chanServicesErr, err := c.WatchServices(stopServices) chanServices, chanServicesErr, err := c.WatchServices(stopServices)
if err != nil { if err != nil {
return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err) return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err)
} }
stopEndpoints := make(chan bool) stopEndpoints := make(chan bool, 10)
chanEndpoints, chanEndpointsErr, err := c.WatchEndpoints(stopEndpoints) chanEndpoints, chanEndpointsErr, err := c.WatchEndpoints(stopEndpoints)
if err != nil { if err != nil {
return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err) return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err)
@@ -257,16 +258,17 @@ func (c *clientImpl) watch(url string, labelSelector string, stopCh <-chan bool)
if err != nil { if err != nil {
return watchCh, errCh, fmt.Errorf("failed to make watch request: GET %q : %v", url, err) return watchCh, errCh, fmt.Errorf("failed to make watch request: GET %q : %v", url, err)
} }
ctx, cancel := context.WithCancel(context.Background())
req = req.WithContext(ctx)
request.Client.Transport = request.Transport request.Client.Transport = request.Transport
res, err := request.Client.Do(req) res, err := request.Client.Do(req)
if err != nil { if err != nil {
cancel()
return watchCh, errCh, fmt.Errorf("failed to do watch request: GET %q: %v", url, err) return watchCh, errCh, fmt.Errorf("failed to do watch request: GET %q: %v", url, err)
} }
go func() { go func() {
finishCh := make(chan bool)
defer close(finishCh)
defer close(watchCh) defer close(watchCh)
defer close(errCh) defer close(errCh)
go func() { go func() {
@@ -277,20 +279,15 @@ func (c *clientImpl) watch(url string, labelSelector string, stopCh <-chan bool)
if !strings.Contains(err.Error(), "net/http: request canceled") { if !strings.Contains(err.Error(), "net/http: request canceled") {
errCh <- fmt.Errorf("failed to decode watch event: GET %q : %v", url, err) errCh <- fmt.Errorf("failed to decode watch event: GET %q : %v", url, err)
} }
finishCh <- true
return return
} }
watchCh <- eventList watchCh <- eventList
} }
}() }()
select { <-stopCh
case <-stopCh: go func() {
go func() { cancel() // cancel watch request
request.Transport.CancelRequest(req) }()
}()
<-finishCh
return
}
}() }()
return watchCh, errCh, nil return watchCh, errCh, nil
} }

View File

@@ -94,7 +94,7 @@ func (provider *Kubernetes) createClient() (k8s.Client, error) {
// 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 *Kubernetes) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { func (provider *Kubernetes) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
k8sClient, err := provider.createClient() k8sClient, err := provider.createClient()
if err != nil { if err != nil {
return err return err
@@ -130,6 +130,7 @@ func (provider *Kubernetes) Provide(configurationChan chan<- types.ConfigMessage
log.Debugf("Received event from kubernetes %+v", event) log.Debugf("Received event from kubernetes %+v", event)
templateObjects, err := provider.loadIngresses(k8sClient) templateObjects, err := provider.loadIngresses(k8sClient)
if err != nil { if err != nil {
stopWatch <- true
return err return err
} }
if reflect.DeepEqual(provider.lastConfiguration.Get(), templateObjects) { if reflect.DeepEqual(provider.lastConfiguration.Get(), templateObjects) {

View File

@@ -83,7 +83,7 @@ func (provider *Kv) watchKv(configurationChan chan<- types.ConfigMessage, prefix
return nil return nil
} }
func (provider *Kv) provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { func (provider *Kv) provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
provider.Constraints = append(provider.Constraints, constraints...) provider.Constraints = append(provider.Constraints, constraints...)
operation := func() error { operation := func() error {
if _, err := provider.kvclient.Exists("qmslkjdfmqlskdjfmqlksjazçueznbvbwzlkajzebvkwjdcqmlsfj"); err != nil { if _, err := provider.kvclient.Exists("qmslkjdfmqlskdjfmqlksjazçueznbvbwzlkajzebvkwjdcqmlsfj"); err != nil {

View File

@@ -50,7 +50,7 @@ type lightMarathonClient interface {
// 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 *Marathon) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { func (provider *Marathon) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
provider.Constraints = append(provider.Constraints, constraints...) provider.Constraints = append(provider.Constraints, constraints...)
operation := func() error { operation := func() error {
config := marathon.NewDefaultConfig() config := marathon.NewDefaultConfig()
@@ -219,10 +219,7 @@ func (provider *Marathon) taskFilter(task marathon.Task, applications *marathon.
log.Debugf("Filtering marathon task %s specifying both traefik.portIndex and traefik.port labels", task.AppID) log.Debugf("Filtering marathon task %s specifying both traefik.portIndex and traefik.port labels", task.AppID)
return false return false
} }
if portIndexLabel == "" && portValueLabel == "" && len(application.Ports) > 1 {
log.Debugf("Filtering marathon task %s with more than 1 port and no traefik.portIndex or traefik.port label", task.AppID)
return false
}
if portIndexLabel != "" { if portIndexLabel != "" {
index, err := strconv.Atoi((*application.Labels)["traefik.portIndex"]) index, err := strconv.Atoi((*application.Labels)["traefik.portIndex"])
if err != nil || index < 0 || index > len(application.Ports)-1 { if err != nil || index < 0 || index > len(application.Ports)-1 {

View File

@@ -371,30 +371,30 @@ func TestMarathonTaskFilter(t *testing.T) {
}, },
{ {
task: marathon.Task{ task: marathon.Task{
AppID: "foo", AppID: "multiple-ports",
Ports: []int{80}, Ports: []int{80, 443},
}, },
applications: &marathon.Applications{ applications: &marathon.Applications{
Apps: []marathon.Application{ Apps: []marathon.Application{
{ {
ID: "foo", ID: "multiple-ports",
Ports: []int{80, 443}, Ports: []int{80, 443},
Labels: &map[string]string{}, Labels: &map[string]string{},
}, },
}, },
}, },
expected: false, expected: true,
exposedByDefault: true, exposedByDefault: true,
}, },
{ {
task: marathon.Task{ task: marathon.Task{
AppID: "foo", AppID: "disable",
Ports: []int{80}, Ports: []int{80},
}, },
applications: &marathon.Applications{ applications: &marathon.Applications{
Apps: []marathon.Application{ Apps: []marathon.Application{
{ {
ID: "foo", ID: "disable",
Ports: []int{80}, Ports: []int{80},
Labels: &map[string]string{ Labels: &map[string]string{
"traefik.enable": "false", "traefik.enable": "false",
@@ -523,7 +523,7 @@ func TestMarathonTaskFilter(t *testing.T) {
}, },
{ {
task: marathon.Task{ task: marathon.Task{
AppID: "foo", AppID: "healthcheck-false",
Ports: []int{80}, Ports: []int{80},
HealthCheckResults: []*marathon.HealthCheckResult{ HealthCheckResults: []*marathon.HealthCheckResult{
{ {
@@ -534,7 +534,7 @@ func TestMarathonTaskFilter(t *testing.T) {
applications: &marathon.Applications{ applications: &marathon.Applications{
Apps: []marathon.Application{ Apps: []marathon.Application{
{ {
ID: "foo", ID: "healthcheck-false",
Ports: []int{80}, Ports: []int{80},
Labels: &map[string]string{}, Labels: &map[string]string{},
HealthChecks: &[]marathon.HealthCheck{ HealthChecks: &[]marathon.HealthCheck{
@@ -576,13 +576,13 @@ func TestMarathonTaskFilter(t *testing.T) {
}, },
{ {
task: marathon.Task{ task: marathon.Task{
AppID: "foo", AppID: "single-port",
Ports: []int{80}, Ports: []int{80},
}, },
applications: &marathon.Applications{ applications: &marathon.Applications{
Apps: []marathon.Application{ Apps: []marathon.Application{
{ {
ID: "foo", ID: "single-port",
Ports: []int{80}, Ports: []int{80},
Labels: &map[string]string{}, Labels: &map[string]string{},
}, },
@@ -593,7 +593,7 @@ func TestMarathonTaskFilter(t *testing.T) {
}, },
{ {
task: marathon.Task{ task: marathon.Task{
AppID: "foo", AppID: "healthcheck-alive",
Ports: []int{80}, Ports: []int{80},
HealthCheckResults: []*marathon.HealthCheckResult{ HealthCheckResults: []*marathon.HealthCheckResult{
{ {
@@ -604,7 +604,7 @@ func TestMarathonTaskFilter(t *testing.T) {
applications: &marathon.Applications{ applications: &marathon.Applications{
Apps: []marathon.Application{ Apps: []marathon.Application{
{ {
ID: "foo", ID: "healthcheck-alive",
Ports: []int{80}, Ports: []int{80},
Labels: &map[string]string{}, Labels: &map[string]string{},
HealthChecks: &[]marathon.HealthCheck{ HealthChecks: &[]marathon.HealthCheck{
@@ -677,7 +677,7 @@ func TestMarathonTaskFilter(t *testing.T) {
for _, c := range cases { for _, c := range cases {
actual := provider.taskFilter(c.task, c.applications, c.exposedByDefault) actual := provider.taskFilter(c.task, c.applications, c.exposedByDefault)
if actual != c.expected { if actual != c.expected {
t.Fatalf("expected %v, got %v", c.expected, actual) t.Fatalf("App %s: expected %v, got %v", c.task.AppID, c.expected, actual)
} }
} }
} }
@@ -740,7 +740,7 @@ func TestMarathonAppConstraints(t *testing.T) {
MarathonLBCompatibility: c.marathonLBCompatibility, MarathonLBCompatibility: c.marathonLBCompatibility,
} }
constraint, _ := types.NewConstraint("tag==valid") constraint, _ := types.NewConstraint("tag==valid")
provider.Constraints = []types.Constraint{*constraint} provider.Constraints = types.Constraints{constraint}
actual := provider.applicationFilter(c.application, c.filteredTasks) actual := provider.applicationFilter(c.application, c.filteredTasks)
if actual != c.expected { if actual != c.expected {
t.Fatalf("expected %v, got %v: %v", c.expected, actual, c.application) t.Fatalf("expected %v, got %v: %v", c.expected, actual, c.application)
@@ -820,7 +820,7 @@ func TestMarathonTaskConstraints(t *testing.T) {
MarathonLBCompatibility: c.marathonLBCompatibility, MarathonLBCompatibility: c.marathonLBCompatibility,
} }
constraint, _ := types.NewConstraint("tag==valid") constraint, _ := types.NewConstraint("tag==valid")
provider.Constraints = []types.Constraint{*constraint} provider.Constraints = types.Constraints{constraint}
apps := new(marathon.Applications) apps := new(marathon.Applications)
apps.Apps = c.applications apps.Apps = c.applications
actual := provider.taskFilter(c.filteredTask, apps, true) actual := provider.taskFilter(c.filteredTask, apps, true)
@@ -927,12 +927,12 @@ func TestMarathonGetPort(t *testing.T) {
{ {
applications: []marathon.Application{ applications: []marathon.Application{
{ {
ID: "test1", ID: "multiple-ports-take-first",
Labels: &map[string]string{}, Labels: &map[string]string{},
}, },
}, },
task: marathon.Task{ task: marathon.Task{
AppID: "test1", AppID: "multiple-ports-take-first",
Ports: []int{80, 443}, Ports: []int{80, 443},
}, },
expected: "80", expected: "80",

View File

@@ -42,7 +42,7 @@ type Mesos struct {
// 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 *Mesos) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { func (provider *Mesos) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
operation := func() error { operation := func() error {
// initialize logging // initialize logging
@@ -212,10 +212,6 @@ func mesosTaskFilter(task state.Task, exposedByDefaultFlag bool) bool {
log.Debugf("Filtering mesos task %s specifying both traefik.portIndex and traefik.port labels", task.Name) log.Debugf("Filtering mesos task %s specifying both traefik.portIndex and traefik.port labels", task.Name)
return false return false
} }
if portIndexLabel == "" && portValueLabel == "" && len(task.DiscoveryInfo.Ports.DiscoveryPorts) > 1 {
log.Debugf("Filtering mesos task %s with more than 1 port and no traefik.portIndex or traefik.port label", task.Name)
return false
}
if portIndexLabel != "" { if portIndexLabel != "" {
index, err := strconv.Atoi(labels(task, "traefik.portIndex")) index, err := strconv.Atoi(labels(task, "traefik.portIndex"))
if err != nil || index < 0 || index > len(task.DiscoveryInfo.Ports.DiscoveryPorts)-1 { if err != nil || index < 0 || index > len(task.DiscoveryInfo.Ports.DiscoveryPorts)-1 {

View File

@@ -95,7 +95,7 @@ func TestMesosTaskFilter(t *testing.T) {
setLabels("traefik.enable", "true"), setLabels("traefik.enable", "true"),
discovery(setDiscoveryPorts("TCP", 80, "WEB HTTP", "TCP", 443, "WEB HTTPS")), discovery(setDiscoveryPorts("TCP", 80, "WEB HTTP", "TCP", 443, "WEB HTTPS")),
), ),
expected: false, // more than 1 discovery port but no traefik.port* label expected: true, // Default to first index
exposedByDefault: true, exposedByDefault: true,
}, },
{ {

View File

@@ -23,7 +23,7 @@ import (
type Provider interface { type Provider interface {
// 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.
Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error
} }
// BaseProvider should be inherited by providers // BaseProvider should be inherited by providers
@@ -44,7 +44,7 @@ func (p *BaseProvider) MatchConstraints(tags []string) (bool, *types.Constraint)
for _, constraint := range p.Constraints { for _, constraint := range p.Constraints {
// xor: if ok and constraint.MustMatch are equal, then no tag is currently matching with the constraint // xor: if ok and constraint.MustMatch are equal, then no tag is currently matching with the constraint
if ok := constraint.MatchConstraintWithAtLeastOneTag(tags); ok != constraint.MustMatch { if ok := constraint.MatchConstraintWithAtLeastOneTag(tags); ok != constraint.MustMatch {
return false, &constraint return false, constraint
} }
} }

View File

@@ -230,13 +230,13 @@ func TestNilClientTLS(t *testing.T) {
func TestMatchingConstraints(t *testing.T) { func TestMatchingConstraints(t *testing.T) {
cases := []struct { cases := []struct {
constraints []types.Constraint constraints types.Constraints
tags []string tags []string
expected bool expected bool
}{ }{
// simple test: must match // simple test: must match
{ {
constraints: []types.Constraint{ constraints: types.Constraints{
{ {
Key: "tag", Key: "tag",
MustMatch: true, MustMatch: true,
@@ -250,7 +250,7 @@ func TestMatchingConstraints(t *testing.T) {
}, },
// simple test: must match but does not match // simple test: must match but does not match
{ {
constraints: []types.Constraint{ constraints: types.Constraints{
{ {
Key: "tag", Key: "tag",
MustMatch: true, MustMatch: true,
@@ -264,7 +264,7 @@ func TestMatchingConstraints(t *testing.T) {
}, },
// simple test: must not match // simple test: must not match
{ {
constraints: []types.Constraint{ constraints: types.Constraints{
{ {
Key: "tag", Key: "tag",
MustMatch: false, MustMatch: false,
@@ -278,7 +278,7 @@ func TestMatchingConstraints(t *testing.T) {
}, },
// complex test: globbing // complex test: globbing
{ {
constraints: []types.Constraint{ constraints: types.Constraints{
{ {
Key: "tag", Key: "tag",
MustMatch: true, MustMatch: true,
@@ -292,7 +292,7 @@ func TestMatchingConstraints(t *testing.T) {
}, },
// complex test: multiple constraints // complex test: multiple constraints
{ {
constraints: []types.Constraint{ constraints: types.Constraints{
{ {
Key: "tag", Key: "tag",
MustMatch: true, MustMatch: true,

View File

@@ -17,7 +17,7 @@ type Zookepper struct {
// 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 *Zookepper) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { func (provider *Zookepper) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
store, err := provider.CreateStore() store, err := provider.CreateStore()
if err != nil { if err != nil {
return fmt.Errorf("Failed to Connect to KV store: %v", err) return fmt.Errorf("Failed to Connect to KV store: %v", err)

View File

@@ -45,7 +45,7 @@ func (r *Rules) hostRegexp(hosts ...string) *mux.Route {
func (r *Rules) path(paths ...string) *mux.Route { func (r *Rules) path(paths ...string) *mux.Route {
router := r.route.route.Subrouter() router := r.route.route.Subrouter()
for _, path := range paths { for _, path := range paths {
router.Path(types.CanonicalDomain(path)) router.Path(strings.TrimSpace(path))
} }
return r.route.route return r.route.route
} }
@@ -53,7 +53,7 @@ func (r *Rules) path(paths ...string) *mux.Route {
func (r *Rules) pathPrefix(paths ...string) *mux.Route { func (r *Rules) pathPrefix(paths ...string) *mux.Route {
router := r.route.route.Subrouter() router := r.route.route.Subrouter()
for _, path := range paths { for _, path := range paths {
router.PathPrefix(types.CanonicalDomain(path)) router.PathPrefix(strings.TrimSpace(path))
} }
return r.route.route return r.route.route
} }
@@ -69,7 +69,7 @@ func (r *Rules) pathStrip(paths ...string) *mux.Route {
r.route.stripPrefixes = paths r.route.stripPrefixes = paths
router := r.route.route.Subrouter() router := r.route.route.Subrouter()
for _, path := range paths { for _, path := range paths {
router.Path(types.CanonicalDomain(path)) router.Path(strings.TrimSpace(path))
} }
return r.route.route return r.route.route
} }
@@ -79,7 +79,7 @@ func (r *Rules) pathPrefixStrip(paths ...string) *mux.Route {
r.route.stripPrefixes = paths r.route.stripPrefixes = paths
router := r.route.route.Subrouter() router := r.route.route.Subrouter()
for _, path := range paths { for _, path := range paths {
router.PathPrefix(types.CanonicalDomain(path)) router.PathPrefix(strings.TrimSpace(path))
} }
return r.route.route return r.route.route
} }

View File

@@ -40,15 +40,23 @@ func TestParseTwoRules(t *testing.T) {
routeResult, err := rules.Parse(expression) routeResult, err := rules.Parse(expression)
if err != nil { if err != nil {
t.Fatal("Error while building route for Host:foo.bar;Path:/foobar") t.Fatal("Error while building route for Host:foo.bar;Path:/FOObar")
} }
request, err := http.NewRequest("GET", "http://foo.bar/foobar", nil) request, err := http.NewRequest("GET", "http://foo.bar/foobar", nil)
routeMatch := routeResult.Match(request, &mux.RouteMatch{Route: routeResult}) routeMatch := routeResult.Match(request, &mux.RouteMatch{Route: routeResult})
if routeMatch == true {
t.Log(err)
t.Fatal("Rule Host:foo.bar;Path:/FOObar don't match")
}
request, err = http.NewRequest("GET", "http://foo.bar/FOObar", nil)
routeMatch = routeResult.Match(request, &mux.RouteMatch{Route: routeResult})
if routeMatch == false { if routeMatch == false {
t.Log(err) t.Log(err)
t.Fatal("Rule Host:foo.bar;Path:/foobar don't match") t.Fatal("Rule Host:foo.bar;Path:/FOObar don't match")
} }
} }

View File

@@ -27,7 +27,7 @@ OS_ARCH_ARG=(386 amd64)
for OS in ${OS_PLATFORM_ARG[@]}; do for OS in ${OS_PLATFORM_ARG[@]}; do
for ARCH in ${OS_ARCH_ARG[@]}; do for ARCH in ${OS_ARCH_ARG[@]}; do
echo "Building binary for $OS/$ARCH..." echo "Building binary for $OS/$ARCH..."
GOARCH=$ARCH GOOS=$OS CGO_ENABLED=0 go build -ldflags "-s -w -X main.Version=$VERSION -X main.Codename=$CODENAME -X main.BuildDate=$DATE" -o "dist/traefik_$OS-$ARCH" . GOARCH=$ARCH GOOS=$OS CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/containous/traefik/version.Version=$VERSION -X github.com/containous/traefik/version.Codename=$CODENAME -X github.com/containous/traefik/version.BuildDate=$DATE" -o "dist/traefik_$OS-$ARCH" .
done done
done done
@@ -38,6 +38,6 @@ OS_ARCH_ARG=(arm arm64)
for OS in ${OS_PLATFORM_ARG[@]}; do for OS in ${OS_PLATFORM_ARG[@]}; do
for ARCH in ${OS_ARCH_ARG[@]}; do for ARCH in ${OS_ARCH_ARG[@]}; do
echo "Building binary for $OS/$ARCH..." echo "Building binary for $OS/$ARCH..."
GOARCH=$ARCH GOOS=$OS CGO_ENABLED=0 go build -ldflags "-s -w -X main.Version=$VERSION -X main.Codename=$CODENAME -X main.BuildDate=$DATE" -o "dist/traefik_$OS-$ARCH" . GOARCH=$ARCH GOOS=$OS CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/containous/traefik/version.Version=$VERSION -X github.com/containous/traefik/version.Codename=$CODENAME -X github.com/containous/traefik/version.BuildDate=$DATE" -o "dist/traefik_$OS-$ARCH" .
done done
done done

View File

@@ -383,6 +383,9 @@ func (server *Server) createTLSConfig(entryPointName string, tlsOption *TLS, rou
return nil, err return nil, err
} }
// ensure http2 enabled
config.NextProtos = []string{"h2", "http/1.1"}
if len(tlsOption.ClientCAFiles) > 0 { if len(tlsOption.ClientCAFiles) > 0 {
pool := x509.NewCertPool() pool := x509.NewCertPool()
for _, caFile := range tlsOption.ClientCAFiles { for _, caFile := range tlsOption.ClientCAFiles {

View File

@@ -11,6 +11,7 @@ import (
"runtime" "runtime"
"strings" "strings"
"text/template" "text/template"
"time"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/containous/flaeg" "github.com/containous/flaeg"
@@ -20,12 +21,12 @@ import (
"github.com/containous/traefik/log" "github.com/containous/traefik/log"
"github.com/containous/traefik/middlewares" "github.com/containous/traefik/middlewares"
"github.com/containous/traefik/provider" "github.com/containous/traefik/provider"
"github.com/containous/traefik/safe"
"github.com/containous/traefik/types" "github.com/containous/traefik/types"
"github.com/containous/traefik/version" "github.com/containous/traefik/version"
"github.com/coreos/go-systemd/daemon"
"github.com/docker/libkv/store" "github.com/docker/libkv/store"
"github.com/satori/go.uuid" "github.com/satori/go.uuid"
"github.com/coreos/go-systemd/daemon"
) )
var versionTemplate = `Version: {{.Version}} var versionTemplate = `Version: {{.Version}}
@@ -263,6 +264,20 @@ func run(traefikConfiguration *TraefikConfiguration) {
} }
jsonConf, _ := json.Marshal(globalConfiguration) jsonConf, _ := json.Marshal(globalConfiguration)
log.Infof("Traefik version %s built on %s", version.Version, version.BuildDate) 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 { if len(traefikConfiguration.ConfigFile) != 0 {
log.Infof("Using TOML configuration file %s", traefikConfiguration.ConfigFile) log.Infof("Using TOML configuration file %s", traefikConfiguration.ConfigFile)
} }

View File

@@ -10,6 +10,20 @@
# #
# graceTimeOut = 10 # graceTimeOut = 10
# Enable debug mode
#
# Optional
# Default: false
#
# debug = true
# Periodically check if a new version has been released
#
# Optional
# Default: true
#
# checkNewVersion = false
# Traefik logs file # Traefik logs file
# If not defined, logs to stdout # If not defined, logs to stdout
# #

View File

@@ -1,6 +1,7 @@
package types package types
import ( import (
"encoding"
"errors" "errors"
"fmt" "fmt"
"github.com/docker/libkv/store" "github.com/docker/libkv/store"
@@ -141,11 +142,25 @@ func (c *Constraint) String() string {
return c.Key + "!=" + c.Regex return c.Key + "!=" + c.Regex
} }
var _ encoding.TextUnmarshaler = (*Constraint)(nil)
// UnmarshalText define how unmarshal in TOML parsing // UnmarshalText define how unmarshal in TOML parsing
func (c *Constraint) UnmarshalText(text []byte) error { func (c *Constraint) UnmarshalText(text []byte) error {
constraint, err := NewConstraint(string(text)) constraint, err := NewConstraint(string(text))
*c = *constraint if err != nil {
return err return err
}
c.Key = constraint.Key
c.MustMatch = constraint.MustMatch
c.Regex = constraint.Regex
return nil
}
var _ encoding.TextMarshaler = (*Constraint)(nil)
// MarshalText encodes the receiver into UTF-8-encoded text and returns the result.
func (c *Constraint) MarshalText() (text []byte, err error) {
return []byte(c.String()), nil
} }
// MatchConstraintWithAtLeastOneTag tests a constraint for one single service // MatchConstraintWithAtLeastOneTag tests a constraint for one single service
@@ -169,16 +184,16 @@ func (cs *Constraints) Set(str string) error {
if err != nil { if err != nil {
return err return err
} }
*cs = append(*cs, *constraint) *cs = append(*cs, constraint)
} }
return nil return nil
} }
// Constraints holds a Constraint parser // Constraints holds a Constraint parser
type Constraints []Constraint type Constraints []*Constraint
//Get []*Constraint //Get []*Constraint
func (cs *Constraints) Get() interface{} { return []Constraint(*cs) } func (cs *Constraints) Get() interface{} { return []*Constraint(*cs) }
//String returns []*Constraint in string //String returns []*Constraint in string
func (cs *Constraints) String() string { return fmt.Sprintf("%+v", *cs) } func (cs *Constraints) String() string { return fmt.Sprintf("%+v", *cs) }

View File

@@ -1,5 +1,12 @@
package version package version
import (
"github.com/containous/traefik/log"
"github.com/google/go-github/github"
goversion "github.com/hashicorp/go-version"
"net/url"
)
var ( var (
// Version holds the current version of traefik. // Version holds the current version of traefik.
Version = "dev" Version = "dev"
@@ -8,3 +15,50 @@ var (
// BuildDate holds the build date of traefik. // BuildDate holds the build date of traefik.
BuildDate = "I don't remember exactly" BuildDate = "I don't remember exactly"
) )
// CheckNewVersion checks if a new version is available
func CheckNewVersion() {
if Version == "dev" {
return
}
client := github.NewClient(nil)
updateURL, err := url.Parse("https://update.traefik.io")
if err != nil {
log.Warnf("Error checking new version: %s", err)
return
}
client.BaseURL = updateURL
releases, resp, err := client.Repositories.ListReleases("containous", "traefik", nil)
if err != nil {
log.Warnf("Error checking new version: %s", err)
return
}
if resp.StatusCode != 200 {
log.Warnf("Error checking new version: status=%s", resp.Status)
return
}
currentVersion, err := goversion.NewVersion(Version)
if err != nil {
log.Warnf("Error checking new version: %s", err)
return
}
for _, release := range releases {
releaseVersion, err := goversion.NewVersion(*release.TagName)
if err != nil {
log.Warnf("Error checking new version: %s", err)
return
}
if len(currentVersion.Prerelease()) == 0 && len(releaseVersion.Prerelease()) > 0 {
continue
}
if releaseVersion.GreaterThan(currentVersion) {
log.Warnf("A new release has been found: %s. Please consider updating.", releaseVersion.String())
return
}
}
}

2
web.go
View File

@@ -50,7 +50,7 @@ func goroutines() interface{} {
// 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 *WebProvider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, _ []types.Constraint) error { func (provider *WebProvider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, _ types.Constraints) error {
systemRouter := mux.NewRouter() systemRouter := mux.NewRouter()

View File

@@ -21,7 +21,8 @@
"angular-ui-bootstrap": "^2.0.0", "angular-ui-bootstrap": "^2.0.0",
"angular-ui-router": "^0.3.1", "angular-ui-router": "^0.3.1",
"bootstrap": "^3.3.6", "bootstrap": "^3.3.6",
"moment": "^2.14.1" "moment": "^2.14.1",
"nvd3": "^1.8.4"
}, },
"devDependencies": { "devDependencies": {
"angular-mocks": "^1.4.2", "angular-mocks": "^1.4.2",
@@ -80,11 +81,6 @@
"test": "gulp test", "test": "gulp test",
"test:auto": "gulp test:auto" "test:auto": "gulp test:auto"
}, },
"overrides": {
"angular-nvd3": {
"main": "dist/angular-nvd3.js"
}
},
"eslintConfig": { "eslintConfig": {
"globals": { "globals": {
"expect": true "expect": true