From 9a840d1904bbcbaccdbacd9ef587a882ca069c29 Mon Sep 17 00:00:00 2001 From: emile Date: Wed, 9 Sep 2015 22:39:08 +0200 Subject: [PATCH] Marathon provider --- docker.go | 52 ++++++++++++++------------ marathon.go | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++ marathon.tmpl | 12 ++++++ træfik.go | 5 +++ træfik.toml | 14 +++++-- 5 files changed, 156 insertions(+), 27 deletions(-) create mode 100644 marathon.go create mode 100644 marathon.tmpl diff --git a/docker.go b/docker.go index 59eff4fed..ac928f716 100644 --- a/docker.go +++ b/docker.go @@ -8,6 +8,15 @@ import ( "text/template" "strings" ) + +type DockerProvider struct { + Watch bool + Endpoint string + dockerClient *docker.Client + Filename string + Domain string +} + var DockerFuncMap = template.FuncMap{ "getBackend": func(container docker.Container) string { for key, value := range container.Config.Labels { @@ -30,33 +39,30 @@ var DockerFuncMap = template.FuncMap{ }, "getHost": getHost, } -type DockerProvider struct { - Watch bool - Endpoint string - dockerClient *docker.Client - Filename string - Domain string -} func (provider *DockerProvider) Provide(configurationChan chan <- *Configuration) { - provider.dockerClient, _ = docker.NewClient(provider.Endpoint) - dockerEvents := make(chan *docker.APIEvents) - if (provider.Watch) { - provider.dockerClient.AddEventListener(dockerEvents) - } - go func() { - for { - event := <-dockerEvents - log.Println("Event receveived", event) - configuration := provider.loadDockerConfig() - if (configuration != nil) { - configurationChan <- configuration - } + if client, err := docker.NewClient(provider.Endpoint); err != nil { + log.Fatalf("Failed to create a client for docker, error: %s", err) + } else { + provider.dockerClient = client + dockerEvents := make(chan *docker.APIEvents) + if (provider.Watch) { + provider.dockerClient.AddEventListener(dockerEvents) } - }() + go func() { + for { + event := <-dockerEvents + log.Println("Event receveived", event) + configuration := provider.loadDockerConfig() + if (configuration != nil) { + configurationChan <- configuration + } + } + }() - configuration := provider.loadDockerConfig() - configurationChan <- configuration + configuration := provider.loadDockerConfig() + configurationChan <- configuration + } } func (provider *DockerProvider) loadDockerConfig() *Configuration { diff --git a/marathon.go b/marathon.go new file mode 100644 index 000000000..70897b2b6 --- /dev/null +++ b/marathon.go @@ -0,0 +1,100 @@ +package main +import ( + "github.com/gambol99/go-marathon" + "log" + "github.com/leekchan/gtf" + "bytes" + "github.com/BurntSushi/toml" + "text/template" + "strings" + "strconv" +) + +type MarathonProvider struct { + Watch bool + Endpoint string + marathonClient marathon.Marathon + Domain string + Filename string +} + +var MarathonFuncMap = template.FuncMap{ + "getPort": func(task marathon.Task) string { + for _, port := range task.Ports { + return strconv.Itoa(port) + } + return "" + }, + "getHost": func(application marathon.Application) string { + for key, value := range application.Labels { + if (key == "træfik.host") { + return value + } + } + return strings.TrimPrefix(application.ID, "/") + }, + "replace": func(s1 string, s2 string, s3 string) string { + return strings.Replace(s3, s1, s2, -1) + }, +} +func (provider *MarathonProvider) Provide(configurationChan chan <- *Configuration) { + config := marathon.NewDefaultConfig() + config.URL = provider.Endpoint + if client, err := marathon.NewClient(config); err != nil { + log.Println("Failed to create a client for marathon, error: %s", err) + return + } else { + provider.marathonClient = client + configuration := provider.loadMarathonConfig() + configurationChan <- configuration + } +} + +func (provider *MarathonProvider) loadMarathonConfig() *Configuration { + configuration := new(Configuration) + + applications, err := provider.marathonClient.Applications(nil) + if (err != nil) { + log.Println("Failed to create a client for marathon, error: %s", err) + return nil + } + tasks, err := provider.marathonClient.AllTasks() + if (err != nil) { + log.Println("Failed to create a client for marathon, error: %s", err) + return nil + } + + templateObjects := struct { + Applications []marathon.Application + Tasks []marathon.Task + Domain string + }{ + applications.Apps, + tasks.Tasks, + provider.Domain, + } + + gtf.Inject(MarathonFuncMap) + tmpl, err := template.New(provider.Filename).Funcs(MarathonFuncMap).ParseFiles(provider.Filename) + if err != nil { + log.Println("Error reading file:", err) + return nil + } + + var buffer bytes.Buffer + + err = tmpl.Execute(&buffer, templateObjects) + if err != nil { + log.Println("Error with docker template:", err) + return nil + } + + if _, err := toml.Decode(buffer.String(), configuration); err != nil { + log.Println("Error creating marathon configuration:", err) + return nil + } + + log.Println(buffer.String()) + + return configuration +} \ No newline at end of file diff --git a/marathon.tmpl b/marathon.tmpl new file mode 100644 index 000000000..68bc13426 --- /dev/null +++ b/marathon.tmpl @@ -0,0 +1,12 @@ +[backends]{{range .Tasks}} + [backends.backend{{.AppID | replace "/" "-"}}.servers.server-{{.ID | replace "." "-"}}] + url = "http://{{.Host}}:{{getPort .}}" +{{end}} + +[routes]{{range .Applications}} + [routes.route{{.ID | replace "/" "-"}}] + backend = ".backend{{.ID | replace "/" "-"}}" + [routes.route-{{getHost .}}.rules.rule-host-{{getHost .}}] + category = "Host" + value = "{{getHost .}}.{{$.Domain}}" +{{end}} \ No newline at end of file diff --git a/træfik.go b/træfik.go index 934e29201..0609490aa 100644 --- a/træfik.go +++ b/træfik.go @@ -23,6 +23,7 @@ type FileConfiguration struct { Docker *DockerProvider File *FileProvider Web *WebProvider + Marathon *MarathonProvider } var srv *graceful.Server @@ -58,6 +59,10 @@ func main() { providers = append(providers, configuration.Docker) } + if (configuration.Marathon != nil) { + providers = append(providers, configuration.Marathon) + } + if (configuration.File != nil) { if (len(configuration.File.Filename) == 0) { // no filename, setting to global config file diff --git a/træfik.toml b/træfik.toml index 2a8ed0cc8..cb9a899da 100644 --- a/træfik.toml +++ b/træfik.toml @@ -1,16 +1,22 @@ port = ":8001" -[docker] -endpoint = "unix:///var/run/docker.sock" +#[docker] +#endpoint = "unix:///var/run/docker.sock" +#watch = true +#domain = "toto.fr" +#filename = "docker.tmpl" + +[marathon] +endpoint = "http://127.0.0.1:8080" watch = true domain = "toto.fr" -filename = "docker.tmpl" +filename = "marathon.tmpl" [web] address = ":8010" #[file] -#filename = "træfik.toml" +#filename = "rules.toml" #watch = true [backends]