Start working on web server (#2)

* Start working on web server

* Some restructure

* Serving static works

* Fix linter complaint

* Enable local dev

* Static files served fine

* Tidy
This commit is contained in:
Andrey Pokhilko
2022-08-23 13:46:11 +03:00
committed by GitHub
parent ee89611b81
commit 925cfa77dd
10 changed files with 178 additions and 728 deletions

55
pkg/dashboard/api.go Normal file
View File

@@ -0,0 +1,55 @@
package dashboard
import (
"embed"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"net/http"
"os"
"path"
)
//go:embed static/*
var staticFS embed.FS
func newRouter(abortWeb ControlChan, data DataLayer) *gin.Engine {
api := gin.Default()
fs := http.FS(staticFS)
// local dev speed-up
localDevPath := "pkg/dashboard/static"
if _, err := os.Stat(localDevPath); err == nil {
log.Warnf("Using local development path to serve static files")
// the root page
api.GET("/", func(c *gin.Context) {
c.File(path.Join(localDevPath, "index.html"))
})
// serve a directory called static
api.GET("/static/*filepath", func(c *gin.Context) {
c.File(path.Join(localDevPath, c.Param("filepath")))
})
} else {
// the root page
api.GET("/", func(c *gin.Context) {
c.FileFromFS("/static/", fs)
})
// serve a directory called static
api.GET("/static/*filepath", func(c *gin.Context) {
c.FileFromFS(c.Request.URL.Path, fs)
})
}
// server shutdown handler
api.DELETE("/", func(c *gin.Context) {
abortWeb <- struct{}{}
})
api.GET("/api", func(c *gin.Context) {
c.IndentedJSON(http.StatusOK, data.ListInstalled())
})
return api
}

16
pkg/dashboard/main.go Normal file
View File

@@ -0,0 +1,16 @@
package dashboard
import (
"helm.sh/helm/v3/pkg/release"
)
type DataLayer struct {
}
func (l *DataLayer) CheckConnectivity() {
// TODO: check that we can work with context and subcommands
}
func (l *DataLayer) ListInstalled() []*release.Release {
return nil // TODO
}

54
pkg/dashboard/server.go Normal file
View File

@@ -0,0 +1,54 @@
package dashboard
import (
"context"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"net/http"
"os"
"strings"
)
func StartServer() (string, ControlChan) {
data := DataLayer{}
data.CheckConnectivity()
address := os.Getenv("HD_BIND")
if os.Getenv("HD_PORT") == "" {
address += ":8080" // TODO: better default port to clash less?
} else {
address += ":" + os.Getenv("HD_PORT")
}
abort := make(ControlChan)
api := newRouter(abort, data)
done := startBackgroundServer(address, api, abort)
if strings.HasPrefix(address, ":") {
address = "localhost" + address
}
return "http://" + address, done
}
func startBackgroundServer(addr string, routes *gin.Engine, abort ControlChan) ControlChan {
done := make(ControlChan)
server := &http.Server{Addr: addr, Handler: routes}
go func() {
err := server.ListenAndServe()
if err != nil && err != http.ErrServerClosed {
panic(err) // TODO: in case of "port busy", check that it's another instance of us and just open browser
}
done <- struct{}{}
}()
go func() {
<-abort
err := server.Shutdown(context.Background())
if err != nil {
log.Warnf("Had problems shutting down the server: %s", err)
}
}()
return done
}

View File

@@ -0,0 +1,19 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Helm Dashboard</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<link href="static/styles.css" rel="stylesheet">
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js"
integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa"
crossorigin="anonymous"></script>
<script src="static/scripts.js"></script>
</body>
</html>

View File

View File

3
pkg/dashboard/utils.go Normal file
View File

@@ -0,0 +1,3 @@
package dashboard
type ControlChan = chan struct{}