Merge pull request #76 from emilevauge/yet-another-refactoring

Yet another refactoring
This commit is contained in:
Vincent Demeester 2015-10-29 21:39:48 +01:00
commit b12c4ac55a
17 changed files with 228 additions and 145 deletions

View file

@ -1,9 +1,9 @@
![Træfɪk](http://traefik.github.io/traefik.logo.svg "Træfɪk") ![Træfɪk](http://traefik.github.io/traefik.logo.svg "Træfɪk")
___ ___
[![Circle CI](https://img.shields.io/circleci/project/EmileVauge/traefik.svg)](https://circleci.com/gh/EmileVauge/traefik) [![Circle CI](https://circleci.com/gh/emilevauge/traefik.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/emilevauge/traefik)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/EmileVauge/traefik/blob/master/LICENSE.md) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/EmileVauge/traefik/blob/master/LICENSE.md)
[![Join the chat at https://gitter.im/EmileVauge/traefik](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/EmileVauge/traefik?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the chat at https://traefik.herokuapp.com](https://img.shields.io/badge/style-register-green.svg?style=social&label=Slack)](https://traefik.herokuapp.com)
Træfɪk is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease. Træfɪk is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease.

View file

@ -103,3 +103,10 @@ func NewLoadBalancerMethod(loadBalancer *LoadBalancer) (LoadBalancerMethod, erro
} }
var ErrInvalidLoadBalancerMethod = errors.New("Invalid method, using default") var ErrInvalidLoadBalancerMethod = errors.New("Invalid method, using default")
type configMessage struct {
providerName string
configuration *Configuration
}
type configs map[string]*Configuration

View file

@ -8,6 +8,7 @@ import (
"text/template" "text/template"
"time" "time"
"fmt"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/BurntSushi/ty/fun" "github.com/BurntSushi/ty/fun"
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
@ -73,18 +74,14 @@ func (provider *DockerProvider) Provide(configurationChan chan<- configMessage)
func (provider *DockerProvider) loadDockerConfig(dockerClient *docker.Client) *Configuration { func (provider *DockerProvider) loadDockerConfig(dockerClient *docker.Client) *Configuration {
var DockerFuncMap = template.FuncMap{ var DockerFuncMap = template.FuncMap{
"getBackend": func(container docker.Container) string { "getBackend": func(container docker.Container) string {
for key, value := range container.Config.Labels { if label, err := provider.getLabel(container, "traefik.backend"); err == nil {
if key == "traefik.backend" { return label
return value
} }
} return provider.getEscapedName(container.Name)
return getHost(container)
}, },
"getPort": func(container docker.Container) string { "getPort": func(container docker.Container) string {
for key, value := range container.Config.Labels { if label, err := provider.getLabel(container, "traefik.port"); err == nil {
if key == "traefik.port" { return label
return value
}
} }
for key := range container.NetworkSettings.Ports { for key := range container.NetworkSettings.Ports {
return key.Port() return key.Port()
@ -92,30 +89,33 @@ func (provider *DockerProvider) loadDockerConfig(dockerClient *docker.Client) *C
return "" return ""
}, },
"getWeight": func(container docker.Container) string { "getWeight": func(container docker.Container) string {
for key, value := range container.Config.Labels { if label, err := provider.getLabel(container, "traefik.weight"); err == nil {
if key == "traefik.weight" { return label
return value
}
} }
return "0" return "0"
}, },
"getDomain": func(container docker.Container) string { "getDomain": func(container docker.Container) string {
for key, value := range container.Config.Labels { if label, err := provider.getLabel(container, "traefik.domain"); err == nil {
if key == "traefik.domain" { return label
return value
}
} }
return provider.Domain return provider.Domain
}, },
"getProtocol": func(container docker.Container) string {
if label, err := provider.getLabel(container, "traefik.protocol"); err == nil {
return label
}
return "http"
},
"getFrontendValue": provider.GetFrontendValue,
"getFrontendRule": provider.GetFrontendRule,
"replace": func(s1 string, s2 string, s3 string) string { "replace": func(s1 string, s2 string, s3 string) string {
return strings.Replace(s3, s1, s2, -1) return strings.Replace(s3, s1, s2, -1)
}, },
"getHost": getHost,
} }
configuration := new(Configuration) configuration := new(Configuration)
containerList, _ := dockerClient.ListContainers(docker.ListContainersOptions{}) containerList, _ := dockerClient.ListContainers(docker.ListContainersOptions{})
containersInspected := []docker.Container{} containersInspected := []docker.Container{}
hosts := map[string][]docker.Container{} frontends := map[string][]docker.Container{}
// get inspect containers // get inspect containers
for _, container := range containerList { for _, container := range containerList {
@ -138,20 +138,26 @@ func (provider *DockerProvider) loadDockerConfig(dockerClient *docker.Client) *C
log.Debugf("Filtering disabled container %s", container.Name) log.Debugf("Filtering disabled container %s", container.Name)
return false return false
} }
if _, err := provider.getLabels(container, []string{"traefik.frontend.rule", "traefik.frontend.value"}); err != nil {
log.Debugf("Filtering bad labeled container %s", container.Name)
return false
}
return true return true
}, containersInspected).([]docker.Container) }, containersInspected).([]docker.Container)
for _, container := range filteredContainers { for _, container := range filteredContainers {
hosts[getHost(container)] = append(hosts[getHost(container)], container) frontends[provider.getFrontendName(container)] = append(frontends[provider.getFrontendName(container)], container)
} }
templateObjects := struct { templateObjects := struct {
Containers []docker.Container Containers []docker.Container
Hosts map[string][]docker.Container Frontends map[string][]docker.Container
Domain string Domain string
}{ }{
filteredContainers, filteredContainers,
hosts, frontends,
provider.Domain, provider.Domain,
} }
tmpl := template.New(provider.Filename).Funcs(DockerFuncMap) tmpl := template.New(provider.Filename).Funcs(DockerFuncMap)
@ -162,7 +168,7 @@ func (provider *DockerProvider) loadDockerConfig(dockerClient *docker.Client) *C
return nil return nil
} }
} else { } else {
buf, err := Asset("providerTemplates/docker.tmpl") buf, err := Asset("templates/docker.tmpl")
if err != nil { if err != nil {
log.Error("Error reading file", err) log.Error("Error reading file", err)
} }
@ -187,11 +193,47 @@ func (provider *DockerProvider) loadDockerConfig(dockerClient *docker.Client) *C
return configuration return configuration
} }
func getHost(container docker.Container) string { func (provider *DockerProvider) getFrontendName(container docker.Container) string {
// Replace '.' with '-' in quoted keys because of this issue https://github.com/BurntSushi/toml/issues/78
frontendName := fmt.Sprintf("%s-%s", provider.GetFrontendRule(container), provider.GetFrontendValue(container))
return strings.Replace(frontendName, ".", "-", -1)
}
func (provider *DockerProvider) getEscapedName(name string) string {
return strings.Replace(name, "/", "", -1)
}
func (provider *DockerProvider) getLabel(container docker.Container, label string) (string, error) {
for key, value := range container.Config.Labels { for key, value := range container.Config.Labels {
if key == "traefik.host" { if key == label {
return value return value, nil
} }
} }
return strings.Replace(strings.Replace(container.Name, "/", "", -1), ".", "-", -1) return "", errors.New("Label not found:" + label)
}
func (provider *DockerProvider) getLabels(container docker.Container, labels []string) (map[string]string, error) {
foundLabels := map[string]string{}
for _, label := range labels {
if foundLabel, err := provider.getLabel(container, label); err != nil {
return nil, errors.New("Label not found: " + label)
} else {
foundLabels[label] = foundLabel
}
}
return foundLabels, nil
}
func (provider *DockerProvider) GetFrontendValue(container docker.Container) string {
if label, err := provider.getLabel(container, "traefik.frontend.value"); err == nil {
return label
}
return provider.getEscapedName(container.Name) + "." + provider.Domain
}
func (provider *DockerProvider) GetFrontendRule(container docker.Container) string {
if label, err := provider.getLabel(container, "traefik.frontend.rule"); err == nil {
return label
}
return "Host"
} }

View file

@ -25,7 +25,7 @@ It supports several backends ([Docker :whale:](https://www.docker.com/), [Mesos/
Basically, Træfɪk is a http router, which sends traffic from frontends to http backends, following rules you have configured. Basically, Træfɪk is a http router, which sends traffic from frontends to http backends, following rules you have configured.
### Frontends ### <a id="frontends"></a> Frontends
Frontends can be defined using the following rules: Frontends can be defined using the following rules:
@ -407,11 +407,14 @@ Labels can be used on containers to override default behaviour:
- `traefik.backend=foo`: assign the container to `foo` backend - `traefik.backend=foo`: assign the container to `foo` backend
- `traefik.port=80`: register this port. Useful when the container exposes multiples ports. - `traefik.port=80`: register this port. Useful when the container exposes multiples ports.
- `traefik.protocol=https`: override the default `http` protocol
- `traefik.weight=10`: assign this weight to the container - `traefik.weight=10`: assign this weight to the container
- `traefik.enable=false`: disable this container in Træfɪk - `traefik.enable=false`: disable this container in Træfɪk
- `traefik.host=bar`: override the default routing from `{containerName}.{domain}` to `bar.{domain}` - `traefik.frontend.rule=Host`: override the default frontend rule (Default: Host). See [frontends](#frontends).
- `traefik.frontend.value=test.example.com`: override the default frontend value (Default: `{containerName}.{domain}`) See [frontends](#frontends).
* `traefik.domain=traefik.localhost`: override the default domain * `traefik.domain=traefik.localhost`: override the default domain
## <a id="marathon"></a> Marathon backend ## <a id="marathon"></a> Marathon backend
Træfɪk can be configured to use Marathon as a backend configuration: Træfɪk can be configured to use Marathon as a backend configuration:
@ -466,10 +469,11 @@ Labels can be used on containers to override default behaviour:
- `traefik.backend=foo`: assign the application to `foo` backend - `traefik.backend=foo`: assign the application to `foo` backend
- `traefik.port=80`: register this port. Useful when the application exposes multiples ports. - `traefik.port=80`: register this port. Useful when the application exposes multiples ports.
- `traefik.protocol=https`: override the default `http` protocol
- `traefik.weight=10`: assign this weight to the application - `traefik.weight=10`: assign this weight to the application
- `traefik.enable=false`: disable this application in Træfɪk - `traefik.enable=false`: disable this application in Træfɪk
- `traefik.host=bar`: override the default routing from `{appName}.{domain}` to `bar.{domain}` - `traefik.frontend.rule=Host`: override the default frontend rule (Default: Host). See [frontends](#frontends).
- `traefik.prefixes=pf1,pf2`: use `PathPrefix(es)` instead of hostname for routing, use `filename="providerTemplates/marathon-prefix.tmpl"` with this option - `traefik.frontend.value=test.example.com`: override the default frontend value (Default: `{appName}.{domain}`) See [frontends](#frontends).
* `traefik.domain=traefik.localhost`: override the default domain * `traefik.domain=traefik.localhost`: override the default domain
## <a id="consul"></a> Consul backend ## <a id="consul"></a> Consul backend

View file

@ -4,6 +4,6 @@ Copyright
//go:generate go get github.com/jteeuwen/go-bindata/... //go:generate go get github.com/jteeuwen/go-bindata/...
//go:generate rm -vf gen.go //go:generate rm -vf gen.go
//go:generate go-bindata -o gen.go static/... templates/... providerTemplates/... //go:generate go-bindata -o gen.go static/... templates/...
package main package main

3
kv.go
View file

@ -88,6 +88,7 @@ func (provider *KvProvider) provide(configurationChan chan<- configMessage) erro
[]string{provider.Endpoint}, []string{provider.Endpoint},
&store.Config{ &store.Config{
ConnectionTimeout: 30 * time.Second, ConnectionTimeout: 30 * time.Second,
Bucket: "traefik",
}, },
) )
if err != nil { if err != nil {
@ -166,7 +167,7 @@ func (provider *KvProvider) loadConfig() *Configuration {
return nil return nil
} }
} else { } else {
buf, err := Asset("providerTemplates/kv.tmpl") buf, err := Asset("templates/kv.tmpl")
if err != nil { if err != nil {
log.Error("Error reading file", err) log.Error("Error reading file", err)
} }

View file

@ -6,6 +6,7 @@ import (
"strings" "strings"
"text/template" "text/template"
"errors"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/BurntSushi/ty/fun" "github.com/BurntSushi/ty/fun"
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
@ -62,41 +63,39 @@ func (provider *MarathonProvider) loadMarathonConfig() *Configuration {
} }
return "" return ""
}, },
"getHost": func(application marathon.Application) string { "getWeight": func(task marathon.Task, applications []marathon.Application) string {
for key, value := range application.Labels { application, errApp := getApplication(task, applications)
if key == "traefik.host" { if errApp != nil {
return value log.Errorf("Unable to get marathon application from task %s", task.AppID)
} return "0"
}
return strings.Replace(application.ID, "/", "", 1)
},
"getWeight": func(application marathon.Application) string {
for key, value := range application.Labels {
if key == "traefik.weight" {
return value
} }
if label, err := provider.getLabel(application, "traefik.weight"); err == nil {
return label
} }
return "0" return "0"
}, },
"getDomain": func(application marathon.Application) string { "getDomain": func(application marathon.Application) string {
for key, value := range application.Labels { if label, err := provider.getLabel(application, "traefik.domain"); err == nil {
if key == "traefik.domain" { return label
return value
}
} }
return provider.Domain return provider.Domain
}, },
"getPrefixes": func(application marathon.Application) ([]string, error) {
for key, value := range application.Labels {
if key == "traefik.prefixes" {
return strings.Split(value, ","), nil
}
}
return []string{}, nil
},
"replace": func(s1 string, s2 string, s3 string) string { "replace": func(s1 string, s2 string, s3 string) string {
return strings.Replace(s3, s1, s2, -1) return strings.Replace(s3, s1, s2, -1)
}, },
"getProtocol": func(task marathon.Task, applications []marathon.Application) string {
application, errApp := getApplication(task, applications)
if errApp != nil {
log.Errorf("Unable to get marathon application from task %s", task.AppID)
return "http"
}
if label, err := provider.getLabel(application, "traefik.protocol"); err == nil {
return label
}
return "http"
},
"getFrontendValue": provider.GetFrontendValue,
"getFrontendRule": provider.GetFrontendRule,
} }
configuration := new(Configuration) configuration := new(Configuration)
@ -118,8 +117,8 @@ func (provider *MarathonProvider) loadMarathonConfig() *Configuration {
log.Debug("Filtering marathon task without port", task.AppID) log.Debug("Filtering marathon task without port", task.AppID)
return false return false
} }
application := getApplication(task, applications.Apps) application, errApp := getApplication(task, applications.Apps)
if application == nil { if errApp != nil {
log.Errorf("Unable to get marathon application from task %s", task.AppID) log.Errorf("Unable to get marathon application from task %s", task.AppID)
return false return false
} }
@ -167,7 +166,7 @@ func (provider *MarathonProvider) loadMarathonConfig() *Configuration {
return nil return nil
} }
} else { } else {
buf, err := Asset("providerTemplates/marathon.tmpl") buf, err := Asset("templates/marathon.tmpl")
if err != nil { if err != nil {
log.Error("Error reading file", err) log.Error("Error reading file", err)
} }
@ -194,11 +193,38 @@ func (provider *MarathonProvider) loadMarathonConfig() *Configuration {
return configuration return configuration
} }
func getApplication(task marathon.Task, apps []marathon.Application) *marathon.Application { func getApplication(task marathon.Task, apps []marathon.Application) (marathon.Application, error) {
for _, application := range apps { for _, application := range apps {
if application.ID == task.AppID { if application.ID == task.AppID {
return &application return application, nil
} }
} }
return nil return marathon.Application{}, errors.New("Application not found: " + task.AppID)
}
func (provider *MarathonProvider) getLabel(application marathon.Application, label string) (string, error) {
for key, value := range application.Labels {
if key == label {
return value, nil
}
}
return "", errors.New("Label not found:" + label)
}
func (provider *MarathonProvider) getEscapedName(name string) string {
return strings.Replace(name, "/", "", -1)
}
func (provider *MarathonProvider) GetFrontendValue(application marathon.Application) string {
if label, err := provider.getLabel(application, "traefik.frontend.value"); err == nil {
return label
}
return provider.getEscapedName(application.ID) + "." + provider.Domain
}
func (provider *MarathonProvider) GetFrontendRule(application marathon.Application) string {
if label, err := provider.getLabel(application, "traefik.frontend.rule"); err == nil {
return label
}
return "Host"
} }

