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))
 | |
| }
 |