2024-01-30 16:45:03 +01:00
|
|
|
package web
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
2024-02-03 11:11:10 +01:00
|
|
|
"net/http"
|
2024-01-30 16:45:03 +01:00
|
|
|
"net/http/httputil"
|
|
|
|
"net/url"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/gin-contrib/sessions"
|
|
|
|
"github.com/gin-gonic/gin"
|
2024-02-03 11:11:10 +01:00
|
|
|
"github.com/spf13/viper"
|
2024-01-30 16:45:03 +01:00
|
|
|
|
|
|
|
"git.jmbit.de/jmb/podterminal/pods"
|
|
|
|
)
|
|
|
|
|
|
|
|
func createReverseProxy(backendService string) (*httputil.ReverseProxy, error) {
|
|
|
|
var err error
|
|
|
|
log.Println("Creating reverse Proxy for ", backendService)
|
|
|
|
|
|
|
|
backendURL, err := url.Parse(backendService)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("Could not parse backend URL: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
proxy := &httputil.ReverseProxy{
|
|
|
|
Rewrite: func(request *httputil.ProxyRequest) {
|
|
|
|
request.SetURL(backendURL)
|
|
|
|
request.Out.Host = request.In.Host
|
|
|
|
},
|
2024-02-05 09:45:28 +01:00
|
|
|
// ModifyResponse: func(response *http.Response) error {
|
|
|
|
// if response.StatusCode == http.StatusBadGateway {
|
|
|
|
// waitForAnswer(backendURL.String())
|
|
|
|
// response.StatusCode = 200
|
|
|
|
// response.Header.Set("Location", "/")
|
|
|
|
|
|
|
|
// }
|
|
|
|
// return nil
|
|
|
|
// },
|
2024-01-30 16:45:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return proxy, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func containerProxy(c *gin.Context) {
|
|
|
|
session := sessions.Default(c)
|
2024-02-03 11:11:10 +01:00
|
|
|
sessionID := ""
|
2024-02-05 09:45:28 +01:00
|
|
|
if session.Get("ct") == nil {
|
2024-02-03 11:11:10 +01:00
|
|
|
session.Set("ready", false)
|
|
|
|
session.Save()
|
2024-01-30 16:45:03 +01:00
|
|
|
log.Println("Creating Container for Session ", sessionID)
|
|
|
|
ct, err := pods.CreateContainer()
|
2024-02-02 18:47:45 +01:00
|
|
|
session.Set("ct", ct)
|
|
|
|
session.Save()
|
2024-01-30 16:45:03 +01:00
|
|
|
if err != nil {
|
|
|
|
c.HTML(500, "Error", fmt.Sprintf("[%s] Could not create Container: %v", sessionID, err))
|
2024-02-02 18:47:45 +01:00
|
|
|
session.Delete("ct")
|
|
|
|
session.Save()
|
2024-01-30 16:45:03 +01:00
|
|
|
c.Abort()
|
2024-02-05 09:45:28 +01:00
|
|
|
return
|
2024-01-30 16:45:03 +01:00
|
|
|
}
|
|
|
|
err = pods.StartContainer(ct)
|
|
|
|
if err != nil {
|
|
|
|
c.HTML(500, "Error", fmt.Sprintf("[%s] Could not start Container: %v", sessionID, err))
|
2024-02-02 18:47:45 +01:00
|
|
|
session.Delete("ct")
|
|
|
|
session.Save()
|
2024-01-30 16:45:03 +01:00
|
|
|
c.Abort()
|
2024-02-05 09:45:28 +01:00
|
|
|
|
|
|
|
return
|
2024-01-30 16:45:03 +01:00
|
|
|
}
|
2024-02-02 18:47:45 +01:00
|
|
|
|
2024-01-30 16:45:03 +01:00
|
|
|
ctip, err := pods.GetContainerIP(ct)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
c.HTML(500, "Error", fmt.Sprintf("[%s] Could not get Container ip: %v", sessionID, err))
|
2024-02-02 18:47:45 +01:00
|
|
|
session.Delete("ct")
|
|
|
|
session.Save()
|
2024-01-30 16:45:03 +01:00
|
|
|
c.Abort()
|
2024-02-05 09:45:28 +01:00
|
|
|
return
|
2024-01-30 16:45:03 +01:00
|
|
|
}
|
|
|
|
|
2024-01-31 13:12:43 +01:00
|
|
|
// Soft fail Skel
|
2024-02-01 17:32:46 +01:00
|
|
|
// _ = pods.CopySkelToContainer(ct)
|
2024-01-30 16:45:03 +01:00
|
|
|
|
2024-02-05 09:45:28 +01:00
|
|
|
err = waitForAnswer(fmt.Sprintf("http://%s:%d", ctip, viper.GetInt("container_port")))
|
2024-02-03 11:11:10 +01:00
|
|
|
proxies[ct], err = createReverseProxy(
|
|
|
|
fmt.Sprintf("http://%s:%d", ctip, viper.GetInt("container_port")),
|
|
|
|
)
|
2024-01-30 16:45:03 +01:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
c.HTML(
|
|
|
|
500,
|
|
|
|
"Error",
|
|
|
|
fmt.Sprintf("[%s] Could not create Container Proxy: %v", sessionID, err),
|
|
|
|
)
|
2024-02-02 18:47:45 +01:00
|
|
|
session.Delete("ct")
|
|
|
|
session.Save()
|
2024-01-30 16:45:03 +01:00
|
|
|
c.Abort()
|
2024-02-05 09:45:28 +01:00
|
|
|
return
|
2024-01-30 16:45:03 +01:00
|
|
|
}
|
2024-02-05 09:45:28 +01:00
|
|
|
if err != nil {
|
|
|
|
c.HTML(
|
|
|
|
500,
|
|
|
|
"Error",
|
|
|
|
fmt.Sprintf("[%s] Timed out waiting for Container: %v", sessionID, err),
|
|
|
|
)
|
2024-02-02 18:47:45 +01:00
|
|
|
session.Delete("ct")
|
|
|
|
session.Save()
|
2024-01-30 16:45:03 +01:00
|
|
|
c.Abort()
|
2024-02-05 09:45:28 +01:00
|
|
|
return
|
2024-01-30 16:45:03 +01:00
|
|
|
}
|
2024-02-05 09:45:28 +01:00
|
|
|
session.Set("ready", true)
|
|
|
|
session.Save()
|
|
|
|
c.HTML(200, "", clientReloadContent)
|
|
|
|
return
|
|
|
|
} else {
|
2024-02-03 11:11:10 +01:00
|
|
|
if session.Get("ready").(bool) == false {
|
2024-02-05 09:45:28 +01:00
|
|
|
time.Sleep(2 * time.Second)
|
2024-02-03 11:11:10 +01:00
|
|
|
c.Redirect(307, "/")
|
2024-02-05 09:45:28 +01:00
|
|
|
return
|
2024-02-02 18:47:45 +01:00
|
|
|
}
|
2024-01-30 16:45:03 +01:00
|
|
|
id := session.Get("ct").(string)
|
|
|
|
proxy := proxies[id]
|
2024-02-03 11:11:10 +01:00
|
|
|
if proxy != nil {
|
|
|
|
proxy.ServeHTTP(c.Writer, c.Request)
|
|
|
|
} else {
|
|
|
|
session.Delete("ct")
|
|
|
|
session.Delete("ready")
|
|
|
|
session.Save()
|
|
|
|
c.Abort()
|
2024-02-05 09:45:28 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func waitForAnswer(url string) error {
|
|
|
|
retries := 0
|
|
|
|
var err error
|
|
|
|
for retries < 50 {
|
|
|
|
err = nil
|
|
|
|
response, err := http.Get(url)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("Error connecting to %s: %v", url, err)
|
|
|
|
}
|
|
|
|
if response.StatusCode == 200 {
|
|
|
|
return nil
|
2024-02-03 11:11:10 +01:00
|
|
|
}
|
|
|
|
|
2024-02-05 09:45:28 +01:00
|
|
|
retries++
|
|
|
|
time.Sleep(500 * time.Millisecond)
|
2024-01-30 16:45:03 +01:00
|
|
|
}
|
2024-02-05 09:45:28 +01:00
|
|
|
log.Println("Timed out waiting for Container")
|
|
|
|
return err
|
2024-01-30 16:45:03 +01:00
|
|
|
|
|
|
|
}
|