From 10a0c66ad8e90a297bc5c05e1ce0ea735491f5e9 Mon Sep 17 00:00:00 2001 From: Tom Clegg Date: Mon, 3 Apr 2023 11:23:03 -0400 Subject: [PATCH] 18790: Fix .../containers/.../log routing. Arvados-DCO-1.1-Signed-off-by: Tom Clegg --- lib/controller/handler.go | 19 +++++++++++++++++++ lib/controller/router/router.go | 14 ++++++++++++++ lib/controller/rpc/conn.go | 4 ++-- sdk/go/arvados/api.go | 6 ++++-- 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/lib/controller/handler.go b/lib/controller/handler.go index 4810ec3c25..2feae76353 100644 --- a/lib/controller/handler.go +++ b/lib/controller/handler.go @@ -139,6 +139,7 @@ func (h *Handler) setup() { hs := http.NotFoundHandler() hs = prepend(hs, h.proxyRailsAPI) + hs = prepend(hs, h.routeContainerEndpoints(rtr)) hs = prepend(hs, h.limitLogCreateRequests) hs = h.setupProxyRemoteCluster(hs) hs = prepend(hs, oidcAuthorizer.Middleware) @@ -194,6 +195,24 @@ func (h *Handler) localClusterRequest(req *http.Request) (*http.Response, error) return h.proxy.Do(req, urlOut, client) } +// Route /arvados/v1/containers/{uuid}/log*, .../ssh, and +// .../gateway_tunnel to rtr, pass everything else to next. +// +// (http.ServeMux doesn't let us route these without also routing +// everything under /containers/, which we don't want yet.) +func (h *Handler) routeContainerEndpoints(rtr http.Handler) middlewareFunc { + return func(w http.ResponseWriter, req *http.Request, next http.Handler) { + trim := strings.TrimPrefix(req.URL.Path, "/arvados/v1/containers/") + if trim != req.URL.Path && (strings.Index(trim, "/log") == 27 || + strings.Index(trim, "/ssh") == 27 || + strings.Index(trim, "/gateway_tunnel") == 27) { + rtr.ServeHTTP(w, req) + } else { + next.ServeHTTP(w, req) + } + } +} + func (h *Handler) limitLogCreateRequests(w http.ResponseWriter, req *http.Request, next http.Handler) { if cap(h.limitLogCreate) > 0 && req.Method == http.MethodPost && strings.HasPrefix(req.URL.Path, "/arvados/v1/logs") { select { diff --git a/lib/controller/router/router.go b/lib/controller/router/router.go index 703c45701b..2cbd9b88dc 100644 --- a/lib/controller/router/router.go +++ b/lib/controller/router/router.go @@ -223,6 +223,13 @@ func (rtr *router) addRoutes() { return rtr.backend.ContainerSSH(ctx, *opts.(*arvados.ContainerSSHOptions)) }, }, + { + arvados.EndpointContainerSSHCompat, + func() interface{} { return &arvados.ContainerSSHOptions{} }, + func(ctx context.Context, opts interface{}) (interface{}, error) { + return rtr.backend.ContainerSSH(ctx, *opts.(*arvados.ContainerSSHOptions)) + }, + }, { // arvados-client built before commit // bdc29d3129f6d75aa9ce0a24ffb849a272b06f08 @@ -241,6 +248,13 @@ func (rtr *router) addRoutes() { return rtr.backend.ContainerGatewayTunnel(ctx, *opts.(*arvados.ContainerGatewayTunnelOptions)) }, }, + { + arvados.EndpointContainerGatewayTunnelCompat, + func() interface{} { return &arvados.ContainerGatewayTunnelOptions{} }, + func(ctx context.Context, opts interface{}) (interface{}, error) { + return rtr.backend.ContainerGatewayTunnel(ctx, *opts.(*arvados.ContainerGatewayTunnelOptions)) + }, + }, { arvados.EndpointContainerRequestCreate, func() interface{} { return &arvados.CreateOptions{} }, diff --git a/lib/controller/rpc/conn.go b/lib/controller/rpc/conn.go index 5176df59f4..70a936a6f6 100644 --- a/lib/controller/rpc/conn.go +++ b/lib/controller/rpc/conn.go @@ -356,7 +356,7 @@ func (conn *Conn) ContainerLog(ctx context.Context, options arvados.ContainerLog // a running container. If the returned error is nil, the caller is // responsible for closing sshconn.Conn. func (conn *Conn) ContainerSSH(ctx context.Context, options arvados.ContainerSSHOptions) (sshconn arvados.ConnectionResponse, err error) { - u, err := conn.baseURL.Parse("/" + strings.Replace(arvados.EndpointContainerSSH.Path, "{uuid}", options.UUID, -1)) + u, err := conn.baseURL.Parse("/" + strings.Replace(arvados.EndpointContainerSSHCompat.Path, "{uuid}", options.UUID, -1)) if err != nil { err = fmt.Errorf("url.Parse: %w", err) return @@ -372,7 +372,7 @@ func (conn *Conn) ContainerSSH(ctx context.Context, options arvados.ContainerSSH // the controller. The caller should connect the returned resp.Conn to // a client-side yamux session. func (conn *Conn) ContainerGatewayTunnel(ctx context.Context, options arvados.ContainerGatewayTunnelOptions) (tunnelconn arvados.ConnectionResponse, err error) { - u, err := conn.baseURL.Parse("/" + strings.Replace(arvados.EndpointContainerGatewayTunnel.Path, "{uuid}", options.UUID, -1)) + u, err := conn.baseURL.Parse("/" + strings.Replace(arvados.EndpointContainerGatewayTunnelCompat.Path, "{uuid}", options.UUID, -1)) if err != nil { err = fmt.Errorf("url.Parse: %w", err) return diff --git a/sdk/go/arvados/api.go b/sdk/go/arvados/api.go index 4d67b5ad4d..861b8e6ceb 100644 --- a/sdk/go/arvados/api.go +++ b/sdk/go/arvados/api.go @@ -50,8 +50,10 @@ var ( EndpointContainerLock = APIEndpoint{"POST", "arvados/v1/containers/{uuid}/lock", ""} EndpointContainerUnlock = APIEndpoint{"POST", "arvados/v1/containers/{uuid}/unlock", ""} EndpointContainerLog = APIEndpoint{"GET", "arvados/v1/containers/{uuid}/log{path:|/.*}", ""} - EndpointContainerSSH = APIEndpoint{"POST", "arvados/v1/connect/{uuid}/ssh", ""} // move to /containers after #17014 fixes routing - EndpointContainerGatewayTunnel = APIEndpoint{"POST", "arvados/v1/connect/{uuid}/gateway_tunnel", ""} // move to /containers after #17014 fixes routing + EndpointContainerSSH = APIEndpoint{"POST", "arvados/v1/containers/{uuid}/ssh", ""} + EndpointContainerSSHCompat = APIEndpoint{"POST", "arvados/v1/connect/{uuid}/ssh", ""} // for compatibility with arvados <2.7 + EndpointContainerGatewayTunnel = APIEndpoint{"POST", "arvados/v1/containers/{uuid}/gateway_tunnel", ""} + EndpointContainerGatewayTunnelCompat = APIEndpoint{"POST", "arvados/v1/connect/{uuid}/gateway_tunnel", ""} // for compatibility with arvados <2.7 EndpointContainerRequestCreate = APIEndpoint{"POST", "arvados/v1/container_requests", "container_request"} EndpointContainerRequestUpdate = APIEndpoint{"PATCH", "arvados/v1/container_requests/{uuid}", "container_request"} EndpointContainerRequestGet = APIEndpoint{"GET", "arvados/v1/container_requests/{uuid}", ""} -- 2.30.2