diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go index a75a662ae..dca47a55e 100644 --- a/pkg/apiserver/apiserver.go +++ b/pkg/apiserver/apiserver.go @@ -65,8 +65,7 @@ import ( clusterkapisv1alpha1 "kubesphere.io/kubesphere/pkg/kapis/cluster/v1alpha1" configv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/config/v1alpha2" crd "kubesphere.io/kubesphere/pkg/kapis/crd" - devopsv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/devops/v1alpha2" - devopsv1alpha3 "kubesphere.io/kubesphere/pkg/kapis/devops/v1alpha3" + kapisdevops "kubesphere.io/kubesphere/pkg/kapis/devops" edgeruntimev1alpha1 "kubesphere.io/kubesphere/pkg/kapis/edgeruntime/v1alpha1" gatewayv1alpha1 "kubesphere.io/kubesphere/pkg/kapis/gateway/v1alpha1" iamapi "kubesphere.io/kubesphere/pkg/kapis/iam/v1alpha2" @@ -244,8 +243,7 @@ func (s *APIServer) installKubeSphereAPIs() { s.Config.AuthenticationOptions)) 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.Config.DevopsOptions.Endpoint)) - urlruntime.Must(devopsv1alpha3.AddToContainer(s.container, s.Config.DevopsOptions.Endpoint)) + urlruntime.Must(kapisdevops.AddToContainer(s.container, s.Config.DevopsOptions.Endpoint)) urlruntime.Must(notificationv1.AddToContainer(s.container, s.Config.NotificationOptions.Endpoint)) urlruntime.Must(alertingv1.AddToContainer(s.container, s.Config.AlertingOptions.Endpoint)) urlruntime.Must(alertingv2alpha1.AddToContainer(s.container, s.InformerFactory, diff --git a/pkg/kapis/devops/group.go b/pkg/kapis/devops/group.go deleted file mode 100644 index 3324fdbdc..000000000 --- a/pkg/kapis/devops/group.go +++ /dev/null @@ -1,17 +0,0 @@ -/* -Copyright 2020 The 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 devops diff --git a/pkg/kapis/devops/v1alpha2/register.go b/pkg/kapis/devops/register.go similarity index 61% rename from pkg/kapis/devops/v1alpha2/register.go rename to pkg/kapis/devops/register.go index 3bc472f9c..c9ed10470 100644 --- a/pkg/kapis/devops/v1alpha2/register.go +++ b/pkg/kapis/devops/register.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The KubeSphere Authors. +Copyright 2022 The KubeSphere Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,26 +14,27 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1alpha2 +package devops import ( "github.com/emicklei/go-restful" - "k8s.io/apimachinery/pkg/runtime/schema" - "kubesphere.io/kubesphere/pkg/kapis/generic" ) -const ( - GroupName = "devops.kubesphere.io" -) +const groupName = "devops.kubesphere.io" -var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"} +var versions = []string{"v1alpha1", "v1alpha2", "v1alpha3"} +// AddToContainer registers DevOps proxies to the container. func AddToContainer(container *restful.Container, endpoint string) error { - proxy, err := generic.NewGenericProxy(endpoint, GroupVersion.Group, GroupVersion.Version) - if err != nil { - return err + for _, version := range versions { + proxy, err := generic.NewGenericProxy(endpoint, groupName, version) + if err != nil { + return err + } + if err = proxy.AddToContainer(container); err != nil { + return err + } } - - return proxy.AddToContainer(container) + return nil } diff --git a/pkg/kapis/devops/register_test.go b/pkg/kapis/devops/register_test.go new file mode 100644 index 000000000..94059db58 --- /dev/null +++ b/pkg/kapis/devops/register_test.go @@ -0,0 +1,112 @@ +/* +Copyright 2022 The 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 devops + +import ( + "github.com/emicklei/go-restful" + "github.com/stretchr/testify/assert" + "net/http" + "net/http/httptest" + "testing" +) + +func TestAddToContainer(t *testing.T) { + fakeResponse := "fake DevOps APIServer response" + type args struct { + target string + mockAPIPattern string + mockResponse string + } + tests := []struct { + name string + args args + wantErr bool + wantResponse string + }{{ + name: "Should proxy v1alpha1 API properly", + args: args{ + target: "/kapis/devops.kubesphere.io/v1alpha1/resources", + mockAPIPattern: "/v1alpha1/resources", + }, + wantResponse: fakeResponse, + }, { + name: "Should proxy v1alpha2 API properly", + args: args{ + target: "/kapis/devops.kubesphere.io/v1alpha2/resources", + mockAPIPattern: "/v1alpha2/resources", + }, + wantResponse: fakeResponse, + }, { + name: "Should proxy v1alpha3 API properly", + args: args{ + target: "/kapis/devops.kubesphere.io/v1alpha3/resources", + mockAPIPattern: "/v1alpha3/resources", + }, + wantResponse: fakeResponse, + }, { + name: "Should return 404 if no pattern matches", + args: args{ + target: "/kapis/devops.kubesphere.io/v1alpha3/resources", + mockAPIPattern: "/v1alpha4/resources", + }, + wantResponse: "404 page not found\n", + }, { + name: "Should not proxy v1alpha123 API properly event if pattern matched", + args: args{ + target: "/kapis/devops.kubesphere.io/v1alpha123/resources", + mockAPIPattern: "/v1alpha123/resources", + }, + wantResponse: "404 page not found\n", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // create a fresh mock DevOps APIServer. + server := mockDevOpsAPIServer(tt.args.mockAPIPattern, 200, tt.args.mockResponse) + defer server.Close() + + // mock to request DevOps API from KubeSphere APIServer + container := restful.NewContainer() + if err := AddToContainer(container, server.URL); (err != nil) != tt.wantErr { + t.Errorf("AddToContainer() error = %v, wantErr %v", err, tt.wantErr) + } + request := httptest.NewRequest(http.MethodGet, tt.args.target, nil) + recorder := &responseRecorder{*httptest.NewRecorder()} + container.ServeHTTP(restful.NewResponse(recorder), request) + + assert.Equal(t, tt.wantResponse, recorder.Body.String()) + }) + } +} + +func mockDevOpsAPIServer(pattern string, fakeCode int, fakeResp string) *httptest.Server { + mux := http.NewServeMux() + mux.HandleFunc(pattern, func(writer http.ResponseWriter, request *http.Request) { + writer.WriteHeader(fakeCode) + _, _ = writer.Write([]byte(fakeResp)) + }) + return httptest.NewServer(mux) +} + +// responseRecorder extends httptest.ResponseRecorder and implements CloseNotifier interface for generic proxy. +type responseRecorder struct { + httptest.ResponseRecorder +} + +func (*responseRecorder) CloseNotify() <-chan bool { + return nil +} diff --git a/pkg/kapis/devops/v1alpha2/OWNERS b/pkg/kapis/devops/v1alpha2/OWNERS deleted file mode 100644 index d616f1051..000000000 --- a/pkg/kapis/devops/v1alpha2/OWNERS +++ /dev/null @@ -1,12 +0,0 @@ -approvers: - - shaowenchen - - linuxsuren - -reviewers: - - runzexia - - soulseen - - shaowenchen - - linuxsuren - -labels: - - area/devops diff --git a/pkg/kapis/devops/v1alpha3/register.go b/pkg/kapis/devops/v1alpha3/register.go deleted file mode 100644 index f496be6ba..000000000 --- a/pkg/kapis/devops/v1alpha3/register.go +++ /dev/null @@ -1,41 +0,0 @@ -/* - - Copyright 2020 The 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 v1alpha3 - -import ( - "github.com/emicklei/go-restful" - "k8s.io/apimachinery/pkg/runtime/schema" - - "kubesphere.io/kubesphere/pkg/kapis/generic" -) - -const ( - GroupName = "devops.kubesphere.io" -) - -var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha3"} - -func AddToContainer(container *restful.Container, endpoint string) error { - proxy, err := generic.NewGenericProxy(endpoint, GroupVersion.Group, GroupVersion.Version) - if err != nil { - return err - } - - return proxy.AddToContainer(container) -} diff --git a/tools/cmd/doc-gen/main.go b/tools/cmd/doc-gen/main.go index 3d1744bf8..f87e8af27 100644 --- a/tools/cmd/doc-gen/main.go +++ b/tools/cmd/doc-gen/main.go @@ -22,6 +22,7 @@ import ( "flag" "fmt" "io/ioutil" + kapisdevops "kubesphere.io/kubesphere/pkg/kapis/devops" "log" "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake" @@ -43,8 +44,6 @@ import ( "kubesphere.io/kubesphere/pkg/informers" alertingv2alpha1 "kubesphere.io/kubesphere/pkg/kapis/alerting/v2alpha1" clusterkapisv1alpha1 "kubesphere.io/kubesphere/pkg/kapis/cluster/v1alpha1" - devopsv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/devops/v1alpha2" - devopsv1alpha3 "kubesphere.io/kubesphere/pkg/kapis/devops/v1alpha3" iamv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/iam/v1alpha2" monitoringv1alpha3 "kubesphere.io/kubesphere/pkg/kapis/monitoring/v1alpha3" networkv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/network/v1alpha2" @@ -120,8 +119,7 @@ func generateSwaggerJson() []byte { urlruntime.Must(oauth.AddToContainer(container, nil, nil, nil, nil, nil, nil)) urlruntime.Must(clusterkapisv1alpha1.AddToContainer(container, clientsets.KubeSphere(), informerFactory.KubernetesSharedInformerFactory(), informerFactory.KubeSphereSharedInformerFactory(), "", "", "")) - urlruntime.Must(devopsv1alpha2.AddToContainer(container, "")) - urlruntime.Must(devopsv1alpha3.AddToContainer(container, "")) + urlruntime.Must(kapisdevops.AddToContainer(container, "")) urlruntime.Must(iamv1alpha2.AddToContainer(container, nil, nil, group.New(informerFactory, clientsets.KubeSphere(), clientsets.Kubernetes()), nil)) urlruntime.Must(monitoringv1alpha3.AddToContainer(container, clientsets.Kubernetes(), nil, nil, informerFactory, nil, nil, nil)) urlruntime.Must(openpitrixv1.AddToContainer(container, informerFactory, fake.NewSimpleClientset(), nil))