160 lines
6.6 KiB
Go
160 lines
6.6 KiB
Go
/*
|
|
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 crd
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/emicklei/go-restful"
|
|
extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
"sigs.k8s.io/controller-runtime/pkg/cache"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
|
|
"kubesphere.io/kubesphere/pkg/api"
|
|
"kubesphere.io/kubesphere/pkg/apiserver/query"
|
|
ksruntime "kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
|
"kubesphere.io/kubesphere/pkg/models/crds"
|
|
)
|
|
|
|
const (
|
|
ok = "OK"
|
|
)
|
|
|
|
//AddToContainer register GET and LIST API for CRD to the web service
|
|
func AddToContainer(c *restful.Container, cli client.Client, cache cache.Cache, crdList *extv1.CustomResourceDefinitionList) error {
|
|
|
|
for _, crd := range crdList.Items {
|
|
gvk := schema.GroupVersionKind{Group: crd.Spec.Group, Version: currentVersion(&crd), Kind: crd.Spec.Names.Kind}
|
|
resource := crd.Spec.Names.Plural
|
|
|
|
var h crds.Handler
|
|
if cli.Scheme().Recognizes(gvk) {
|
|
h = crds.NewTyped(cache, gvk, cli.Scheme())
|
|
} else {
|
|
h = crds.NewUnstructured(cache, gvk)
|
|
}
|
|
|
|
if containsRouter(c.RegisteredWebServices(), gvk.GroupVersion().String()) {
|
|
//Skip existing Root service for now
|
|
//TODO Register to existing WebService
|
|
continue
|
|
}
|
|
|
|
//Create new WebService
|
|
webservice := ksruntime.NewWebService(gvk.GroupVersion())
|
|
|
|
listURL := fmt.Sprintf("/%s", resource)
|
|
webservice.Route(webservice.GET(listURL).
|
|
To(func(request *restful.Request, response *restful.Response) {
|
|
h.ListResources(request, response)
|
|
}).
|
|
Doc(fmt.Sprintf("Cluster level resource %s query", resource)).
|
|
Param(webservice.QueryParameter(query.ParameterName, "name used to do filtering").Required(false)).
|
|
Param(webservice.QueryParameter(query.ParameterPage, "page").Required(false).DataFormat("page=%d").DefaultValue("page=1")).
|
|
Param(webservice.QueryParameter(query.ParameterLimit, "limit").Required(false)).
|
|
Param(webservice.QueryParameter(query.ParameterAscending, "sort parameters, e.g. reverse=true").Required(false).DefaultValue("ascending=false")).
|
|
Param(webservice.QueryParameter(query.ParameterOrderBy, "sort parameters, e.g. orderBy=createTime")).
|
|
Returns(http.StatusOK, ok, api.ListResult{}))
|
|
|
|
if crd.Spec.Scope == extv1.ClusterScoped {
|
|
getURL := fmt.Sprintf("/%s/{name}", resource)
|
|
webservice.Route(webservice.GET(getURL).
|
|
To(func(request *restful.Request, response *restful.Response) {
|
|
h.GetResources(request, response)
|
|
}).
|
|
Doc(fmt.Sprintf("Cluster level resource %s", resource)).
|
|
Param(webservice.PathParameter("name", "the name of the clustered resources")).
|
|
Returns(http.StatusOK, api.StatusOK, nil))
|
|
}
|
|
|
|
if crd.Spec.Scope == extv1.NamespaceScoped {
|
|
listNsURL := fmt.Sprintf("/namespaces/{namespace}/%s/", resource)
|
|
webservice.Route(webservice.GET(listNsURL).
|
|
To(func(request *restful.Request, response *restful.Response) {
|
|
h.ListResources(request, response)
|
|
}).
|
|
Doc(fmt.Sprintf("Namespace level resource %s query", resource)).
|
|
Param(webservice.PathParameter("namespace", "the name of the project")).
|
|
Param(webservice.QueryParameter(query.ParameterName, "name used to do filtering").Required(false)).
|
|
Param(webservice.QueryParameter(query.ParameterPage, "page").Required(false).DataFormat("page=%d").DefaultValue("page=1")).
|
|
Param(webservice.QueryParameter(query.ParameterLimit, "limit").Required(false)).
|
|
Param(webservice.QueryParameter(query.ParameterAscending, "sort parameters, e.g. reverse=true").Required(false).DefaultValue("ascending=false")).
|
|
Param(webservice.QueryParameter(query.ParameterOrderBy, "sort parameters, e.g. orderBy=createTime")).
|
|
Returns(http.StatusOK, ok, api.ListResult{}))
|
|
|
|
getNsURL := fmt.Sprintf("/namespaces/{namespace}/%s/{name}", resource)
|
|
webservice.Route(webservice.GET(getNsURL).
|
|
To(func(request *restful.Request, response *restful.Response) {
|
|
h.GetResources(request, response)
|
|
}).
|
|
Doc(fmt.Sprintf("Namespace level resource %s", resource)).
|
|
Param(webservice.PathParameter("namespace", "the name of the project")).
|
|
Param(webservice.PathParameter("name", "the name of resource")).
|
|
Returns(http.StatusOK, ok, nil))
|
|
}
|
|
|
|
if crd.Spec.Scope == extv1.ClusterScoped && crd.Annotations != nil && crd.Annotations["kubesphere.io/resource-scope"] == "workspaced" {
|
|
listWsURL := fmt.Sprintf("/workspaces/{workspace}/%s/", resource)
|
|
webservice.Route(webservice.GET(listWsURL).
|
|
To(func(request *restful.Request, response *restful.Response) {
|
|
h.ListResources(request, response)
|
|
}).
|
|
Doc(fmt.Sprintf("Workspace level resource %s query", resource)).
|
|
Param(webservice.PathParameter("workspace", "the name of the workspace")).
|
|
Param(webservice.QueryParameter(query.ParameterName, "name used to do filtering").Required(false)).
|
|
Param(webservice.QueryParameter(query.ParameterPage, "page").Required(false).DataFormat("page=%d").DefaultValue("page=1")).
|
|
Param(webservice.QueryParameter(query.ParameterLimit, "limit").Required(false)).
|
|
Param(webservice.QueryParameter(query.ParameterAscending, "sort parameters, e.g. reverse=true").Required(false).DefaultValue("ascending=false")).
|
|
Param(webservice.QueryParameter(query.ParameterOrderBy, "sort parameters, e.g. orderBy=createTime")).
|
|
Returns(http.StatusOK, ok, api.ListResult{}))
|
|
|
|
getWsURL := fmt.Sprintf("/workspaces/{workspace}/%s/{name}", resource)
|
|
webservice.Route(webservice.GET(getWsURL).
|
|
To(func(request *restful.Request, response *restful.Response) {
|
|
h.GetResources(request, response)
|
|
}).
|
|
Doc(fmt.Sprintf("Workspace level resource %s", resource)).
|
|
Param(webservice.PathParameter("workspace", "the name of the workspace")).
|
|
Param(webservice.PathParameter("name", "the name of resource")).
|
|
Returns(http.StatusOK, ok, nil))
|
|
}
|
|
c.Add(webservice)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func containsRouter(services []*restful.WebService, root string) bool {
|
|
for _, svc := range services {
|
|
if svc.RootPath() == "/kapis/"+root {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func currentVersion(crd *extv1.CustomResourceDefinition) string {
|
|
for _, v := range crd.Spec.Versions {
|
|
if v.Served && v.Storage {
|
|
return v.Name
|
|
}
|
|
}
|
|
return ""
|
|
}
|