/* * * 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 openpitrix import ( "github.com/go-openapi/strfmt" "github.com/golang/protobuf/ptypes/wrappers" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "k8s.io/klog" "kubesphere.io/kubesphere/pkg/models" "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/simple/client/openpitrix" "openpitrix.io/openpitrix/pkg/pb" "strings" ) type AppTemplateInterface interface { ListApps(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) DescribeApp(id string) (*App, error) DeleteApp(id string) error CreateApp(request *CreateAppRequest) (*CreateAppResponse, error) ModifyApp(appId string, request *ModifyAppRequest) error DeleteAppVersion(id string) error ModifyAppVersion(id string, request *ModifyAppVersionRequest) error DescribeAppVersion(id string) (*AppVersion, error) CreateAppVersion(request *CreateAppVersionRequest) (*CreateAppVersionResponse, error) ValidatePackage(request *ValidatePackageRequest) (*ValidatePackageResponse, error) GetAppVersionPackage(appId, versionId string) (*GetAppVersionPackageResponse, error) DoAppAction(appId string, request *ActionRequest) error DoAppVersionAction(versionId string, request *ActionRequest) error GetAppVersionFiles(versionId string, request *GetAppVersionFilesRequest) (*GetAppVersionPackageFilesResponse, error) ListAppVersionAudits(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) ListAppVersionReviews(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) ListAppVersions(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) } type appTemplateOperator struct { opClient openpitrix.Client } func newAppTemplateOperator(opClient openpitrix.Client) AppTemplateInterface { return &appTemplateOperator{ opClient: opClient, } } func (c *appTemplateOperator) ListApps(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) { describeAppsRequest := &pb.DescribeAppsRequest{} if keyword := conditions.Match[Keyword]; keyword != "" { describeAppsRequest.SearchWord = &wrappers.StringValue{Value: keyword} } if appId := conditions.Match[AppId]; appId != "" { describeAppsRequest.AppId = strings.Split(appId, "|") } if isv := conditions.Match[ISV]; isv != "" { describeAppsRequest.Isv = strings.Split(isv, "|") } if categoryId := conditions.Match[CategoryId]; categoryId != "" { describeAppsRequest.CategoryId = strings.Split(categoryId, "|") } if repoId := conditions.Match[RepoId]; repoId != "" { // hard code, app template in built-in repo has no repo_id attribute if repoId == BuiltinRepoId { describeAppsRequest.RepoId = []string{"\u0000"} } else { describeAppsRequest.RepoId = strings.Split(repoId, "|") } } if status := conditions.Match[Status]; status != "" { describeAppsRequest.Status = strings.Split(status, "|") } if orderBy != "" { describeAppsRequest.SortKey = &wrappers.StringValue{Value: orderBy} } describeAppsRequest.Reverse = &wrappers.BoolValue{Value: reverse} describeAppsRequest.Limit = uint32(limit) describeAppsRequest.Offset = uint32(offset) resp, err := c.opClient.DescribeApps(openpitrix.SystemContext(), describeAppsRequest) if err != nil { klog.Error(err) return nil, err } items := make([]interface{}, 0) for _, item := range resp.AppSet { items = append(items, convertApp(item)) } return &models.PageableResponse{Items: items, TotalCount: int(resp.TotalCount)}, nil } func (c *appTemplateOperator) DescribeApp(id string) (*App, error) { resp, err := c.opClient.DescribeApps(openpitrix.SystemContext(), &pb.DescribeAppsRequest{ AppId: []string{id}, Limit: 1, }) if err != nil { klog.Error(err) return nil, err } var app *App if len(resp.AppSet) > 0 { app = convertApp(resp.AppSet[0]) return app, nil } else { err := status.New(codes.NotFound, "resource not found").Err() klog.Error(err) return nil, err } } func (c *appTemplateOperator) DeleteApp(id string) error { _, err := c.opClient.DeleteApps(openpitrix.SystemContext(), &pb.DeleteAppsRequest{ AppId: []string{id}, }) if err != nil { klog.Error(err) return err } return nil } func (c *appTemplateOperator) CreateApp(request *CreateAppRequest) (*CreateAppResponse, error) { createAppRequest := &pb.CreateAppRequest{ Name: &wrappers.StringValue{Value: request.Name}, VersionType: &wrappers.StringValue{Value: request.VersionType}, VersionName: &wrappers.StringValue{Value: request.VersionName}, } if request.VersionPackage != nil { createAppRequest.VersionPackage = &wrappers.BytesValue{Value: request.VersionPackage} } if request.Icon != nil { createAppRequest.Icon = &wrappers.BytesValue{Value: request.Icon} } if request.Isv != "" { createAppRequest.Isv = &wrappers.StringValue{Value: request.Isv} } resp, err := c.opClient.CreateApp(openpitrix.ContextWithUsername(request.Username), createAppRequest) if err != nil { klog.Error(err) return nil, err } return &CreateAppResponse{ AppID: resp.GetAppId().GetValue(), VersionID: resp.GetVersionId().GetValue(), }, nil } func (c *appTemplateOperator) ModifyApp(appId string, request *ModifyAppRequest) error { // upload app attachment if request.AttachmentContent != nil { uploadAttachmentRequest := &pb.UploadAppAttachmentRequest{ AppId: &wrappers.StringValue{Value: appId}, AttachmentContent: &wrappers.BytesValue{Value: request.AttachmentContent}, } if request.Type != nil { uploadAttachmentRequest.Type = pb.UploadAppAttachmentRequest_Type(pb.UploadAppAttachmentRequest_Type_value[*request.Type]) } if request.Sequence != nil { uploadAttachmentRequest.Sequence = &wrappers.UInt32Value{Value: uint32(*request.Sequence)} } _, err := c.opClient.UploadAppAttachment(openpitrix.SystemContext(), uploadAttachmentRequest) if err != nil { klog.Error(err) return err } // patch app } else { patchAppRequest := &pb.ModifyAppRequest{ AppId: &wrappers.StringValue{Value: appId}, } if request.Abstraction != nil { patchAppRequest.Abstraction = &wrappers.StringValue{Value: *request.Abstraction} } if request.CategoryID != nil { patchAppRequest.CategoryId = &wrappers.StringValue{Value: *request.CategoryID} } if request.Description != nil { patchAppRequest.Description = &wrappers.StringValue{Value: *request.Description} } if request.Home != nil { patchAppRequest.Home = &wrappers.StringValue{Value: *request.Home} } if request.Keywords != nil { patchAppRequest.Keywords = &wrappers.StringValue{Value: *request.Keywords} } if request.Maintainers != nil { patchAppRequest.Maintainers = &wrappers.StringValue{Value: *request.Maintainers} } if request.Name != nil { patchAppRequest.Name = &wrappers.StringValue{Value: *request.Name} } if request.Readme != nil { patchAppRequest.Readme = &wrappers.StringValue{Value: *request.Readme} } if request.Sources != nil { patchAppRequest.Sources = &wrappers.StringValue{Value: *request.Sources} } if request.Tos != nil { patchAppRequest.Tos = &wrappers.StringValue{Value: *request.Tos} } _, err := c.opClient.ModifyApp(openpitrix.SystemContext(), patchAppRequest) if err != nil { klog.Error(err) return err } } return nil } func (c *appTemplateOperator) CreateAppVersion(request *CreateAppVersionRequest) (*CreateAppVersionResponse, error) { createAppVersionRequest := &pb.CreateAppVersionRequest{ AppId: &wrappers.StringValue{Value: request.AppId}, Name: &wrappers.StringValue{Value: request.Name}, Description: &wrappers.StringValue{Value: request.Description}, Type: &wrappers.StringValue{Value: request.Type}, } if request.Package != nil { createAppVersionRequest.Package = &wrappers.BytesValue{Value: request.Package} } resp, err := c.opClient.CreateAppVersion(openpitrix.ContextWithUsername(request.Username), createAppVersionRequest) if err != nil { klog.Error(err) return nil, err } return &CreateAppVersionResponse{ VersionId: resp.GetVersionId().GetValue(), }, nil } func (c *appTemplateOperator) ValidatePackage(request *ValidatePackageRequest) (*ValidatePackageResponse, error) { r := &pb.ValidatePackageRequest{} if request.VersionPackage != nil { r.VersionPackage = request.VersionPackage } if request.VersionType != "" { r.VersionType = request.VersionType } resp, err := c.opClient.ValidatePackage(openpitrix.SystemContext(), r) if err != nil { klog.Error(err) return nil, err } result := &ValidatePackageResponse{} if resp.Error != nil { result.Error = resp.Error.Value } if resp.Description != nil { result.Description = resp.Description.Value } if resp.Error != nil { result.Error = resp.Error.Value } if resp.ErrorDetails != nil { result.ErrorDetails = resp.ErrorDetails } if resp.Name != nil { result.Name = resp.Name.Value } if resp.Url != nil { result.URL = resp.Url.Value } if resp.VersionName != nil { result.VersionName = resp.VersionName.Value } return result, nil } func (c *appTemplateOperator) DeleteAppVersion(id string) error { _, err := c.opClient.DeleteAppVersion(openpitrix.SystemContext(), &pb.DeleteAppVersionRequest{ VersionId: &wrappers.StringValue{Value: id}, }) if err != nil { klog.Error(err) return err } return nil } func (c *appTemplateOperator) ModifyAppVersion(id string, request *ModifyAppVersionRequest) error { modifyAppVersionRequest := &pb.ModifyAppVersionRequest{ VersionId: &wrappers.StringValue{Value: id}, } if request.Name != nil { modifyAppVersionRequest.Name = &wrappers.StringValue{Value: *request.Name} } if request.Description != nil { modifyAppVersionRequest.Description = &wrappers.StringValue{Value: *request.Description} } if request.Package != nil { modifyAppVersionRequest.Package = &wrappers.BytesValue{Value: request.Package} } if request.PackageFiles != nil { modifyAppVersionRequest.PackageFiles = request.PackageFiles } _, err := c.opClient.ModifyAppVersion(openpitrix.SystemContext(), modifyAppVersionRequest) if err != nil { klog.Error(err) return err } return nil } func (c *appTemplateOperator) DescribeAppVersion(id string) (*AppVersion, error) { resp, err := c.opClient.DescribeAppVersions(openpitrix.SystemContext(), &pb.DescribeAppVersionsRequest{ VersionId: []string{id}, Limit: 1, }) if err != nil { klog.Error(err) return nil, err } var app *AppVersion if len(resp.AppVersionSet) > 0 { app = convertAppVersion(resp.AppVersionSet[0]) return app, nil } else { err := status.New(codes.NotFound, "resource not found").Err() klog.Error(err) return nil, err } } func (c *appTemplateOperator) GetAppVersionPackage(appId, versionId string) (*GetAppVersionPackageResponse, error) { resp, err := c.opClient.GetAppVersionPackage(openpitrix.SystemContext(), &pb.GetAppVersionPackageRequest{ VersionId: &wrappers.StringValue{Value: versionId}, }) if err != nil { klog.Error(err) return nil, err } app := &GetAppVersionPackageResponse{ AppId: appId, VersionId: versionId, } if resp.Package != nil { app.Package = resp.Package } return app, nil } func (c *appTemplateOperator) DoAppAction(appId string, request *ActionRequest) error { switch request.Action { case ActionRecover: // TODO openpitrix need to implement app recover interface resp, err := c.opClient.DescribeAppVersions(openpitrix.SystemContext(), &pb.DescribeAppVersionsRequest{ AppId: []string{appId}, Status: []string{StatusSuspended}, Limit: 200, Offset: 0, }) if err != nil { klog.Error(err) return err } for _, version := range resp.AppVersionSet { _, err = c.opClient.RecoverAppVersion(openpitrix.SystemContext(), &pb.RecoverAppVersionRequest{ VersionId: version.VersionId, }) if err != nil { klog.Error(err) return err } } case ActionSuspend: // TODO openpitrix need to implement app suspend interface resp, err := c.opClient.DescribeAppVersions(openpitrix.SystemContext(), &pb.DescribeAppVersionsRequest{ AppId: []string{appId}, Status: []string{StatusActive}, Limit: 200, Offset: 0, }) if err != nil { klog.Error(err) return err } for _, version := range resp.AppVersionSet { _, err = c.opClient.SuspendAppVersion(openpitrix.SystemContext(), &pb.SuspendAppVersionRequest{ VersionId: version.VersionId, }) if err != nil { klog.Error(err) return err } } default: err := status.New(codes.InvalidArgument, "action not support").Err() klog.Error(err) return err } return nil } func (c *appTemplateOperator) DoAppVersionAction(versionId string, request *ActionRequest) error { var err error switch request.Action { case ActionCancel: _, err = c.opClient.CancelAppVersion(openpitrix.ContextWithUsername(request.Username), &pb.CancelAppVersionRequest{ VersionId: &wrappers.StringValue{Value: versionId}, }) case ActionPass: _, err = c.opClient.AdminPassAppVersion(openpitrix.ContextWithUsername(request.Username), &pb.PassAppVersionRequest{ VersionId: &wrappers.StringValue{Value: versionId}, }) case ActionRecover: _, err = c.opClient.RecoverAppVersion(openpitrix.ContextWithUsername(request.Username), &pb.RecoverAppVersionRequest{ VersionId: &wrappers.StringValue{Value: versionId}, }) case ActionReject: _, err = c.opClient.AdminRejectAppVersion(openpitrix.ContextWithUsername(request.Username), &pb.RejectAppVersionRequest{ VersionId: &wrappers.StringValue{Value: versionId}, Message: &wrappers.StringValue{Value: request.Message}, }) case ActionSubmit: _, err = c.opClient.SubmitAppVersion(openpitrix.ContextWithUsername(request.Username), &pb.SubmitAppVersionRequest{ VersionId: &wrappers.StringValue{Value: versionId}, }) case ActionSuspend: _, err = c.opClient.SuspendAppVersion(openpitrix.ContextWithUsername(request.Username), &pb.SuspendAppVersionRequest{ VersionId: &wrappers.StringValue{Value: versionId}, }) case ActionRelease: _, err = c.opClient.ReleaseAppVersion(openpitrix.ContextWithUsername(request.Username), &pb.ReleaseAppVersionRequest{ VersionId: &wrappers.StringValue{Value: versionId}, }) default: err = status.New(codes.InvalidArgument, "action not support").Err() } if err != nil { klog.Error(err) return err } return nil } func (c *appTemplateOperator) GetAppVersionFiles(versionId string, request *GetAppVersionFilesRequest) (*GetAppVersionPackageFilesResponse, error) { getAppVersionPackageFilesRequest := &pb.GetAppVersionPackageFilesRequest{ VersionId: &wrappers.StringValue{Value: versionId}, } if request.Files != nil { getAppVersionPackageFilesRequest.Files = request.Files } resp, err := c.opClient.GetAppVersionPackageFiles(openpitrix.SystemContext(), getAppVersionPackageFilesRequest) if err != nil { klog.Error(err) return nil, err } version := &GetAppVersionPackageFilesResponse{ VersionId: versionId, } if resp.Files != nil { version.Files = make(map[string]strfmt.Base64) for k, v := range resp.Files { version.Files[k] = v } } return version, nil } func (c *appTemplateOperator) ListAppVersionAudits(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) { describeAppVersionAudits := &pb.DescribeAppVersionAuditsRequest{} if keyword := conditions.Match["keyword"]; keyword != "" { describeAppVersionAudits.SearchWord = &wrappers.StringValue{Value: keyword} } if appId := conditions.Match["app"]; appId != "" { describeAppVersionAudits.AppId = []string{appId} } if versionId := conditions.Match["version"]; versionId != "" { describeAppVersionAudits.VersionId = []string{versionId} } if status := conditions.Match["status"]; status != "" { describeAppVersionAudits.Status = strings.Split(status, "|") } if orderBy != "" { describeAppVersionAudits.SortKey = &wrappers.StringValue{Value: orderBy} } describeAppVersionAudits.Reverse = &wrappers.BoolValue{Value: reverse} describeAppVersionAudits.Limit = uint32(limit) describeAppVersionAudits.Offset = uint32(offset) resp, err := c.opClient.DescribeAppVersionAudits(openpitrix.SystemContext(), describeAppVersionAudits) if err != nil { klog.Error(err) return nil, err } items := make([]interface{}, 0) for _, item := range resp.AppVersionAuditSet { appVersion := convertAppVersionAudit(item) items = append(items, appVersion) } return &models.PageableResponse{Items: items, TotalCount: int(resp.TotalCount)}, nil } func (c *appTemplateOperator) ListAppVersionReviews(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) { describeAppVersionReviews := &pb.DescribeAppVersionReviewsRequest{} if keyword := conditions.Match["keyword"]; keyword != "" { describeAppVersionReviews.SearchWord = &wrappers.StringValue{Value: keyword} } if status := conditions.Match["status"]; status != "" { describeAppVersionReviews.Status = strings.Split(status, "|") } if orderBy != "" { describeAppVersionReviews.SortKey = &wrappers.StringValue{Value: orderBy} } describeAppVersionReviews.Reverse = &wrappers.BoolValue{Value: reverse} describeAppVersionReviews.Limit = uint32(limit) describeAppVersionReviews.Offset = uint32(offset) // TODO icon is needed resp, err := c.opClient.DescribeAppVersionReviews(openpitrix.SystemContext(), describeAppVersionReviews) if err != nil { klog.Error(err) return nil, err } items := make([]interface{}, 0) for _, item := range resp.AppVersionReviewSet { appVersion := convertAppVersionReview(item) items = append(items, appVersion) } return &models.PageableResponse{Items: items, TotalCount: int(resp.TotalCount)}, nil } func (c *appTemplateOperator) ListAppVersions(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) { describeAppVersionsRequest := &pb.DescribeAppVersionsRequest{} if keyword := conditions.Match["keyword"]; keyword != "" { describeAppVersionsRequest.SearchWord = &wrappers.StringValue{Value: keyword} } if appId := conditions.Match["app"]; appId != "" { describeAppVersionsRequest.AppId = []string{appId} } if status := conditions.Match["status"]; status != "" { describeAppVersionsRequest.Status = strings.Split(status, "|") } if orderBy != "" { describeAppVersionsRequest.SortKey = &wrappers.StringValue{Value: orderBy} } describeAppVersionsRequest.Reverse = &wrappers.BoolValue{Value: reverse} describeAppVersionsRequest.Limit = uint32(limit) describeAppVersionsRequest.Offset = uint32(offset) resp, err := c.opClient.DescribeAppVersions(openpitrix.SystemContext(), describeAppVersionsRequest) if err != nil { klog.Error(err) return nil, err } items := make([]interface{}, 0) for _, item := range resp.AppVersionSet { appVersion := convertAppVersion(item) items = append(items, appVersion) } return &models.PageableResponse{Items: items, TotalCount: int(resp.TotalCount)}, nil }