From de592ed6b8c549b1341f8d10d9d59a533007574b Mon Sep 17 00:00:00 2001 From: emile Date: Thu, 10 Sep 2015 22:54:37 +0200 Subject: [PATCH] Filters in Docker & Marathon --- ROADMAP.md | 6 +++--- docker.go | 43 ++++++++++++++++++++++++++++++++++--------- marathon.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- traefik.toml | 2 +- 4 files changed, 84 insertions(+), 15 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 2dbc6f0cc..dc439eb79 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,8 +1,6 @@ * Default configuration values * Godoc * Licence -* Filter no exposed port apps -* Filter traefik.enabled=false apps * Add traefik.indlude all/enabled policy * SSL frontend support * SSL backends support @@ -11,7 +9,9 @@ * Kubernetes support * Smart configuration diff * README - +* API enhancements * ~~GraceTimeout~~ * ~~Weights~~ +* ~~Filter traefik.enabled=false apps~~ +* ~~Filter no exposed port apps~~ diff --git a/docker.go b/docker.go index 70a162702..4547ff832 100644 --- a/docker.go +++ b/docker.go @@ -7,6 +7,8 @@ import ( "log" "text/template" "strings" + "github.com/BurntSushi/ty/fun" + "strconv" ) type DockerProvider struct { @@ -62,10 +64,12 @@ func (provider *DockerProvider) Provide(configurationChan chan <- *Configuration go func() { for { event := <-dockerEvents - log.Println("Docker event receveived", event) - configuration := provider.loadDockerConfig() - if (configuration != nil) { - configurationChan <- configuration + if(event.Status == "start" || event.Status == "die"){ + log.Println("Docker event receveived", event) + configuration := provider.loadDockerConfig() + if (configuration != nil) { + configurationChan <- configuration + } } } }() @@ -81,12 +85,33 @@ func (provider *DockerProvider) loadDockerConfig() *Configuration { containerList, _ := provider.dockerClient.ListContainers(docker.ListContainersOptions{}) containersInspected := []docker.Container{} hosts := map[string][]docker.Container{} + + // get inspect containers for _, container := range containerList { - if(container.Labels["traefik.enable"] != "false"){ - containerInspected, _ := provider.dockerClient.InspectContainer(container.ID) - containersInspected = append(containersInspected, *containerInspected) - hosts[getHost(*containerInspected)] = append(hosts[getHost(*containerInspected)], *containerInspected) + containerInspected, _ := provider.dockerClient.InspectContainer(container.ID) + containersInspected = append(containersInspected, *containerInspected) + } + + // filter containers + filteredContainers := fun.Filter(func(container docker.Container) bool { + if (len(container.NetworkSettings.Ports) == 0) { + log.Println("Filtering container without port", container.Name) + return false } + _, err := strconv.Atoi(container.Config.Labels["traefik.port"]) + if (len(container.NetworkSettings.Ports) > 1 && err != nil) { + log.Println("Filtering container with more than 1 port and no traefik.port label", container.Name) + return false + } + if (container.Config.Labels["traefik.enable"] == "false") { + log.Println("Filtering disabled container", container.Name) + return false + } + return true + }, containersInspected).([]docker.Container) + + for _, container := range filteredContainers { + hosts[getHost(container)] = append(hosts[getHost(container)], container) } templateObjects := struct { @@ -94,7 +119,7 @@ func (provider *DockerProvider) loadDockerConfig() *Configuration { Hosts map[string][]docker.Container Domain string }{ - containersInspected, + filteredContainers, hosts, provider.Domain, } diff --git a/marathon.go b/marathon.go index 4c1db8b5d..c06e3b940 100644 --- a/marathon.go +++ b/marathon.go @@ -8,6 +8,7 @@ import ( "text/template" "strings" "strconv" + "github.com/BurntSushi/ty/fun" ) type MarathonProvider struct { @@ -86,19 +87,53 @@ func (provider *MarathonProvider) loadMarathonConfig() *Configuration { 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 } + //filter tasks + filteredTasks := fun.Filter(func(task marathon.Task) bool { + if (len(task.Ports) == 0) { + log.Println("Filtering marathon task without port", task.AppID) + return false + } + application := getApplication(task, applications.Apps) + _, err := strconv.Atoi(application.Labels["traefik.port"]) + if (len(application.Ports) > 1 && err != nil) { + log.Println("Filtering marathon task with more than 1 port and no traefik.port label", task.AppID) + return false + } + if (application.Labels["traefik.enable"] == "false") { + log.Println("Filtering disabled marathon task", task.AppID) + return false + } + return true + }, tasks.Tasks).([]marathon.Task) + + //filter apps + filteredApps := fun.Filter(func(app marathon.Application) bool { + //get ports from app tasks + if (!fun.Exists(func(task marathon.Task) bool { + if (task.AppID == app.ID) { + return true + } + return false + }, filteredTasks)) { + return false + } + return true + }, applications.Apps).([]marathon.Application) + templateObjects := struct { Applications []marathon.Application Tasks []marathon.Task Domain string }{ - applications.Apps, - tasks.Tasks, + filteredApps, + filteredTasks, provider.Domain, } @@ -123,4 +158,13 @@ func (provider *MarathonProvider) loadMarathonConfig() *Configuration { } return configuration +} + +func getApplication(task marathon.Task, apps []marathon.Application) *marathon.Application { + for _, application := range apps { + if (application.ID == task.AppID) { + return &application + } + } + return nil } \ No newline at end of file diff --git a/traefik.toml b/traefik.toml index c9ef0fa92..5085de608 100644 --- a/traefik.toml +++ b/traefik.toml @@ -6,7 +6,7 @@ endpoint = "unix:///var/run/docker.sock" watch = true domain = "toto.fr" filename = "docker.tmpl" - +# # [marathon] # endpoint = "http://127.0.0.1:8080" # networkInterface = "eth0"