diff --git a/cmd/ks-apiserver/app/server.go b/cmd/ks-apiserver/app/server.go index 48b4be1f7..c02003e16 100644 --- a/cmd/ks-apiserver/app/server.go +++ b/cmd/ks-apiserver/app/server.go @@ -29,8 +29,6 @@ import ( "kubesphere.io/kubesphere/pkg/utils/signals" "kubesphere.io/kubesphere/pkg/utils/term" "kubesphere.io/kubesphere/pkg/version" - - tracing "kubesphere.io/kubesphere/pkg/kapis/servicemesh/metrics/v1alpha2" ) func NewAPIServerCommand() *cobra.Command { @@ -90,8 +88,6 @@ cluster's shared state through which all other components interact.`, func Run(s *options.ServerRunOptions, stopCh <-chan struct{}) error { - initializeServicemeshConfig(s) - apiserver, err := s.NewAPIServer(stopCh) if err != nil { return err @@ -104,15 +100,3 @@ func Run(s *options.ServerRunOptions, stopCh <-chan struct{}) error { return apiserver.Run(stopCh) } - -func initializeServicemeshConfig(s *options.ServerRunOptions) { - // Config jaeger query endpoint address - if s.ServiceMeshOptions != nil && len(s.ServiceMeshOptions.JaegerQueryHost) != 0 { - tracing.JaegerQueryUrl = s.ServiceMeshOptions.JaegerQueryHost - } - - // Set the kiali query endpoint address - if s.ServiceMeshOptions != nil && len(s.ServiceMeshOptions.KialiQueryHost) != 0 { - tracing.KialiQueryUrl = s.ServiceMeshOptions.KialiQueryHost - } -} diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go index 632365d0f..d0a460aa5 100644 --- a/pkg/apiserver/apiserver.go +++ b/pkg/apiserver/apiserver.go @@ -254,7 +254,7 @@ func (s *APIServer) installKubeSphereAPIs() { auth.NewLoginRecorder(s.KubernetesClient.KubeSphere(), s.InformerFactory.KubeSphereSharedInformerFactory().Iam().V1alpha2().Users().Lister()), s.Config.AuthenticationOptions)) - urlruntime.Must(servicemeshv1alpha2.AddToContainer(s.container)) + urlruntime.Must(servicemeshv1alpha2.AddToContainer(s.Config.ServiceMeshOptions, s.container, s.KubernetesClient.Kubernetes(), s.CacheClient)) urlruntime.Must(networkv1alpha2.AddToContainer(s.container, s.Config.NetworkOptions.WeaveScopeHost)) urlruntime.Must(devopsv1alpha2.AddToContainer(s.container, s.InformerFactory.KubeSphereSharedInformerFactory(), diff --git a/pkg/kapis/servicemesh/metrics/install/install.go b/pkg/kapis/servicemesh/metrics/install/install.go index e17c6f179..c524d569b 100644 --- a/pkg/kapis/servicemesh/metrics/install/install.go +++ b/pkg/kapis/servicemesh/metrics/install/install.go @@ -29,5 +29,5 @@ func init() { } func Install(c *restful.Container) { - urlruntime.Must(v1alpha2.AddToContainer(c)) + urlruntime.Must(v1alpha2.AddToContainer(nil, c, nil, nil)) } diff --git a/pkg/kapis/servicemesh/metrics/v1alpha2/handler.go b/pkg/kapis/servicemesh/metrics/v1alpha2/handler.go index fb1142d35..ea27e23f9 100644 --- a/pkg/kapis/servicemesh/metrics/v1alpha2/handler.go +++ b/pkg/kapis/servicemesh/metrics/v1alpha2/handler.go @@ -17,44 +17,67 @@ limitations under the License. package v1alpha2 import ( + "context" + "errors" "fmt" "io/ioutil" "net/http" "github.com/emicklei/go-restful" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" "k8s.io/klog" "kubesphere.io/kubesphere/pkg/api" + "kubesphere.io/kubesphere/pkg/simple/client/cache" + "kubesphere.io/kubesphere/pkg/simple/client/kiali" + "kubesphere.io/kubesphere/pkg/simple/client/servicemesh" ) -// default jaeger query api endpoint address -var JaegerQueryUrl = "http://jaeger-query.istio-system.svc:16686" +const ( + KubesphereNamespace = "kubesphere-system" + KubeSphereServiceAccount = "kubesphere" +) -/* -Use Kiali API directly if config existed in configmap. -Such as: -kubectl -n kubesphere-system get cm kubesphere-config -oyaml -... -kialiQueryHost: http://kiali.istio-system:20001 -... +type Handler struct { + opt *servicemesh.Options + client *kiali.Client +} -Otherwise, use the API provided by kiali code. - -Announce: The API provided by kiali code will deprecated in the future. -*/ - -var KialiQueryUrl string +func NewHandler(o *servicemesh.Options, client kubernetes.Interface, cache cache.Interface) *Handler { + if o != nil && o.KialiQueryHost != "" { + sa, err := client.CoreV1().ServiceAccounts(KubesphereNamespace).Get(context.TODO(), KubeSphereServiceAccount, metav1.GetOptions{}) + if err == nil { + secret, err := client.CoreV1().Secrets(KubesphereNamespace).Get(context.TODO(), sa.Secrets[0].Name, metav1.GetOptions{}) + if err == nil { + return &Handler{ + opt: o, + client: kiali.NewDefaultClient( + cache, + string(secret.Data["token"]), + o.KialiQueryHost, + ), + } + } + klog.Warningf("get ServiceAccount's Secret failed %v", err) + } + klog.Warningf("get ServiceAccount failed %v", err) + } + // Handler should return Status code 400, instead of crash ks-apiserver + // when no client is defined. + return &Handler{opt: o, client: nil} +} // Get app metrics -func getAppMetrics(request *restful.Request, response *restful.Response) { +func (h *Handler) GetAppMetrics(request *restful.Request, response *restful.Response) { namespace := request.PathParameter("namespace") app := request.PathParameter("app") - url := fmt.Sprintf("%s/kiali/api/namespaces/%s/apps/%s/metrics?%s", KialiQueryUrl, namespace, app, request.Request.URL.RawQuery) - getData(response, url) + url := fmt.Sprintf("/kiali/api/namespaces/%s/apps/%s/metrics?%s", namespace, app, request.Request.URL.RawQuery) + h.getData(response, url) } // Get workload metrics -func getWorkloadMetrics(request *restful.Request, response *restful.Response) { +func (h *Handler) GetWorkloadMetrics(request *restful.Request, response *restful.Response) { namespace := request.PathParameter("namespace") workload := request.PathParameter("workload") @@ -62,77 +85,114 @@ func getWorkloadMetrics(request *restful.Request, response *restful.Response) { request.Request.URL.RawQuery = fmt.Sprintf("%s&namespaces=%s&workload=%s", request.Request.URL.RawQuery, namespace, workload) } - url := fmt.Sprintf("%s/kiali/api/namespaces/%s/workloads/%s/metrics?%s", KialiQueryUrl, namespace, workload, request.Request.URL.RawQuery) - getData(response, url) + url := fmt.Sprintf("/kiali/api/namespaces/%s/workloads/%s/metrics?%s", namespace, workload, request.Request.URL.RawQuery) + h.getData(response, url) } // Get service metrics -func getServiceMetrics(request *restful.Request, response *restful.Response) { +func (h *Handler) GetServiceMetrics(request *restful.Request, response *restful.Response) { namespace := request.PathParameter("namespace") service := request.PathParameter("service") - url := fmt.Sprintf("%s/kiali/api/namespaces/%s/services/%s/metrics?%s", KialiQueryUrl, namespace, service, request.Request.URL.RawQuery) - getData(response, url) + url := fmt.Sprintf("/kiali/api/namespaces/%s/services/%s/metrics?%s", namespace, service, request.Request.URL.RawQuery) + h.getData(response, url) } // Get namespace metrics -func getNamespaceMetrics(request *restful.Request, response *restful.Response) { +func (h *Handler) GetNamespaceMetrics(request *restful.Request, response *restful.Response) { namespace := request.PathParameter("namespace") - url := fmt.Sprintf("%s/kiali/api/namespaces/%s/metrics?%s", KialiQueryUrl, namespace, request.Request.URL.RawQuery) - getData(response, url) + url := fmt.Sprintf("/kiali/api/namespaces/%s/metrics?%s", namespace, request.Request.URL.RawQuery) + h.getData(response, url) } // Get service graph for namespace -func getNamespaceGraph(request *restful.Request, response *restful.Response) { +func (h *Handler) GetNamespaceGraph(request *restful.Request, response *restful.Response) { namespace := request.PathParameter("namespace") if len(namespace) > 0 { request.Request.URL.RawQuery = fmt.Sprintf("%s&namespaces=%s", request.Request.URL.RawQuery, namespace) } - url := fmt.Sprintf("%s/kiali/api/namespaces/graph?%s", KialiQueryUrl, request.Request.URL.RawQuery) - getData(response, url) + url := fmt.Sprintf("/kiali/api/namespaces/graph?%s", request.Request.URL.RawQuery) + h.getData(response, url) } // Get namespace health -func getNamespaceHealth(request *restful.Request, response *restful.Response) { +func (h *Handler) GetNamespaceHealth(request *restful.Request, response *restful.Response) { namespace := request.PathParameter("namespace") - url := fmt.Sprintf("%s/kiali/api/namespaces/%s/health?%s", KialiQueryUrl, namespace, request.Request.URL.RawQuery) - getData(response, url) + url := fmt.Sprintf("/kiali/api/namespaces/%s/health?%s", namespace, request.Request.URL.RawQuery) + h.getData(response, url) } // Get workload health -func getWorkloadHealth(request *restful.Request, response *restful.Response) { +func (h *Handler) GetWorkloadHealth(request *restful.Request, response *restful.Response) { namespace := request.PathParameter("namespace") workload := request.PathParameter("workload") - url := fmt.Sprintf("%s/kiali/api/namespaces/%s/workloads/%s/health?%s", KialiQueryUrl, namespace, workload, request.Request.URL.RawQuery) - getData(response, url) + url := fmt.Sprintf("/kiali/api/namespaces/%s/workloads/%s/health?%s", namespace, workload, request.Request.URL.RawQuery) + h.getData(response, url) } // Get app health -func getAppHealth(request *restful.Request, response *restful.Response) { +func (h *Handler) GetAppHealth(request *restful.Request, response *restful.Response) { namespace := request.PathParameter("namespace") app := request.PathParameter("app") - url := fmt.Sprintf("%s/kiali/api/namespaces/%s/apps/%s/health?%s", KialiQueryUrl, namespace, app, request.Request.URL.RawQuery) - getData(response, url) + url := fmt.Sprintf("/kiali/api/namespaces/%s/apps/%s/health?%s", namespace, app, request.Request.URL.RawQuery) + h.getData(response, url) } // Get service health -func getServiceHealth(request *restful.Request, response *restful.Response) { +func (h *Handler) GetServiceHealth(request *restful.Request, response *restful.Response) { namespace := request.PathParameter("namespace") service := request.PathParameter("service") - url := fmt.Sprintf("%s/kiali/api/namespaces/%s/services/%s/health?%s", KialiQueryUrl, namespace, service, request.Request.URL.RawQuery) - getData(response, url) + url := fmt.Sprintf("/kiali/api/namespaces/%s/services/%s/health?%s", namespace, service, request.Request.URL.RawQuery) + h.getData(response, url) } -func getServiceTracing(request *restful.Request, response *restful.Response) { +func (h *Handler) GetServiceTracing(request *restful.Request, response *restful.Response) { namespace := request.PathParameter("namespace") service := request.PathParameter("service") serviceName := fmt.Sprintf("%s.%s", service, namespace) - url := fmt.Sprintf("%s/api/traces?%s&service=%s", JaegerQueryUrl, request.Request.URL.RawQuery, serviceName) - getData(response, url) + url := fmt.Sprintf("%s/api/traces?%s&service=%s", h.opt.JaegerQueryHost, request.Request.URL.RawQuery, serviceName) + h.getJaegerData(response, url) } -func getData(response *restful.Response, url string) { +func (h *Handler) getData(response *restful.Response, url string) { + + if h.client == nil { + err := errors.New("kiali url is not defined") + api.HandleInternalError(response, nil, err) + return + } + + resp, err := h.client.Get(url) + klog.V(4).Infof("Proxy request to %s", url) + + if err != nil { + klog.Errorf("query url %s failed with err %v", url, err) + api.HandleInternalError(response, nil, err) + return + } + + body, err := ioutil.ReadAll(resp.Body) + defer resp.Body.Close() + + if err != nil { + klog.Errorf("read response error : %v", err) + api.HandleInternalError(response, nil, err) + return + } + + // need to set header for proper response + response.Header().Set("Content-Type", "application/json") + _, err = response.Write(body) + + if err != nil { + klog.Errorf("write response failed %v", err) + } +} + +// TODO: to be removed with a security Jaeger client +func (h *Handler) getJaegerData(response *restful.Response, url string) { + resp, err := http.Get(url) klog.V(4).Infof("Proxy request to %s", url) diff --git a/pkg/kapis/servicemesh/metrics/v1alpha2/register.go b/pkg/kapis/servicemesh/metrics/v1alpha2/register.go index 211bee4ce..fae7c1536 100644 --- a/pkg/kapis/servicemesh/metrics/v1alpha2/register.go +++ b/pkg/kapis/servicemesh/metrics/v1alpha2/register.go @@ -22,24 +22,29 @@ import ( "github.com/emicklei/go-restful" restfulspec "github.com/emicklei/go-restful-openapi" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/kubernetes" "kubesphere.io/kubesphere/pkg/apiserver/runtime" + "kubesphere.io/kubesphere/pkg/simple/client/cache" + "kubesphere.io/kubesphere/pkg/simple/client/servicemesh" ) const groupName = "servicemesh.kubesphere.io" var GroupVersion = schema.GroupVersion{Group: groupName, Version: "v1alpha2"} -func AddToContainer(c *restful.Container) error { +func AddToContainer(o *servicemesh.Options, c *restful.Container, client kubernetes.Interface, cache cache.Interface) error { tags := []string{"ServiceMesh"} webservice := runtime.NewWebService(GroupVersion) + h := NewHandler(o, client, cache) + // Get service metrics // GET /namespaces/{namespace}/services/{service}/metrics webservice.Route(webservice.GET("/namespaces/{namespace}/services/{service}/metrics"). - To(getServiceMetrics). + To(h.GetServiceMetrics). Metadata(restfulspec.KeyOpenAPITags, tags). Doc("Get service metrics from a specific namespace"). Param(webservice.PathParameter("namespace", "name of the namespace")). @@ -59,7 +64,7 @@ func AddToContainer(c *restful.Container) error { // Get app metrics // Get /namespaces/{namespace}/apps/{app}/metrics webservice.Route(webservice.GET("/namespaces/{namespace}/apps/{app}/metrics"). - To(getAppMetrics). + To(h.GetAppMetrics). Metadata(restfulspec.KeyOpenAPITags, tags). Doc("Get app metrics from a specific namespace"). Param(webservice.PathParameter("namespace", "name of the namespace")). @@ -79,7 +84,7 @@ func AddToContainer(c *restful.Container) error { // Get workload metrics // Get /namespaces/{namespace}/workloads/{workload}/metrics webservice.Route(webservice.GET("/namespaces/{namespace}/workloads/{workload}/metrics"). - To(getWorkloadMetrics). + To(h.GetWorkloadMetrics). Metadata(restfulspec.KeyOpenAPITags, tags). Doc("Get workload metrics from a specific namespace"). Param(webservice.PathParameter("namespace", "name of the namespace").Required(true)). @@ -99,7 +104,7 @@ func AddToContainer(c *restful.Container) error { // Get namespace metrics // Get /namespaces/{namespace}/metrics webservice.Route(webservice.GET("/namespaces/{namespace}/metrics"). - To(getNamespaceMetrics). + To(h.GetNamespaceMetrics). Metadata(restfulspec.KeyOpenAPITags, tags). Doc("Get metrics from a specific namespace"). Param(webservice.PathParameter("namespace", "name of the namespace").Required(true)). @@ -118,7 +123,7 @@ func AddToContainer(c *restful.Container) error { // Get namespace graph // Get /namespaces/{namespace}/graph webservice.Route(webservice.GET("/namespaces/{namespace}/graph"). - To(getNamespaceGraph). + To(h.GetNamespaceGraph). Metadata(restfulspec.KeyOpenAPITags, tags). Doc("Get service graph for a specific namespace"). Param(webservice.PathParameter("namespace", "name of a namespace").Required(true)). @@ -133,7 +138,7 @@ func AddToContainer(c *restful.Container) error { // Get namespace health webservice.Route(webservice.GET("/namespaces/{namespace}/health"). - To(getNamespaceHealth). + To(h.GetNamespaceHealth). Metadata(restfulspec.KeyOpenAPITags, tags). Doc("Get app/service/workload health of a namespace"). Param(webservice.PathParameter("namespace", "name of a namespace").Required(true)). @@ -145,7 +150,7 @@ func AddToContainer(c *restful.Container) error { // Get workloads health webservice.Route(webservice.GET("/namespaces/{namespace}/workloads/{workload}/health"). - To(getWorkloadHealth). + To(h.GetWorkloadHealth). Metadata(restfulspec.KeyOpenAPITags, tags). Doc("Get workload health"). Param(webservice.PathParameter("namespace", "name of a namespace").Required(true)). @@ -156,7 +161,7 @@ func AddToContainer(c *restful.Container) error { // Get app health webservice.Route(webservice.GET("/namespaces/{namespace}/apps/{app}/health"). - To(getAppHealth). + To(h.GetAppHealth). Metadata(restfulspec.KeyOpenAPITags, tags). Doc("Get app health"). Param(webservice.PathParameter("namespace", "name of a namespace").Required(true)). @@ -167,7 +172,7 @@ func AddToContainer(c *restful.Container) error { // Get service health webservice.Route(webservice.GET("/namespaces/{namespace}/services/{service}/health"). - To(getServiceHealth). + To(h.GetServiceHealth). Metadata(restfulspec.KeyOpenAPITags, tags). Doc("Get service health"). Param(webservice.PathParameter("namespace", "name of a namespace").Required(true)). @@ -178,7 +183,7 @@ func AddToContainer(c *restful.Container) error { // Get service tracing webservice.Route(webservice.GET("/namespaces/{namespace}/services/{service}/traces"). - To(getServiceTracing). + To(h.GetServiceTracing). Doc("Get tracing of a service, should have servicemesh enabled first"). Metadata(restfulspec.KeyOpenAPITags, tags). Param(webservice.PathParameter("namespace", "namespace of service").Required(true)). diff --git a/pkg/simple/client/kiali/client.go b/pkg/simple/client/kiali/client.go new file mode 100644 index 000000000..c58db91b5 --- /dev/null +++ b/pkg/simple/client/kiali/client.go @@ -0,0 +1,174 @@ +/* +Copyright 2021 KubeSphere Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kiali + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "time" + + "kubesphere.io/kubesphere/pkg/simple/client/cache" +) + +// Kiali token Response +type TokenResponse struct { + // The username for the token + Username string `json:"username"` + // The authentication token + Token string `json:"token"` + // The expired time for the token + ExpiresOn string `json:"expiresOn"` +} + +// Kiali Authentication Strategy +type Strategy string + +const ( + AuthStrategyToken Strategy = "token" + AuthStrategyAnonymous Strategy = "anonymous" +) + +const ( + AuthURL = "%s/kiali/api/authenticate" + KialiTokenCacheKey = "kubesphere:kubesphere:kiali" +) + +type HttpClient interface { + // Do is an interface of http client Do method, + // that sends an HTTP request and returns an HTTP response. + Do(req *http.Request) (*http.Response, error) + + // PostForm is an interface of http client PostForm method, + // that issues a POST to the specified URL. + PostForm(url string, data url.Values) (resp *http.Response, err error) +} + +// Kiali Client +type Client struct { + Strategy Strategy + cache cache.Interface + client HttpClient + ServiceToken string + Host string +} + +// NewClient creates an instance of Kiali Client. +func NewClient(strategy Strategy, + cache cache.Interface, + client HttpClient, + serviceToken string, + host string) *Client { + + return &Client{ + Strategy: strategy, + cache: cache, + client: client, + ServiceToken: serviceToken, + Host: host, + } + +} + +// NewDefaultClient creates an instance of Kiali Client with default http settings. +func NewDefaultClient( + cache cache.Interface, + serviceToken string, + host string) *Client { + return &Client{ + Strategy: AuthStrategyToken, + cache: cache, + client: &http.Client{}, + ServiceToken: serviceToken, + Host: host, + } +} + +// authenticate sends auth request with Kubernetes token and +// get Kiali token from the response. +func (c *Client) authenticate() (*TokenResponse, error) { + resp, err := c.client.PostForm(fmt.Sprintf(AuthURL, c.Host), url.Values{ + "token": {c.ServiceToken}, + }) + if err != nil { + return nil, err + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + defer resp.Body.Close() + token := TokenResponse{} + err = json.Unmarshal(body, &token) + if err != nil { + return nil, err + } + + return &token, nil +} + +// Get issues a GET to the Kiali server with the url. +func (c *Client) Get(url string) (resp *http.Response, err error) { + + if req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s%s", c.Host, url), nil); err != nil { + return nil, err + } else { + if c.Strategy == AuthStrategyToken { + err := c.SetToken(req) + if err != nil { + return nil, err + } + } + resp, err := c.client.Do(req) + + if err != nil { + c.clearTokenCache(err) + } + + return resp, err + } +} + +func (c *Client) clearTokenCache(err error) { + if c.cache != nil && err != nil { + c.cache.Del(KialiTokenCacheKey) + } +} + +// SetToken gets token from the Kiali server/cache and sets Bearer token to the request header. +func (c *Client) SetToken(req *http.Request) error { + if c.cache != nil { + token, err := c.cache.Get(KialiTokenCacheKey) + if err == nil { + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token)) + return nil + } + } + + token, err := c.authenticate() + if err != nil { + return err + } + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token.Token)) + + if c.cache != nil { + c.cache.Set(KialiTokenCacheKey, token.Token, time.Hour) + } + return nil +} diff --git a/pkg/simple/client/kiali/client_test.go b/pkg/simple/client/kiali/client_test.go new file mode 100644 index 000000000..6f75f5f3c --- /dev/null +++ b/pkg/simple/client/kiali/client_test.go @@ -0,0 +1,150 @@ +/* +Copyright 2021 KubeSphere Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kiali + +import ( + "bytes" + "encoding/json" + "io/ioutil" + "net/http" + "net/url" + "reflect" + "testing" + + "kubesphere.io/kubesphere/pkg/simple/client/cache" +) + +func TestClient_Get(t *testing.T) { + type fields struct { + Strategy Strategy + cache cache.Interface + client HttpClient + ServiceToken string + Host string + } + type args struct { + url string + } + token, _ := json.Marshal( + &TokenResponse{ + Username: "test", + Token: "test", + }, + ) + tests := []struct { + name string + fields fields + args args + wantResp *http.Response + wantErr bool + }{ + { + name: "Anonymous", + fields: fields{ + Strategy: AuthStrategyAnonymous, + cache: nil, + client: &MockClient{ + requestResult: "fake", + }, + ServiceToken: "token", + Host: "http://kiali.istio-system.svc", + }, + args: args{url: "http://kiali.istio-system.svc"}, + wantResp: &http.Response{ + StatusCode: 200, + Body: ioutil.NopCloser(bytes.NewReader([]byte("fake"))), + }, + wantErr: false, + }, + { + name: "Token", + fields: fields{ + Strategy: AuthStrategyToken, + cache: nil, + client: &MockClient{ + tokenResult: token, + requestResult: "fake", + }, + ServiceToken: "token", + Host: "http://kiali.istio-system.svc", + }, + args: args{url: "http://kiali.istio-system.svc"}, + wantResp: &http.Response{ + StatusCode: 200, + Body: ioutil.NopCloser(bytes.NewReader([]byte("fake"))), + }, + wantErr: false, + }, + { + name: "Token", + fields: fields{ + Strategy: AuthStrategyToken, + cache: cache.NewSimpleCache(), + client: &MockClient{ + tokenResult: token, + requestResult: "fake", + }, + ServiceToken: "token", + Host: "http://kiali.istio-system.svc", + }, + args: args{url: "http://kiali.istio-system.svc"}, + wantResp: &http.Response{ + StatusCode: 200, + Body: ioutil.NopCloser(bytes.NewReader([]byte("fake"))), + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := NewClient( + tt.fields.Strategy, + tt.fields.cache, + tt.fields.client, + tt.fields.ServiceToken, + tt.fields.Host, + ) + gotResp, err := c.Get(tt.args.url) + if (err != nil) != tt.wantErr { + t.Errorf("Client.Get() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(gotResp, tt.wantResp) { + t.Errorf("Client.Get() = %v, want %v", gotResp, tt.wantResp) + } + }) + } +} + +type MockClient struct { + tokenResult []byte + requestResult string +} + +func (c *MockClient) Do(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: 200, + Body: ioutil.NopCloser(bytes.NewReader([]byte(c.requestResult))), + }, nil +} + +func (c *MockClient) PostForm(url string, data url.Values) (resp *http.Response, err error) { + return &http.Response{ + StatusCode: 200, + Body: ioutil.NopCloser(bytes.NewReader(c.tokenResult)), + }, nil +} diff --git a/tools/cmd/doc-gen/main.go b/tools/cmd/doc-gen/main.go index 731f46779..7abd3deb9 100644 --- a/tools/cmd/doc-gen/main.go +++ b/tools/cmd/doc-gen/main.go @@ -133,7 +133,7 @@ func generateSwaggerJson() []byte { urlruntime.Must(resourcesv1alpha3.AddToContainer(container, informerFactory, nil)) urlruntime.Must(tenantv1alpha2.AddToContainer(container, informerFactory, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)) urlruntime.Must(terminalv1alpha2.AddToContainer(container, clientsets.Kubernetes(), nil, nil)) - urlruntime.Must(metricsv1alpha2.AddToContainer(container)) + urlruntime.Must(metricsv1alpha2.AddToContainer(nil, container, clientsets.Kubernetes(), nil)) urlruntime.Must(networkv1alpha2.AddToContainer(container, "")) alertingOptions := &alerting.Options{} alertingClient, _ := alerting.NewRuleClient(alertingOptions)