Merge pull request #429 from lstocchi/i425

Add --services flag to start API without using --listen flag
This commit is contained in:
openshift-merge-bot[bot]
2025-01-30 16:01:54 +00:00
committed by GitHub
3 changed files with 59 additions and 41 deletions

View File

@@ -112,7 +112,7 @@ With the executable:
### API
When `gvproxy` is started with the `--listen` option, it exposes a HTTP API on the host.
When `gvproxy` is started with the `--listen` or `--services` option, it exposes a HTTP API on the host.
This API can be used with curl.
```
@@ -127,6 +127,8 @@ $ curl --unix-socket /tmp/network.sock http:/unix/stats
...
```
N.B: The `--services` option exposes the same HTTP API as the `--listen` option, but without the `/connect` endpoint. This is useful for scenarios where the `gvforwarder`/`vm` tool is not run on the guest but you still want to expose services and stats endpoints.
### Gateway
The executable running on the host runs a virtual gateway that can be used by the VM.
@@ -144,7 +146,7 @@ nameserver 192.168.127.1
### Port forwarding
Dynamic port forwarding is supported over the host HTTP API when `gvproxy` was
started with `--listen`, but also in the VM over http://192.168.127.1:80.
started with `--listen` or `--services`, but also in the VM over http://192.168.127.1:80.
Expose a port:
```

View File

@@ -46,6 +46,7 @@ var (
pidFile string
exitCode int
logFile string
servicesEndpoint string
)
const (
@@ -74,6 +75,7 @@ func main() {
flag.Var(&forwardIdentify, "forward-identity", "Path to SSH identity key for forwarding")
flag.StringVar(&pidFile, "pid-file", "", "Generate a file with the PID in it")
flag.StringVar(&logFile, "log-file", "", "Output log messages (logrus) to a given file path")
flag.StringVar(&servicesEndpoint, "services", "", "Exposes the same HTTP API as the --listen flag, without the /connect endpoint")
flag.Parse()
if version.ShowVersion() {
@@ -262,7 +264,7 @@ func main() {
}
groupErrs.Go(func() error {
return run(ctx, groupErrs, &config, endpoints)
return run(ctx, groupErrs, &config, endpoints, servicesEndpoint)
})
// Wait for something to happen
@@ -310,7 +312,7 @@ func captureFile() string {
return "capture.pcap"
}
func run(ctx context.Context, g *errgroup.Group, configuration *types.Configuration, endpoints []string) error {
func run(ctx context.Context, g *errgroup.Group, configuration *types.Configuration, endpoints []string, servicesEndpoint string) error {
vn, err := virtualnetwork.New(configuration)
if err != nil {
return err
@@ -326,6 +328,15 @@ func run(ctx context.Context, g *errgroup.Group, configuration *types.Configurat
httpServe(ctx, g, ln, withProfiler(vn))
}
if servicesEndpoint != "" {
log.Infof("enabling services API. Listening %s", servicesEndpoint)
ln, err := transport.Listen(servicesEndpoint)
if err != nil {
return errors.Wrap(err, "cannot listen")
}
httpServe(ctx, g, ln, vn.ServicesMux())
}
ln, err := vn.Listen("tcp", fmt.Sprintf("%s:80", gatewayIP))
if err != nil {
return err

View File

@@ -15,7 +15,7 @@ import (
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
)
func (n *VirtualNetwork) Mux() *http.ServeMux {
func (n *VirtualNetwork) ServicesMux() *http.ServeMux {
mux := http.NewServeMux()
mux.Handle("/services/", http.StripPrefix("/services", n.servicesMux))
mux.HandleFunc("/stats", func(w http.ResponseWriter, _ *http.Request) {
@@ -27,26 +27,6 @@ func (n *VirtualNetwork) Mux() *http.ServeMux {
mux.HandleFunc("/leases", func(w http.ResponseWriter, _ *http.Request) {
_ = json.NewEncoder(w).Encode(n.ipPool.Leases())
})
mux.HandleFunc(types.ConnectPath, func(w http.ResponseWriter, _ *http.Request) {
hj, ok := w.(http.Hijacker)
if !ok {
http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
return
}
conn, bufrw, err := hj.Hijack()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer conn.Close()
if err := bufrw.Flush(); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
_ = n.networkSwitch.Accept(context.Background(), conn, n.configuration.Protocol)
})
mux.HandleFunc("/tunnel", func(w http.ResponseWriter, r *http.Request) {
ip := r.URL.Query().Get("ip")
if ip == "" {
@@ -98,3 +78,28 @@ func (n *VirtualNetwork) Mux() *http.ServeMux {
})
return mux
}
func (n *VirtualNetwork) Mux() *http.ServeMux {
mux := n.ServicesMux()
mux.HandleFunc(types.ConnectPath, func(w http.ResponseWriter, _ *http.Request) {
hj, ok := w.(http.Hijacker)
if !ok {
http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
return
}
conn, bufrw, err := hj.Hijack()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer conn.Close()
if err := bufrw.Flush(); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
_ = n.networkSwitch.Accept(context.Background(), conn, n.configuration.Protocol)
})
return mux
}