feat: kubesphere 4.0 (#6115)

* feat: kubesphere 4.0

Signed-off-by: ci-bot <ci-bot@kubesphere.io>

* feat: kubesphere 4.0

Signed-off-by: ci-bot <ci-bot@kubesphere.io>

---------

Signed-off-by: ci-bot <ci-bot@kubesphere.io>
Co-authored-by: ks-ci-bot <ks-ci-bot@example.com>
Co-authored-by: joyceliu <joyceliu@yunify.com>
This commit is contained in:
KubeSphere CI Bot
2024-09-06 11:05:52 +08:00
committed by GitHub
parent b5015ec7b9
commit 447a51f08b
8557 changed files with 546695 additions and 1146174 deletions

View File

@@ -1,71 +1,54 @@
/*
Copyright 2020 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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package v1alpha3
import (
"fmt"
"github.com/Masterminds/semver/v3"
"github.com/emicklei/go-restful/v3"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/client-go/kubernetes"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/klog/v2"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/apiserver/request"
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/apiserver/rest"
"kubesphere.io/kubesphere/pkg/models/iam/am"
"kubesphere.io/kubesphere/pkg/models/iam/im"
"kubesphere.io/kubesphere/pkg/models/openpitrix"
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
"kubesphere.io/kubesphere/pkg/models/tenant"
"kubesphere.io/kubesphere/pkg/simple/client/auditing"
"kubesphere.io/kubesphere/pkg/simple/client/events"
"kubesphere.io/kubesphere/pkg/simple/client/logging"
meteringclient "kubesphere.io/kubesphere/pkg/simple/client/metering"
monitoringclient "kubesphere.io/kubesphere/pkg/simple/client/monitoring"
"kubesphere.io/kubesphere/pkg/utils/clusterclient"
)
type tenantHandler struct {
tenant tenant.Interface
meteringOptions *meteringclient.Options
type handler struct {
tenant tenant.Interface
auth authorizer.Authorizer
client runtimeclient.Client
}
func newTenantHandler(factory informers.InformerFactory, k8sclient kubernetes.Interface, ksclient kubesphere.Interface,
evtsClient events.Client, loggingClient logging.Client, auditingclient auditing.Client,
am am.AccessManagementInterface, im im.IdentityManagementInterface, authorizer authorizer.Authorizer,
monitoringclient monitoringclient.Interface, resourceGetter *resourcev1alpha3.ResourceGetter,
meteringOptions *meteringclient.Options, opClient openpitrix.Interface) *tenantHandler {
if meteringOptions == nil || meteringOptions.RetentionDay == "" {
meteringOptions = &meteringclient.DefaultMeteringOption
}
return &tenantHandler{
tenant: tenant.New(factory, k8sclient, ksclient, evtsClient, loggingClient, auditingclient, am, im, authorizer, monitoringclient, resourceGetter, opClient),
meteringOptions: meteringOptions,
func NewHandler(client runtimeclient.Client, k8sVersion *semver.Version, clusterClient clusterclient.Interface,
am am.AccessManagementInterface, im im.IdentityManagementInterface, authorizer authorizer.Authorizer) rest.Handler {
return &handler{
tenant: tenant.New(client, k8sVersion, clusterClient, am, im, authorizer),
client: client,
auth: authorizer,
}
}
func (h *tenantHandler) ListWorkspaces(req *restful.Request, resp *restful.Response) {
func NewFakeHandler() rest.Handler {
return &handler{}
}
func (h *handler) ListWorkspaceTemplates(req *restful.Request, resp *restful.Response) {
authenticated, ok := request.UserFrom(req.Request.Context())
queryParam := query.ParseQueryParameter(req)
user, ok := request.UserFrom(req.Request.Context())
if !ok {
err := fmt.Errorf("cannot obtain user info")
klog.Errorln(err)
@@ -73,16 +56,137 @@ func (h *tenantHandler) ListWorkspaces(req *restful.Request, resp *restful.Respo
return
}
result, err := h.tenant.ListWorkspaces(user, queryParam)
result, err := h.tenant.ListWorkspaceTemplates(authenticated, queryParam)
if err != nil {
api.HandleInternalError(resp, nil, err)
return
}
resp.WriteEntity(result)
_ = resp.WriteEntity(result)
}
func (h *tenantHandler) GetWorkspace(request *restful.Request, response *restful.Response) {
func (h *handler) ListNamespaces(req *restful.Request, resp *restful.Response) {
workspace := req.PathParameter("workspace")
queryParam := query.ParseQueryParameter(req)
var workspaceMember user.Info
if username := req.PathParameter("workspacemember"); username != "" {
workspaceMember = &user.DefaultInfo{
Name: username,
}
} else {
requestUser, ok := request.UserFrom(req.Request.Context())
if !ok {
err := fmt.Errorf("cannot obtain user info")
klog.Errorln(err)
api.HandleForbidden(resp, nil, err)
return
}
workspaceMember = requestUser
}
result, err := h.tenant.ListNamespaces(workspaceMember, workspace, queryParam)
if err != nil {
api.HandleInternalError(resp, nil, err)
return
}
_ = resp.WriteEntity(result)
}
func (h *handler) DescribeWorkspaceTemplate(request *restful.Request, response *restful.Response) {
workspaceName := request.PathParameter("workspace")
workspace, err := h.tenant.DescribeWorkspaceTemplate(workspaceName)
if err != nil {
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleInternalError(response, request, err)
return
}
_ = response.WriteEntity(workspace)
}
func (h *handler) ListWorkspaceClusters(request *restful.Request, response *restful.Response) {
workspaceName := request.PathParameter("workspace")
result, err := h.tenant.ListWorkspaceClusters(workspaceName)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleInternalError(response, request, err)
return
}
_ = response.WriteEntity(result)
}
func (h *handler) DescribeNamespace(request *restful.Request, response *restful.Response) {
workspaceName := request.PathParameter("workspace")
namespaceName := request.PathParameter("namespace")
ns, err := h.tenant.DescribeNamespace(workspaceName, namespaceName)
if err != nil {
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleInternalError(response, request, err)
return
}
_ = response.WriteEntity(ns)
}
func (h *handler) ListClusters(r *restful.Request, response *restful.Response) {
authenticated, ok := request.UserFrom(r.Request.Context())
if !ok {
_ = response.WriteEntity([]interface{}{})
return
}
queryParam := query.ParseQueryParameter(r)
result, err := h.tenant.ListClusters(authenticated, queryParam)
if err != nil {
klog.Error(err)
if errors.IsNotFound(err) {
api.HandleNotFound(response, r, err)
return
}
api.HandleInternalError(response, r, err)
return
}
_ = response.WriteEntity(result)
}
func (h *handler) ListWorkspaces(req *restful.Request, resp *restful.Response) {
queryParam := query.ParseQueryParameter(req)
authenticated, ok := request.UserFrom(req.Request.Context())
if !ok {
err := fmt.Errorf("cannot obtain user info")
klog.Errorln(err)
api.HandleForbidden(resp, nil, err)
return
}
result, err := h.tenant.ListWorkspaces(authenticated, queryParam)
if err != nil {
api.HandleInternalError(resp, nil, err)
return
}
_ = resp.WriteEntity(result)
}
func (h *handler) GetWorkspace(request *restful.Request, response *restful.Response) {
workspace, err := h.tenant.GetWorkspace(request.PathParameter("workspace"))
if err != nil {
klog.Error(err)
@@ -94,5 +198,5 @@ func (h *tenantHandler) GetWorkspace(request *restful.Request, response *restful
return
}
response.WriteEntity(workspace)
_ = response.WriteEntity(workspace)
}

View File

@@ -1,18 +1,7 @@
/*
Copyright 2019 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.
*/
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package v1alpha3
@@ -21,31 +10,15 @@ import (
restfulspec "github.com/emicklei/go-restful-openapi/v2"
"github.com/emicklei/go-restful/v3"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/kubernetes"
tenantv1alpha1 "kubesphere.io/api/tenant/v1alpha1"
"sigs.k8s.io/controller-runtime/pkg/cache"
tenantv1alpha2 "kubesphere.io/api/tenant/v1alpha2"
tenantv1beta1 "kubesphere.io/api/tenant/v1beta1"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/kapis/tenant/v1alpha2"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/iam/am"
"kubesphere.io/kubesphere/pkg/models/iam/im"
"kubesphere.io/kubesphere/pkg/models/openpitrix"
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
"kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/simple/client/auditing"
"kubesphere.io/kubesphere/pkg/simple/client/events"
"kubesphere.io/kubesphere/pkg/simple/client/logging"
meteringclient "kubesphere.io/kubesphere/pkg/simple/client/metering"
monitoringclient "kubesphere.io/kubesphere/pkg/simple/client/monitoring"
)
const (
@@ -54,76 +27,93 @@ const (
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha3"}
func Resource(resource string) schema.GroupResource {
return GroupVersion.WithResource(resource).GroupResource()
}
func AddToContainer(c *restful.Container, factory informers.InformerFactory, k8sclient kubernetes.Interface,
ksclient kubesphere.Interface, evtsClient events.Client, loggingClient logging.Client,
auditingclient auditing.Client, am am.AccessManagementInterface, im im.IdentityManagementInterface, authorizer authorizer.Authorizer,
monitoringclient monitoringclient.Interface, cache cache.Cache, meteringOptions *meteringclient.Options, opClient openpitrix.Interface) error {
mimePatch := []string{restful.MIME_JSON, runtime.MimeMergePatchJson, runtime.MimeJsonPatchJson}
func (h *handler) AddToContainer(c *restful.Container) error {
ws := runtime.NewWebService(GroupVersion)
v1alpha2Handler := v1alpha2.NewTenantHandler(factory, k8sclient, ksclient, evtsClient, loggingClient, auditingclient, am, im, authorizer, monitoringclient, resourcev1alpha3.NewResourceGetter(factory, cache), meteringOptions, opClient)
handler := newTenantHandler(factory, k8sclient, ksclient, evtsClient, loggingClient, auditingclient, am, im, authorizer, monitoringclient, resourcev1alpha3.NewResourceGetter(factory, cache), meteringOptions, opClient)
ws.Route(ws.POST("/workspacetemplates").
To(v1alpha2Handler.CreateWorkspaceTemplate).
Reads(tenantv1alpha2.WorkspaceTemplate{}).
Returns(http.StatusOK, api.StatusOK, tenantv1alpha2.WorkspaceTemplate{}).
Doc("Create workspace.").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.WorkspaceTag}))
ws.Route(ws.GET("/clusters").
To(h.ListClusters).
Deprecate().
Doc("List clusters available to users").
Returns(http.StatusOK, api.StatusOK, api.ListResult{}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagUserRelatedResources}))
ws.Route(ws.DELETE("/workspacetemplates/{workspace}").
To(v1alpha2Handler.DeleteWorkspaceTemplate).
Param(ws.PathParameter("workspace", "workspace name")).
Returns(http.StatusOK, api.StatusOK, errors.None).
Doc("Delete workspace.").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.WorkspaceTag}))
ws.Route(ws.PUT("/workspacetemplates/{workspace}").
To(v1alpha2Handler.UpdateWorkspaceTemplate).
Param(ws.PathParameter("workspace", "workspace name")).
Reads(tenantv1alpha2.WorkspaceTemplate{}).
Returns(http.StatusOK, api.StatusOK, tenantv1alpha2.WorkspaceTemplate{}).
Doc("Update workspace.").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.WorkspaceTag}))
ws.Route(ws.PATCH("/workspacetemplates/{workspace}").
To(v1alpha2Handler.PatchWorkspaceTemplate).
Param(ws.PathParameter("workspace", "workspace name")).
Consumes(mimePatch...).
Reads(tenantv1alpha2.WorkspaceTemplate{}).
Returns(http.StatusOK, api.StatusOK, tenantv1alpha2.WorkspaceTemplate{}).
Doc("Update workspace.").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.WorkspaceTag}))
ws.Route(ws.GET("/workspacetemplates").
To(v1alpha2Handler.ListWorkspaceTemplates).
ws.Route(ws.GET("/workspaces").
To(h.ListWorkspaceTemplates).
Deprecate().
Returns(http.StatusOK, api.StatusOK, models.PageableResponse{}).
Doc("List all workspaces that belongs to the current user").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.WorkspaceTag}))
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagUserRelatedResources}))
ws.Route(ws.GET("/workspaces/{workspace}").
To(h.DescribeWorkspaceTemplate).
Deprecate().
Param(ws.PathParameter("workspace", "workspace name")).
Returns(http.StatusOK, api.StatusOK, tenantv1beta1.WorkspaceTemplate{}).
Doc("Describe workspace.").
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagUserRelatedResources}))
ws.Route(ws.GET("/workspaces/{workspace}/clusters").
To(h.ListWorkspaceClusters).
Deprecate().
Param(ws.PathParameter("workspace", "workspace name")).
Returns(http.StatusOK, api.StatusOK, api.ListResult{}).
Doc("List clusters authorized to the specified workspace.").
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagUserRelatedResources}))
ws.Route(ws.GET("/namespaces").
To(h.ListNamespaces).
Deprecate().
Doc("List the namespaces for the current user").
Returns(http.StatusOK, api.StatusOK, api.ListResult{}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagUserRelatedResources}))
ws.Route(ws.GET("/workspaces/{workspace}/namespaces").
To(h.ListNamespaces).
Deprecate().
Param(ws.PathParameter("workspace", "workspace name")).
Doc("List the namespaces of the specified workspace for the current user").
Returns(http.StatusOK, api.StatusOK, api.ListResult{}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagUserRelatedResources}))
ws.Route(ws.GET("/workspaces/{workspace}/namespaces/{namespace}").
To(h.DescribeNamespace).
Deprecate().
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("namespace", "project name")).
Doc("Retrieve namespace details.").
Returns(http.StatusOK, api.StatusOK, corev1.Namespace{}).
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagUserRelatedResources}))
ws.Route(ws.GET("/workspacetemplates").
To(h.ListWorkspaceTemplates).
Deprecate().
Returns(http.StatusOK, api.StatusOK, models.PageableResponse{}).
Doc("List all workspaces that belongs to the current user").
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagUserRelatedResources}))
ws.Route(ws.GET("/workspacetemplates/{workspace}").
To(v1alpha2Handler.DescribeWorkspaceTemplate).
To(h.DescribeWorkspaceTemplate).
Deprecate().
Param(ws.PathParameter("workspace", "workspace name")).
Returns(http.StatusOK, api.StatusOK, tenantv1alpha2.WorkspaceTemplate{}).
Doc("Describe workspace.").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.WorkspaceTag}))
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagUserRelatedResources}))
ws.Route(ws.GET("/workspaces").
To(handler.ListWorkspaces).
To(h.ListWorkspaces).
Deprecate().
Returns(http.StatusOK, api.StatusOK, models.PageableResponse{}).
Doc("List all workspaces that belongs to the current user").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.WorkspaceTag}))
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagUserRelatedResources}))
ws.Route(ws.GET("/workspaces/{workspace}").
To(handler.GetWorkspace).
To(h.GetWorkspace).
Deprecate().
Param(ws.PathParameter("workspace", "workspace name")).
Returns(http.StatusOK, api.StatusOK, tenantv1alpha1.Workspace{}).
Doc("Get workspace.").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.WorkspaceTag}))
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagUserRelatedResources}))
c.Add(ws)
return nil