mirror of
https://github.com/rancher/steve.git
synced 2025-04-28 03:10:32 +00:00
Add k8s proxy
This commit is contained in:
parent
24e6192504
commit
71faff9d2a
15
pkg/proxy/error.go
Normal file
15
pkg/proxy/error.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package proxy
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
var (
|
||||||
|
er = &errorResponder{}
|
||||||
|
)
|
||||||
|
|
||||||
|
type errorResponder struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *errorResponder) Error(w http.ResponseWriter, req *http.Request, err error) {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
w.Write([]byte(err.Error()))
|
||||||
|
}
|
101
pkg/proxy/proxy.go
Normal file
101
pkg/proxy/proxy.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/rancher/wrangler/pkg/kubeconfig"
|
||||||
|
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||||
|
"k8s.io/apimachinery/pkg/util/proxy"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
|
"k8s.io/client-go/transport"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Mostly copied from "kubectl proxy" code
|
||||||
|
func HandlerFromConfig(prefix, kubeConfig string) (http.Handler, error) {
|
||||||
|
loader := kubeconfig.GetInteractiveClientConfig(kubeConfig)
|
||||||
|
cfg, err := loader.ClientConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Handler(prefix, cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mostly copied from "kubectl proxy" code
|
||||||
|
func Handler(prefix string, cfg *rest.Config) (http.Handler, error) {
|
||||||
|
host := cfg.Host
|
||||||
|
if !strings.HasSuffix(host, "/") {
|
||||||
|
host = host + "/"
|
||||||
|
}
|
||||||
|
target, err := url.Parse(host)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
transport, err := rest.TransportFor(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
upgradeTransport, err := makeUpgradeTransport(cfg, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy := proxy.NewUpgradeAwareHandler(target, transport, false, false, er)
|
||||||
|
proxy.UpgradeTransport = upgradeTransport
|
||||||
|
proxy.UseRequestLocation = true
|
||||||
|
|
||||||
|
if len(prefix) > 2 {
|
||||||
|
return stripLeaveSlash(prefix, proxy), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return proxy, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// like http.StripPrefix, but always leaves an initial slash. (so that our
|
||||||
|
// regexps will work.)
|
||||||
|
func stripLeaveSlash(prefix string, h http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
fmt.Println(req.Method, req.URL.Path)
|
||||||
|
p := strings.TrimPrefix(req.URL.Path, prefix)
|
||||||
|
if len(p) >= len(req.URL.Path) {
|
||||||
|
http.NotFound(w, req)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(p) > 0 && p[:1] != "/" {
|
||||||
|
p = "/" + p
|
||||||
|
}
|
||||||
|
req.URL.Path = p
|
||||||
|
h.ServeHTTP(w, req)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeUpgradeTransport(config *rest.Config, keepalive time.Duration) (proxy.UpgradeRequestRoundTripper, error) {
|
||||||
|
transportConfig, err := config.TransportConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tlsConfig, err := transport.TLSConfigFor(transportConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rt := utilnet.SetOldTransportDefaults(&http.Transport{
|
||||||
|
TLSClientConfig: tlsConfig,
|
||||||
|
DialContext: (&net.Dialer{
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
KeepAlive: keepalive,
|
||||||
|
}).DialContext,
|
||||||
|
})
|
||||||
|
|
||||||
|
upgrader, err := transport.HTTPWrappersForConfig(transportConfig, proxy.MirrorRequest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return proxy.NewUpgradeRequestRoundTripper(rt, upgrader), nil
|
||||||
|
}
|
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/rancher/naok/pkg/accesscontrol"
|
"github.com/rancher/naok/pkg/accesscontrol"
|
||||||
"github.com/rancher/naok/pkg/attributes"
|
"github.com/rancher/naok/pkg/attributes"
|
||||||
|
k8sproxy "github.com/rancher/naok/pkg/proxy"
|
||||||
"github.com/rancher/naok/pkg/schemas"
|
"github.com/rancher/naok/pkg/schemas"
|
||||||
"github.com/rancher/norman/pkg/api"
|
"github.com/rancher/norman/pkg/api"
|
||||||
"github.com/rancher/norman/pkg/store/proxy"
|
"github.com/rancher/norman/pkg/store/proxy"
|
||||||
@ -13,9 +14,14 @@ import (
|
|||||||
"github.com/rancher/norman/pkg/types"
|
"github.com/rancher/norman/pkg/types"
|
||||||
"github.com/rancher/norman/pkg/urlbuilder"
|
"github.com/rancher/norman/pkg/urlbuilder"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newAPIServer(cf proxy.ClientGetter, as *accesscontrol.AccessStore, sf schemas.SchemaFactory) http.Handler {
|
func newAPIServer(cfg *rest.Config, cf proxy.ClientGetter, as *accesscontrol.AccessStore, sf schemas.SchemaFactory) (http.Handler, error) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
a := &apiServer{
|
a := &apiServer{
|
||||||
Router: mux.NewRouter(),
|
Router: mux.NewRouter(),
|
||||||
cf: cf,
|
cf: cf,
|
||||||
@ -23,10 +29,15 @@ func newAPIServer(cf proxy.ClientGetter, as *accesscontrol.AccessStore, sf schem
|
|||||||
sf: sf,
|
sf: sf,
|
||||||
server: api.NewAPIServer(),
|
server: api.NewAPIServer(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.Router.NotFoundHandler, err = k8sproxy.Handler("/", cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
a.Router.StrictSlash(true)
|
a.Router.StrictSlash(true)
|
||||||
a.server.AccessControl = accesscontrol.NewAccessControl()
|
a.server.AccessControl = accesscontrol.NewAccessControl()
|
||||||
a.routes()
|
return a, a.routes()
|
||||||
return a
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type apiServer struct {
|
type apiServer struct {
|
||||||
|
@ -3,16 +3,15 @@ package server
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/rancher/naok/pkg/attributes"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/rancher/naok/pkg/attributes"
|
||||||
"github.com/rancher/norman/pkg/types"
|
"github.com/rancher/norman/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
type APIFunc func(*types.APIRequest)
|
type APIFunc func(*types.APIRequest)
|
||||||
|
|
||||||
func (a *apiServer) routes() {
|
func (a *apiServer) routes() error {
|
||||||
a.Path("/v1/{type:schemas}").Handler(a.handle(nil))
|
a.Path("/v1/{type:schemas}").Handler(a.handle(nil))
|
||||||
a.Path("/v1/{type:schemas}/{name}").Handler(a.handle(nil))
|
a.Path("/v1/{type:schemas}/{name}").Handler(a.handle(nil))
|
||||||
a.Path("/v1/{type:subscribe}").Handler(a.handle(nil))
|
a.Path("/v1/{type:subscribe}").Handler(a.handle(nil))
|
||||||
@ -23,6 +22,8 @@ func (a *apiServer) routes() {
|
|||||||
|
|
||||||
a.Path("/v1/apis/{group}/{version}/{resource}").Handler(a.handle(a.k8sAPI))
|
a.Path("/v1/apis/{group}/{version}/{resource}").Handler(a.handle(a.k8sAPI))
|
||||||
a.Path("/v1/apis/{group}/{version}/{resource}/{nameorns}").Handler(a.handle(a.k8sAPI))
|
a.Path("/v1/apis/{group}/{version}/{resource}/{nameorns}").Handler(a.handle(a.k8sAPI))
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *apiServer) handle(apiFunc APIFunc) http.Handler {
|
func (a *apiServer) handle(apiFunc APIFunc) http.Handler {
|
||||||
|
Loading…
Reference in New Issue
Block a user