fix proxy bug (#2146)
This commit is contained in:
@@ -39,6 +39,8 @@ import (
|
|||||||
const proxyURLFormat = "/api/v1/namespaces/kubesphere-system/services/:ks-apiserver:/proxy%s"
|
const proxyURLFormat = "/api/v1/namespaces/kubesphere-system/services/:ks-apiserver:/proxy%s"
|
||||||
|
|
||||||
// Dispatcher defines how to forward request to designated cluster based on cluster name
|
// Dispatcher defines how to forward request to designated cluster based on cluster name
|
||||||
|
// This should only be used in host cluster when multicluster mode enabled, use in any other cases may cause
|
||||||
|
// unexpected behavior
|
||||||
type Dispatcher interface {
|
type Dispatcher interface {
|
||||||
Dispatch(w http.ResponseWriter, req *http.Request, handler http.Handler)
|
Dispatch(w http.ResponseWriter, req *http.Request, handler http.Handler)
|
||||||
}
|
}
|
||||||
@@ -127,17 +129,10 @@ func (c *clusterDispatch) Dispatch(w http.ResponseWriter, req *http.Request, han
|
|||||||
|
|
||||||
transport := http.DefaultTransport
|
transport := http.DefaultTransport
|
||||||
|
|
||||||
|
// change request host to actually cluster hosts
|
||||||
u := *req.URL
|
u := *req.URL
|
||||||
u.Path = strings.Replace(u.Path, fmt.Sprintf("/clusters/%s", info.Cluster), "", 1)
|
u.Path = strings.Replace(u.Path, fmt.Sprintf("/clusters/%s", info.Cluster), "", 1)
|
||||||
|
|
||||||
// change request host to actually cluster hosts
|
|
||||||
if info.IsKubernetesRequest {
|
|
||||||
u.Host = innCluster.kubernetesURL.Host
|
|
||||||
u.Scheme = innCluster.kubernetesURL.Scheme
|
|
||||||
} else {
|
|
||||||
u.Host = innCluster.kubesphereURL.Host
|
|
||||||
u.Scheme = innCluster.kubesphereURL.Scheme
|
|
||||||
|
|
||||||
// if cluster connection is direct and kubesphere apiserver endpoint is empty
|
// if cluster connection is direct and kubesphere apiserver endpoint is empty
|
||||||
// we use kube-apiserver proxy way
|
// we use kube-apiserver proxy way
|
||||||
if cluster.Spec.Connection.Type == clusterv1alpha1.ConnectionTypeDirect &&
|
if cluster.Spec.Connection.Type == clusterv1alpha1.ConnectionTypeDirect &&
|
||||||
@@ -155,7 +150,11 @@ func (c *clusterDispatch) Dispatch(w http.ResponseWriter, req *http.Request, han
|
|||||||
// designated cluster kube-apiserver, then copy req.Header['X-KubeSphere-Authorization'] to
|
// designated cluster kube-apiserver, then copy req.Header['X-KubeSphere-Authorization'] to
|
||||||
// req.Header['Authorization'] before authentication.
|
// req.Header['Authorization'] before authentication.
|
||||||
req.Header.Set("X-KubeSphere-Authorization", req.Header.Get("Authorization"))
|
req.Header.Set("X-KubeSphere-Authorization", req.Header.Get("Authorization"))
|
||||||
}
|
} else {
|
||||||
|
// everything else goes to ks-apiserver, since our ks-apiserver has the ability to proxy kube-apiserver requests
|
||||||
|
|
||||||
|
u.Host = innCluster.kubesphereURL.Host
|
||||||
|
u.Scheme = innCluster.kubesphereURL.Scheme
|
||||||
}
|
}
|
||||||
|
|
||||||
httpProxy := proxy.NewUpgradeAwareHandler(&u, transport, false, false, c)
|
httpProxy := proxy.NewUpgradeAwareHandler(&u, transport, false, false, c)
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ func (h *handler) ValidateCluster(request *restful.Request, response *restful.Re
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = validateKubeSphereAPIServer(cluster.Spec.Connection.KubeSphereAPIEndpoint)
|
_, err = validateKubeSphereAPIServer(cluster.Spec.Connection.KubeSphereAPIEndpoint, cluster.Spec.Connection.KubeConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleBadRequest(response, request, fmt.Errorf("unable validate kubesphere endpoint, %v", err))
|
api.HandleBadRequest(response, request, fmt.Errorf("unable validate kubesphere endpoint, %v", err))
|
||||||
return
|
return
|
||||||
@@ -286,16 +286,36 @@ func loadKubeConfigFromBytes(kubeconfig []byte) (*rest.Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validateKubeSphereAPIServer uses version api to check the accessibility
|
// validateKubeSphereAPIServer uses version api to check the accessibility
|
||||||
func validateKubeSphereAPIServer(ksEndpoint string) (*version.Info, error) {
|
// If ksEndpoint is empty, use
|
||||||
_, err := url.Parse(ksEndpoint)
|
func validateKubeSphereAPIServer(ksEndpoint string, kubeconfig []byte) (*version.Info, error) {
|
||||||
if err != nil {
|
if len(ksEndpoint) == 0 && len(kubeconfig) == 0 {
|
||||||
return nil, err
|
return nil, fmt.Errorf("neither kubesphere api endpoint nor kubeconfig was provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
client := http.Client{
|
||||||
|
Timeout: defaultTimeout,
|
||||||
}
|
}
|
||||||
|
|
||||||
path := fmt.Sprintf("%s/kapis/version", ksEndpoint)
|
path := fmt.Sprintf("%s/kapis/version", ksEndpoint)
|
||||||
|
|
||||||
client := http.Client{
|
if len(ksEndpoint) != 0 {
|
||||||
Timeout: defaultTimeout,
|
_, err := url.Parse(ksEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
config, err := loadKubeConfigFromBytes(kubeconfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
transport, err := rest.TransportFor(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
client.Transport = transport
|
||||||
|
path = fmt.Sprintf("%s/api/v1/namespaces/kubesphere-system/services/:ks-apiserver:/proxy/kapis/version", config.Host)
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := client.Get(path)
|
response, err := client.Get(path)
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ func TestValidateKubeSphereEndpoint(t *testing.T) {
|
|||||||
svr := httptest.NewServer(http.HandlerFunc(endpoint))
|
svr := httptest.NewServer(http.HandlerFunc(endpoint))
|
||||||
defer svr.Close()
|
defer svr.Close()
|
||||||
|
|
||||||
got, err := validateKubeSphereAPIServer(svr.URL)
|
got, err := validateKubeSphereAPIServer(svr.URL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user