service -> configuration
This commit is contained in:
parent
7fcc4761da
commit
cef926379c
5 changed files with 53 additions and 51 deletions
|
@ -19,7 +19,7 @@ type Route struct {
|
||||||
Rules map[string]Rule
|
Rules map[string]Rule
|
||||||
}
|
}
|
||||||
|
|
||||||
type Service struct {
|
type Configuration struct {
|
||||||
Backends map[string]Backend
|
Backends map[string]Backend
|
||||||
Routes map[string]Route
|
Routes map[string]Route
|
||||||
}
|
}
|
26
docker.go
26
docker.go
|
@ -1,5 +1,5 @@
|
||||||
package main
|
package main
|
||||||
import(
|
import (
|
||||||
"github.com/fsouza/go-dockerclient"
|
"github.com/fsouza/go-dockerclient"
|
||||||
"github.com/leekchan/gtf"
|
"github.com/leekchan/gtf"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -13,27 +13,29 @@ type DockerProvider struct {
|
||||||
dockerClient *docker.Client
|
dockerClient *docker.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *DockerProvider) Provide(serviceChan chan<- *Service){
|
func (provider *DockerProvider) Provide(configurationChan chan <- *Configuration) {
|
||||||
provider.dockerClient, _ = docker.NewClient(provider.Endpoint)
|
provider.dockerClient, _ = docker.NewClient(provider.Endpoint)
|
||||||
dockerEvents := make(chan *docker.APIEvents)
|
dockerEvents := make(chan *docker.APIEvents)
|
||||||
if(provider.Watch) {
|
if (provider.Watch) {
|
||||||
provider.dockerClient.AddEventListener(dockerEvents)
|
provider.dockerClient.AddEventListener(dockerEvents)
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
event := <-dockerEvents
|
event := <-dockerEvents
|
||||||
log.Println("Event receveived", event)
|
log.Println("Event receveived", event)
|
||||||
service:= provider.loadDockerConfig()
|
configuration := provider.loadDockerConfig()
|
||||||
serviceChan <- service
|
if (configuration != nil) {
|
||||||
|
configurationChan <- configuration
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
service:= provider.loadDockerConfig()
|
configuration := provider.loadDockerConfig()
|
||||||
serviceChan <- service
|
configurationChan <- configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *DockerProvider) loadDockerConfig() *Service {
|
func (provider *DockerProvider) loadDockerConfig() *Configuration {
|
||||||
service := new(Service)
|
configuration := new(Configuration)
|
||||||
containerList, _ := provider.dockerClient.ListContainers(docker.ListContainersOptions{})
|
containerList, _ := provider.dockerClient.ListContainers(docker.ListContainersOptions{})
|
||||||
containersInspected := []docker.Container{}
|
containersInspected := []docker.Container{}
|
||||||
for _, container := range containerList {
|
for _, container := range containerList {
|
||||||
|
@ -59,9 +61,9 @@ func (provider *DockerProvider) loadDockerConfig() *Service {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := toml.Decode(buffer.String(), service); err != nil {
|
if _, err := toml.Decode(buffer.String(), configuration); err != nil {
|
||||||
log.Println("Error creating docker service:", err)
|
log.Println("Error creating docker configuration:", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return service
|
return configuration
|
||||||
}
|
}
|
20
file.go
20
file.go
|
@ -14,7 +14,7 @@ type FileProvider struct {
|
||||||
Filename string
|
Filename string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *FileProvider) Provide(serviceChan chan<- *Service){
|
func (provider *FileProvider) Provide(configurationChan chan<- *Configuration){
|
||||||
watcher, err := fsnotify.NewWatcher()
|
watcher, err := fsnotify.NewWatcher()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
|
@ -37,9 +37,9 @@ func (provider *FileProvider) Provide(serviceChan chan<- *Service){
|
||||||
case event := <-watcher.Events:
|
case event := <-watcher.Events:
|
||||||
if(strings.Contains(event.Name,file.Name())){
|
if(strings.Contains(event.Name,file.Name())){
|
||||||
log.Println("File event:", event)
|
log.Println("File event:", event)
|
||||||
service := provider.LoadFileConfig(file.Name())
|
configuration := provider.LoadFileConfig(file.Name())
|
||||||
if(service != nil) {
|
if(configuration != nil) {
|
||||||
serviceChan <- service
|
configurationChan <- configuration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case error := <-watcher.Errors:
|
case error := <-watcher.Errors:
|
||||||
|
@ -58,17 +58,17 @@ func (provider *FileProvider) Provide(serviceChan chan<- *Service){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
service:= provider.LoadFileConfig(file.Name())
|
configuration := provider.LoadFileConfig(file.Name())
|
||||||
serviceChan <- service
|
configurationChan <- configuration
|
||||||
<-done
|
<-done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (provider *FileProvider) LoadFileConfig(filename string) *Service {
|
func (provider *FileProvider) LoadFileConfig(filename string) *Configuration {
|
||||||
service := new(Service)
|
configuration := new(Configuration)
|
||||||
if _, err := toml.DecodeFile(filename, service); err != nil {
|
if _, err := toml.DecodeFile(filename, configuration); err != nil {
|
||||||
log.Println("Error reading file:", err)
|
log.Println("Error reading file:", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return service
|
return configuration
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
type Provider interface {
|
type Provider interface {
|
||||||
Provide(chan<- *Service)
|
Provide(chan<- *Configuration)
|
||||||
}
|
}
|
||||||
|
|
46
tortuous.go
46
tortuous.go
|
@ -18,16 +18,16 @@ import (
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Configuration struct {
|
type FileConfiguration struct {
|
||||||
Docker *DockerProvider
|
Docker *DockerProvider
|
||||||
File *FileProvider
|
File *FileProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
var srv *graceful.Server
|
var srv *graceful.Server
|
||||||
var serviceRouter *mux.Router
|
var configurationRouter *mux.Router
|
||||||
var renderer = render.New()
|
var renderer = render.New()
|
||||||
var currentService = new(Service)
|
var currentConfiguration = new(Configuration)
|
||||||
var serviceChan = make(chan *Service)
|
var configurationChan = make(chan *Configuration)
|
||||||
var providers = []Provider{}
|
var providers = []Provider{}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -41,15 +41,15 @@ func main() {
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
service := <-serviceChan
|
configuration := <-configurationChan
|
||||||
log.Println("Service receveived", service)
|
log.Println("Configuration receveived", configuration)
|
||||||
if service == nil {
|
if configuration == nil {
|
||||||
log.Println("Skipping nil service")
|
log.Println("Skipping empty configuration")
|
||||||
} else if(reflect.DeepEqual(currentService, service)){
|
} else if(reflect.DeepEqual(currentConfiguration, configuration)){
|
||||||
log.Println("Skipping same service")
|
log.Println("Skipping same configuration")
|
||||||
} else{
|
} else{
|
||||||
currentService = service
|
currentConfiguration = configuration
|
||||||
serviceRouter = LoadConfig(service)
|
configurationRouter = LoadConfig(configuration)
|
||||||
srv.Stop(10 * time.Second)
|
srv.Stop(10 * time.Second)
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
}
|
}
|
||||||
|
@ -66,11 +66,11 @@ func main() {
|
||||||
providers = append(providers, configuration.File)
|
providers = append(providers, configuration.File)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
|
||||||
for _, provider := range providers {
|
for _, provider := range providers {
|
||||||
provider.Provide(serviceChan)
|
go func() {
|
||||||
}
|
provider.Provide(configurationChan)
|
||||||
}()
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
goAway := false
|
goAway := false
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -94,7 +94,7 @@ func main() {
|
||||||
|
|
||||||
Server: &http.Server{
|
Server: &http.Server{
|
||||||
Addr: ":8001",
|
Addr: ":8001",
|
||||||
Handler: serviceRouter,
|
Handler: configurationRouter,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,9 +105,9 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadConfig(service *Service) *mux.Router {
|
func LoadConfig(configuration *Configuration) *mux.Router {
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
for routeName, route := range service.Routes {
|
for routeName, route := range configuration.Routes {
|
||||||
log.Println("Creating route", routeName)
|
log.Println("Creating route", routeName)
|
||||||
fwd, _ := forward.New()
|
fwd, _ := forward.New()
|
||||||
newRoutes := []*mux.Route{}
|
newRoutes := []*mux.Route{}
|
||||||
|
@ -121,7 +121,7 @@ func LoadConfig(service *Service) *mux.Router {
|
||||||
log.Println("Creating backend", backendName)
|
log.Println("Creating backend", backendName)
|
||||||
lb, _ := roundrobin.New(fwd)
|
lb, _ := roundrobin.New(fwd)
|
||||||
rb, _ := roundrobin.NewRebalancer(lb)
|
rb, _ := roundrobin.NewRebalancer(lb)
|
||||||
for serverName, server := range service.Backends[backendName].Servers {
|
for serverName, server := range configuration.Backends[backendName].Servers {
|
||||||
log.Println("Creating server", serverName)
|
log.Println("Creating server", serverName)
|
||||||
url, _ := url.Parse(server.Url)
|
url, _ := url.Parse(server.Url)
|
||||||
rb.UpsertServer(url)
|
rb.UpsertServer(url)
|
||||||
|
@ -135,7 +135,7 @@ func LoadConfig(service *Service) *mux.Router {
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeployService() {
|
func DeployService() {
|
||||||
serviceRouter = LoadConfig(currentService)
|
configurationRouter = LoadConfig(currentConfiguration)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReloadConfigHandler(rw http.ResponseWriter, r *http.Request) {
|
func ReloadConfigHandler(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -149,7 +149,7 @@ func RestartHandler(rw http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetConfigHandler(rw http.ResponseWriter, r *http.Request) {
|
func GetConfigHandler(rw http.ResponseWriter, r *http.Request) {
|
||||||
renderer.JSON(rw, http.StatusOK, currentService)
|
renderer.JSON(rw, http.StatusOK, currentConfiguration)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Invoke(any interface{}, name string, args ...interface{}) []reflect.Value {
|
func Invoke(any interface{}, name string, args ...interface{}) []reflect.Value {
|
||||||
|
@ -160,8 +160,8 @@ func Invoke(any interface{}, name string, args ...interface{}) []reflect.Value {
|
||||||
return reflect.ValueOf(any).MethodByName(name).Call(inputs)
|
return reflect.ValueOf(any).MethodByName(name).Call(inputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadFileConfig() *Configuration {
|
func LoadFileConfig() *FileConfiguration {
|
||||||
configuration := new(Configuration)
|
configuration := new(FileConfiguration)
|
||||||
if _, err := toml.DecodeFile("tortuous.toml", configuration); err != nil {
|
if _, err := toml.DecodeFile("tortuous.toml", configuration); err != nil {
|
||||||
log.Fatal("Error reading file:", err)
|
log.Fatal("Error reading file:", err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue