99 lines
3.2 KiB
Go
99 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"converge/pkg/converge"
|
|
"converge/pkg/websocketutil"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"regexp"
|
|
)
|
|
|
|
func parsePublicId(path string) (publicId string, _ error) {
|
|
pattern := regexp.MustCompile("^/[^/]+/([^/]+)$")
|
|
matches := pattern.FindStringSubmatch(path)
|
|
if len(matches) != 2 {
|
|
return "", fmt.Errorf("Invalid URL path '%s'", path)
|
|
}
|
|
return matches[1], nil
|
|
}
|
|
|
|
func catchAllHandler(w http.ResponseWriter, r *http.Request) {
|
|
http.Redirect(w, r, "/docs", http.StatusFound)
|
|
return
|
|
}
|
|
|
|
func main() {
|
|
downloadOption := flag.String("d", "downloads",
|
|
"directory where documentation is located, either relative to current directory or an absolute path")
|
|
|
|
flag.Usage = func() {
|
|
fmt.Fprintln(os.Stderr, "Usage: converge [options]")
|
|
fmt.Fprintln(os.Stderr)
|
|
fmt.Fprintln(os.Stderr, "Converge server is a rendez-vous server for debugging continuous integration")
|
|
fmt.Fprintln(os.Stderr, "jobs be providing the capability to log into the agents where jobs are running.")
|
|
fmt.Fprintln(os.Stderr, "This is achieve by starting an agent in the continuous integration job")
|
|
fmt.Fprintln(os.Stderr, "which connects to Converge using a websocket connection. The end user also connects")
|
|
fmt.Fprintln(os.Stderr, "to Converge using ssh over websockets. The server then matches the end-user with")
|
|
fmt.Fprintln(os.Stderr, "the agent running in the continous integration job (the rendez-vous) and sets up")
|
|
fmt.Fprintln(os.Stderr, "an end-to-end SSH connection between end-user and agent, with the agent providing")
|
|
fmt.Fprintln(os.Stderr, "an embedded SSH server to provide interactive access to the end-user. This works")
|
|
fmt.Fprintln(os.Stderr, "both on linux and on windows.")
|
|
fmt.Fprintln(os.Stderr)
|
|
flag.PrintDefaults()
|
|
}
|
|
flag.Parse()
|
|
if flag.NArg() != 0 {
|
|
flag.Usage()
|
|
os.Exit(1)
|
|
}
|
|
downloadDir := *downloadOption
|
|
log.Println("Download directory", downloadDir)
|
|
|
|
admin := converge.NewAdmin()
|
|
registrationService := websocketutil.WebSocketService{
|
|
Handler: func(w http.ResponseWriter, r *http.Request, conn net.Conn) {
|
|
publicId, err := parsePublicId(r.URL.Path)
|
|
if err != nil {
|
|
log.Printf("Cannot parse public id from url: '%v'\n", err)
|
|
return
|
|
}
|
|
log.Printf("Got registration connection: '%s'\n", publicId)
|
|
err = admin.Register(publicId, conn)
|
|
if err != nil {
|
|
log.Printf("Error %v\n", err)
|
|
}
|
|
},
|
|
}
|
|
clientService := websocketutil.WebSocketService{
|
|
Handler: func(w http.ResponseWriter, r *http.Request, conn net.Conn) {
|
|
publicId, err := parsePublicId(r.URL.Path)
|
|
if err != nil {
|
|
log.Printf("Cannot parse public id from url: '%v'\n", err)
|
|
return
|
|
}
|
|
log.Printf("Got client connection: '%s'\n", publicId)
|
|
err = admin.Connect(publicId, conn)
|
|
if err != nil {
|
|
log.Printf("Error %v\n", err)
|
|
}
|
|
},
|
|
}
|
|
|
|
// websocket endpoints
|
|
http.HandleFunc("/agent/", registrationService.Handle)
|
|
http.HandleFunc("/client/", clientService.Handle)
|
|
|
|
// create filehandler with templating for html files.
|
|
fileHandler := NewFileHandler(downloadDir)
|
|
http.Handle("/docs/", http.StripPrefix("/docs/", fileHandler))
|
|
http.HandleFunc("/", catchAllHandler)
|
|
|
|
// Start HTTP server
|
|
fmt.Println("Rendez-vous server listening on :8000")
|
|
log.Fatal(http.ListenAndServe(":8000", nil))
|
|
}
|