moved all ui stuff to the ui package.
The structure of converge server is now much more clear in the package // structure below pkg/server.
This commit is contained in:
parent
2b9821f967
commit
2c42f89547
@ -6,6 +6,7 @@ import (
|
||||
"git.wamblee.org/converge/pkg/models"
|
||||
"git.wamblee.org/converge/pkg/server/matchmaker"
|
||||
"git.wamblee.org/converge/pkg/server/prometheus"
|
||||
"git.wamblee.org/converge/pkg/server/ui"
|
||||
"git.wamblee.org/converge/pkg/support/websocketutil"
|
||||
"log"
|
||||
"net"
|
||||
@ -128,7 +129,7 @@ func main() {
|
||||
// And the MatchMaker. The MatchMakers sends state notifications to websessions
|
||||
// and prometheus.
|
||||
notifications := NewStateNotifier(throttlingInterval)
|
||||
websessions := matchmaker.NewWebSessions(notifications.webNotificationChannel)
|
||||
websessions := ui.NewWebSessions(notifications.webNotificationChannel)
|
||||
// monitoring
|
||||
prometheusMux := http.NewServeMux()
|
||||
prometheus.SetupPrometheus(prometheusMux, notifications.prometheusNotificationChannel)
|
||||
@ -161,18 +162,18 @@ func setupWebUI(context HttpContext, registrationService websocketutil.WebSocket
|
||||
context.HandleFunc("ws/sessions", sessionService.Handle)
|
||||
|
||||
// create filehandler with templating for html files.
|
||||
context.Handle("docs/", http.StripPrefix("docs/", http.HandlerFunc(pageHandler)))
|
||||
context.Handle("docs/", http.StripPrefix("docs/", http.HandlerFunc(ui.PageHandler)))
|
||||
context.Handle("static/", http.StripPrefix("static/",
|
||||
http.FileServer(http.Dir(staticdir))))
|
||||
context.Handle("downloads/", http.StripPrefix("downloads/",
|
||||
http.FileServer(http.Dir(downloaddir))))
|
||||
// create usage generator
|
||||
context.HandleFunc("usage", generateCLIExammple)
|
||||
context.HandleFunc("usage", ui.GenerateCLIExammples)
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
func setupWebSockets(admin *matchmaker.MatchMaker, websessions *matchmaker.WebSessions) (websocketutil.WebSocketService, websocketutil.WebSocketService, websocketutil.WebSocketService) {
|
||||
func setupWebSockets(admin *matchmaker.MatchMaker, websessions *ui.WebSessions) (websocketutil.WebSocketService, websocketutil.WebSocketService, websocketutil.WebSocketService) {
|
||||
// websocket endpoints
|
||||
|
||||
// For agents connecting
|
||||
@ -214,7 +215,7 @@ func setupWebSockets(admin *matchmaker.MatchMaker, websessions *matchmaker.WebSe
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
websession := websessions.NewSession(conn, ctx, cancel)
|
||||
defer websessions.SessionClosed(websession)
|
||||
location, err := matchmaker.GetUserLocation(r)
|
||||
location, err := ui.GetUserLocation(r)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
templates2 "git.wamblee.org/converge/pkg/server/ui"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func pageHandler(w http.ResponseWriter, r *http.Request) {
|
||||
access := getConvergeAccess(r)
|
||||
|
||||
switch r.URL.Path {
|
||||
case "":
|
||||
fallthrough
|
||||
case "/":
|
||||
fallthrough
|
||||
case "index.html":
|
||||
templates2.AboutTab().Render(r.Context(), w)
|
||||
// TODO use contexts later.
|
||||
case "usage.html":
|
||||
templates2.UsageTab(access).Render(r.Context(), w)
|
||||
case "downloads.html":
|
||||
templates2.DownloadsTab().Render(r.Context(), w)
|
||||
case "sessions.html":
|
||||
templates2.SessionsTab(nil, nil, access.Location).Render(r.Context(), w)
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
}
|
4
pkg/server/admin/doc.go
Normal file
4
pkg/server/admin/doc.go
Normal file
@ -0,0 +1,4 @@
|
||||
// Basic administration of the matchmaker.
|
||||
// Put in its separate package to make sure only public methods can be called because
|
||||
// these are the only ones that are thread-safe.
|
||||
package admin
|
6
pkg/server/matchmaker/doc.go
Normal file
6
pkg/server/matchmaker/doc.go
Normal file
@ -0,0 +1,6 @@
|
||||
// The matchmaker package matches up agents and clients based on their rendez-vous
|
||||
// ids and pumps data between client and agent. This is the core cunctionality of
|
||||
// converge. It uses notifications with the new state in case something changes.
|
||||
// The notifications are routed to components that are interested in them: the web ui
|
||||
// and prometheus integration.
|
||||
package matchmaker
|
4
pkg/server/prometheus/doc.go
Normal file
4
pkg/server/prometheus/doc.go
Normal file
@ -0,0 +1,4 @@
|
||||
// Prometheus integration of converge. It relies on state notifications of converge that
|
||||
// describe the current state. It computes the deltas based on the state itself and updates
|
||||
// prometheus metrics accordingly.
|
||||
package prometheus
|
@ -1,13 +1,24 @@
|
||||
package main
|
||||
package ui
|
||||
|
||||
import (
|
||||
"git.wamblee.org/converge/pkg/models"
|
||||
"git.wamblee.org/converge/pkg/server/matchmaker"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func GetUserLocation(r *http.Request) (*time.Location, error) {
|
||||
tzName := r.URL.Query().Get("timezone")
|
||||
if tzName == "" {
|
||||
tzName = r.Header.Get("X-Timezone")
|
||||
}
|
||||
if tzName == "" {
|
||||
tzName = "UTC"
|
||||
}
|
||||
return time.LoadLocation(tzName)
|
||||
}
|
||||
|
||||
func getConvergeAccess(r *http.Request) models.ConvergeAccess {
|
||||
|
||||
pattern := regexp.MustCompile("^(.*)/usage$")
|
||||
@ -32,7 +43,7 @@ func getConvergeAccess(r *http.Request) models.ConvergeAccess {
|
||||
}
|
||||
}
|
||||
|
||||
location, err := matchmaker.GetUserLocation(r)
|
||||
location, err := GetUserLocation(r)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
6
pkg/server/ui/doc.go
Normal file
6
pkg/server/ui/doc.go
Normal file
@ -0,0 +1,6 @@
|
||||
// This provides the user interface consisting of a number of an information page,
|
||||
// a downloads page, an interfactive usage page and a sessions page.
|
||||
// The usage page uses HTMX to get updated CLI examples based on the user's input.
|
||||
// The sessions page uses HTMX with a websocket so that the server can push the live
|
||||
// status of the server to clients.
|
||||
package ui
|
27
pkg/server/ui/pagehandler.go
Normal file
27
pkg/server/ui/pagehandler.go
Normal file
@ -0,0 +1,27 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func PageHandler(w http.ResponseWriter, r *http.Request) {
|
||||
access := getConvergeAccess(r)
|
||||
|
||||
switch r.URL.Path {
|
||||
case "":
|
||||
fallthrough
|
||||
case "/":
|
||||
fallthrough
|
||||
case "index.html":
|
||||
AboutTab().Render(r.Context(), w)
|
||||
// TODO use contexts later.
|
||||
case "usage.html":
|
||||
UsageTab(access).Render(r.Context(), w)
|
||||
case "downloads.html":
|
||||
DownloadsTab().Render(r.Context(), w)
|
||||
case "sessions.html":
|
||||
SessionsTab(nil, nil, access.Location).Render(r.Context(), w)
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
package main
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.wamblee.org/converge/pkg/server/ui"
|
||||
"github.com/gliderlabs/ssh"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
@ -11,7 +10,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func generateCLIExammple(w http.ResponseWriter, r *http.Request) {
|
||||
func GenerateCLIExammples(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
http.Error(w, "Error parsing form", http.StatusBadRequest)
|
||||
@ -32,7 +31,7 @@ func generateCLIExammple(w http.ResponseWriter, r *http.Request) {
|
||||
downloadCommand := r.FormValue("download-command")
|
||||
certificateValidation := r.FormValue("certificate-validation") != ""
|
||||
sshPublicKeys := strings.Split(keysString, "\n")
|
||||
usageInputs := ui.NewUsageInputs(id, sshPublicKeys, remoteShells, localShells, downloadCommand,
|
||||
usageInputs := NewUsageInputs(id, sshPublicKeys, remoteShells, localShells, downloadCommand,
|
||||
certificateValidation)
|
||||
if generatedId {
|
||||
usageInputs.ErrorMessages = append(usageInputs.ErrorMessages, "rendez-vous id is randomly generated, changes on every page refresh")
|
||||
@ -64,7 +63,7 @@ func generateCLIExammple(w http.ResponseWriter, r *http.Request) {
|
||||
"No valid public keys configured. Without these the agent will not work.")
|
||||
}
|
||||
|
||||
err = ui.ShellUsage(access, usageInputs).Render(r.Context(), w)
|
||||
err = ShellUsage(access, usageInputs).Render(r.Context(), w)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
package matchmaker
|
||||
package ui
|
||||
|
||||
import (
|
||||
"context"
|
||||
"git.wamblee.org/converge/pkg/models"
|
||||
"git.wamblee.org/converge/pkg/server/ui"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
@ -98,17 +97,6 @@ func (sessions *WebSessions) NewSession(wsConnection net.Conn, ctx context.Conte
|
||||
return session
|
||||
}
|
||||
|
||||
func GetUserLocation(r *http.Request) (*time.Location, error) {
|
||||
tzName := r.URL.Query().Get("timezone")
|
||||
if tzName == "" {
|
||||
tzName = r.Header.Get("X-Timezone")
|
||||
}
|
||||
if tzName == "" {
|
||||
tzName = "UTC"
|
||||
}
|
||||
return time.LoadLocation(tzName)
|
||||
}
|
||||
|
||||
func (session *WebSession) WriteNotifications(location *time.Location, ctx context.Context, cancel context.CancelFunc) {
|
||||
timer := time.NewTicker(10 * time.Second)
|
||||
defer timer.Stop()
|
||||
@ -138,7 +126,7 @@ func (session *WebSession) WriteNotifications(location *time.Location, ctx conte
|
||||
|
||||
func (session *WebSession) writeNotificationToClient(location *time.Location, notification *models.State) bool {
|
||||
agents, clients := notification.Slices()
|
||||
err := ui.State(agents, clients, location).Render(context.Background(), session.conn)
|
||||
err := State(agents, clients, location).Render(context.Background(), session.conn)
|
||||
if err != nil {
|
||||
log.Printf("WS connection closed: %v", err)
|
||||
return false
|
Loading…
Reference in New Issue
Block a user