web provider
This commit is contained in:
parent
cef926379c
commit
e894ae9f0a
5 changed files with 113 additions and 29 deletions
54
configuration.html
Normal file
54
configuration.html
Normal 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>
|
|
@ -1,5 +1,5 @@
|
|||
package main
|
||||
|
||||
type Provider interface {
|
||||
Provide(chan<- *Configuration)
|
||||
Provide(configurationChan chan<- *Configuration)
|
||||
}
|
||||
|
|
38
tortuous.go
38
tortuous.go
|
@ -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 {
|
||||
|
|
|
@ -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
45
web.go
Normal 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})
|
||||
}
|
Loading…
Reference in a new issue