karmada/pkg/registry/search/storage/proxy.go

85 lines
2.4 KiB
Go

package storage
import (
"context"
"fmt"
"net/http"
"path"
"k8s.io/apimachinery/pkg/runtime"
genericrequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/klog/v2"
searchapis "github.com/karmada-io/karmada/pkg/apis/search"
"github.com/karmada-io/karmada/pkg/search/proxy"
)
var proxyMethods = []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"}
// ProxyingREST implements a RESTStorage for proxying resource.
type ProxyingREST struct {
ctl *proxy.Controller
}
var _ rest.Scoper = &ProxyingREST{}
var _ rest.Storage = &ProxyingREST{}
var _ rest.Connecter = &ProxyingREST{}
var _ rest.SingularNameProvider = &ProxyingREST{}
// NewProxyingREST returns a RESTStorage object that will work against search.
func NewProxyingREST(ctl *proxy.Controller) *ProxyingREST {
return &ProxyingREST{
ctl: ctl,
}
}
// New return empty Proxy object.
func (r *ProxyingREST) New() runtime.Object {
return &searchapis.Proxying{}
}
// NamespaceScoped returns false because Proxy is not namespaced.
func (r *ProxyingREST) NamespaceScoped() bool {
return false
}
// ConnectMethods returns the list of HTTP methods handled by Connect.
func (r *ProxyingREST) ConnectMethods() []string {
return proxyMethods
}
// NewConnectOptions returns an empty options object that will be used to pass options to the Connect method.
func (r *ProxyingREST) NewConnectOptions() (runtime.Object, bool, string) {
return nil, true, ""
}
// Connect returns a handler for proxy.
func (r *ProxyingREST) Connect(ctx context.Context, _ string, _ runtime.Object, responder rest.Responder) (http.Handler, error) {
info, ok := genericrequest.RequestInfoFrom(ctx)
if !ok {
return nil, fmt.Errorf("no RequestInfo found in the context")
}
if len(info.Parts) < 2 {
return nil, fmt.Errorf("invalid requestInfo parts: %v", info.Parts)
}
// For example, the whole request URL is /apis/search.karmada.io/v1alpha1/proxying/foo/proxy/api/v1/nodes
// info.Parts is [proxying foo proxy api v1 nodes], so proxyPath is /api/v1/nodes
proxyPath := "/" + path.Join(info.Parts[3:]...)
klog.V(4).Infof("ProxyingREST connect %v", proxyPath)
return r.ctl.Connect(ctx, proxyPath, responder)
}
// Destroy cleans up its resources on shutdown.
func (r *ProxyingREST) Destroy() {
// Given no underlying store, so we don't
// need to destroy anything.
}
// GetSingularName returns singular name of resources
func (r *ProxyingREST) GetSingularName() string {
return "proxying"
}