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
|
package main
|
||||||
|
|
||||||
type Provider interface {
|
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/forward"
|
||||||
"github.com/mailgun/oxy/roundrobin"
|
"github.com/mailgun/oxy/roundrobin"
|
||||||
"github.com/tylerb/graceful"
|
"github.com/tylerb/graceful"
|
||||||
"github.com/unrolled/render"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -16,16 +15,17 @@ import (
|
||||||
"time"
|
"time"
|
||||||
"log"
|
"log"
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
|
"github.com/gorilla/handlers"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FileConfiguration struct {
|
type FileConfiguration struct {
|
||||||
Docker *DockerProvider
|
Docker *DockerProvider
|
||||||
File *FileProvider
|
File *FileProvider
|
||||||
|
Web *WebProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
var srv *graceful.Server
|
var srv *graceful.Server
|
||||||
var configurationRouter *mux.Router
|
var configurationRouter *mux.Router
|
||||||
var renderer = render.New()
|
|
||||||
var currentConfiguration = new(Configuration)
|
var currentConfiguration = new(Configuration)
|
||||||
var configurationChan = make(chan *Configuration)
|
var configurationChan = make(chan *Configuration)
|
||||||
var providers = []Provider{}
|
var providers = []Provider{}
|
||||||
|
@ -34,11 +34,6 @@ func main() {
|
||||||
sigs := make(chan os.Signal, 1)
|
sigs := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
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() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
configuration := <-configurationChan
|
configuration := <-configurationChan
|
||||||
|
@ -57,7 +52,6 @@ func main() {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
configuration := LoadFileConfig()
|
configuration := LoadFileConfig()
|
||||||
log.Println("Configuration loaded", configuration)
|
|
||||||
if(configuration.Docker != nil){
|
if(configuration.Docker != nil){
|
||||||
providers = append(providers, configuration.Docker)
|
providers = append(providers, configuration.Docker)
|
||||||
}
|
}
|
||||||
|
@ -66,9 +60,15 @@ func main() {
|
||||||
providers = append(providers, configuration.File)
|
providers = append(providers, configuration.File)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(configuration.Web != nil){
|
||||||
|
providers = append(providers, configuration.Web)
|
||||||
|
}
|
||||||
|
|
||||||
for _, provider := range providers {
|
for _, provider := range providers {
|
||||||
|
log.Printf("Starting provider %v %+v\n", reflect.TypeOf(provider), provider)
|
||||||
|
currentProvider := provider
|
||||||
go func() {
|
go func() {
|
||||||
provider.Provide(configurationChan)
|
currentProvider.Provide(configurationChan)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,31 +127,13 @@ func LoadConfig(configuration *Configuration) *mux.Router {
|
||||||
rb.UpsertServer(url)
|
rb.UpsertServer(url)
|
||||||
}
|
}
|
||||||
for _, route := range newRoutes {
|
for _, route := range newRoutes {
|
||||||
route.Handler(lb)
|
route.Handler(handlers.CombinedLoggingHandler(os.Stdout, lb))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return router
|
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 {
|
func Invoke(any interface{}, name string, args ...interface{}) []reflect.Value {
|
||||||
inputs := make([]reflect.Value, len(args))
|
inputs := make([]reflect.Value, len(args))
|
||||||
for i, _ := range args {
|
for i, _ := range args {
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
#endpoint = "unix:///var/run/docker.sock"
|
#endpoint = "unix:///var/run/docker.sock"
|
||||||
#watch = true
|
#watch = true
|
||||||
|
|
||||||
|
[web]
|
||||||
|
address = ":8010"
|
||||||
|
|
||||||
[file]
|
[file]
|
||||||
filename = "tortuous.toml"
|
filename = "tortuous.toml"
|
||||||
watch = true
|
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