diff --git a/docker.go b/docker.go index b8bdcee47..012febcdf 100644 --- a/docker.go +++ b/docker.go @@ -1,17 +1,17 @@ package main import( "github.com/fsouza/go-dockerclient" - "fmt" "github.com/leekchan/gtf" "bytes" "github.com/BurntSushi/toml" + "log" ) type DockerProvider struct { dockerClient *docker.Client } -func (provider *DockerProvider) Provide(serviceChan chan<- Service){ +func (provider *DockerProvider) Provide(serviceChan chan<- *Service){ endpoint := "unix:///var/run/docker.sock" provider.dockerClient, _ = docker.NewClient(endpoint) dockerEvents := make(chan *docker.APIEvents) @@ -19,15 +19,14 @@ func (provider *DockerProvider) Provide(serviceChan chan<- Service){ go func() { for { event := <-dockerEvents - fmt.Println("Event receveived", event) + log.Println("Event receveived", event) service:= provider.loadDockerConfig() - serviceChan <- *service + serviceChan <- service } }() service:= provider.loadDockerConfig() - fmt.Println("Sending service") - serviceChan <- *service + serviceChan <- service } func (provider *DockerProvider) loadDockerConfig() *Service { @@ -45,20 +44,20 @@ func (provider *DockerProvider) loadDockerConfig() *Service { } tmpl, err := gtf.New("docker.tmpl").ParseFiles("docker.tmpl") if err != nil { - panic(err) + log.Println("Error reading file:", err) + return nil } var buffer bytes.Buffer err = tmpl.Execute(&buffer, containers) if err != nil { - panic(err) + log.Println("Error with docker template:", err) + return nil } - fmt.Println(buffer.String()) - if _, err := toml.Decode(buffer.String(), service); err != nil { - fmt.Println(err) + log.Println("Error creating docker service:", err) return nil } return service diff --git a/file.go b/file.go new file mode 100644 index 000000000..a24e9b01c --- /dev/null +++ b/file.go @@ -0,0 +1,57 @@ +package main + +import ( + "log" + "gopkg.in/fsnotify.v1" + "github.com/BurntSushi/toml" +) + +type FileProvider struct { +} + +func (provider *FileProvider) Provide(serviceChan chan<- *Service){ + watcher, err := fsnotify.NewWatcher() + if err != nil { + log.Fatal(err) + } + defer watcher.Close() + + + err = watcher.Add(".") + if err != nil { + log.Fatal(err) + } + + done := make(chan bool) + // Process events + go func() { + for { + select { + case event := <-watcher.Events: + if(event.Name == "./tortuous.toml"){ + log.Println("event:", event) + service := provider.LoadFileConfig() + serviceChan <- service + } + case error := <-watcher.Errors: + log.Println("error:", error) + } + } + }() + + + service:= provider.LoadFileConfig() + serviceChan <- service + <-done + log.Println("DONE") +} + + +func (provider *FileProvider) LoadFileConfig() *Service { + service := new(Service) + if _, err := toml.DecodeFile("tortuous.toml", service); err != nil { + log.Println("Error reading file:", err) + return nil + } + return service +} \ No newline at end of file diff --git a/provider.go b/provider.go index 91d36656f..67f0f20ad 100644 --- a/provider.go +++ b/provider.go @@ -1,5 +1,5 @@ package main type Provider interface { - Provide(chan<- Service) + Provide(chan<- *Service) } diff --git a/tortuous.go b/tortuous.go index 2a7d5214f..190b3043c 100644 --- a/tortuous.go +++ b/tortuous.go @@ -1,12 +1,7 @@ package main import ( - "bytes" - "fmt" - "github.com/BurntSushi/toml" - "github.com/fsouza/go-dockerclient" "github.com/gorilla/mux" - "github.com/leekchan/gtf" "github.com/mailgun/oxy/forward" "github.com/mailgun/oxy/roundrobin" "github.com/tylerb/graceful" @@ -19,17 +14,19 @@ import ( "reflect" "syscall" "time" + "log" ) var srv *graceful.Server -var userRouter *mux.Router +var systemRouter *mux.Router var renderer = render.New() var currentService = new(Service) -var serviceChan = make(chan Service) +var serviceChan = make(chan *Service) var providers = []Provider{} func main() { - providers = append(providers, new(DockerProvider)) + //providers = append(providers, new(DockerProvider)) + providers = append(providers, new(FileProvider)) sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) @@ -42,21 +39,30 @@ func main() { go func() { for { service := <-serviceChan - fmt.Println("Service receveived", service) - currentService = &service - userRouter = LoadConfig(service) - srv.Stop(10 * time.Second) + log.Println("Service receveived", service) + if service == nil { + log.Println("Skipping nil service") + } else if(reflect.DeepEqual(currentService, service)){ + log.Println("Skipping same service") + } else{ + currentService = service + systemRouter = LoadConfig(service) + srv.Stop(10 * time.Second) + time.Sleep(3 * time.Second) + } } }() - for _, provider := range providers { - provider.Provide(serviceChan) - } + go func() { + for _, provider := range providers { + provider.Provide(serviceChan) + } + }() goAway := false go func() { sig := <-sigs - fmt.Println("I have to go...", sig) + log.Println("I have to go...", sig) goAway = true srv.Stop(10 * time.Second) }() @@ -75,87 +81,35 @@ func main() { Server: &http.Server{ Addr: ":8001", - Handler: userRouter, + Handler: systemRouter, }, } go srv.ListenAndServe() - fmt.Println("Started") + log.Println("Started") <-srv.StopChan() - fmt.Println("Stopped") + log.Println("Stopped") } } -func LoadDockerConfig(client *docker.Client, service Service) { - containerList, _ := client.ListContainers(docker.ListContainersOptions{}) - containersInspected := []docker.Container{} - for _, container := range containerList { - containerInspected, _ := client.InspectContainer(container.ID) - containersInspected = append(containersInspected, *containerInspected) - } - containers := struct { - Containers []docker.Container - }{ - containersInspected, - } - tmpl, err := gtf.New("docker.tmpl").ParseFiles("docker.tmpl") - if err != nil { - panic(err) - } - - var buffer bytes.Buffer - - err = tmpl.Execute(&buffer, containers) - if err != nil { - panic(err) - } - - fmt.Println(buffer.String()) - - if _, err := toml.Decode(buffer.String(), service); err != nil { - fmt.Println(err) - return - } -} - -func LoadFileConfig(service Service) { - if _, err := toml.DecodeFile("tortuous.toml", service); err != nil { - fmt.Println(err) - return - } -} - -func LoadConfig(service Service) *mux.Router { - /*endpoint := "unix:///var/run/docker.sock" - client, _ := docker.NewClient(endpoint) - dockerEvents := make(chan *docker.APIEvents) - LoadDockerConfig(client) - client.AddEventListener(dockerEvents) - go func() { - for { - event := <-dockerEvents - fmt.Println("Event receveived", event) - } - }()*/ - //LoadFileConfig() - +func LoadConfig(service *Service) *mux.Router { router := mux.NewRouter() for routeName, route := range service.Routes { - fmt.Println("Creating route", routeName) + log.Println("Creating route", routeName) fwd, _ := forward.New() newRoutes := []*mux.Route{} for ruleName, rule := range route.Rules { - fmt.Println("Creating rule", ruleName) + log.Println("Creating rule", ruleName) newRouteReflect := Invoke(router.NewRoute(), rule.Category, rule.Value) newRoute := newRouteReflect[0].Interface().(*mux.Route) newRoutes = append(newRoutes, newRoute) } for _, backendName := range route.Backends { - fmt.Println("Creating backend", backendName) + log.Println("Creating backend", backendName) lb, _ := roundrobin.New(fwd) rb, _ := roundrobin.NewRebalancer(lb) for serverName, server := range service.Backends[backendName].Servers { - fmt.Println("Creating server", serverName) + log.Println("Creating server", serverName) url, _ := url.Parse(server.Url) rb.UpsertServer(url) } @@ -168,7 +122,7 @@ func LoadConfig(service Service) *mux.Router { } func DeployService() { - userRouter = LoadConfig(*currentService) + systemRouter = LoadConfig(currentService) } func ReloadConfigHandler(rw http.ResponseWriter, r *http.Request) { diff --git a/tortuous.toml b/tortuous.toml index c7cadfddc..2804cf7bb 100644 --- a/tortuous.toml +++ b/tortuous.toml @@ -16,4 +16,3 @@ [routes.route2.rules.test_zenika_2] category = "Path" value = "/test" -