View file

@ -73,15 +73,16 @@ func NewProxy(target *url.URL) *WebsocketProxy {
// ServeHTTP implements the http.Handler that proxies WebSocket connections. // ServeHTTP implements the http.Handler that proxies WebSocket connections.
func (w *WebsocketProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { func (w *WebsocketProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if w.Backend == nil { if w.Backend == nil {
log.Println("websocketproxy: backend function is not defined") log.Errorf("Websocketproxy: backend function is not defined")
http.Error(rw, "internal server error (code: 1)", http.StatusInternalServerError) http.Error(rw, "Backend not found", http.StatusInternalServerError)
http.NotFound(rw, req)
return return
} }
backendURL := w.Backend(req) backendURL := w.Backend(req)
if backendURL == nil { if backendURL == nil {
log.Println("websocketproxy: backend URL is nil") log.Errorf("Websocketproxy: backend URL is nil")
http.Error(rw, "internal server error (code: 2)", http.StatusInternalServerError) http.Error(rw, "Backend URL is nil", http.StatusInternalServerError)
return return
} }
@ -131,7 +132,8 @@ func (w *WebsocketProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
// http://tools.ietf.org/html/draft-ietf-hybi-websocket-multiplexing-01 // http://tools.ietf.org/html/draft-ietf-hybi-websocket-multiplexing-01
connBackend, resp, err := dialer.Dial(backendURL.String(), nil) connBackend, resp, err := dialer.Dial(backendURL.String(), nil)
if err != nil { if err != nil {
log.Printf("websocketproxy: couldn't dial to remote backend url %s, %s, %+v", backendURL.String(), err, resp) log.Errorf("Websocketproxy: couldn't dial to remote backend url %s, %s, %+v", backendURL.String(), err, resp)
http.Error(rw, "Remote backend unreachable", http.StatusBadGateway)
return return
} }
defer connBackend.Close() defer connBackend.Close()
@ -152,7 +154,8 @@ func (w *WebsocketProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
// Also pass the header that we gathered from the Dial handshake. // Also pass the header that we gathered from the Dial handshake.
connPub, err := upgrader.Upgrade(rw, req, upgradeHeader) connPub, err := upgrader.Upgrade(rw, req, upgradeHeader)
if err != nil { if err != nil {
log.Printf("websocketproxy: couldn't upgrade %s\n", err) log.Errorf("Websocketproxy: couldn't upgrade %s", err)
http.NotFound(rw, req)
return return
} }
defer connPub.Close() defer connPub.Close()

View file

@ -1,14 +0,0 @@
[backends]{{range .Containers}}
[backends.backend-{{getBackend .}}.servers.server-{{.Name | replace "/" "" | replace "." "-"}}]
url = "http://{{.NetworkSettings.IPAddress}}:{{getPort .}}"
weight = {{getWeight .}}
{{end}}
[frontends]{{range $host, $containers := .Hosts}}
[frontends.frontend-{{$host}}]
{{$container := index $containers 0}}
backend = "backend-{{getBackend $container}}"
[frontends.frontend-{{$host}}.routes.route-host-{{$host}}]
rule = "Host"
value = "{{$host}}.{{getDomain $container}}"
{{end}}

View file

@ -1,27 +0,0 @@
{{$apps := .Applications}}
[backends]{{range .Tasks}}
[backends.backend{{.AppID | replace "/" "-"}}.servers.server-{{.ID | replace "." "-"}}]
url = "http://{{.Host}}:{{getPort .}}"
{{$appID := .AppID}}
{{range $apps}}
{{if eq $appID .ID}}
weight = {{getWeight .}}
{{end}}
{{end}}
{{end}}
[frontends]{{ range $app := .Applications}}
{{range $prefix := getPrefixes .}}
[frontends.frontend{{$app.ID | replace "/" "-"}}{{$prefix | replace "/" "-"}}]
backend = "backend{{$app.ID | replace "/" "-"}}"
[frontends.frontend-{{getHost $app | replace "/" "-"}}{{$prefix | replace "/" "-"}}.routes.route-prefix{{$prefix | replace "/" "-"}}]
rule = "PathPrefix"
value = "{{.}}"
{{else}}
[frontends.frontend{{.ID | replace "/" "-"}}]
backend = "backend{{.ID | replace "/" "-"}}"
[frontends.frontend-{{getHost $app | replace "/" "-"}}.routes.route-host-{{getHost $app | replace "/" "-"}}]
rule = "Host"
value = "{{getHost $app | replace "/" "-"}}.{{getDomain .}}"
{{end}}
{{end}}

View file

@ -1,19 +0,0 @@
{{$apps := .Applications}}
[backends]{{range .Tasks}}
[backends.backend{{.AppID | replace "/" "-"}}.servers.server-{{.ID | replace "." "-"}}]
url = "http://{{.Host}}:{{getPort .}}"
{{$appID := .AppID}}
{{range $apps}}
{{if eq $appID .ID}}
weight = {{getWeight .}}
{{end}}
{{end}}
{{end}}
[frontends]{{range .Applications}}
[frontends.frontend{{.ID | replace "/" "-"}}]
backend = "backend{{.ID | replace "/" "-"}}"
[frontends.frontend-{{getHost . | replace "/" "-"}}.routes.route-host-{{getHost . | replace "/" "-"}}]
rule = "Host"
value = "{{getHost . | replace "/" "-"}}.{{getDomain .}}"
{{end}}

13
templates/docker.tmpl Normal file
View file

@ -0,0 +1,13 @@
[backends]{{range .Containers}}
[backends.backend-{{getBackend .}}.servers.server-{{.Name | replace "/" "" | replace "." "-"}}]
url = "{{getProtocol .}}://{{.NetworkSettings.IPAddress}}:{{getPort .}}"
weight = {{getWeight .}}
{{end}}
[frontends]{{range $frontend, $containers := .Frontends}}
[frontends."frontend-{{$frontend}}"]{{$container := index $containers 0}}
backend = "backend-{{getBackend $container}}"
[frontends."frontend-{{$frontend}}".routes."route-frontend-{{$frontend}}"]
rule = "{{getFrontendRule $container}}"
value = "{{getFrontendValue $container}}"
{{end}}

14
templates/marathon.tmpl Normal file
View file

@ -0,0 +1,14 @@
{{$apps := .Applications}}
[backends]{{range .Tasks}}
[backends.backend{{.AppID | replace "/" "-"}}.servers.server-{{.ID | replace "." "-"}}]
url = "{{getProtocol . $apps}}://{{.Host}}:{{getPort .}}"
weight = {{getWeight . $apps}}
{{end}}
[frontends]{{range .Applications}}
[frontends.frontend{{.ID | replace "/" "-"}}]
backend = "backend{{.ID | replace "/" "-"}}"
[frontends.frontend-{{.ID | replace "/" ""}}.routes.route-host-{{.ID | replace "/" ""}}]
rule = "{{getFrontendRule .}}"
value = "{{getFrontendValue .}}"
{{end}}

39
tests/whoami.json Normal file
View file

@ -0,0 +1,39 @@
{
"id": "whoami",
"cpus": 0.1,
"mem": 64.0,
"instances": 3,
"container": {
"type": "DOCKER",
"docker": {
"image": "emilevauge/whoami",
"network": "BRIDGE",
"portMappings": [
{ "containerPort": 80, "hostPort": 0, "protocol": "tcp" }
],
"parameters": [{
"key": "log-driver",
"value": "gelf"
}, {
"key": "log-opt",
"value": "gelf-address=udp://172.17.42.1:12201"
}]
}
},
"healthChecks": [
{
"protocol": "HTTP",
"portIndex": 0,
"path": "/",
"gracePeriodSeconds": 5,
"intervalSeconds": 20,
"maxConsecutiveFailures": 3
}
],
"labels": {
"traefik.weight": "1",
"traefik.protocole": "https",
"traefik.frontend.rule": "Path",
"traefik.frontend.value": "/test"
}
}

View file

@ -23,7 +23,6 @@ import (
"github.com/mailgun/oxy/forward" "github.com/mailgun/oxy/forward"
"github.com/mailgun/oxy/roundrobin" "github.com/mailgun/oxy/roundrobin"
"github.com/thoas/stats" "github.com/thoas/stats"
"github.com/unrolled/render"
"gopkg.in/alecthomas/kingpin.v2" "gopkg.in/alecthomas/kingpin.v2"
"runtime" "runtime"
) )
@ -36,20 +35,8 @@ var (
currentConfigurations = make(configs) currentConfigurations = make(configs)
metrics = stats.New() metrics = stats.New()
oxyLogger = &OxyLogger{} oxyLogger = &OxyLogger{}
templatesRenderer = render.New(render.Options{
Directory: "templates",
Asset: Asset,
AssetNames: AssetNames,
})
) )
type configMessage struct {
providerName string
configuration *Configuration
}
type configs map[string]*Configuration
func main() { func main() {
runtime.GOMAXPROCS(runtime.NumCPU()) runtime.GOMAXPROCS(runtime.NumCPU())
kingpin.Version(Version + " built on the " + BuildDate) kingpin.Version(Version + " built on the " + BuildDate)

7
web.go
View file

@ -9,6 +9,7 @@ import (
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
"github.com/elazarl/go-bindata-assetfs" "github.com/elazarl/go-bindata-assetfs"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/unrolled/render"
) )
type WebProvider struct { type WebProvider struct {
@ -16,6 +17,12 @@ type WebProvider struct {
CertFile, KeyFile string CertFile, KeyFile string
} }
var (
templatesRenderer = render.New(render.Options{
Directory: "nowhere",
})
)
func (provider *WebProvider) Provide(configurationChan chan<- configMessage) error { func (provider *WebProvider) Provide(configurationChan chan<- configMessage) error {
systemRouter := mux.NewRouter() systemRouter := mux.NewRouter()