web provider

This commit is contained in:
emile 2015-09-08 13:33:10 +02:00
parent cef926379c
commit e894ae9f0a
5 changed files with 113 additions and 29 deletions

54
configuration.html Normal file
View file

@ -0,0 +1,54 @@
<!DOCTYPE html>
<html>
<head>
<title>{{.Title}}</title>
<!-- Bootstrap -->
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap-theme.min.css">
<script src="/static/jquery-2.1.4.min.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
<style type="text/css">
body {padding-bottom: 70px;}
.content {margin:10px;}
</style>
</head>
<body>
<nav class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<a class="navbar-brand" href="/html/">Tortuous</a>
</div>
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav">
<li><a href="/html/">Configuration</a></li>
</ul>
</div>
</nav>
<div class="panel panel-default">
<div class="panel-heading">Backends</div>
<div class="panel-body">
{{range $keyBackends, $valueBackends := .Configuration.Backends}}
<div class="panel panel-default">
<div class="panel-heading">Backend {{$keyBackends}}</div>
<div class="panel-body">
{{range $keyServers, $valueServers := $valueBackends.Servers}}
<div class="panel panel-default">
<div class="panel-heading">Server {{$keyServers}}</div>
<div class="panel-body">
Url: {{$valueServers.Url}}
</div>
</div>
{{end}}
</div>
</div>
{{end}}
</div>
</div>
</body>
</html>

View file

@ -1,5 +1,5 @@
package main
type Provider interface {
Provide(chan<- *Configuration)
Provide(configurationChan chan<- *Configuration)
}

View file

@ -5,7 +5,6 @@ import (
"github.com/mailgun/oxy/forward"
"github.com/mailgun/oxy/roundrobin"
"github.com/tylerb/graceful"
"github.com/unrolled/render"
"net"
"net/http"
"net/url"
@ -16,16 +15,17 @@ import (
"time"
"log"
"github.com/BurntSushi/toml"
"github.com/gorilla/handlers"
)
type FileConfiguration struct {
Docker *DockerProvider
File *FileProvider
Web *WebProvider
}
var srv *graceful.Server
var configurationRouter *mux.Router
var renderer = render.New()
var currentConfiguration = new(Configuration)
var configurationChan = make(chan *Configuration)
var providers = []Provider{}
@ -34,11 +34,6 @@ func main() {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
systemRouter := mux.NewRouter()
systemRouter.Methods("POST").Path("/reload").HandlerFunc(ReloadConfigHandler)
systemRouter.Methods("GET").Path("/").HandlerFunc(GetConfigHandler)
go http.ListenAndServe(":8000", systemRouter)
go func() {
for {
configuration := <-configurationChan
@ -57,7 +52,6 @@ func main() {
}()
configuration := LoadFileConfig()
log.Println("Configuration loaded", configuration)
if(configuration.Docker != nil){
providers = append(providers, configuration.Docker)
}
@ -66,9 +60,15 @@ func main() {
providers = append(providers, configuration.File)
}
if(configuration.Web != nil){
providers = append(providers, configuration.Web)
}
for _, provider := range providers {
log.Printf("Starting provider %v %+v\n", reflect.TypeOf(provider), provider)
currentProvider := provider
go func() {
provider.Provide(configurationChan)
currentProvider.Provide(configurationChan)
}()
}
@ -127,31 +127,13 @@ func LoadConfig(configuration *Configuration) *mux.Router {
rb.UpsertServer(url)
}
for _, route := range newRoutes {
route.Handler(lb)
route.Handler(handlers.CombinedLoggingHandler(os.Stdout, lb))
}
}
}
return router
}
func DeployService() {
configurationRouter = LoadConfig(currentConfiguration)
}
func ReloadConfigHandler(rw http.ResponseWriter, r *http.Request) {
DeployService()
srv.Stop(10 * time.Second)
renderer.JSON(rw, http.StatusOK, map[string]interface{}{"status": "reloaded"})
}
func RestartHandler(rw http.ResponseWriter, r *http.Request) {
renderer.JSON(rw, http.StatusOK, map[string]interface{}{"status": "restarted"})
}
func GetConfigHandler(rw http.ResponseWriter, r *http.Request) {
renderer.JSON(rw, http.StatusOK, currentConfiguration)
}
func Invoke(any interface{}, name string, args ...interface{}) []reflect.Value {
inputs := make([]reflect.Value, len(args))
for i, _ := range args {

View file

@ -2,6 +2,9 @@
#endpoint = "unix:///var/run/docker.sock"
#watch = true
[web]
address = ":8010"
[file]
filename = "tortuous.toml"
watch = true

45
web.go Normal file
View file

@ -0,0 +1,45 @@
package main
import (
"github.com/gorilla/mux"
"net/http"
"os"
"github.com/gorilla/handlers"
"github.com/unrolled/render"
"fmt"
"html/template"
)
var renderer = render.New()
type WebProvider struct {
Address string
}
type Page struct {
Title string
Configuration Configuration
}
func (provider *WebProvider) Provide(configurationChan chan<- *Configuration){
systemRouter := mux.NewRouter()
systemRouter.Methods("GET").PathPrefix("/html/").Handler(handlers.CombinedLoggingHandler(os.Stdout, http.HandlerFunc(GetHtmlConfigHandler)))
systemRouter.Methods("GET").PathPrefix("/json/").Handler(handlers.CombinedLoggingHandler(os.Stdout, http.HandlerFunc(GetConfigHandler)))
systemRouter.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("static/"))))
go http.ListenAndServe(provider.Address, systemRouter)
}
func GetConfigHandler(rw http.ResponseWriter, r *http.Request) {
renderer.JSON(rw, http.StatusOK, currentConfiguration)
}
func GetHtmlConfigHandler(response http.ResponseWriter, request *http.Request) {
templates := template.Must(template.ParseFiles("configuration.html"))
response.Header().Set("Content-type", "text/html")
err := request.ParseForm()
if err != nil {
http.Error(response, fmt.Sprintf("error parsing url %v", err), 500)
}
templates.ExecuteTemplate(response, "configuration.html", Page{Title: "Home", Configuration:*currentConfiguration})
}