Commit 25283c6a authored by ale's avatar ale

Add an index page with links, with an option to customize it

parent a4c33c03
......@@ -17,6 +17,7 @@
// templates/header.html
// templates/index.html
// templates/service_details.html
// templates/service_list.html
// DO NOT EDIT!
package main
......@@ -911,12 +912,72 @@ func templatesHeaderHtml() (*asset, error) {
return a, nil
}
var _templatesIndexHtml = []byte(`{{template "header" "float services"}}
var _templatesIndexHtml = []byte(`{{template "header" "float admin"}}
<h1>{{.Config.Domain}} Admin</h1>
<ul>
<li><a href="/services">Service Overview</a></li>
<li><a href="https://logs.{{.Config.PublicDomain}}/">Log Analysis</a></li>
<li>
Monitoring
<ul>
<li><a href="https://monitor.{{.Config.PublicDomain}}/alerts">Active Alerts</a></li>
<li><a href="https://grafana.{{.Config.PublicDomain}}/">Dashboards</a></li>
</ul>
</li>
</p>
{{template "footer"}}
`)
func templatesIndexHtmlBytes() ([]byte, error) {
return _templatesIndexHtml, nil
}
func templatesIndexHtml() (*asset, error) {
bytes, err := templatesIndexHtmlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "templates/index.html", size: 456, mode: os.FileMode(420), modTime: time.Unix(1566984330, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _templatesService_detailsHtml = []byte(`{{template "header" "service details"}}
{{$domain := .Config.Domain}}
<h1>{{$domain}} / service {{.Service.Name}}</h1>
<pre>{{.Service | yaml}}</pre>
{{template "footer"}}
`)
func templatesService_detailsHtmlBytes() ([]byte, error) {
return _templatesService_detailsHtml, nil
}
func templatesService_detailsHtml() (*asset, error) {
bytes, err := templatesService_detailsHtmlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "templates/service_details.html", size: 176, mode: os.FileMode(420), modTime: time.Unix(1561268261, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _templatesService_listHtml = []byte(`{{template "header" "float services"}}
{{$domain := .Config.Domain}}
<h1>{{$domain}} services</h1>
<table class="table">
<table class="table table-striped">
<thead>
<tr>
......@@ -1034,43 +1095,17 @@ var _templatesIndexHtml = []byte(`{{template "header" "float services"}}
{{template "footer"}}
`)
func templatesIndexHtmlBytes() ([]byte, error) {
return _templatesIndexHtml, nil
}
func templatesIndexHtml() (*asset, error) {
bytes, err := templatesIndexHtmlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "templates/index.html", size: 3002, mode: os.FileMode(420), modTime: time.Unix(1561280744, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _templatesService_detailsHtml = []byte(`{{template "header" "service details"}}
{{$domain := .Config.Domain}}
<h1>{{$domain}} / service {{.Service.Name}}</h1>
<pre>{{.Service | yaml}}</pre>
{{template "footer"}}
`)
func templatesService_detailsHtmlBytes() ([]byte, error) {
return _templatesService_detailsHtml, nil
func templatesService_listHtmlBytes() ([]byte, error) {
return _templatesService_listHtml, nil
}
func templatesService_detailsHtml() (*asset, error) {
bytes, err := templatesService_detailsHtmlBytes()
func templatesService_listHtml() (*asset, error) {
bytes, err := templatesService_listHtmlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "templates/service_details.html", size: 176, mode: os.FileMode(420), modTime: time.Unix(1561268261, 0)}
info := bindataFileInfo{name: "templates/service_list.html", size: 3016, mode: os.FileMode(420), modTime: time.Unix(1566246083, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
......@@ -1144,6 +1179,7 @@ var _bindata = map[string]func() (*asset, error){
"templates/header.html": templatesHeaderHtml,
"templates/index.html": templatesIndexHtml,
"templates/service_details.html": templatesService_detailsHtml,
"templates/service_list.html": templatesService_listHtml,
}
// AssetDir returns the file names below a certain
......@@ -1212,6 +1248,7 @@ var _bintree = &bintree{nil, map[string]*bintree{
"header.html": &bintree{templatesHeaderHtml, map[string]*bintree{}},
"index.html": &bintree{templatesIndexHtml, map[string]*bintree{}},
"service_details.html": &bintree{templatesService_detailsHtml, map[string]*bintree{}},
"service_list.html": &bintree{templatesService_listHtml, map[string]*bintree{}},
}},
}}
......@@ -24,6 +24,7 @@ var (
floatServicesPath = flag.String("services-file", getenv("SERVICES", "/etc/float/services.yml"), "float services `file`")
floatServiceAssignmentsPath = flag.String("service-assignments-file", getenv("SERVICES", "/etc/float/service_assignments.yml"), "float service assignments map `file`")
floatServiceMastersPath = flag.String("service-masters-file", getenv("SERVICES", "/etc/float/service_masters.yml"), "float service masters map `file`")
indexPage = flag.String("index-page", getenv("INDEX_PAGE", "/etc/float/admin_index.html"), "custom index page template `file`")
tpl *template.Template
config *Config
......@@ -156,6 +157,10 @@ func handleIndex(w http.ResponseWriter, r *http.Request) {
renderTemplate(w, "index.html", nil)
}
func handleServiceList(w http.ResponseWriter, r *http.Request) {
renderTemplate(w, "service_list.html", nil)
}
func handleServiceDetails(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
s, ok := serviceMap.Services[vars["service"]]
......@@ -206,15 +211,31 @@ func makeServer() http.Handler {
root.Handle("/service/{service}/details", withDynamicHeaders(http.HandlerFunc(handleServiceDetails)))
root.Handle("/service/{service}/container/{container}/details", withDynamicHeaders(http.HandlerFunc(handleContainerDetails)))
setupRedirects(root.PathPrefix("/link/").Subrouter())
root.Handle("/services", withDynamicHeaders(http.HandlerFunc(handleServiceList)))
root.Handle("/", withDynamicHeaders(http.HandlerFunc(handleIndex)))
return root
}
func loadCustomIndexPage(tpl *template.Template, path string) (*template.Template, error) {
idxTpl, err := template.ParseFiles(path)
if err != nil {
return nil, err
}
return tpl.AddParseTree("index.html", idxTpl.Tree)
}
func main() {
log.SetFlags(0)
flag.Parse()
tpl = mustParseEmbeddedTemplates()
if *indexPage != "" {
if newTpl, err := loadCustomIndexPage(tpl, *indexPage); err != nil {
log.Printf("warning: error loading custom index page: %v", err)
} else {
tpl = newTpl
}
}
config = mustReadConfig()
serviceMap = mustReadServiceMap()
......
package main
import (
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"strings"
"testing"
)
func TestDash(t *testing.T) {
tpl = mustParseEmbeddedTemplates()
config = &Config{
Domain: "investici.org",
PublicDomain: "autistici.org",
}
serviceMap = newServiceMap(
func createTestServiceMap() *ServiceMap {
return newServiceMap(
map[string]*Service{
"svc1": &Service{
Name: "svc1",
NumInstances: 1,
NumInstances: "1",
Ports: []int{4040},
PublicEndpoints: []*PublicEndpoint{
&PublicEndpoint{
......@@ -39,9 +38,52 @@ func TestDash(t *testing.T) {
},
map[string]string{},
)
}
func TestDash(t *testing.T) {
tpl = mustParseEmbeddedTemplates()
config = &Config{
Domain: "investici.org",
PublicDomain: "autistici.org",
}
serviceMap = createTestServiceMap()
srv := httptest.NewServer(makeServer())
resp, err := http.Get(srv.URL + "/services")
if err != nil {
t.Fatalf("http.Get(%s/services): %v", srv.URL, err)
}
if resp.StatusCode != 200 {
t.Fatalf("got error %s", resp.Status)
}
}
func TestCustomIndexPage(t *testing.T) {
tmpf, err := ioutil.TempFile("", "index-")
if err != nil {
t.Fatal("TempFile", err)
}
defer os.Remove(tmpf.Name())
// nolint:errcheck
io.WriteString(tmpf, `{{template "header" "title"}}
hello world
{{template "footer"}}`)
tmpf.Close()
tpl = mustParseEmbeddedTemplates()
tpl, err = loadCustomIndexPage(tpl, tmpf.Name())
if err != nil {
t.Fatal("loadCustomIndexPage", err)
}
config = &Config{
Domain: "investici.org",
PublicDomain: "autistici.org",
}
serviceMap = createTestServiceMap()
srv := httptest.NewServer(makeServer())
resp, err := http.Get(srv.URL)
if err != nil {
t.Fatalf("http.Get(%s): %v", srv.URL, err)
......@@ -49,4 +91,9 @@ func TestDash(t *testing.T) {
if resp.StatusCode != 200 {
t.Fatalf("got error %s", resp.Status)
}
data, _ := ioutil.ReadAll(resp.Body)
dataStr := string(data)
if !strings.Contains(dataStr, "hello world") {
t.Fatalf("index page does not contain custom template text:\n%s", dataStr)
}
}
......@@ -86,7 +86,7 @@ type Service struct {
Ports []int `yaml:"ports,omitempty"`
ServiceCredentials []*ServiceCredentials `yaml:"service_credentials,omitempty"`
LDAPCredentials []struct {
Name string `yaml:"name"`
Name string `yaml:"name"` // nolint:unused
} `yaml:"ldap_credentials,omitempty"`
MonitoringEndpoints []*MonitoringEndpoint `yaml:"monitoring_endpoints,omitempty"`
PublicEndpoints []*PublicEndpoint `yaml:"public_endpoints,omitempty"`
......
......@@ -6,11 +6,11 @@ import (
)
var sriMap = map[string]string{
"/static/js/bootstrap.bundle.min.js": "sha384-CS0nxkpPy+xUkNGhObAISrkg/xjb3USVCwy+0/NMzd5VxgY4CMCyTkItmy5n0voC",
"/static/js/jquery.slim.min.js": "sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo",
"/static/css/bootstrap.min.css": "sha384-Smlep5jCw/wG7hdkwQ/Z5nLIefveQRIY9nfy6xoR1uRYBtpZgI6339F5dgvm/e9B",
"/static/css/open-iconic-bootstrap.min.css": "sha384-wWci3BOzr88l+HNsAtr3+e5bk9qh5KfjU6gl/rbzfTYdsAVHBEbxB33veLYmFg/a",
"/static/css/style.css": "sha384-OLBgp1GsljhM2TJ+sbHjaiH9txEUvgdDTAzHv2P24donTt6/529l+9Ua0vFImLlb",
"/static/js/bootstrap.bundle.min.js": "sha384-CS0nxkpPy+xUkNGhObAISrkg/xjb3USVCwy+0/NMzd5VxgY4CMCyTkItmy5n0voC",
"/static/js/jquery.slim.min.js": "sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo",
}
// SRIScript returns a <script> tag with resource integrity attributes.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment