diff --git a/.github/workflows/apiserver-test.yaml b/.github/workflows/apiserver-test.yaml index f13ee9618..e12a17730 100644 --- a/.github/workflows/apiserver-test.yaml +++ b/.github/workflows/apiserver-test.yaml @@ -99,6 +99,9 @@ jobs: kind create cluster --image kindest/node:${{ matrix.k8s-version }} kubectl version kubectl cluster-info + + - name: Run api server unit test + run: make unit-test-apiserver - name: Load Image to kind cluster run: make kind-load @@ -114,9 +117,6 @@ jobs: kubectl wait --for=condition=Ready pod -l app=source-controller -n flux-system --timeout=600s kubectl wait --for=condition=Ready pod -l app=helm-controller -n flux-system --timeout=600s - - name: Run api server unit test - run: make unit-test-apiserver - - name: Run api server e2e test run: | export ALIYUN_ACCESS_KEY_ID=${{ secrets.ALIYUN_ACCESS_KEY_ID }} diff --git a/cmd/apiserver/main.go b/cmd/apiserver/main.go index e7f1872d5..ba479b75d 100644 --- a/cmd/apiserver/main.go +++ b/cmd/apiserver/main.go @@ -30,23 +30,24 @@ import ( "github.com/go-openapi/spec" "github.com/google/uuid" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/rest" + "github.com/oam-dev/kubevela/pkg/apiserver" + "github.com/oam-dev/kubevela/pkg/apiserver/config" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/version" ) func main() { s := &Server{} - flag.StringVar(&s.restCfg.BindAddr, "bind-addr", "0.0.0.0:8000", "The bind address used to serve the http APIs.") - flag.StringVar(&s.restCfg.MetricPath, "metrics-path", "/metrics", "The path to expose the metrics.") - flag.StringVar(&s.restCfg.Datastore.Type, "datastore-type", "kubeapi", "Metadata storage driver type, support kubeapi and mongodb") - flag.StringVar(&s.restCfg.Datastore.Database, "datastore-database", "kubevela", "Metadata storage database name, takes effect when the storage driver is mongodb.") - flag.StringVar(&s.restCfg.Datastore.URL, "datastore-url", "", "Metadata storage database url,takes effect when the storage driver is mongodb.") - flag.StringVar(&s.restCfg.LeaderConfig.ID, "id", uuid.New().String(), "the holder identity name") - flag.StringVar(&s.restCfg.LeaderConfig.LockName, "lock-name", "apiserver-lock", "the lease lock resource name") - flag.DurationVar(&s.restCfg.LeaderConfig.Duration, "duration", time.Second*5, "the lease lock resource name") - flag.DurationVar(&s.restCfg.AddonCacheTime, "addon-cache-duration", time.Minute*10, "how long between two addon cache operation") - flag.BoolVar(&s.restCfg.DisableStatisticCronJob, "disable-statistic-cronJob", false, "close the system statistic info calculating cronJob") + flag.StringVar(&s.serverConfig.BindAddr, "bind-addr", "0.0.0.0:8000", "The bind address used to serve the http APIs.") + flag.StringVar(&s.serverConfig.MetricPath, "metrics-path", "/metrics", "The path to expose the metrics.") + flag.StringVar(&s.serverConfig.Datastore.Type, "datastore-type", "kubeapi", "Metadata storage driver type, support kubeapi and mongodb") + flag.StringVar(&s.serverConfig.Datastore.Database, "datastore-database", "kubevela", "Metadata storage database name, takes effect when the storage driver is mongodb.") + flag.StringVar(&s.serverConfig.Datastore.URL, "datastore-url", "", "Metadata storage database url,takes effect when the storage driver is mongodb.") + flag.StringVar(&s.serverConfig.LeaderConfig.ID, "id", uuid.New().String(), "the holder identity name") + flag.StringVar(&s.serverConfig.LeaderConfig.LockName, "lock-name", "apiserver-lock", "the lease lock resource name") + flag.DurationVar(&s.serverConfig.LeaderConfig.Duration, "duration", time.Second*5, "the lease lock resource name") + flag.DurationVar(&s.serverConfig.AddonCacheTime, "addon-cache-duration", time.Minute*10, "how long between two addon cache operation") + flag.BoolVar(&s.serverConfig.DisableStatisticCronJob, "disable-statistic-cronJob", false, "close the system statistic info calculating cronJob") flag.Parse() if len(os.Args) > 2 && os.Args[1] == "build-swagger" { @@ -77,14 +78,13 @@ func main() { return } - srvc := make(chan struct{}) + errChan := make(chan error) ctx, cancel := context.WithCancel(context.Background()) - + defer cancel() go func() { - if err := s.run(ctx); err != nil { - log.Logger.Errorf("failed to run apiserver: %v", err) + if err := s.run(ctx, errChan); err != nil { + errChan <- fmt.Errorf("failed to run apiserver: %w", err) } - close(srvc) }() var term = make(chan os.Signal, 1) signal.Notify(term, os.Interrupt, syscall.SIGTERM) @@ -92,34 +92,36 @@ func main() { select { case <-term: log.Logger.Infof("Received SIGTERM, exiting gracefully...") - cancel() - case <-srvc: - cancel() - os.Exit(1) + case err := <-errChan: + log.Logger.Errorf("Received an error: %s, exiting gracefully...", err.Error()) } log.Logger.Infof("See you next time!") } // Server apiserver type Server struct { - restCfg rest.Config + serverConfig config.Config } -func (s *Server) run(ctx context.Context) error { +func (s *Server) run(ctx context.Context, errChan chan error) error { log.Logger.Infof("KubeVela information: version: %v, gitRevision: %v", version.VelaVersion, version.GitRevision) - server, err := rest.New(s.restCfg) + server, err := apiserver.New(s.serverConfig) if err != nil { return fmt.Errorf("create apiserver failed : %w ", err) } - return server.Run(ctx) + return server.Run(ctx, errChan) } func (s *Server) buildSwagger() (*spec.Swagger, error) { - server, err := rest.New(s.restCfg) + server, err := apiserver.New(s.serverConfig) if err != nil { - return nil, fmt.Errorf("create apiserver failed : %w ", err) + return nil, err } - return restfulspec.BuildSwagger(server.RegisterServices(context.Background(), false)), nil + config, err := server.BuildRestfulConfig() + if err != nil { + return nil, err + } + return restfulspec.BuildSwagger(*config), nil } diff --git a/docs/apidoc/swagger.json b/docs/apidoc/swagger.json index 2ca605151..a628c1761 100644 --- a/docs/apidoc/swagger.json +++ b/docs/apidoc/swagger.json @@ -4644,6 +4644,55 @@ } } }, + "/api/v1/projects/{projectName}/validate_image": { + "get": { + "consumes": [ + "application/xml", + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "tags": [ + "project" + ], + "summary": "validate an image in a project", + "operationId": "validateImage", + "parameters": [ + { + "type": "string", + "description": "image name", + "name": "image", + "in": "query" + }, + { + "type": "string", + "description": "identifier of the project", + "name": "projectName", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/*v1.ImageResponse" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/bcode.Bcode" + } + } + } + } + }, "/api/v1/query": { "get": { "consumes": [ @@ -5683,6 +5732,7 @@ "*v1.ApplicationTriggerBase": {}, "*v1.Config": {}, "*v1.EmptyResponse": {}, + "*v1.ImageResponse": {}, "addon.Dependency": { "properties": { "name": { @@ -5752,8 +5802,14 @@ }, "addon.HelmSource": { "properties": { + "password": { + "type": "string" + }, "url": { "type": "string" + }, + "username": { + "type": "string" } } }, @@ -6722,6 +6778,9 @@ "updateTime": { "type": "string", "format": "date-time" + }, + "workloadType": { + "$ref": "#/definitions/common.WorkloadTypeDescriptor" } } }, @@ -6838,8 +6897,8 @@ }, "model.Cluster": { "required": [ - "updateTime", "createTime", + "updateTime", "name", "alias", "description", @@ -7547,12 +7606,12 @@ }, "v1.ApplicationDeployResponse": { "required": [ - "version", - "status", + "note", + "envName", "triggerType", "createTime", - "note", - "envName" + "version", + "status" ], "properties": { "codeInfo": { @@ -8057,6 +8116,9 @@ "updateTime": { "type": "string", "format": "date-time" + }, + "workloadType": { + "$ref": "#/definitions/common.WorkloadTypeDescriptor" } } }, @@ -8714,11 +8776,11 @@ }, "v1.DetailAddonResponse": { "required": [ - "icon", - "description", - "invisible", "name", "version", + "description", + "icon", + "invisible", "schema", "uiSchema", "definitions", @@ -8798,25 +8860,21 @@ }, "v1.DetailApplicationResponse": { "required": [ - "name", - "description", - "alias", "project", + "description", "createTime", - "updateTime", "icon", + "alias", + "updateTime", + "name", "policies", "envBindings", - "applicationType", "resourceInfo" ], "properties": { "alias": { "type": "string" }, - "applicationType": { - "type": "string" - }, "createTime": { "type": "string", "format": "date-time" @@ -8865,20 +8923,20 @@ }, "v1.DetailClusterResponse": { "required": [ + "kubeConfig", "name", + "description", "apiServerURL", - "labels", "status", + "reason", + "icon", "provider", "kubeConfigSecret", - "kubeConfig", - "updateTime", - "createTime", - "alias", - "description", - "icon", - "reason", + "labels", "dashboardURL", + "createTime", + "updateTime", + "alias", "resourceInfo" ], "properties": { @@ -8936,14 +8994,14 @@ }, "v1.DetailComponentResponse": { "required": [ - "creator", - "name", - "main", - "updateTime", - "appPrimaryKey", - "createTime", "alias", + "updateTime", + "name", "type", + "main", + "createTime", + "appPrimaryKey", + "creator", "definition" ], "properties": { @@ -9023,17 +9081,20 @@ "updateTime": { "type": "string", "format": "date-time" + }, + "workloadType": { + "$ref": "#/definitions/common.WorkloadTypeDescriptor" } } }, "v1.DetailDefinitionResponse": { "required": [ - "alias", - "icon", + "name", "status", "labels", - "name", + "alias", "description", + "icon", "schema", "uiSchema" ], @@ -9091,6 +9152,7 @@ "properties", "createTime", "updateTime", + "envName", "name", "type", "description" @@ -9106,6 +9168,9 @@ "description": { "type": "string" }, + "envName": { + "type": "string" + }, "name": { "type": "string" }, @@ -9123,17 +9188,17 @@ }, "v1.DetailRevisionResponse": { "required": [ - "reason", - "deployUser", - "triggerType", - "createTime", + "updateTime", "note", + "triggerType", + "reason", + "envName", + "createTime", + "deployUser", "appPrimaryKey", "version", "status", - "workflowName", - "envName", - "updateTime" + "workflowName" ], "properties": { "appPrimaryKey": { @@ -9187,9 +9252,9 @@ }, "v1.DetailTargetResponse": { "required": [ + "name", "createTime", "project", - "name", "updateTime" ], "properties": { @@ -9230,11 +9295,11 @@ }, "v1.DetailUserResponse": { "required": [ - "email", - "disabled", "createTime", "lastLoginTime", "name", + "email", + "disabled", "projects", "roles" ], @@ -9332,14 +9397,14 @@ }, "v1.DetailWorkflowResponse": { "required": [ - "name", + "createTime", "alias", "description", "enable", - "envName", + "updateTime", + "name", "default", - "createTime", - "updateTime" + "envName" ], "properties": { "alias": { @@ -9918,11 +9983,11 @@ }, "v1.LoginUserInfoResponse": { "required": [ + "lastLoginTime", + "name", "email", "disabled", "createTime", - "lastLoginTime", - "name", "projects", "platformPermissions", "projectPermissions" @@ -10068,7 +10133,8 @@ "creator", "properties", "createTime", - "updateTime" + "updateTime", + "envName" ], "properties": { "createTime": { @@ -10081,6 +10147,9 @@ "description": { "type": "string" }, + "envName": { + "type": "string" + }, "name": { "type": "string" }, diff --git a/go.mod b/go.mod index a77f9fcf9..e2a64cb62 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/alibabacloud-go/darabonba-openapi v0.1.4 github.com/alibabacloud-go/tea v1.1.15 github.com/aryann/difflib v0.0.0-20210328193216-ff5ff6dc229b + github.com/barnettZQG/inject v0.0.1 github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 github.com/briandowns/spinner v1.11.1 github.com/containerd/containerd v1.5.10 @@ -165,6 +166,7 @@ require ( github.com/emirpasic/gods v1.12.0 // indirect github.com/evanphx/json-patch/v5 v5.1.0 // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect + github.com/facebookgo/structtag v0.0.0-20150214074306-217e25fb9691 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/fvbommel/sortorder v1.0.1 // indirect diff --git a/go.sum b/go.sum index f55477033..4c0cfd122 100644 --- a/go.sum +++ b/go.sum @@ -303,6 +303,8 @@ github.com/aws/aws-sdk-go v1.36.30 h1:hAwyfe7eZa7sM+S5mIJZFiNFwJMia9Whz6CYblioLo github.com/aws/aws-sdk-go v1.36.30/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= +github.com/barnettZQG/inject v0.0.1 h1:VjJHLxvl47FynKZEC3rpMZJYsNZmvP0Eaxucl9LqiwI= +github.com/barnettZQG/inject v0.0.1/go.mod h1:o83X2SlEKFliJx6UHai8bzFj+5isdBfOZsl6nQ2nT3M= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -643,6 +645,14 @@ github.com/evanphx/json-patch/v5 v5.1.0 h1:B0aXl1o/1cP8NbviYiBMkcHBtUjIJ1/Ccg6b+ github.com/evanphx/json-patch/v5 v5.1.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/structtag v0.0.0-20150214074306-217e25fb9691 h1:KnnwHN59Jxec0htA2pe/i0/WI9vxXLQifdhBrP3lqcQ= +github.com/facebookgo/structtag v0.0.0-20150214074306-217e25fb9691/go.mod h1:sKLL1iua/0etWfo/nPCmyz+v2XDMXy+Ho53W7RAuZNY= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW64qjjJq8M2u4dxNaBiDfKK+z/3eGDpXEQhc= github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= diff --git a/pkg/addon/cache.go b/pkg/addon/cache.go index d3c464df9..de68e5fe0 100644 --- a/pkg/addon/cache.go +++ b/pkg/addon/cache.go @@ -23,7 +23,7 @@ import ( "sync" "time" - "github.com/oam-dev/kubevela/pkg/apiserver/log" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/utils" "github.com/oam-dev/kubevela/pkg/utils/common" ) diff --git a/pkg/addon/type.go b/pkg/addon/type.go index d921ed8e3..ec50255c7 100644 --- a/pkg/addon/type.go +++ b/pkg/addon/type.go @@ -20,7 +20,7 @@ import ( "github.com/getkin/kin-openapi/openapi3" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" ) // UIData contains all information represent an addon for UI diff --git a/pkg/apiserver/README.md b/pkg/apiserver/README.md new file mode 100644 index 000000000..90f1ef1e1 --- /dev/null +++ b/pkg/apiserver/README.md @@ -0,0 +1,48 @@ +# APIServer Module Architecture + +![apiserver architecture](./apiserver.jpg) + +## Interfaces + +Typically, it includes user interfaces, web services, and so on. + +* API + +Define the Restful API and perform basic validation on user input parameters. + +* DTO + +The carrier of data transmission. Here does not have any business logic inside, and the internal domain models can be isolated from the outside world through DTO. + +* Assembler + +Realize the mutual conversion and data exchange between DTO and DO. + +## Event + +Asynchronous task module. All workers under this module only run on the master node. Domain layer can be called. + +## Domain + +Code related to core business logic. + +* Service + +A domain service is a piece of business logic composed of multiple entities. You can put all domain services in the aggregate in one domain service class, or you can design each domain service as a class. + +* Repository + +Usually includes repository interface and repository implementation method. In order to facilitate the splitting and combination of aggregates, the principle is set: one aggregate corresponds to one repository. For example, save user information to a database. + +* Model + +Database model entity. + +## Infrastructure + +Provide general technical basic services for other layers, such as: + +* Database +* Cache +* Kube Client +* MQ diff --git a/pkg/apiserver/apiserver.jpg b/pkg/apiserver/apiserver.jpg new file mode 100644 index 000000000..e506e5736 Binary files /dev/null and b/pkg/apiserver/apiserver.jpg differ diff --git a/pkg/apiserver/config/config.go b/pkg/apiserver/config/config.go new file mode 100644 index 000000000..617d60a2b --- /dev/null +++ b/pkg/apiserver/config/config.go @@ -0,0 +1,49 @@ +/* +Copyright 2022 The KubeVela 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 config + +import ( + "time" + + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" +) + +// Config config for server +type Config struct { + // api server bind address + BindAddr string + // monitor metric path + MetricPath string + + // Datastore config + Datastore datastore.Config + + // LeaderConfig for leader election + LeaderConfig leaderConfig + + // AddonCacheTime is how long between two cache operations + AddonCacheTime time.Duration + + // DisableStatisticCronJob close the calculate system info cronJob + DisableStatisticCronJob bool +} + +type leaderConfig struct { + ID string + LockName string + Duration time.Duration +} diff --git a/pkg/apiserver/model/application.go b/pkg/apiserver/domain/model/application.go similarity index 100% rename from pkg/apiserver/model/application.go rename to pkg/apiserver/domain/model/application.go diff --git a/pkg/apiserver/model/cluster.go b/pkg/apiserver/domain/model/cluster.go similarity index 100% rename from pkg/apiserver/model/cluster.go rename to pkg/apiserver/domain/model/cluster.go diff --git a/pkg/apiserver/model/env.go b/pkg/apiserver/domain/model/env.go similarity index 100% rename from pkg/apiserver/model/env.go rename to pkg/apiserver/domain/model/env.go diff --git a/pkg/apiserver/model/envbinding.go b/pkg/apiserver/domain/model/envbinding.go similarity index 100% rename from pkg/apiserver/model/envbinding.go rename to pkg/apiserver/domain/model/envbinding.go diff --git a/pkg/apiserver/model/model.go b/pkg/apiserver/domain/model/model.go similarity index 98% rename from pkg/apiserver/model/model.go rename to pkg/apiserver/domain/model/model.go index 57fe45c50..503c1bf11 100644 --- a/pkg/apiserver/model/model.go +++ b/pkg/apiserver/domain/model/model.go @@ -25,7 +25,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/yaml" - "github.com/oam-dev/kubevela/pkg/apiserver/log" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" ) var tableNamePrefix = "vela_" diff --git a/pkg/apiserver/model/project.go b/pkg/apiserver/domain/model/project.go similarity index 100% rename from pkg/apiserver/model/project.go rename to pkg/apiserver/domain/model/project.go diff --git a/pkg/apiserver/model/system_info.go b/pkg/apiserver/domain/model/system_info.go similarity index 100% rename from pkg/apiserver/model/system_info.go rename to pkg/apiserver/domain/model/system_info.go diff --git a/pkg/apiserver/model/target.go b/pkg/apiserver/domain/model/target.go similarity index 100% rename from pkg/apiserver/model/target.go rename to pkg/apiserver/domain/model/target.go diff --git a/pkg/apiserver/model/user.go b/pkg/apiserver/domain/model/user.go similarity index 100% rename from pkg/apiserver/model/user.go rename to pkg/apiserver/domain/model/user.go diff --git a/pkg/apiserver/model/whole.go b/pkg/apiserver/domain/model/whole.go similarity index 100% rename from pkg/apiserver/model/whole.go rename to pkg/apiserver/domain/model/whole.go diff --git a/pkg/apiserver/model/workflow.go b/pkg/apiserver/domain/model/workflow.go similarity index 100% rename from pkg/apiserver/model/workflow.go rename to pkg/apiserver/domain/model/workflow.go diff --git a/pkg/apiserver/rest/usecase/env_model.go b/pkg/apiserver/domain/repository/env.go similarity index 80% rename from pkg/apiserver/rest/usecase/env_model.go rename to pkg/apiserver/domain/repository/env.go index 7abd4454d..7b30dbca7 100644 --- a/pkg/apiserver/rest/usecase/env_model.go +++ b/pkg/apiserver/domain/repository/env.go @@ -14,7 +14,7 @@ limitations under the License. */ -package usecase +package repository import ( "context" @@ -22,16 +22,17 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/oam" util "github.com/oam-dev/kubevela/pkg/utils" velaerr "github.com/oam-dev/kubevela/pkg/utils/errors" ) -func createEnv(ctx context.Context, kubeClient client.Client, ds datastore.DataStore, env *model.Env) error { +// CreateEnv create the environment +func CreateEnv(ctx context.Context, kubeClient client.Client, ds datastore.DataStore, env *model.Env) error { tenv := &model.Env{} tenv.Name = env.Name @@ -67,7 +68,8 @@ func createEnv(ctx context.Context, kubeClient client.Client, ds datastore.DataS return nil } -func getEnv(ctx context.Context, ds datastore.DataStore, envName string) (*model.Env, error) { +// GetEnv get the environment +func GetEnv(ctx context.Context, ds datastore.DataStore, envName string) (*model.Env, error) { env := &model.Env{} env.Name = envName if err := ds.Get(ctx, env); err != nil { @@ -79,7 +81,8 @@ func getEnv(ctx context.Context, ds datastore.DataStore, envName string) (*model return env, nil } -func listEnvs(ctx context.Context, ds datastore.DataStore, listOption *datastore.ListOptions) ([]*model.Env, error) { +// ListEnvs list the environments +func ListEnvs(ctx context.Context, ds datastore.DataStore, listOption *datastore.ListOptions) ([]*model.Env, error) { var env = model.Env{} entities, err := ds.List(ctx, &env, listOption) if err != nil { diff --git a/pkg/apiserver/domain/repository/envbinding.go b/pkg/apiserver/domain/repository/envbinding.go new file mode 100644 index 000000000..67acdbb45 --- /dev/null +++ b/pkg/apiserver/domain/repository/envbinding.go @@ -0,0 +1,112 @@ +/* + Copyright 2021 The KubeVela 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 repository + +import ( + "context" + + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + assembler "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/assembler/v1" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" +) + +const ( + // EnvBindingPolicyDefaultName default policy name + EnvBindingPolicyDefaultName string = "env-bindings" +) + +// EnvListOption the option for listing the env +type EnvListOption struct { + AppPrimaryKey string + EnvName string + ProjectName string +} + +// ListFullEnvBinding list the envbinding and convert to DTO +func ListFullEnvBinding(ctx context.Context, ds datastore.DataStore, option EnvListOption) ([]*apisv1.EnvBindingBase, error) { + envBindings, err := ListEnvBindings(ctx, ds, option) + if err != nil { + return nil, bcode.ErrEnvBindingsNotExist + } + targets, err := ListTarget(ctx, ds, option.ProjectName, nil) + if err != nil { + return nil, err + } + var listOption *datastore.ListOptions + if option.ProjectName != "" { + listOption = &datastore.ListOptions{ + FilterOptions: datastore.FilterOptions{ + In: []datastore.InQueryOption{ + { + Key: "project", + Values: []string{option.ProjectName}, + }, + }, + }, + } + } + envs, err := ListEnvs(ctx, ds, listOption) + if err != nil { + return nil, err + } + var list []*apisv1.EnvBindingBase + for _, eb := range envBindings { + env, err := pickEnv(envs, eb.Name) + if err != nil { + log.Logger.Errorf("envbinding invalid %s", err.Error()) + continue + } + list = append(list, assembler.ConvertEnvBindingModelToBase(eb, env, targets)) + } + return list, nil +} + +// ListEnvBindings list the envbinding +func ListEnvBindings(ctx context.Context, ds datastore.DataStore, listOption EnvListOption) ([]*model.EnvBinding, error) { + var envBinding = model.EnvBinding{} + if listOption.AppPrimaryKey != "" { + envBinding.AppPrimaryKey = listOption.AppPrimaryKey + } + if listOption.EnvName != "" { + envBinding.Name = listOption.EnvName + } + envBindings, err := ds.List(ctx, &envBinding, &datastore.ListOptions{}) + if err != nil { + return nil, err + } + var ret []*model.EnvBinding + for _, et := range envBindings { + eb, ok := et.(*model.EnvBinding) + if !ok { + continue + } + ret = append(ret, eb) + } + return ret, nil +} + +func pickEnv(envs []*model.Env, name string) (*model.Env, error) { + for _, e := range envs { + if e.Name == name { + return e, nil + } + } + return nil, bcode.ErrEnvNotExisted +} diff --git a/pkg/apiserver/domain/repository/suite_test.go b/pkg/apiserver/domain/repository/suite_test.go new file mode 100644 index 000000000..67a19ab47 --- /dev/null +++ b/pkg/apiserver/domain/repository/suite_test.go @@ -0,0 +1,117 @@ +/* +Copyright 2021 The KubeVela 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 repository + +import ( + "context" + "fmt" + "math/rand" + "testing" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8stypes "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/rest" + "k8s.io/utils/pointer" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + + "github.com/oam-dev/kubevela/apis/types" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore/kubeapi" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore/mongodb" + "github.com/oam-dev/kubevela/pkg/utils/common" +) + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment + +func TestService(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Service Suite") +} + +var _ = BeforeSuite(func(done Done) { + rand.Seed(time.Now().UnixNano()) + By("bootstrapping test environment") + + testEnv = &envtest.Environment{ + ControlPlaneStartTimeout: time.Minute * 3, + ControlPlaneStopTimeout: time.Minute, + UseExistingCluster: pointer.BoolPtr(false), + CRDDirectoryPaths: []string{"../../../../charts/vela-core/crds"}, + } + + By("start kube test env") + var err error + cfg, err = testEnv.Start() + Expect(err).ShouldNot(HaveOccurred()) + Expect(cfg).ToNot(BeNil()) + + By("new kube client") + cfg.Timeout = time.Minute * 2 + k8sClient, err = client.New(cfg, client.Options{Scheme: common.Scheme}) + Expect(err).Should(BeNil()) + Expect(k8sClient).ToNot(BeNil()) + By("new kube client success") + clients.SetKubeClient(k8sClient) + Expect(err).Should(BeNil()) + + var namespace corev1.Namespace + err = k8sClient.Get(context.TODO(), k8stypes.NamespacedName{Name: types.DefaultKubeVelaNS}, &namespace) + if apierrors.IsNotFound(err) { + err := k8sClient.Create(context.TODO(), &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: types.DefaultKubeVelaNS, + }, + }) + Expect(err).Should(BeNil()) + } else { + Expect(err).Should(BeNil()) + } + close(done) +}, 240) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).ToNot(HaveOccurred()) +}) + +func NewDatastore(cfg datastore.Config) (ds datastore.DataStore, err error) { + switch cfg.Type { + case "mongodb": + ds, err = mongodb.New(context.Background(), cfg) + if err != nil { + return nil, fmt.Errorf("create mongodb datastore instance failure %w", err) + } + case "kubeapi": + ds, err = kubeapi.New(context.Background(), cfg) + if err != nil { + return nil, fmt.Errorf("create mongodb datastore instance failure %w", err) + } + default: + return nil, fmt.Errorf("not support datastore type %s", cfg.Type) + } + return ds, nil +} diff --git a/pkg/apiserver/rest/usecase/target_model.go b/pkg/apiserver/domain/repository/target.go similarity index 81% rename from pkg/apiserver/rest/usecase/target_model.go rename to pkg/apiserver/domain/repository/target.go index 2a5042656..2f4a793a5 100644 --- a/pkg/apiserver/rest/usecase/target_model.go +++ b/pkg/apiserver/domain/repository/target.go @@ -14,7 +14,7 @@ limitations under the License. */ -package usecase +package repository import ( "context" @@ -22,17 +22,18 @@ import ( apierror "k8s.io/apimachinery/pkg/api/errors" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/multicluster" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/utils" velaerr "github.com/oam-dev/kubevela/pkg/utils/errors" ) -func createTargetNamespace(ctx context.Context, k8sClient client.Client, clusterName, namespace, targetName string) error { +// CreateTargetNamespace create the namespace of the target +func CreateTargetNamespace(ctx context.Context, k8sClient client.Client, clusterName, namespace, targetName string) error { if clusterName == "" || namespace == "" { return bcode.ErrTargetInvalidWithEmptyClusterOrNamespace } @@ -51,7 +52,8 @@ func createTargetNamespace(ctx context.Context, k8sClient client.Client, cluster return nil } -func deleteTargetNamespace(ctx context.Context, k8sClient client.Client, clusterName, namespace, targetName string) error { +// DeleteTargetNamespace delete the namespace of the target +func DeleteTargetNamespace(ctx context.Context, k8sClient client.Client, clusterName, namespace, targetName string) error { err := utils.UpdateNamespace(multicluster.ContextWithClusterName(ctx, clusterName), k8sClient, namespace, // check no conflict label first to make sure the namespace belong to the target, then override it utils.MergeNoConflictLabels(map[string]string{ @@ -67,7 +69,8 @@ func deleteTargetNamespace(ctx context.Context, k8sClient client.Client, cluster return err } -func createTarget(ctx context.Context, ds datastore.DataStore, tg *model.Target) error { +// CreateTarget create a target +func CreateTarget(ctx context.Context, ds datastore.DataStore, tg *model.Target) error { // check Target name. exit, err := ds.IsExist(ctx, tg) if err != nil { @@ -85,7 +88,8 @@ func createTarget(ctx context.Context, ds datastore.DataStore, tg *model.Target) return nil } -func listTarget(ctx context.Context, ds datastore.DataStore, project string, dsOption *datastore.ListOptions) ([]*model.Target, error) { +// ListTarget list the targets +func ListTarget(ctx context.Context, ds datastore.DataStore, project string, dsOption *datastore.ListOptions) ([]*model.Target, error) { if dsOption == nil { dsOption = &datastore.ListOptions{} } diff --git a/pkg/apiserver/rest/usecase/workflow_model.go b/pkg/apiserver/domain/repository/workflow.go similarity index 91% rename from pkg/apiserver/rest/usecase/workflow_model.go rename to pkg/apiserver/domain/repository/workflow.go index a1a29c259..58aef23d3 100644 --- a/pkg/apiserver/rest/usecase/workflow_model.go +++ b/pkg/apiserver/domain/repository/workflow.go @@ -14,7 +14,7 @@ limitations under the License. */ -package usecase +package repository import ( "context" @@ -30,11 +30,11 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/oam/util" utils2 "github.com/oam-dev/kubevela/pkg/utils" "github.com/oam-dev/kubevela/pkg/workflow/step" @@ -55,6 +55,17 @@ const ( modifyState ) +const ( + // Deploy2Env deploy app to target cluster, suitable for common applications + Deploy2Env string = "deploy2env" + // DeployCloudResource deploy app to local and copy secret to target cluster, suitable for cloud application. + DeployCloudResource string = "deploy-cloud-resource" + // TerraformWorkloadType cloud application + TerraformWorkloadType string = "configurations.terraform.core.oam.dev" + // TerraformWorkloadKind terraform workload kind + TerraformWorkloadKind string = "Configuration" +) + type workflowStep struct { name string stepType string @@ -325,7 +336,7 @@ func compareWorkflowSteps(old, new steps) steps { func UpdateEnvWorkflow(ctx context.Context, kubeClient client.Client, ds datastore.DataStore, app *model.Application, env *model.Env) error { // The existing step configuration should be maintained and the delivery target steps should be automatically updated. envSteps, policies := GenEnvWorkflowStepsAndPolicies(ctx, kubeClient, ds, env, app) - workflow, err := getWorkflowForApp(ctx, ds, app, convertWorkflowName(env.Name)) + workflow, err := GetWorkflowForApp(ctx, ds, app, ConvertWorkflowName(env.Name)) if err != nil { // no workflow exist mean no need to update if errors.Is(err, bcode.ErrWorkflowNotExist) { @@ -349,7 +360,7 @@ func UpdateEnvWorkflow(ctx context.Context, kubeClient client.Client, ds datasto workflowSteps := compareWorkflowSteps(createWorkflowSteps(workflow.Steps, existPolicies), createWorkflowSteps(envSteps, policies)) // update the workflow - if err := updateWorkflowSteps(ctx, ds, workflow, workflowSteps.getSteps(envSteps, workflow.Steps)); err != nil { + if err := UpdateWorkflowSteps(ctx, ds, workflow, workflowSteps.getSteps(envSteps, workflow.Steps)); err != nil { return fmt.Errorf("fail to update the workflow steps %w", err) } @@ -378,7 +389,7 @@ func UpdateEnvWorkflow(ctx context.Context, kubeClient client.Client, ds datasto // UpdateAppEnvWorkflow will update the all env workflows internally of the specified app func UpdateAppEnvWorkflow(ctx context.Context, kubeClient client.Client, ds datastore.DataStore, app *model.Application) error { - envbindings, err := listEnvBindings(ctx, ds, envListOption{appPrimaryKey: app.PrimaryKey(), projectName: app.Project}) + envbindings, err := ListEnvBindings(ctx, ds, EnvListOption{AppPrimaryKey: app.PrimaryKey(), ProjectName: app.Project}) if err != nil { return err } @@ -389,7 +400,7 @@ func UpdateAppEnvWorkflow(ctx context.Context, kubeClient client.Client, ds data if len(envNames) == 0 { return nil } - envs, err := listEnvs(ctx, ds, &datastore.ListOptions{ + envs, err := ListEnvs(ctx, ds, &datastore.ListOptions{ FilterOptions: datastore.FilterOptions{ In: []datastore.InQueryOption{ { @@ -407,7 +418,7 @@ func UpdateAppEnvWorkflow(ctx context.Context, kubeClient client.Client, ds data log.Logger.Errorf("fail to update the env workflow %s", envs[i].PrimaryKey()) } } - log.Logger.Infof("The env workflows of app %s updated successfully", app.PrimaryKey()) + log.Logger.Infof("The env workflows of app %s updated successfully", utils2.Sanitize(app.PrimaryKey())) return nil } @@ -606,7 +617,14 @@ func GenEnvWorkflowStepsAndPolicies(ctx context.Context, kubeClient client.Clien return steps, policies } -func getWorkflowForApp(ctx context.Context, ds datastore.DataStore, app *model.Application, workflowName string) (*model.Workflow, error) { +// UpdateWorkflowSteps will update workflow with new steps +func UpdateWorkflowSteps(ctx context.Context, ds datastore.DataStore, workflow *model.Workflow, steps []model.WorkflowStep) error { + workflow.Steps = steps + return ds.Put(ctx, workflow) +} + +// GetWorkflowForApp get the specified workflow of the application +func GetWorkflowForApp(ctx context.Context, ds datastore.DataStore, app *model.Application, workflowName string) (*model.Workflow, error) { var workflow = model.Workflow{ Name: workflowName, AppPrimaryKey: app.PrimaryKey(), @@ -619,3 +637,16 @@ func getWorkflowForApp(ctx context.Context, ds datastore.DataStore, app *model.A } return &workflow, nil } + +// ConvertWorkflowName generate the workflow name +func ConvertWorkflowName(envName string) string { + return fmt.Sprintf("workflow-%s", envName) +} + +func genPolicyName(envName string) string { + return fmt.Sprintf("%s-%s", EnvBindingPolicyDefaultName, envName) +} + +func genPolicyEnvName(targetName string) string { + return targetName +} diff --git a/pkg/apiserver/rest/usecase/workflow_model_test.go b/pkg/apiserver/domain/repository/workflow_test.go similarity index 72% rename from pkg/apiserver/rest/usecase/workflow_model_test.go rename to pkg/apiserver/domain/repository/workflow_test.go index f923ce810..4d8ce24a1 100644 --- a/pkg/apiserver/rest/usecase/workflow_model_test.go +++ b/pkg/apiserver/domain/repository/workflow_test.go @@ -14,24 +14,27 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package repository import ( "context" + "fmt" "testing" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" + utils2 "github.com/oam-dev/kubevela/pkg/utils" ) func TestCompareWorkflowSteps(t *testing.T) { @@ -171,26 +174,14 @@ func TestCompareWorkflowSteps(t *testing.T) { } var _ = Describe("Test workflow model", func() { - var ds datastore.DataStore - var ( - envUsecase *envUsecaseImpl - envBindingUsecase *envBindingUsecaseImpl - workflowUsecase *workflowUsecaseImpl - definitionUsecase DefinitionUsecase - ) + var store datastore.DataStore BeforeEach(func() { var err error - ds, err = NewDatastore(datastore.Config{Type: "kubeapi", Database: "workflow-test-kubevela"}) - Expect(ds).ToNot(BeNil()) + store, err = NewDatastore(datastore.Config{Type: "kubeapi", Database: "workflow-test-kubevela"}) Expect(err).Should(BeNil()) - rbacUsecase := &rbacUsecaseImpl{ds: ds} - projectUsecase := &projectUsecaseImpl{ds: ds, k8sClient: k8sClient, rbacUsecase: rbacUsecase} - envUsecase = &envUsecaseImpl{ds: ds, kubeClient: k8sClient, projectUsecase: projectUsecase} - workflowUsecase = &workflowUsecaseImpl{ds: ds, kubeClient: k8sClient, envUsecase: envUsecase} - definitionUsecase = &definitionUsecaseImpl{kubeClient: k8sClient, caches: utils.NewMemoryCacheStore(context.TODO())} - envBindingUsecase = &envBindingUsecaseImpl{ds: ds, workflowUsecase: workflowUsecase, definitionUsecase: definitionUsecase, kubeClient: k8sClient, envUsecase: envUsecase} - + Expect(store).ToNot(BeNil()) }) + It("update the workflow after added a cloud component", func() { definition := &v1beta1.ComponentDefinition{ ObjectMeta: metav1.ObjectMeta{ @@ -230,13 +221,13 @@ var _ = Describe("Test workflow model", func() { Project: "default", Cluster: &model.ClusterTarget{ClusterName: "local", Namespace: "target2"}, } - err = ds.BatchAdd(context.TODO(), []datastore.Entity{app, webComponent, target1, target2, env}) + err = store.BatchAdd(context.TODO(), []datastore.Entity{app, webComponent, target1, target2, env}) Expect(err).Should(BeNil()) - err = envBindingUsecase.createEnvWorkflow(context.TODO(), app, env, true) + err = CreateEnvWorkflow(context.TODO(), store, k8sClient, app, env, true) Expect(err).Should(BeNil()) - workflow, err := workflowUsecase.GetWorkflow(context.TODO(), app, convertWorkflowName(env.Name)) + workflow, err := GetWorkflowForApp(context.TODO(), store, app, ConvertWorkflowName(env.Name)) Expect(err).Should(BeNil()) Expect(len(workflow.Steps)).Should(Equal(2)) @@ -246,18 +237,18 @@ var _ = Describe("Test workflow model", func() { Type: "aliyun-rds", } - err = ds.BatchAdd(context.TODO(), []datastore.Entity{cloudComponent}) + err = store.BatchAdd(context.TODO(), []datastore.Entity{cloudComponent}) Expect(err).Should(BeNil()) - err = UpdateEnvWorkflow(context.Background(), k8sClient, ds, app, env) + err = UpdateEnvWorkflow(context.Background(), k8sClient, store, app, env) Expect(err).Should(BeNil()) - workflow, err = workflowUsecase.GetWorkflow(context.TODO(), app, convertWorkflowName(env.Name)) + workflow, err = GetWorkflowForApp(context.TODO(), store, app, ConvertWorkflowName(env.Name)) Expect(err).Should(BeNil()) Expect(len(workflow.Steps)).Should(Equal(4)) Expect(workflow.Steps[0].Type).Should(Equal(DeployCloudResource)) - entities, err := ds.List(context.TODO(), &model.ApplicationPolicy{AppPrimaryKey: app.PrimaryKey()}, &datastore.ListOptions{ + entities, err := store.List(context.TODO(), &model.ApplicationPolicy{AppPrimaryKey: app.PrimaryKey()}, &datastore.ListOptions{ FilterOptions: datastore.FilterOptions{ In: []datastore.InQueryOption{{ Key: "type", @@ -270,11 +261,11 @@ var _ = Describe("Test workflow model", func() { Expect(entities[0].(*model.ApplicationPolicy).Name).Should(Equal("env-bindings-dev")) By("test the case that delete the cloud component") - err = ds.Delete(context.TODO(), cloudComponent) + err = store.Delete(context.TODO(), cloudComponent) Expect(err).Should(BeNil()) - err = UpdateEnvWorkflow(context.Background(), k8sClient, ds, app, env) + err = UpdateEnvWorkflow(context.Background(), k8sClient, store, app, env) Expect(err).Should(BeNil()) - workflow, err = workflowUsecase.GetWorkflow(context.TODO(), app, convertWorkflowName(env.Name)) + workflow, err = GetWorkflowForApp(context.TODO(), store, app, ConvertWorkflowName(env.Name)) Expect(err).Should(BeNil()) Expect(len(workflow.Steps)).Should(Equal(2)) }) @@ -297,13 +288,13 @@ var _ = Describe("Test workflow model", func() { Targets: []string{"target1", "target2"}, } - err := ds.BatchAdd(context.TODO(), []datastore.Entity{app, cloudComponent}) + err := store.BatchAdd(context.TODO(), []datastore.Entity{app, cloudComponent}) Expect(err).Should(BeNil()) - err = envBindingUsecase.createEnvWorkflow(context.TODO(), app, env, true) + err = CreateEnvWorkflow(context.TODO(), store, k8sClient, app, env, true) Expect(err).Should(BeNil()) - workflow, err := workflowUsecase.GetWorkflow(context.TODO(), app, convertWorkflowName(env.Name)) + workflow, err := GetWorkflowForApp(context.TODO(), store, app, ConvertWorkflowName(env.Name)) Expect(err).Should(BeNil()) Expect(len(workflow.Steps)).Should(Equal(2)) @@ -321,21 +312,21 @@ var _ = Describe("Test workflow model", func() { env.Targets = []string{"target1", "target2", "target3"} - err = ds.Put(context.TODO(), env) + err = store.Put(context.TODO(), env) Expect(err).Should(BeNil()) - err = ds.BatchAdd(context.TODO(), []datastore.Entity{webComponent, target3}) + err = store.BatchAdd(context.TODO(), []datastore.Entity{webComponent, target3}) Expect(err).Should(BeNil()) - err = UpdateEnvWorkflow(context.Background(), k8sClient, ds, app, env) + err = UpdateEnvWorkflow(context.Background(), k8sClient, store, app, env) Expect(err).Should(BeNil()) - workflow, err = workflowUsecase.GetWorkflow(context.TODO(), app, convertWorkflowName(env.Name)) + workflow, err = GetWorkflowForApp(context.TODO(), store, app, ConvertWorkflowName(env.Name)) Expect(err).Should(BeNil()) Expect(len(workflow.Steps)).Should(Equal(6)) Expect(workflow.Steps[0].Type).Should(Equal(DeployCloudResource)) - entities, err := ds.List(context.TODO(), &model.ApplicationPolicy{AppPrimaryKey: app.PrimaryKey()}, &datastore.ListOptions{ + entities, err := store.List(context.TODO(), &model.ApplicationPolicy{AppPrimaryKey: app.PrimaryKey()}, &datastore.ListOptions{ FilterOptions: datastore.FilterOptions{ In: []datastore.InQueryOption{{ Key: "type", @@ -366,13 +357,13 @@ var _ = Describe("Test workflow model", func() { Targets: []string{"target1", "target2"}, } - err := ds.BatchAdd(context.TODO(), []datastore.Entity{app, webComponent}) + err := store.BatchAdd(context.TODO(), []datastore.Entity{app, webComponent}) Expect(err).Should(BeNil()) - err = envBindingUsecase.createEnvWorkflow(context.TODO(), app, env, true) + err = CreateEnvWorkflow(context.TODO(), store, k8sClient, app, env, true) Expect(err).Should(BeNil()) - workflow, err := workflowUsecase.GetWorkflow(context.TODO(), app, convertWorkflowName(env.Name)) + workflow, err := GetWorkflowForApp(context.TODO(), store, app, ConvertWorkflowName(env.Name)) Expect(err).Should(BeNil()) workflow.Steps = []model.WorkflowStep{ @@ -385,18 +376,18 @@ var _ = Describe("Test workflow model", func() { }, } - err = ds.Put(context.TODO(), workflow) + err = store.Put(context.TODO(), workflow) Expect(err).Should(BeNil()) env.Targets = []string{"target1", "target2", "target3"} - err = ds.Put(context.TODO(), env) + err = store.Put(context.TODO(), env) Expect(err).Should(BeNil()) - err = UpdateEnvWorkflow(context.Background(), k8sClient, ds, app, env) + err = UpdateEnvWorkflow(context.Background(), k8sClient, store, app, env) Expect(err).Should(BeNil()) - workflow, err = workflowUsecase.GetWorkflow(context.TODO(), app, convertWorkflowName(env.Name)) + workflow, err = GetWorkflowForApp(context.TODO(), store, app, ConvertWorkflowName(env.Name)) Expect(err).Should(BeNil()) Expect(len(workflow.Steps)).Should(Equal(5)) Expect(workflow.Steps[1].Type).Should(Equal("suspend")) @@ -420,31 +411,31 @@ var _ = Describe("Test workflow model", func() { Targets: []string{"target1", "target2"}, } - err := ds.BatchAdd(context.TODO(), []datastore.Entity{app, webComponent}) + err := store.BatchAdd(context.TODO(), []datastore.Entity{app, webComponent}) Expect(err).Should(BeNil()) - err = envBindingUsecase.createEnvWorkflow(context.TODO(), app, env, true) + err = CreateEnvWorkflow(context.TODO(), store, k8sClient, app, env, true) Expect(err).Should(BeNil()) - workflow, err := workflowUsecase.GetWorkflow(context.TODO(), app, convertWorkflowName(env.Name)) + workflow, err := GetWorkflowForApp(context.TODO(), store, app, ConvertWorkflowName(env.Name)) Expect(err).Should(BeNil()) step := workflow.Steps[0] (*step.Properties)["policies"] = []string{"target1", "target2"} workflow.Steps = []model.WorkflowStep{step} - err = ds.Put(context.TODO(), workflow) + err = store.Put(context.TODO(), workflow) Expect(err).Should(BeNil()) env.Targets = []string{"target1", "target2", "target3"} - err = ds.Put(context.TODO(), env) + err = store.Put(context.TODO(), env) Expect(err).Should(BeNil()) - err = UpdateEnvWorkflow(context.Background(), k8sClient, ds, app, env) + err = UpdateEnvWorkflow(context.Background(), k8sClient, store, app, env) Expect(err).Should(BeNil()) - workflow, err = workflowUsecase.GetWorkflow(context.TODO(), app, convertWorkflowName(env.Name)) + workflow, err = GetWorkflowForApp(context.TODO(), store, app, ConvertWorkflowName(env.Name)) Expect(err).Should(BeNil()) Expect(len(workflow.Steps)).Should(Equal(2)) Expect(workflow.Steps[0].Properties).ShouldNot(BeNil()) @@ -454,13 +445,13 @@ var _ = Describe("Test workflow model", func() { env.Targets = []string{"target2", "target3"} - err = ds.Put(context.TODO(), env) + err = store.Put(context.TODO(), env) Expect(err).Should(BeNil()) - err = UpdateEnvWorkflow(context.Background(), k8sClient, ds, app, env) + err = UpdateEnvWorkflow(context.Background(), k8sClient, store, app, env) Expect(err).Should(BeNil()) - workflow, err = workflowUsecase.GetWorkflow(context.TODO(), app, convertWorkflowName(env.Name)) + workflow, err = GetWorkflowForApp(context.TODO(), store, app, ConvertWorkflowName(env.Name)) Expect(err).Should(BeNil()) Expect(len(workflow.Steps)).Should(Equal(2)) // the concurrent step should be kept. @@ -469,7 +460,7 @@ var _ = Describe("Test workflow model", func() { Expect((*workflow.Steps[0].Properties)["policies"].([]interface{})[0]).Should(Equal("target2")) Expect((*workflow.Steps[1].Properties)["policies"].([]interface{})[0].(string)).Should(Equal("target3")) - entities, err := ds.List(context.TODO(), &model.ApplicationPolicy{AppPrimaryKey: app.PrimaryKey()}, &datastore.ListOptions{ + entities, err := store.List(context.TODO(), &model.ApplicationPolicy{AppPrimaryKey: app.PrimaryKey()}, &datastore.ListOptions{ FilterOptions: datastore.FilterOptions{ In: []datastore.InQueryOption{{ Key: "type", @@ -505,30 +496,30 @@ var _ = Describe("Test workflow model", func() { Targets: []string{"target1", "target2"}, } - err := ds.BatchAdd(context.TODO(), []datastore.Entity{app, cloudComponent, webComponent}) + err := store.BatchAdd(context.TODO(), []datastore.Entity{app, cloudComponent, webComponent}) Expect(err).Should(BeNil()) - err = envBindingUsecase.createEnvWorkflow(context.TODO(), app, env, true) + err = CreateEnvWorkflow(context.TODO(), store, k8sClient, app, env, true) Expect(err).Should(BeNil()) - workflow, err := workflowUsecase.GetWorkflow(context.TODO(), app, convertWorkflowName(env.Name)) + workflow, err := GetWorkflowForApp(context.TODO(), store, app, ConvertWorkflowName(env.Name)) Expect(err).Should(BeNil()) Expect(len(workflow.Steps)).Should(Equal(4)) env.Targets = []string{"target1"} - err = ds.Put(context.TODO(), env) + err = store.Put(context.TODO(), env) Expect(err).Should(BeNil()) - err = UpdateEnvWorkflow(context.Background(), k8sClient, ds, app, env) + err = UpdateEnvWorkflow(context.Background(), k8sClient, store, app, env) Expect(err).Should(BeNil()) - workflow, err = workflowUsecase.GetWorkflow(context.TODO(), app, convertWorkflowName(env.Name)) + workflow, err = GetWorkflowForApp(context.TODO(), store, app, ConvertWorkflowName(env.Name)) Expect(err).Should(BeNil()) Expect(len(workflow.Steps)).Should(Equal(2)) Expect(workflow.Steps[0].Type).Should(Equal(DeployCloudResource)) - entities, err := ds.List(context.TODO(), &model.ApplicationPolicy{AppPrimaryKey: app.PrimaryKey()}, &datastore.ListOptions{ + entities, err := store.List(context.TODO(), &model.ApplicationPolicy{AppPrimaryKey: app.PrimaryKey()}, &datastore.ListOptions{ FilterOptions: datastore.FilterOptions{ In: []datastore.InQueryOption{{ Key: "type", @@ -540,3 +531,25 @@ var _ = Describe("Test workflow model", func() { Expect(len(entities)).Should(Equal(2)) }) }) + +func CreateEnvWorkflow(ctx context.Context, store datastore.DataStore, kubeClient client.Client, app *model.Application, env *model.Env, isDefault bool) error { + steps, policies := GenEnvWorkflowStepsAndPolicies(ctx, kubeClient, store, env, app) + workflow := &model.Workflow{ + Steps: steps, + Name: ConvertWorkflowName(env.Name), + Alias: fmt.Sprintf("%s Workflow", env.Alias), + Description: "Created automatically by envbinding.", + Default: &isDefault, + EnvName: env.Name, + AppPrimaryKey: app.PrimaryKey(), + } + log.Logger.Infof("create workflow %s for app %s", utils2.Sanitize(workflow.Name), utils2.Sanitize(app.PrimaryKey())) + if err := store.Add(ctx, workflow); err != nil { + return err + } + err := store.BatchAdd(ctx, policies) + if err != nil { + return fmt.Errorf("fail to create policies %w", err) + } + return nil +} diff --git a/pkg/apiserver/rest/usecase/addon.go b/pkg/apiserver/domain/service/addon.go similarity index 87% rename from pkg/apiserver/rest/usecase/addon.go rename to pkg/apiserver/domain/service/addon.go index c84064f5f..a6c669a44 100644 --- a/pkg/apiserver/rest/usecase/addon.go +++ b/pkg/apiserver/domain/service/addon.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -39,19 +39,19 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" pkgaddon "github.com/oam-dev/kubevela/pkg/addon" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/multicluster" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/utils/apply" velaerr "github.com/oam-dev/kubevela/pkg/utils/errors" ) -// AddonHandler handle CRUD and installation of addons -type AddonHandler interface { +// AddonService handle CRUD and installation of addons +type AddonService interface { GetAddonRegistry(ctx context.Context, name string) (*apis.AddonRegistry, error) CreateAddonRegistry(ctx context.Context, req apis.CreateAddonRegistryRequest) (*apis.AddonRegistry, error) DeleteAddonRegistry(ctx context.Context, name string) error @@ -97,8 +97,8 @@ func AddonImpl2AddonRes(impl *pkgaddon.UIData) (*apis.DetailAddonResponse, error }, nil } -// NewAddonUsecase returns an addon usecase -func NewAddonUsecase(cacheTime time.Duration) AddonHandler { +// NewAddonService returns an addon service +func NewAddonService(cacheTime time.Duration) AddonService { config, err := clients.GetKubeConfig() if err != nil { panic(err) @@ -117,7 +117,7 @@ func NewAddonUsecase(cacheTime time.Duration) AddonHandler { // TODO(@wonderflow): it's better to add a close channel here, but it should be fine as it's only invoke once in APIServer. go cache.DiscoverAndRefreshLoop(cacheTime) - return &defaultAddonHandler{ + return &addonServiceImpl{ addonRegistryCache: cache, addonRegistryDS: ds, kubeClient: kubecli, @@ -128,7 +128,7 @@ func NewAddonUsecase(cacheTime time.Duration) AddonHandler { } } -type defaultAddonHandler struct { +type addonServiceImpl struct { addonRegistryCache *pkgaddon.Cache addonRegistryDS pkgaddon.RegistryDataStore kubeClient client.Client @@ -140,7 +140,7 @@ type defaultAddonHandler struct { } // GetAddon will get addon information -func (u *defaultAddonHandler) GetAddon(ctx context.Context, name string, registry string, version string) (*apis.DetailAddonResponse, error) { +func (u *addonServiceImpl) GetAddon(ctx context.Context, name string, registry string, version string) (*apis.DetailAddonResponse, error) { var addon *pkgaddon.UIData var err error if registry == "" { @@ -181,7 +181,7 @@ func (u *defaultAddonHandler) GetAddon(ctx context.Context, name string, registr return a, nil } -func (u *defaultAddonHandler) StatusAddon(ctx context.Context, name string) (*apis.AddonStatusResponse, error) { +func (u *addonServiceImpl) StatusAddon(ctx context.Context, name string) (*apis.AddonStatusResponse, error) { status, err := pkgaddon.GetAddonStatus(ctx, u.kubeClient, name) if err != nil { return nil, bcode.ErrGetAddonApplication @@ -236,7 +236,7 @@ func (u *defaultAddonHandler) StatusAddon(ctx context.Context, name string) (*ap return &res, nil } -func (u *defaultAddonHandler) ListAddons(ctx context.Context, registry, query string) ([]*apis.DetailAddonResponse, error) { +func (u *addonServiceImpl) ListAddons(ctx context.Context, registry, query string) ([]*apis.DetailAddonResponse, error) { var addons []*pkgaddon.UIData rs, err := u.addonRegistryDS.ListRegistries(ctx) if err != nil { @@ -296,11 +296,11 @@ func (u *defaultAddonHandler) ListAddons(ctx context.Context, registry, query st return addonResources, nil } -func (u *defaultAddonHandler) DeleteAddonRegistry(ctx context.Context, name string) error { +func (u *addonServiceImpl) DeleteAddonRegistry(ctx context.Context, name string) error { return u.addonRegistryDS.DeleteRegistry(ctx, name) } -func (u *defaultAddonHandler) CreateAddonRegistry(ctx context.Context, req apis.CreateAddonRegistryRequest) (*apis.AddonRegistry, error) { +func (u *addonServiceImpl) CreateAddonRegistry(ctx context.Context, req apis.CreateAddonRegistryRequest) (*apis.AddonRegistry, error) { r := addonRegistryModelFromCreateAddonRegistryRequest(req) err := u.addonRegistryDS.AddRegistry(ctx, r) @@ -322,7 +322,7 @@ func convertAddonRegistry(r pkgaddon.Registry) *apis.AddonRegistry { } } -func (u *defaultAddonHandler) GetAddonRegistry(ctx context.Context, name string) (*apis.AddonRegistry, error) { +func (u *addonServiceImpl) GetAddonRegistry(ctx context.Context, name string) (*apis.AddonRegistry, error) { r, err := u.addonRegistryDS.GetRegistry(ctx, name) if err != nil { return nil, err @@ -330,7 +330,7 @@ func (u *defaultAddonHandler) GetAddonRegistry(ctx context.Context, name string) return convertAddonRegistry(r), nil } -func (u defaultAddonHandler) UpdateAddonRegistry(ctx context.Context, name string, req apis.UpdateAddonRegistryRequest) (*apis.AddonRegistry, error) { +func (u addonServiceImpl) UpdateAddonRegistry(ctx context.Context, name string, req apis.UpdateAddonRegistryRequest) (*apis.AddonRegistry, error) { r, err := u.addonRegistryDS.GetRegistry(ctx, name) if err != nil { return nil, bcode.ErrAddonRegistryNotExist @@ -356,7 +356,7 @@ func (u defaultAddonHandler) UpdateAddonRegistry(ctx context.Context, name strin return convertAddonRegistry(r), nil } -func (u *defaultAddonHandler) ListAddonRegistries(ctx context.Context) ([]*apis.AddonRegistry, error) { +func (u *addonServiceImpl) ListAddonRegistries(ctx context.Context) ([]*apis.AddonRegistry, error) { var list []*apis.AddonRegistry registries, err := u.addonRegistryDS.ListRegistries(ctx) @@ -377,7 +377,7 @@ func (u *defaultAddonHandler) ListAddonRegistries(ctx context.Context) ([]*apis. return list, nil } -func (u *defaultAddonHandler) EnableAddon(ctx context.Context, name string, args apis.EnableAddonRequest) error { +func (u *addonServiceImpl) EnableAddon(ctx context.Context, name string, args apis.EnableAddonRequest) error { var err error registries, err := u.addonRegistryDS.ListRegistries(ctx) if err != nil { @@ -402,7 +402,6 @@ func (u *defaultAddonHandler) EnableAddon(ctx context.Context, name string, args // wrap this error with special bcode if errors.As(err, &pkgaddon.VersionUnMatchError{}) { - log.Logger.Error(err) return bcode.ErrAddonSystemVersionMismatch } // except `addon not found`, other errors should return directly @@ -411,7 +410,7 @@ func (u *defaultAddonHandler) EnableAddon(ctx context.Context, name string, args return bcode.ErrAddonNotExist } -func (u *defaultAddonHandler) DisableAddon(ctx context.Context, name string, force bool) error { +func (u *addonServiceImpl) DisableAddon(ctx context.Context, name string, force bool) error { err := pkgaddon.DisableAddon(ctx, u.kubeClient, name, u.config, force) if err != nil { log.Logger.Errorf("delete application fail: %s", err.Error()) @@ -420,7 +419,7 @@ func (u *defaultAddonHandler) DisableAddon(ctx context.Context, name string, for return nil } -func (u *defaultAddonHandler) ListEnabledAddon(ctx context.Context) ([]*apis.AddonBaseStatus, error) { +func (u *addonServiceImpl) ListEnabledAddon(ctx context.Context) ([]*apis.AddonBaseStatus, error) { apps := &v1beta1.ApplicationList{} if err := u.kubeClient.List(ctx, apps, client.InNamespace(types.DefaultKubeVelaNS), client.HasLabels{oam.LabelAddonName}); err != nil { return nil, err @@ -440,7 +439,7 @@ func (u *defaultAddonHandler) ListEnabledAddon(ctx context.Context) ([]*apis.Add return response, nil } -func (u *defaultAddonHandler) UpdateAddon(ctx context.Context, name string, args apis.EnableAddonRequest) error { +func (u *addonServiceImpl) UpdateAddon(ctx context.Context, name string, args apis.EnableAddonRequest) error { var app v1beta1.Application // check addon application whether exist diff --git a/pkg/apiserver/rest/usecase/addon_test.go b/pkg/apiserver/domain/service/addon_test.go similarity index 95% rename from pkg/apiserver/rest/usecase/addon_test.go rename to pkg/apiserver/domain/service/addon_test.go index 39acc8d44..810ff088d 100644 --- a/pkg/apiserver/rest/usecase/addon_test.go +++ b/pkg/apiserver/domain/service/addon_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -30,10 +30,10 @@ import ( "sigs.k8s.io/yaml" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" ) -var _ = Describe("addon usecase test", func() { +var _ = Describe("addon service test", func() { var ctx context.Context BeforeEach(func() { diff --git a/pkg/apiserver/rest/usecase/application.go b/pkg/apiserver/domain/service/application.go similarity index 77% rename from pkg/apiserver/rest/usecase/application.go rename to pkg/apiserver/domain/service/application.go index 176ac3635..1b8f343a7 100644 --- a/pkg/apiserver/rest/usecase/application.go +++ b/pkg/apiserver/domain/service/application.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "bytes" @@ -41,14 +41,15 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" velatypes "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" - syncconvert "github.com/oam-dev/kubevela/pkg/apiserver/sync/convert" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/repository" + syncconvert "github.com/oam-dev/kubevela/pkg/apiserver/event/sync/convert" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + assembler "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/assembler/v1" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/appfile/dryrun" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/discoverymapper" @@ -61,15 +62,11 @@ import ( type PolicyType string const ( - - // EnvBindingPolicyDefaultName default policy name - EnvBindingPolicyDefaultName string = "env-bindings" - defaultTokenLen int = 16 ) -// ApplicationUsecase application usecase -type ApplicationUsecase interface { +// ApplicationService application service +type ApplicationService interface { ListApplications(ctx context.Context, listOptions apisv1.ListApplicationOptions) ([]*apisv1.ApplicationBase, error) GetApplication(ctx context.Context, appName string) (*model.Application, error) GetApplicationStatus(ctx context.Context, app *model.Application, envName string) (*common.AppStatus, error) @@ -105,51 +102,23 @@ type ApplicationUsecase interface { DeleteApplicationTrigger(ctx context.Context, app *model.Application, triggerName string) error } -type applicationUsecaseImpl struct { - ds datastore.DataStore - kubeClient client.Client - kubeConfig *rest.Config - apply apply.Applicator - workflowUsecase WorkflowUsecase - envUsecase EnvUsecase - envBindingUsecase EnvBindingUsecase - targetUsecase TargetUsecase - definitionUsecase DefinitionUsecase - projectUsecase ProjectUsecase - userUsecase UserUsecase +type applicationServiceImpl struct { + Store datastore.DataStore `inject:"datastore"` + KubeClient client.Client `inject:"kubeClient"` + KubeConfig *rest.Config `inject:"kubeConfig"` + Apply apply.Applicator `inject:"apply"` + WorkflowService WorkflowService `inject:""` + EnvService EnvService `inject:""` + EnvBindingService EnvBindingService `inject:""` + TargetService TargetService `inject:""` + DefinitionService DefinitionService `inject:""` + ProjectService ProjectService `inject:""` + UserService UserService `inject:""` } -// NewApplicationUsecase new application usecase -func NewApplicationUsecase(ds datastore.DataStore, - workflowUsecase WorkflowUsecase, - envBindingUsecase EnvBindingUsecase, - envUsecase EnvUsecase, - targetUsecase TargetUsecase, - definitionUsecase DefinitionUsecase, - projectUsecase ProjectUsecase, - userUsecase UserUsecase, -) ApplicationUsecase { - kubecli, err := clients.GetKubeClient() - if err != nil { - log.Logger.Fatalf("get kube client failure %s", err.Error()) - } - config, err := clients.GetKubeConfig() - if err != nil { - log.Logger.Fatalf("get kube rest config failure %s", err.Error()) - } - return &applicationUsecaseImpl{ - ds: ds, - workflowUsecase: workflowUsecase, - envBindingUsecase: envBindingUsecase, - targetUsecase: targetUsecase, - kubeClient: kubecli, - kubeConfig: config, - apply: apply.NewAPIApplicator(kubecli), - definitionUsecase: definitionUsecase, - projectUsecase: projectUsecase, - envUsecase: envUsecase, - userUsecase: userUsecase, - } +// NewApplicationService new application service +func NewApplicationService() ApplicationService { + return &applicationServiceImpl{} } func listApp(ctx context.Context, ds datastore.DataStore, listOptions apisv1.ListApplicationOptions) ([]*model.Application, error) { @@ -157,7 +126,7 @@ func listApp(ctx context.Context, ds datastore.DataStore, listOptions apisv1.Lis var err error var envBinding []*apisv1.EnvBindingBase if listOptions.Env != "" || listOptions.TargetName != "" { - envBinding, err = listFullEnvBinding(ctx, ds, envListOption{}) + envBinding, err = repository.ListFullEnvBinding(ctx, ds, repository.EnvListOption{}) if err != nil { log.Logger.Errorf("list envbinding for list application in env %s err %v", utils2.Sanitize(listOptions.Env), err) return nil, err @@ -211,12 +180,12 @@ func listApp(ctx context.Context, ds datastore.DataStore, listOptions apisv1.Lis } // ListApplications list applications -func (c *applicationUsecaseImpl) ListApplications(ctx context.Context, listOptions apisv1.ListApplicationOptions) ([]*apisv1.ApplicationBase, error) { +func (c *applicationServiceImpl) ListApplications(ctx context.Context, listOptions apisv1.ListApplicationOptions) ([]*apisv1.ApplicationBase, error) { userName, ok := ctx.Value(&apisv1.CtxKeyUser).(string) if !ok { return nil, bcode.ErrUnauthorized } - projects, err := c.projectUsecase.ListUserProjects(ctx, userName) + projects, err := c.ProjectService.ListUserProjects(ctx, userName) if err != nil { return nil, err } @@ -235,13 +204,13 @@ func (c *applicationUsecaseImpl) ListApplications(ctx context.Context, listOptio if len(listOptions.Projects) == 0 { listOptions.Projects = availableProjectNames } - apps, err := listApp(ctx, c.ds, listOptions) + apps, err := listApp(ctx, c.Store, listOptions) if err != nil { return nil, err } var list []*apisv1.ApplicationBase for _, app := range apps { - appBase := c.convertAppModelToBase(app, projects) + appBase := assembler.ConvertAppModelToBase(app, projects) list = append(list, appBase) } sort.Slice(list, func(i, j int) bool { @@ -251,11 +220,11 @@ func (c *applicationUsecaseImpl) ListApplications(ctx context.Context, listOptio } // GetApplication get application model -func (c *applicationUsecaseImpl) GetApplication(ctx context.Context, appName string) (*model.Application, error) { +func (c *applicationServiceImpl) GetApplication(ctx context.Context, appName string) (*model.Application, error) { var app = model.Application{ Name: appName, } - if err := c.ds.Get(ctx, &app); err != nil { + if err := c.Store.Get(ctx, &app); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil, bcode.ErrApplicationNotExist } @@ -265,25 +234,25 @@ func (c *applicationUsecaseImpl) GetApplication(ctx context.Context, appName str } // DetailApplication detail application info -func (c *applicationUsecaseImpl) DetailApplication(ctx context.Context, app *model.Application) (*apisv1.DetailApplicationResponse, error) { +func (c *applicationServiceImpl) DetailApplication(ctx context.Context, app *model.Application) (*apisv1.DetailApplicationResponse, error) { var project *apisv1.ProjectBase if app.Project != "" { var err error - project, err = c.projectUsecase.DetailProject(ctx, app.Project) + project, err = c.ProjectService.DetailProject(ctx, app.Project) if err != nil { return nil, bcode.ErrProjectIsNotExist } } - base := c.convertAppModelToBase(app, []*apisv1.ProjectBase{project}) + base := assembler.ConvertAppModelToBase(app, []*apisv1.ProjectBase{project}) policies, err := c.queryApplicationPolicies(ctx, app) if err != nil { return nil, err } - componentNum, err := c.ds.Count(ctx, &model.ApplicationComponent{AppPrimaryKey: app.PrimaryKey()}, &datastore.FilterOptions{}) + componentNum, err := c.Store.Count(ctx, &model.ApplicationComponent{AppPrimaryKey: app.PrimaryKey()}, &datastore.FilterOptions{}) if err != nil { return nil, err } - envBindings, err := c.envBindingUsecase.GetEnvBindings(ctx, app) + envBindings, err := c.EnvBindingService.GetEnvBindings(ctx, app) if err != nil { return nil, err } @@ -308,13 +277,13 @@ func (c *applicationUsecaseImpl) DetailApplication(ctx context.Context, app *mod } // GetApplicationStatus get application status from controller cluster -func (c *applicationUsecaseImpl) GetApplicationStatus(ctx context.Context, appmodel *model.Application, envName string) (*common.AppStatus, error) { +func (c *applicationServiceImpl) GetApplicationStatus(ctx context.Context, appmodel *model.Application, envName string) (*common.AppStatus, error) { var app v1beta1.Application - env, err := c.envUsecase.GetEnv(ctx, envName) + env, err := c.EnvService.GetEnv(ctx, envName) if err != nil { return nil, err } - err = c.kubeClient.Get(ctx, types.NamespacedName{Namespace: env.Namespace, Name: appmodel.GetAppNameForSynced()}, &app) + err = c.KubeClient.Get(ctx, types.NamespacedName{Namespace: env.Namespace, Name: appmodel.GetAppNameForSynced()}, &app) if err != nil { if apierrors.IsNotFound(err) { return nil, nil @@ -328,11 +297,11 @@ func (c *applicationUsecaseImpl) GetApplicationStatus(ctx context.Context, appmo } // GetApplicationCR get application CR in cluster -func (c *applicationUsecaseImpl) GetApplicationCR(ctx context.Context, appModel *model.Application) (*v1beta1.ApplicationList, error) { +func (c *applicationServiceImpl) GetApplicationCR(ctx context.Context, appModel *model.Application) (*v1beta1.ApplicationList, error) { var apps v1beta1.ApplicationList if appModel.IsSynced() { var app v1beta1.Application - err := c.kubeClient.Get(ctx, types.NamespacedName{Namespace: appModel.GetAppNamespaceForSynced(), Name: appModel.GetAppNameForSynced()}, &app) + err := c.KubeClient.Get(ctx, types.NamespacedName{Namespace: appModel.GetAppNamespaceForSynced(), Name: appModel.GetAppNameForSynced()}, &app) if err != nil && !apierrors.IsNotFound(err) { return nil, err } @@ -347,7 +316,7 @@ func (c *applicationUsecaseImpl) GetApplicationCR(ctx context.Context, appModel return nil, err } selector = selector.Add(*re) - err = c.kubeClient.List(ctx, &apps, &client.ListOptions{ + err = c.KubeClient.List(ctx, &apps, &client.ListOptions{ LabelSelector: selector, }) if err != nil { @@ -360,13 +329,13 @@ func (c *applicationUsecaseImpl) GetApplicationCR(ctx context.Context, appModel } // PublishApplicationTemplate publish app template -func (c *applicationUsecaseImpl) PublishApplicationTemplate(ctx context.Context, app *model.Application) (*apisv1.ApplicationTemplateBase, error) { +func (c *applicationServiceImpl) PublishApplicationTemplate(ctx context.Context, app *model.Application) (*apisv1.ApplicationTemplateBase, error) { // TODO: return nil, nil } // CreateApplication create application -func (c *applicationUsecaseImpl) CreateApplication(ctx context.Context, req apisv1.CreateApplicationRequest) (*apisv1.ApplicationBase, error) { +func (c *applicationServiceImpl) CreateApplication(ctx context.Context, req apisv1.CreateApplicationRequest) (*apisv1.ApplicationBase, error) { application := model.Application{ Name: req.Name, Alias: req.Alias, @@ -375,7 +344,7 @@ func (c *applicationUsecaseImpl) CreateApplication(ctx context.Context, req apis Labels: req.Labels, } // check app name. - exist, err := c.ds.IsExist(ctx, &application) + exist, err := c.Store.IsExist(ctx, &application) if err != nil { log.Logger.Errorf("check application name is exist failure %s", err.Error()) return nil, bcode.ErrApplicationExist @@ -384,7 +353,7 @@ func (c *applicationUsecaseImpl) CreateApplication(ctx context.Context, req apis return nil, bcode.ErrApplicationExist } // check project - project, err := c.projectUsecase.DetailProject(ctx, req.Project) + project, err := c.ProjectService.DetailProject(ctx, req.Project) if err != nil { return nil, bcode.ErrProjectIsNotExist } @@ -408,25 +377,25 @@ func (c *applicationUsecaseImpl) CreateApplication(ctx context.Context, req apis Name: fmt.Sprintf("%s-%s", application.Name, "default"), PayloadType: model.PayloadTypeCustom, Type: apisv1.TriggerTypeWebhook, - WorkflowName: convertWorkflowName(req.EnvBinding[0].Name), + WorkflowName: repository.ConvertWorkflowName(req.EnvBinding[0].Name), }); err != nil { return nil, err } } // add application to db. - if err := c.ds.Add(ctx, &application); err != nil { + if err := c.Store.Add(ctx, &application); err != nil { if errors.Is(err, datastore.ErrRecordExist) { return nil, bcode.ErrApplicationExist } return nil, err } // render app base info. - base := c.convertAppModelToBase(&application, []*apisv1.ProjectBase{project}) + base := assembler.ConvertAppModelToBase(&application, []*apisv1.ProjectBase{project}) return base, nil } // CreateApplicationTrigger create application trigger -func (c *applicationUsecaseImpl) CreateApplicationTrigger(ctx context.Context, app *model.Application, req apisv1.CreateApplicationTriggerRequest) (*apisv1.ApplicationTriggerBase, error) { +func (c *applicationServiceImpl) CreateApplicationTrigger(ctx context.Context, app *model.Application, req apisv1.CreateApplicationTriggerRequest) (*apisv1.ApplicationTriggerBase, error) { trigger := &model.ApplicationTrigger{ AppPrimaryKey: app.Name, WorkflowName: req.WorkflowName, @@ -438,7 +407,7 @@ func (c *applicationUsecaseImpl) CreateApplicationTrigger(ctx context.Context, a ComponentName: req.ComponentName, Token: genWebhookToken(), } - if err := c.ds.Add(ctx, trigger); err != nil { + if err := c.Store.Add(ctx, trigger); err != nil { log.Logger.Errorf("failed to create application trigger, %s", err.Error()) return nil, err } @@ -458,12 +427,12 @@ func (c *applicationUsecaseImpl) CreateApplicationTrigger(ctx context.Context, a } // DeleteApplicationTrigger delete application trigger -func (c *applicationUsecaseImpl) DeleteApplicationTrigger(ctx context.Context, app *model.Application, token string) error { +func (c *applicationServiceImpl) DeleteApplicationTrigger(ctx context.Context, app *model.Application, token string) error { trigger := model.ApplicationTrigger{ AppPrimaryKey: app.PrimaryKey(), Token: token, } - if err := c.ds.Delete(ctx, &trigger); err != nil { + if err := c.Store.Delete(ctx, &trigger); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return bcode.ErrApplicationTriggerNotExist } @@ -474,11 +443,11 @@ func (c *applicationUsecaseImpl) DeleteApplicationTrigger(ctx context.Context, a } // ListApplicationTrigger list application triggers -func (c *applicationUsecaseImpl) ListApplicationTriggers(ctx context.Context, app *model.Application) ([]*apisv1.ApplicationTriggerBase, error) { +func (c *applicationServiceImpl) ListApplicationTriggers(ctx context.Context, app *model.Application) ([]*apisv1.ApplicationTriggerBase, error) { trigger := &model.ApplicationTrigger{ AppPrimaryKey: app.Name, } - triggers, err := c.ds.List(ctx, trigger, &datastore.ListOptions{ + triggers, err := c.Store.List(ctx, trigger, &datastore.ListOptions{ SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}}, ) if err != nil { @@ -507,19 +476,19 @@ func (c *applicationUsecaseImpl) ListApplicationTriggers(ctx context.Context, ap return resp, nil } -func (c *applicationUsecaseImpl) saveApplicationEnvBinding(ctx context.Context, app model.Application, envBindings []*apisv1.EnvBinding) error { - err := c.envBindingUsecase.BatchCreateEnvBinding(ctx, &app, envBindings) +func (c *applicationServiceImpl) saveApplicationEnvBinding(ctx context.Context, app model.Application, envBindings []*apisv1.EnvBinding) error { + err := c.EnvBindingService.BatchCreateEnvBinding(ctx, &app, envBindings) if err != nil { return err } return nil } -func (c *applicationUsecaseImpl) UpdateApplication(ctx context.Context, app *model.Application, req apisv1.UpdateApplicationRequest) (*apisv1.ApplicationBase, error) { +func (c *applicationServiceImpl) UpdateApplication(ctx context.Context, app *model.Application, req apisv1.UpdateApplicationRequest) (*apisv1.ApplicationBase, error) { var project *apisv1.ProjectBase if app.Project != "" { var err error - project, err = c.projectUsecase.DetailProject(ctx, app.Project) + project, err = c.ProjectService.DetailProject(ctx, app.Project) if err != nil { return nil, bcode.ErrProjectIsNotExist } @@ -528,25 +497,25 @@ func (c *applicationUsecaseImpl) UpdateApplication(ctx context.Context, app *mod app.Description = req.Description app.Labels = req.Labels app.Icon = req.Icon - if err := c.ds.Put(ctx, app); err != nil { + if err := c.Store.Put(ctx, app); err != nil { return nil, err } - return c.convertAppModelToBase(app, []*apisv1.ProjectBase{project}), nil + return assembler.ConvertAppModelToBase(app, []*apisv1.ProjectBase{project}), nil } // ListRecords list application record -func (c *applicationUsecaseImpl) ListRecords(ctx context.Context, appName string) (*apisv1.ListWorkflowRecordsResponse, error) { +func (c *applicationServiceImpl) ListRecords(ctx context.Context, appName string) (*apisv1.ListWorkflowRecordsResponse, error) { var record = model.WorkflowRecord{ AppPrimaryKey: appName, Finished: "false", } - records, err := c.ds.List(ctx, &record, &datastore.ListOptions{}) + records, err := c.Store.List(ctx, &record, &datastore.ListOptions{}) if err != nil { return nil, err } if len(records) == 0 { record.Finished = "true" - records, err = c.ds.List(ctx, &record, &datastore.ListOptions{ + records, err = c.Store.List(ctx, &record, &datastore.ListOptions{ Page: 1, PageSize: 1, SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}, @@ -562,7 +531,7 @@ func (c *applicationUsecaseImpl) ListRecords(ctx context.Context, appName string for _, raw := range records { record, ok := raw.(*model.WorkflowRecord) if ok { - resp.Records = append(resp.Records, *convertFromRecordModel(record)) + resp.Records = append(resp.Records, *assembler.ConvertFromRecordModel(record)) } } resp.Total = int64(len(records)) @@ -570,11 +539,11 @@ func (c *applicationUsecaseImpl) ListRecords(ctx context.Context, appName string return resp, nil } -func (c *applicationUsecaseImpl) ListComponents(ctx context.Context, app *model.Application, op apisv1.ListApplicationComponentOptions) ([]*apisv1.ComponentBase, error) { +func (c *applicationServiceImpl) ListComponents(ctx context.Context, app *model.Application, op apisv1.ListApplicationComponentOptions) ([]*apisv1.ComponentBase, error) { var component = model.ApplicationComponent{ AppPrimaryKey: app.PrimaryKey(), } - components, err := c.ds.List(ctx, &component, &datastore.ListOptions{SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}}) + components, err := c.Store.List(ctx, &component, &datastore.ListOptions{SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}}) if err != nil { return nil, err } @@ -584,9 +553,9 @@ func (c *applicationUsecaseImpl) ListComponents(ctx context.Context, app *model. for _, component := range components { pm := component.(*model.ApplicationComponent) if !pm.Main { - list = append(list, convertComponentModelToBase(pm)) + list = append(list, assembler.ConvertComponentModelToBase(pm)) } else { - main = convertComponentModelToBase(pm) + main = assembler.ConvertComponentModelToBase(pm) } } // the main component must be first @@ -598,18 +567,18 @@ func (c *applicationUsecaseImpl) ListComponents(ctx context.Context, app *model. // DetailComponent detail app component // TODO: Add status data about the component. -func (c *applicationUsecaseImpl) DetailComponent(ctx context.Context, app *model.Application, compName string) (*apisv1.DetailComponentResponse, error) { +func (c *applicationServiceImpl) DetailComponent(ctx context.Context, app *model.Application, compName string) (*apisv1.DetailComponentResponse, error) { var component = model.ApplicationComponent{ AppPrimaryKey: app.PrimaryKey(), Name: compName, } - err := c.ds.Get(ctx, &component) + err := c.Store.Get(ctx, &component) if err != nil { return nil, err } var cd v1beta1.ComponentDefinition - if err := c.kubeClient.Get(ctx, types.NamespacedName{Name: component.Type, Namespace: velatypes.DefaultKubeVelaNS}, &cd); err != nil { - log.Logger.Warnf("component definition %s get failure. %s", component.Type, err.Error()) + if err := c.KubeClient.Get(ctx, types.NamespacedName{Name: component.Type, Namespace: velatypes.DefaultKubeVelaNS}, &cd); err != nil { + log.Logger.Warnf("component definition %s get failure. %s", utils2.Sanitize(component.Type), err.Error()) } return &apisv1.DetailComponentResponse{ @@ -619,23 +588,23 @@ func (c *applicationUsecaseImpl) DetailComponent(ctx context.Context, app *model } // ListPolicies list application policies -func (c *applicationUsecaseImpl) ListPolicies(ctx context.Context, app *model.Application) ([]*apisv1.PolicyBase, error) { +func (c *applicationServiceImpl) ListPolicies(ctx context.Context, app *model.Application) ([]*apisv1.PolicyBase, error) { policies, err := c.queryApplicationPolicies(ctx, app) if err != nil { return nil, err } var list []*apisv1.PolicyBase for _, policy := range policies { - list = append(list, convertPolicyModelToBase(policy)) + list = append(list, assembler.ConvertPolicyModelToBase(policy)) } return list, nil } -func (c *applicationUsecaseImpl) queryApplicationPolicies(ctx context.Context, app *model.Application) (list []*model.ApplicationPolicy, err error) { +func (c *applicationServiceImpl) queryApplicationPolicies(ctx context.Context, app *model.Application) (list []*model.ApplicationPolicy, err error) { var policy = model.ApplicationPolicy{ AppPrimaryKey: app.PrimaryKey(), } - policies, err := c.ds.List(ctx, &policy, &datastore.ListOptions{}) + policies, err := c.Store.List(ctx, &policy, &datastore.ListOptions{}) if err != nil { return nil, err } @@ -648,24 +617,24 @@ func (c *applicationUsecaseImpl) queryApplicationPolicies(ctx context.Context, a // DetailPolicy detail app policy // TODO: Add status data about the policy. -func (c *applicationUsecaseImpl) DetailPolicy(ctx context.Context, app *model.Application, policyName string) (*apisv1.DetailPolicyResponse, error) { +func (c *applicationServiceImpl) DetailPolicy(ctx context.Context, app *model.Application, policyName string) (*apisv1.DetailPolicyResponse, error) { var policy = model.ApplicationPolicy{ AppPrimaryKey: app.PrimaryKey(), Name: policyName, } - err := c.ds.Get(ctx, &policy) + err := c.Store.Get(ctx, &policy) if err != nil { return nil, err } return &apisv1.DetailPolicyResponse{ - PolicyBase: *convertPolicyModelToBase(&policy), + PolicyBase: *assembler.ConvertPolicyModelToBase(&policy), }, nil } // Deploy deploys app to cluster // means to render oam application config and apply to cluster. // An event record is generated for each deploy. -func (c *applicationUsecaseImpl) Deploy(ctx context.Context, app *model.Application, req apisv1.ApplicationDeployRequest) (*apisv1.ApplicationDeployResponse, error) { +func (c *applicationServiceImpl) Deploy(ctx context.Context, app *model.Application, req apisv1.ApplicationDeployRequest) (*apisv1.ApplicationDeployResponse, error) { var userName string if user := ctx.Value(&apisv1.CtxKeyUser); user != nil { if u, ok := user.(string); ok { @@ -682,7 +651,7 @@ func (c *applicationUsecaseImpl) Deploy(ctx context.Context, app *model.Applicat } configByte, _ := yaml.Marshal(oamApp) - workflow, err := c.workflowUsecase.GetWorkflow(ctx, app, oamApp.Annotations[oam.AnnotationWorkflowName]) + workflow, err := c.WorkflowService.GetWorkflow(ctx, app, oamApp.Annotations[oam.AnnotationWorkflowName]) if err != nil { return nil, err } @@ -698,7 +667,7 @@ func (c *applicationUsecaseImpl) Deploy(ctx context.Context, app *model.Applicat AppPrimaryKey: app.PrimaryKey(), EnvName: workflow.EnvName, } - list, err := c.ds.List(ctx, &lastVersion, &datastore.ListOptions{ + list, err := c.Store.List(ctx, &lastVersion, &datastore.ListOptions{ PageSize: 1, Page: 1, SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}}) if err != nil && !errors.Is(err, datastore.ErrRecordNotExist) { log.Logger.Errorf("query app latest revision failure %s", err.Error()) @@ -712,7 +681,7 @@ func (c *applicationUsecaseImpl) Deploy(ctx context.Context, app *model.Applicat AppPrimaryKey: revision.AppPrimaryKey, Version: revision.RollbackVersion, } - if err := c.ds.Get(ctx, rollbackRevision); err == nil { + if err := c.Store.Get(ctx, rollbackRevision); err == nil { status = rollbackRevision.Status } } else { @@ -738,24 +707,24 @@ func (c *applicationUsecaseImpl) Deploy(ctx context.Context, app *model.Applicat CodeInfo: req.CodeInfo, ImageInfo: req.ImageInfo, } - if err := c.ds.Add(ctx, appRevision); err != nil { + if err := c.Store.Add(ctx, appRevision); err != nil { return nil, err } // step3: check and create namespace var namespace corev1.Namespace - if err := c.kubeClient.Get(ctx, types.NamespacedName{Name: oamApp.Namespace}, &namespace); apierrors.IsNotFound(err) { + if err := c.KubeClient.Get(ctx, types.NamespacedName{Name: oamApp.Namespace}, &namespace); apierrors.IsNotFound(err) { namespace.Name = oamApp.Namespace - if err := c.kubeClient.Create(ctx, &namespace); err != nil { + if err := c.KubeClient.Create(ctx, &namespace); err != nil { log.Logger.Errorf("auto create namespace failure %s", err.Error()) return nil, bcode.ErrCreateNamespace } } // step4: apply to controller cluster - err = c.apply.Apply(ctx, oamApp) + err = c.Apply.Apply(ctx, oamApp) if err != nil { appRevision.Status = model.RevisionStatusFail appRevision.Reason = err.Error() - if err := c.ds.Put(ctx, appRevision); err != nil { + if err := c.Store.Put(ctx, appRevision); err != nil { log.Logger.Warnf("update deploy event failure %s", err.Error()) } @@ -764,13 +733,13 @@ func (c *applicationUsecaseImpl) Deploy(ctx context.Context, app *model.Applicat } // step5: create workflow record - if err := c.workflowUsecase.CreateWorkflowRecord(ctx, app, oamApp, workflow); err != nil { + if err := c.WorkflowService.CreateWorkflowRecord(ctx, app, oamApp, workflow); err != nil { log.Logger.Warnf("create workflow record failure %s", err.Error()) } // step6: update app revision status appRevision.Status = model.RevisionStatusRunning - if err := c.ds.Put(ctx, appRevision); err != nil { + if err := c.Store.Put(ctx, appRevision); err != nil { log.Logger.Warnf("update app revision failure %s", err.Error()) } @@ -780,11 +749,11 @@ func (c *applicationUsecaseImpl) Deploy(ctx context.Context, app *model.Applicat } // sync configs to clusters -func (c *applicationUsecaseImpl) syncConfigs4Application(ctx context.Context, app *v1beta1.Application, projectName, envName string) error { +func (c *applicationServiceImpl) syncConfigs4Application(ctx context.Context, app *v1beta1.Application, projectName, envName string) error { var areTerraformComponents = true for _, m := range app.Spec.Components { d := &v1beta1.ComponentDefinition{} - if err := c.kubeClient.Get(ctx, client.ObjectKey{Namespace: velatypes.DefaultKubeVelaNS, Name: m.Type}, d); err != nil { + if err := c.KubeClient.Get(ctx, client.ObjectKey{Namespace: velatypes.DefaultKubeVelaNS, Name: m.Type}, d); err != nil { klog.ErrorS(err, "failed to get config type", "ComponentDefinition", m.Type) } // check the type of the componentDefinition is Terraform @@ -796,13 +765,13 @@ func (c *applicationUsecaseImpl) syncConfigs4Application(ctx context.Context, ap if areTerraformComponents { return nil } - env, err := c.envUsecase.GetEnv(ctx, envName) + env, err := c.EnvService.GetEnv(ctx, envName) if err != nil { return err } var clusterTargets []*model.ClusterTarget for _, t := range env.Targets { - target, err := c.targetUsecase.GetTarget(ctx, t) + target, err := c.TargetService.GetTarget(ctx, t) if err != nil { return err } @@ -811,24 +780,24 @@ func (c *applicationUsecaseImpl) syncConfigs4Application(ctx context.Context, ap } } - if err := SyncConfigs(ctx, c.kubeClient, projectName, clusterTargets); err != nil { + if err := SyncConfigs(ctx, c.KubeClient, projectName, clusterTargets); err != nil { return fmt.Errorf("sync config failure %w", err) } return nil } -func (c *applicationUsecaseImpl) renderOAMApplication(ctx context.Context, appModel *model.Application, reqWorkflowName, version string) (*v1beta1.Application, error) { +func (c *applicationServiceImpl) renderOAMApplication(ctx context.Context, appModel *model.Application, reqWorkflowName, version string) (*v1beta1.Application, error) { // Priority 1 uses the requested workflow as release . // Priority 2 uses the default workflow as release . var workflow *model.Workflow var err error if reqWorkflowName != "" { - workflow, err = c.workflowUsecase.GetWorkflow(ctx, appModel, reqWorkflowName) + workflow, err = c.WorkflowService.GetWorkflow(ctx, appModel, reqWorkflowName) if err != nil { return nil, err } } else { - workflow, err = c.workflowUsecase.GetApplicationDefaultWorkflow(ctx, appModel) + workflow, err = c.WorkflowService.GetApplicationDefaultWorkflow(ctx, appModel) if err != nil && !errors.Is(err, bcode.ErrWorkflowNoDefault) { return nil, err } @@ -836,7 +805,7 @@ func (c *applicationUsecaseImpl) renderOAMApplication(ctx context.Context, appMo if workflow == nil || workflow.EnvName == "" { return nil, bcode.ErrWorkflowNotExist } - env, err := c.envUsecase.GetEnv(ctx, workflow.EnvName) + env, err := c.EnvService.GetEnv(ctx, workflow.EnvName) if err != nil { return nil, err } @@ -865,7 +834,7 @@ func (c *applicationUsecaseImpl) renderOAMApplication(ctx context.Context, appMo }, } originalApp := &v1beta1.Application{} - if err := c.kubeClient.Get(ctx, types.NamespacedName{ + if err := c.KubeClient.Get(ctx, types.NamespacedName{ Name: appModel.Name, Namespace: env.Namespace, }, originalApp); err == nil { @@ -875,7 +844,7 @@ func (c *applicationUsecaseImpl) renderOAMApplication(ctx context.Context, appMo var component = model.ApplicationComponent{ AppPrimaryKey: appModel.PrimaryKey(), } - components, err := c.ds.List(ctx, &component, &datastore.ListOptions{}) + components, err := c.Store.List(ctx, &component, &datastore.ListOptions{}) if err != nil { return nil, err } @@ -887,7 +856,7 @@ func (c *applicationUsecaseImpl) renderOAMApplication(ctx context.Context, appMo var policy = model.ApplicationPolicy{ AppPrimaryKey: appModel.PrimaryKey(), } - policies, err := c.ds.List(ctx, &policy, &datastore.ListOptions{ + policies, err := c.Store.List(ctx, &policy, &datastore.ListOptions{ FilterOptions: datastore.FilterOptions{ IsNotExist: []datastore.IsNotExistQueryOption{{ Key: "envName", @@ -899,7 +868,7 @@ func (c *applicationUsecaseImpl) renderOAMApplication(ctx context.Context, appMo return nil, err } policy.EnvName = env.Name - envPolicies, err := c.ds.List(ctx, &policy, &datastore.ListOptions{}) + envPolicies, err := c.Store.List(ctx, &policy, &datastore.ListOptions{}) if err != nil { return nil, err } @@ -967,52 +936,16 @@ func (c *applicationUsecaseImpl) renderOAMApplication(ctx context.Context, appMo return app, nil } -func (c *applicationUsecaseImpl) convertAppModelToBase(app *model.Application, projects []*apisv1.ProjectBase) *apisv1.ApplicationBase { - appBase := &apisv1.ApplicationBase{ - Name: app.Name, - Alias: app.Alias, - CreateTime: app.CreateTime, - UpdateTime: app.UpdateTime, - Description: app.Description, - Icon: app.Icon, - Labels: app.Labels, - Project: &apisv1.ProjectBase{Name: app.Project}, - } - if app.IsSynced() { - appBase.ReadOnly = true - } - for _, project := range projects { - if project.Name == app.Project { - appBase.Project = project - } - } - return appBase -} - -func (c *applicationUsecaseImpl) convertRevisionModelToBase(ctx context.Context, revision *model.ApplicationRevision) apisv1.ApplicationRevisionBase { - base := apisv1.ApplicationRevisionBase{ - Version: revision.Version, - Status: revision.Status, - Reason: revision.Reason, - Note: revision.Note, - TriggerType: revision.TriggerType, - CreateTime: revision.CreateTime, - EnvName: revision.EnvName, - CodeInfo: revision.CodeInfo, - ImageInfo: revision.ImageInfo, - } +func (c *applicationServiceImpl) convertRevisionModelToBase(ctx context.Context, revision *model.ApplicationRevision) apisv1.ApplicationRevisionBase { + var deployUser *model.User if revision.DeployUser != "" { - base.DeployUser = &apisv1.NameAlias{Name: revision.DeployUser} - deployUser, _ := c.userUsecase.GetUser(ctx, revision.DeployUser) - if deployUser != nil { - base.DeployUser.Alias = deployUser.Alias - } + deployUser, _ = c.UserService.GetUser(ctx, revision.DeployUser) } - return base + return assembler.ConvertRevisionModelToBase(revision, deployUser) } // DeleteApplication delete application -func (c *applicationUsecaseImpl) DeleteApplication(ctx context.Context, app *model.Application) error { +func (c *applicationServiceImpl) DeleteApplication(ctx context.Context, app *model.Application) error { crs, err := c.GetApplicationCR(ctx, app) if err != nil { return err @@ -1034,7 +967,7 @@ func (c *applicationUsecaseImpl) DeleteApplication(ctx context.Context, app *mod var revision = model.ApplicationRevision{ AppPrimaryKey: app.PrimaryKey(), } - revisions, err := c.ds.List(ctx, &revision, &datastore.ListOptions{}) + revisions, err := c.Store.List(ctx, &revision, &datastore.ListOptions{}) if err != nil { return err } @@ -1045,19 +978,19 @@ func (c *applicationUsecaseImpl) DeleteApplication(ctx context.Context, app *mod } // delete workflow - if err := c.workflowUsecase.DeleteWorkflowByApp(ctx, app); err != nil && !errors.Is(err, bcode.ErrWorkflowNotExist) { + if err := c.WorkflowService.DeleteWorkflowByApp(ctx, app); err != nil && !errors.Is(err, bcode.ErrWorkflowNotExist) { log.Logger.Errorf("delete workflow %s failure %s", app.Name, err.Error()) } for _, component := range components { - err := c.ds.Delete(ctx, &model.ApplicationComponent{AppPrimaryKey: app.PrimaryKey(), Name: component.Name}) + err := c.Store.Delete(ctx, &model.ApplicationComponent{AppPrimaryKey: app.PrimaryKey(), Name: component.Name}) if err != nil && !errors.Is(err, datastore.ErrRecordNotExist) { log.Logger.Errorf("delete component %s in app %s failure %s", component.Name, app.Name, err.Error()) } } for _, policy := range policies { - err := c.ds.Delete(ctx, &model.ApplicationPolicy{AppPrimaryKey: app.PrimaryKey(), Name: policy.Name}) + err := c.Store.Delete(ctx, &model.ApplicationPolicy{AppPrimaryKey: app.PrimaryKey(), Name: policy.Name}) if err != nil && errors.Is(err, datastore.ErrRecordNotExist) { log.Logger.Errorf("delete policy %s in app %s failure %s", policy.Name, app.Name, err.Error()) } @@ -1065,30 +998,30 @@ func (c *applicationUsecaseImpl) DeleteApplication(ctx context.Context, app *mod for _, entity := range revisions { revision := entity.(*model.ApplicationRevision) - if err := c.ds.Delete(ctx, &model.ApplicationRevision{AppPrimaryKey: app.PrimaryKey(), Version: revision.Version}); err != nil { + if err := c.Store.Delete(ctx, &model.ApplicationRevision{AppPrimaryKey: app.PrimaryKey(), Version: revision.Version}); err != nil { log.Logger.Errorf("delete revision %s in app %s failure %s", revision.Version, app.Name, err.Error()) } } for _, trigger := range triggers { - if err := c.ds.Delete(ctx, &model.ApplicationTrigger{AppPrimaryKey: app.PrimaryKey(), Name: trigger.Name, Token: trigger.Token}); err != nil { + if err := c.Store.Delete(ctx, &model.ApplicationTrigger{AppPrimaryKey: app.PrimaryKey(), Name: trigger.Name, Token: trigger.Token}); err != nil { log.Logger.Errorf("delete trigger %s in app %s failure %s", trigger.Name, app.Name, err.Error()) } } - if err := c.envBindingUsecase.BatchDeleteEnvBinding(ctx, app); err != nil { + if err := c.EnvBindingService.BatchDeleteEnvBinding(ctx, app); err != nil { log.Logger.Errorf("delete envbindings in app %s failure %s", app.Name, err.Error()) } - return c.ds.Delete(ctx, app) + return c.Store.Delete(ctx, app) } -func (c *applicationUsecaseImpl) GetApplicationComponent(ctx context.Context, app *model.Application, componentName string) (*model.ApplicationComponent, error) { +func (c *applicationServiceImpl) GetApplicationComponent(ctx context.Context, app *model.Application, componentName string) (*model.ApplicationComponent, error) { var component = model.ApplicationComponent{ AppPrimaryKey: app.PrimaryKey(), Name: componentName, } - err := c.ds.Get(ctx, &component) + err := c.Store.Get(ctx, &component) if err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil, bcode.ErrApplicationComponentNotExist @@ -1098,7 +1031,7 @@ func (c *applicationUsecaseImpl) GetApplicationComponent(ctx context.Context, ap return &component, nil } -func (c *applicationUsecaseImpl) UpdateComponent(ctx context.Context, app *model.Application, component *model.ApplicationComponent, req apisv1.UpdateApplicationComponentRequest) (*apisv1.ComponentBase, error) { +func (c *applicationServiceImpl) UpdateComponent(ctx context.Context, app *model.Application, component *model.ApplicationComponent, req apisv1.UpdateApplicationComponentRequest) (*apisv1.ComponentBase, error) { if req.Alias != nil { component.Alias = *req.Alias } @@ -1121,16 +1054,16 @@ func (c *applicationUsecaseImpl) UpdateComponent(ctx context.Context, app *model } component.Properties = properties } - if err := c.ds.Put(ctx, component); err != nil { + if err := c.Store.Put(ctx, component); err != nil { return nil, err } - return convertComponentModelToBase(component), nil + return assembler.ConvertComponentModelToBase(component), nil } -func (c *applicationUsecaseImpl) createComponent(ctx context.Context, app *model.Application, com apisv1.CreateComponentRequest, main bool) (*apisv1.ComponentBase, error) { +func (c *applicationServiceImpl) createComponent(ctx context.Context, app *model.Application, com apisv1.CreateComponentRequest, main bool) (*apisv1.ComponentBase, error) { var cd v1beta1.ComponentDefinition - if err := c.kubeClient.Get(ctx, types.NamespacedName{Name: com.ComponentType, Namespace: velatypes.DefaultKubeVelaNS}, &cd); err != nil { - log.Logger.Warnf("component definition %s get failure. %s", com.ComponentType, err.Error()) + if err := c.KubeClient.Get(ctx, types.NamespacedName{Name: com.ComponentType, Namespace: velatypes.DefaultKubeVelaNS}, &cd); err != nil { + log.Logger.Warnf("component definition %s get failure. %s", utils2.Sanitize(com.ComponentType), err.Error()) return nil, bcode.ErrComponentTypeNotSupport } userName, _ := ctx.Value(&apisv1.CtxKeyUser).(string) @@ -1181,7 +1114,7 @@ func (c *applicationUsecaseImpl) createComponent(ctx context.Context, app *model c.initCreateDefaultTrait(&componentModel) } - if err := c.ds.Add(ctx, &componentModel); err != nil { + if err := c.Store.Add(ctx, &componentModel); err != nil { if errors.Is(err, datastore.ErrRecordExist) { return nil, bcode.ErrApplicationComponentExist } @@ -1189,18 +1122,18 @@ func (c *applicationUsecaseImpl) createComponent(ctx context.Context, app *model return nil, err } // update the env workflow, the automatically generated workflow is determined by the component type. - if err := UpdateAppEnvWorkflow(ctx, c.kubeClient, c.ds, app); err != nil { + if err := repository.UpdateAppEnvWorkflow(ctx, c.KubeClient, c.Store, app); err != nil { return nil, bcode.ErrEnvBindingUpdateWorkflow } - return convertComponentModelToBase(&componentModel), nil + return assembler.ConvertComponentModelToBase(&componentModel), nil } -func (c *applicationUsecaseImpl) CreateComponent(ctx context.Context, app *model.Application, com apisv1.CreateComponentRequest) (*apisv1.ComponentBase, error) { +func (c *applicationServiceImpl) CreateComponent(ctx context.Context, app *model.Application, com apisv1.CreateComponentRequest) (*apisv1.ComponentBase, error) { return c.createComponent(ctx, app, com, false) } -func (c *applicationUsecaseImpl) initCreateDefaultTrait(component *model.ApplicationComponent) { +func (c *applicationServiceImpl) initCreateDefaultTrait(component *model.ApplicationComponent) { replicationTrait := model.ApplicationTrait{ Alias: "Set Replicas", Type: "scaler", @@ -1218,59 +1151,24 @@ func (c *applicationUsecaseImpl) initCreateDefaultTrait(component *model.Applica component.Traits = initTraits } -func convertComponentModelToBase(componentModel *model.ApplicationComponent) *apisv1.ComponentBase { - if componentModel == nil { - return nil - } - return &apisv1.ComponentBase{ - Name: componentModel.Name, - Alias: componentModel.Alias, - Description: componentModel.Description, - Labels: componentModel.Labels, - ComponentType: componentModel.Type, - Icon: componentModel.Icon, - DependsOn: componentModel.DependsOn, - Inputs: componentModel.Inputs, - Outputs: componentModel.Outputs, - Creator: componentModel.Creator, - Main: componentModel.Main, - CreateTime: componentModel.CreateTime, - UpdateTime: componentModel.UpdateTime, - Traits: func() (traits []*apisv1.ApplicationTrait) { - for _, trait := range componentModel.Traits { - traits = append(traits, &apisv1.ApplicationTrait{ - Type: trait.Type, - Properties: trait.Properties, - Alias: trait.Alias, - Description: trait.Description, - CreateTime: trait.CreateTime, - UpdateTime: trait.UpdateTime, - }) - } - return - }(), - WorkloadType: componentModel.WorkloadType, - } -} - -func (c *applicationUsecaseImpl) DeleteComponent(ctx context.Context, app *model.Application, component *model.ApplicationComponent) error { +func (c *applicationServiceImpl) DeleteComponent(ctx context.Context, app *model.Application, component *model.ApplicationComponent) error { if component.Main { return bcode.ErrApplicationComponentNotAllowDelete } - if err := c.ds.Delete(ctx, component); err != nil { + if err := c.Store.Delete(ctx, component); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return bcode.ErrApplicationComponentNotExist } log.Logger.Warnf("delete app component %s failure %s", app.PrimaryKey(), err.Error()) return err } - if err := UpdateAppEnvWorkflow(ctx, c.kubeClient, c.ds, app); err != nil { + if err := repository.UpdateAppEnvWorkflow(ctx, c.KubeClient, c.Store, app); err != nil { return bcode.ErrEnvBindingUpdateWorkflow } return nil } -func (c *applicationUsecaseImpl) CreatePolicy(ctx context.Context, app *model.Application, createpolicy apisv1.CreatePolicyRequest) (*apisv1.PolicyBase, error) { +func (c *applicationServiceImpl) CreatePolicy(ctx context.Context, app *model.Application, createpolicy apisv1.CreatePolicyRequest) (*apisv1.PolicyBase, error) { userName, _ := ctx.Value(&apisv1.CtxKeyUser).(string) policyModel := model.ApplicationPolicy{ AppPrimaryKey: app.PrimaryKey(), @@ -1284,22 +1182,22 @@ func (c *applicationUsecaseImpl) CreatePolicy(ctx context.Context, app *model.Ap return nil, bcode.ErrInvalidProperties } policyModel.Properties = properties - if err := c.ds.Add(ctx, &policyModel); err != nil { + if err := c.Store.Add(ctx, &policyModel); err != nil { if errors.Is(err, datastore.ErrRecordExist) { return nil, bcode.ErrApplicationPolicyExist } log.Logger.Warnf("add policy for app %s failure %s", app.PrimaryKey(), err.Error()) return nil, err } - return convertPolicyModelToBase(&policyModel), nil + return assembler.ConvertPolicyModelToBase(&policyModel), nil } -func (c *applicationUsecaseImpl) DeletePolicy(ctx context.Context, app *model.Application, policyName string) error { +func (c *applicationServiceImpl) DeletePolicy(ctx context.Context, app *model.Application, policyName string) error { var policy = model.ApplicationPolicy{ AppPrimaryKey: app.PrimaryKey(), Name: policyName, } - if err := c.ds.Delete(ctx, &policy); err != nil { + if err := c.Store.Delete(ctx, &policy); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return bcode.ErrApplicationPolicyNotExist } @@ -1309,12 +1207,12 @@ func (c *applicationUsecaseImpl) DeletePolicy(ctx context.Context, app *model.Ap return nil } -func (c *applicationUsecaseImpl) UpdatePolicy(ctx context.Context, app *model.Application, policyName string, policyUpdate apisv1.UpdatePolicyRequest) (*apisv1.DetailPolicyResponse, error) { +func (c *applicationServiceImpl) UpdatePolicy(ctx context.Context, app *model.Application, policyName string, policyUpdate apisv1.UpdatePolicyRequest) (*apisv1.DetailPolicyResponse, error) { var policy = model.ApplicationPolicy{ AppPrimaryKey: app.PrimaryKey(), Name: policyName, } - err := c.ds.Get(ctx, &policy) + err := c.Store.Get(ctx, &policy) if err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil, bcode.ErrApplicationPolicyNotExist @@ -1330,20 +1228,20 @@ func (c *applicationUsecaseImpl) UpdatePolicy(ctx context.Context, app *model.Ap policy.Properties = properties policy.Description = policyUpdate.Description - if err := c.ds.Put(ctx, &policy); err != nil { + if err := c.Store.Put(ctx, &policy); err != nil { return nil, err } return &apisv1.DetailPolicyResponse{ - PolicyBase: *convertPolicyModelToBase(&policy), + PolicyBase: *assembler.ConvertPolicyModelToBase(&policy), }, nil } -func (c *applicationUsecaseImpl) CreateApplicationTrait(ctx context.Context, app *model.Application, component *model.ApplicationComponent, req apisv1.CreateApplicationTraitRequest) (*apisv1.ApplicationTrait, error) { +func (c *applicationServiceImpl) CreateApplicationTrait(ctx context.Context, app *model.Application, component *model.ApplicationComponent, req apisv1.CreateApplicationTraitRequest) (*apisv1.ApplicationTrait, error) { var comp = model.ApplicationComponent{ AppPrimaryKey: app.PrimaryKey(), Name: component.Name, } - if err := c.ds.Get(ctx, &comp); err != nil { + if err := c.Store.Get(ctx, &comp); err != nil { return nil, err } for _, trait := range comp.Traits { @@ -1358,24 +1256,24 @@ func (c *applicationUsecaseImpl) CreateApplicationTrait(ctx context.Context, app } trait := model.ApplicationTrait{CreateTime: time.Now(), Type: req.Type, Properties: properties, Alias: req.Alias, Description: req.Description} comp.Traits = append(comp.Traits, trait) - if err := c.ds.Put(ctx, &comp); err != nil { + if err := c.Store.Put(ctx, &comp); err != nil { return nil, err } return &apisv1.ApplicationTrait{Type: trait.Type, Properties: properties, Alias: req.Alias, Description: req.Description, CreateTime: trait.CreateTime, UpdateTime: trait.UpdateTime}, nil } -func (c *applicationUsecaseImpl) DeleteApplicationTrait(ctx context.Context, app *model.Application, component *model.ApplicationComponent, traitType string) error { +func (c *applicationServiceImpl) DeleteApplicationTrait(ctx context.Context, app *model.Application, component *model.ApplicationComponent, traitType string) error { var comp = model.ApplicationComponent{ AppPrimaryKey: app.PrimaryKey(), Name: component.Name, } - if err := c.ds.Get(ctx, &comp); err != nil { + if err := c.Store.Get(ctx, &comp); err != nil { return err } for i, trait := range comp.Traits { if trait.Type == traitType { comp.Traits = append(comp.Traits[:i], comp.Traits[i+1:]...) - if err := c.ds.Put(ctx, &comp); err != nil { + if err := c.Store.Put(ctx, &comp); err != nil { return err } return nil @@ -1384,12 +1282,12 @@ func (c *applicationUsecaseImpl) DeleteApplicationTrait(ctx context.Context, app return bcode.ErrTraitNotExist } -func (c *applicationUsecaseImpl) UpdateApplicationTrait(ctx context.Context, app *model.Application, component *model.ApplicationComponent, traitType string, req apisv1.UpdateApplicationTraitRequest) (*apisv1.ApplicationTrait, error) { +func (c *applicationServiceImpl) UpdateApplicationTrait(ctx context.Context, app *model.Application, component *model.ApplicationComponent, traitType string, req apisv1.UpdateApplicationTraitRequest) (*apisv1.ApplicationTrait, error) { var comp = model.ApplicationComponent{ AppPrimaryKey: app.PrimaryKey(), Name: component.Name, } - if err := c.ds.Get(ctx, &comp); err != nil { + if err := c.Store.Get(ctx, &comp); err != nil { return nil, err } for i, trait := range comp.Traits { @@ -1401,7 +1299,7 @@ func (c *applicationUsecaseImpl) UpdateApplicationTrait(ctx context.Context, app } updatedTrait := model.ApplicationTrait{CreateTime: trait.CreateTime, UpdateTime: time.Now(), Properties: properties, Type: traitType, Alias: req.Alias, Description: req.Description} comp.Traits[i] = updatedTrait - if err := c.ds.Put(ctx, &comp); err != nil { + if err := c.Store.Put(ctx, &comp); err != nil { return nil, err } return &apisv1.ApplicationTrait{Type: trait.Type, Properties: properties, @@ -1411,7 +1309,7 @@ func (c *applicationUsecaseImpl) UpdateApplicationTrait(ctx context.Context, app return nil, bcode.ErrTraitNotExist } -func (c *applicationUsecaseImpl) ListRevisions(ctx context.Context, appName, envName, status string, page, pageSize int) (*apisv1.ListRevisionsResponse, error) { +func (c *applicationServiceImpl) ListRevisions(ctx context.Context, appName, envName, status string, page, pageSize int) (*apisv1.ListRevisionsResponse, error) { var revision = model.ApplicationRevision{ AppPrimaryKey: appName, } @@ -1422,7 +1320,7 @@ func (c *applicationUsecaseImpl) ListRevisions(ctx context.Context, appName, env revision.Status = status } - revisions, err := c.ds.List(ctx, &revision, &datastore.ListOptions{ + revisions, err := c.Store.List(ctx, &revision, &datastore.ListOptions{ Page: page, PageSize: pageSize, SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}, @@ -1440,7 +1338,7 @@ func (c *applicationUsecaseImpl) ListRevisions(ctx context.Context, appName, env resp.Revisions = append(resp.Revisions, c.convertRevisionModelToBase(ctx, r)) } } - count, err := c.ds.Count(ctx, &revision, nil) + count, err := c.Store.Count(ctx, &revision, nil) if err != nil { return nil, err } @@ -1449,12 +1347,12 @@ func (c *applicationUsecaseImpl) ListRevisions(ctx context.Context, appName, env return resp, nil } -func (c *applicationUsecaseImpl) DetailRevision(ctx context.Context, appName, revisionVersion string) (*apisv1.DetailRevisionResponse, error) { +func (c *applicationServiceImpl) DetailRevision(ctx context.Context, appName, revisionVersion string) (*apisv1.DetailRevisionResponse, error) { var revision = model.ApplicationRevision{ AppPrimaryKey: appName, Version: revisionVersion, } - if err := c.ds.Get(ctx, &revision); err != nil { + if err := c.Store.Get(ctx, &revision); err != nil { return nil, err } @@ -1466,7 +1364,7 @@ func (c *applicationUsecaseImpl) DetailRevision(ctx context.Context, appName, re } if revision.DeployUser != "" { - deployUser, _ := c.userUsecase.GetUser(ctx, revision.DeployUser) + deployUser, _ := c.UserService.GetUser(ctx, revision.DeployUser) if deployUser != nil { resp.DeployUser.Alias = deployUser.Alias } @@ -1475,9 +1373,9 @@ func (c *applicationUsecaseImpl) DetailRevision(ctx context.Context, appName, re return resp, nil } -func (c *applicationUsecaseImpl) Statistics(ctx context.Context, app *model.Application) (*apisv1.ApplicationStatisticsResponse, error) { +func (c *applicationServiceImpl) Statistics(ctx context.Context, app *model.Application) (*apisv1.ApplicationStatisticsResponse, error) { var targetMap = make(map[string]int) - envbinding, err := c.envBindingUsecase.GetEnvBindings(ctx, app) + envbinding, err := c.EnvBindingService.GetEnvBindings(ctx, app) if err != nil { log.Logger.Errorf("query app envbinding failure %s", err.Error()) } @@ -1486,7 +1384,7 @@ func (c *applicationUsecaseImpl) Statistics(ctx context.Context, app *model.Appl targetMap[target]++ } } - count, err := c.ds.Count(ctx, &model.ApplicationRevision{AppPrimaryKey: app.PrimaryKey()}, &datastore.FilterOptions{}) + count, err := c.Store.Count(ctx, &model.ApplicationRevision{AppPrimaryKey: app.PrimaryKey()}, &datastore.FilterOptions{}) if err != nil { return nil, err } @@ -1494,15 +1392,15 @@ func (c *applicationUsecaseImpl) Statistics(ctx context.Context, app *model.Appl EnvCount: int64(len(envbinding)), TargetCount: int64(len(targetMap)), RevisionCount: count, - WorkflowCount: c.workflowUsecase.CountWorkflow(ctx, app), + WorkflowCount: c.WorkflowService.CountWorkflow(ctx, app), }, nil } // CompareAppWithLatestRevision compare application with last revision -func (c *applicationUsecaseImpl) CompareAppWithLatestRevision(ctx context.Context, appModel *model.Application, compareReq apisv1.AppCompareReq) (*apisv1.AppCompareResponse, error) { +func (c *applicationServiceImpl) CompareAppWithLatestRevision(ctx context.Context, appModel *model.Application, compareReq apisv1.AppCompareReq) (*apisv1.AppCompareResponse, error) { var reqWorkflowName string if compareReq.Env != "" { - reqWorkflowName = convertWorkflowName(compareReq.Env) + reqWorkflowName = repository.ConvertWorkflowName(compareReq.Env) } newApp, err := c.renderOAMApplication(ctx, appModel, reqWorkflowName, "") if err != nil { @@ -1529,8 +1427,8 @@ func (c *applicationUsecaseImpl) CompareAppWithLatestRevision(ctx context.Contex args := common2.Args{ Schema: common2.Scheme, } - _ = args.SetConfig(c.kubeConfig) - args.SetClient(c.kubeClient) + _ = args.SetConfig(c.KubeConfig) + args.SetClient(c.KubeClient) diffResult, buff, err := compare(ctx, args, newApp, oldApp) if err != nil { log.Logger.Errorf("fail to compare the app %s", err.Error()) @@ -1540,7 +1438,7 @@ func (c *applicationUsecaseImpl) CompareAppWithLatestRevision(ctx context.Contex } // ResetAppToLatestRevision reset app's component to last revision -func (c *applicationUsecaseImpl) ResetAppToLatestRevision(ctx context.Context, appName string) (*apisv1.AppResetResponse, error) { +func (c *applicationServiceImpl) ResetAppToLatestRevision(ctx context.Context, appName string) (*apisv1.AppResetResponse, error) { targetApp, err := c.getAppFromLatestRevision(ctx, appName, "", "") if err != nil { return nil, err @@ -1549,13 +1447,13 @@ func (c *applicationUsecaseImpl) ResetAppToLatestRevision(ctx context.Context, a } // DryRunAppOrRevision dry-run application or revision -func (c *applicationUsecaseImpl) DryRunAppOrRevision(ctx context.Context, appModel *model.Application, dryRunReq apisv1.AppDryRunReq) (*apisv1.AppDryRunResponse, error) { +func (c *applicationServiceImpl) DryRunAppOrRevision(ctx context.Context, appModel *model.Application, dryRunReq apisv1.AppDryRunReq) (*apisv1.AppDryRunResponse, error) { var app *v1beta1.Application var err error if dryRunReq.DryRunType == "APP" { var reqWorkflowName string if dryRunReq.Env != "" { - reqWorkflowName = convertWorkflowName(dryRunReq.Env) + reqWorkflowName = repository.ConvertWorkflowName(dryRunReq.Env) } app, err = c.renderOAMApplication(ctx, appModel, reqWorkflowName, "") if err != nil { @@ -1570,8 +1468,8 @@ func (c *applicationUsecaseImpl) DryRunAppOrRevision(ctx context.Context, appMod args := common2.Args{ Schema: common2.Scheme, } - _ = args.SetConfig(c.kubeConfig) - args.SetClient(c.kubeClient) + _ = args.SetConfig(c.KubeConfig) + args.SetClient(c.KubeClient) dryRunResult, err := dryRunApplication(ctx, args, app) if err != nil { return nil, err @@ -1579,14 +1477,6 @@ func (c *applicationUsecaseImpl) DryRunAppOrRevision(ctx context.Context, appMod return &apisv1.AppDryRunResponse{YAML: dryRunResult.String()}, nil } -func genPolicyName(envName string) string { - return fmt.Sprintf("%s-%s", EnvBindingPolicyDefaultName, envName) -} - -func genPolicyEnvName(targetName string) string { - return targetName -} - func genWebhookToken() string { rand.Seed(time.Now().UnixNano()) runes := []rune("abcdefghijklmnopqrstuvwxyz0123456789") @@ -1598,7 +1488,7 @@ func genWebhookToken() string { return string(b) } -func (c *applicationUsecaseImpl) getAppFromLatestRevision(ctx context.Context, appName string, envName string, version string) (*v1beta1.Application, error) { +func (c *applicationServiceImpl) getAppFromLatestRevision(ctx context.Context, appName string, envName string, version string) (*v1beta1.Application, error) { ar := &model.ApplicationRevision{AppPrimaryKey: appName} if envName != "" { @@ -1607,7 +1497,7 @@ func (c *applicationUsecaseImpl) getAppFromLatestRevision(ctx context.Context, a if version != "" { ar.Version = version } - revisions, err := c.ds.List(ctx, ar, &datastore.ListOptions{ + revisions, err := c.Store.List(ctx, ar, &datastore.ListOptions{ Page: 1, PageSize: 1, SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}, @@ -1627,10 +1517,10 @@ func (c *applicationUsecaseImpl) getAppFromLatestRevision(ctx context.Context, a return oldApp, nil } -func (c *applicationUsecaseImpl) resetApp(ctx context.Context, targetApp *v1beta1.Application) (*apisv1.AppResetResponse, error) { +func (c *applicationServiceImpl) resetApp(ctx context.Context, targetApp *v1beta1.Application) (*apisv1.AppResetResponse, error) { appPrimaryKey := targetApp.Name - originComps, err := c.ds.List(ctx, &model.ApplicationComponent{AppPrimaryKey: appPrimaryKey}, &datastore.ListOptions{}) + originComps, err := c.Store.List(ctx, &model.ApplicationComponent{AppPrimaryKey: appPrimaryKey}, &datastore.ListOptions{}) if err != nil { return nil, bcode.ErrApplicationComponentNotExist } @@ -1655,7 +1545,7 @@ func (c *applicationUsecaseImpl) resetApp(ctx context.Context, targetApp *v1beta AppPrimaryKey: appPrimaryKey, Name: compName, } - if err := c.ds.Delete(ctx, &component); err != nil { + if err := c.Store.Delete(ctx, &component); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { continue } @@ -1675,9 +1565,9 @@ func (c *applicationUsecaseImpl) resetApp(ctx context.Context, targetApp *v1beta return &apisv1.AppResetResponse{}, bcode.ErrInvalidProperties } compModel.Properties = properties - if err := c.ds.Add(ctx, &compModel); err != nil { + if err := c.Store.Add(ctx, &compModel); err != nil { if errors.Is(err, datastore.ErrRecordExist) { - err := c.ds.Put(ctx, &compModel) + err := c.Store.Put(ctx, &compModel) if err != nil { log.Logger.Warnf("update comp %s for app %s failure %s", comp.Name, utils2.Sanitize(appPrimaryKey), err.Error()) } diff --git a/pkg/apiserver/rest/usecase/application_test.go b/pkg/apiserver/domain/service/application_test.go similarity index 69% rename from pkg/apiserver/rest/usecase/application_test.go rename to pkg/apiserver/domain/service/application_test.go index 9de6a3692..2ba8dc373 100644 --- a/pkg/apiserver/rest/usecase/application_test.go +++ b/pkg/apiserver/domain/service/application_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -36,27 +36,28 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - v1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/repository" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + v1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/util" "github.com/oam-dev/kubevela/pkg/utils/apply" ) -var _ = Describe("Test application usecase function", func() { +var _ = Describe("Test application service function", func() { var ( - rbacUsecase *rbacUsecaseImpl - appUsecase *applicationUsecaseImpl - workflowUsecase *workflowUsecaseImpl - envUsecase *envUsecaseImpl - envBindingUsecase *envBindingUsecaseImpl - targetUsecase *targetUsecaseImpl - definitionUsecase *definitionUsecaseImpl - projectUsecase *projectUsecaseImpl - userUsecase *userUsecaseImpl + rbacService *rbacServiceImpl + appService *applicationServiceImpl + workflowService *workflowServiceImpl + envService *envServiceImpl + envBindingService *envBindingServiceImpl + targetService *targetServiceImpl + definitionService *definitionServiceImpl + projectService *projectServiceImpl + userService *userServiceImpl testProject = "app-project" testApp = "test-app" defaultTarget = "default" @@ -72,26 +73,26 @@ var _ = Describe("Test application usecase function", func() { ds, err := NewDatastore(datastore.Config{Type: "kubeapi", Database: "app-test-kubevela"}) Expect(ds).ToNot(BeNil()) Expect(err).Should(BeNil()) - rbacUsecase = &rbacUsecaseImpl{ds: ds} - userUsecase = &userUsecaseImpl{ds: ds, k8sClient: k8sClient} - projectUsecase = &projectUsecaseImpl{ds: ds, k8sClient: k8sClient, rbacUsecase: rbacUsecase} - envUsecase = &envUsecaseImpl{ds: ds, kubeClient: k8sClient, projectUsecase: projectUsecase} - workflowUsecase = &workflowUsecaseImpl{ds: ds, envUsecase: envUsecase} - definitionUsecase = &definitionUsecaseImpl{kubeClient: k8sClient, caches: utils.NewMemoryCacheStore(context.Background())} - envBindingUsecase = &envBindingUsecaseImpl{ds: ds, envUsecase: envUsecase, workflowUsecase: workflowUsecase, kubeClient: k8sClient, definitionUsecase: definitionUsecase} - targetUsecase = &targetUsecaseImpl{ds: ds, k8sClient: k8sClient} - appUsecase = &applicationUsecaseImpl{ - ds: ds, - workflowUsecase: workflowUsecase, - apply: apply.NewAPIApplicator(k8sClient), - kubeClient: k8sClient, - kubeConfig: cfg, - envBindingUsecase: envBindingUsecase, - envUsecase: envUsecase, - definitionUsecase: definitionUsecase, - targetUsecase: targetUsecase, - projectUsecase: projectUsecase, - userUsecase: userUsecase, + rbacService = &rbacServiceImpl{Store: ds} + userService = &userServiceImpl{Store: ds, K8sClient: k8sClient} + projectService = &projectServiceImpl{Store: ds, K8sClient: k8sClient, RbacService: rbacService} + envService = &envServiceImpl{Store: ds, KubeClient: k8sClient, ProjectService: projectService} + workflowService = &workflowServiceImpl{Store: ds, EnvService: envService} + definitionService = &definitionServiceImpl{KubeClient: k8sClient, caches: utils.NewMemoryCacheStore(context.Background())} + envBindingService = &envBindingServiceImpl{Store: ds, EnvService: envService, WorkflowService: workflowService, KubeClient: k8sClient, DefinitionService: definitionService} + targetService = &targetServiceImpl{Store: ds, K8sClient: k8sClient} + appService = &applicationServiceImpl{ + Store: ds, + WorkflowService: workflowService, + Apply: apply.NewAPIApplicator(k8sClient), + KubeClient: k8sClient, + KubeConfig: cfg, + EnvBindingService: envBindingService, + EnvService: envService, + DefinitionService: definitionService, + TargetService: targetService, + ProjectService: projectService, + UserService: userService, } }) @@ -103,25 +104,25 @@ var _ = Describe("Test application usecase function", func() { err := k8sClient.Create(context.TODO(), &ns) Expect(err).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) - err = userUsecase.Init(context.TODO()) + err = userService.Init(context.TODO()) Expect(err).Should(BeNil()) By("prepare test project") - _, err = projectUsecase.CreateProject(context.TODO(), v1.CreateProjectRequest{Name: testProject, Owner: model.DefaultAdminUserName}) + _, err = projectService.CreateProject(context.TODO(), v1.CreateProjectRequest{Name: testProject, Owner: model.DefaultAdminUserName}) Expect(err).Should(BeNil()) - _, err = targetUsecase.CreateTarget(context.TODO(), v1.CreateTargetRequest{ + _, err = targetService.CreateTarget(context.TODO(), v1.CreateTargetRequest{ Name: defaultTarget, Project: testProject, Cluster: &v1.ClusterTarget{ClusterName: "local", Namespace: namespace1}}) Expect(err).Should(BeNil()) - _, err = targetUsecase.CreateTarget(context.TODO(), v1.CreateTargetRequest{ + _, err = targetService.CreateTarget(context.TODO(), v1.CreateTargetRequest{ Name: defaultTarget2, Project: testProject, Cluster: &v1.ClusterTarget{ClusterName: "local", Namespace: namespace2}}) Expect(err).Should(BeNil()) - _, err = envUsecase.CreateEnv(context.TODO(), v1.CreateEnvRequest{Name: "app-dev", Namespace: envnsdev, Targets: []string{defaultTarget}, Project: testProject}) + _, err = envService.CreateEnv(context.TODO(), v1.CreateEnvRequest{Name: "app-dev", Namespace: envnsdev, Targets: []string{defaultTarget}, Project: testProject}) Expect(err).Should(BeNil()) - _, err = envUsecase.CreateEnv(context.TODO(), v1.CreateEnvRequest{Name: "app-test", Namespace: envnstest, Targets: []string{defaultTarget2}, Project: testProject}) + _, err = envService.CreateEnv(context.TODO(), v1.CreateEnvRequest{Name: "app-test", Namespace: envnstest, Targets: []string{defaultTarget2}, Project: testProject}) Expect(err).Should(BeNil()) req := v1.CreateApplicationRequest{ Name: testApp, @@ -139,11 +140,11 @@ var _ = Describe("Test application usecase function", func() { }, } By("test create application") - base, err := appUsecase.CreateApplication(context.TODO(), req) + base, err := appService.CreateApplication(context.TODO(), req) Expect(err).Should(BeNil()) Expect(cmp.Diff(base.Description, req.Description)).Should(BeEmpty()) - triggers, err := appUsecase.ListApplicationTriggers(context.TODO(), &model.Application{Name: testApp}) + triggers, err := appService.ListApplicationTriggers(context.TODO(), &model.Application{Name: testApp}) Expect(err).Should(BeNil()) Expect(len(triggers)).Should(Equal(1)) @@ -169,21 +170,21 @@ var _ = Describe("Test application usecase function", func() { Properties: "{\"password\":\"test\"}", }, } - _, err = appUsecase.CreateApplication(context.TODO(), req2) + _, err = appService.CreateApplication(context.TODO(), req2) Expect(err).Should(BeNil()) - err = appUsecase.DeleteApplication(context.TODO(), &model.Application{Project: testProject, Name: "test-cloud-application"}) + err = appService.DeleteApplication(context.TODO(), &model.Application{Project: testProject, Name: "test-cloud-application"}) Expect(err).Should(BeNil()) err = k8sClient.Delete(context.TODO(), &cd) Expect(err).Should(BeNil()) }) It("Test ListApplications function", func() { - _, err := appUsecase.ListApplications(context.WithValue(context.TODO(), &v1.CtxKeyUser, model.DefaultAdminUserName), v1.ListApplicationOptions{}) + _, err := appService.ListApplications(context.WithValue(context.TODO(), &v1.CtxKeyUser, model.DefaultAdminUserName), v1.ListApplicationOptions{}) Expect(err).Should(BeNil()) }) It("Test ListApplications and filter by targetName function", func() { - list, err := appUsecase.ListApplications(context.WithValue(context.TODO(), &v1.CtxKeyUser, model.DefaultAdminUserName), v1.ListApplicationOptions{ + list, err := appService.ListApplications(context.WithValue(context.TODO(), &v1.CtxKeyUser, model.DefaultAdminUserName), v1.ListApplicationOptions{ Projects: []string{testProject}, TargetName: defaultTarget}) Expect(err).Should(BeNil()) @@ -191,24 +192,24 @@ var _ = Describe("Test application usecase function", func() { }) It("Test DetailApplication function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty()) - detail, err := appUsecase.DetailApplication(context.TODO(), appModel) + detail, err := appService.DetailApplication(context.TODO(), appModel) Expect(err).Should(BeNil()) Expect(cmp.Diff(detail.ResourceInfo.ComponentNum, int64(1))).Should(BeEmpty()) Expect(cmp.Diff(len(detail.Policies), 2)).Should(BeEmpty()) }) It("Test CreateTrigger function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) - _, err = appUsecase.CreateApplicationTrigger(context.TODO(), appModel, v1.CreateApplicationTriggerRequest{ + _, err = appService.CreateApplicationTrigger(context.TODO(), appModel, v1.CreateApplicationTriggerRequest{ Name: "trigger-name", }) Expect(err).Should(BeNil()) - base, err := appUsecase.CreateApplicationTrigger(context.TODO(), appModel, v1.CreateApplicationTriggerRequest{ + base, err := appService.CreateApplicationTrigger(context.TODO(), appModel, v1.CreateApplicationTriggerRequest{ Name: "trigger-name-2", ComponentName: "trigger-component", }) @@ -217,17 +218,17 @@ var _ = Describe("Test application usecase function", func() { }) It("Test ListTriggers function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) - triggers, err := appUsecase.ListApplicationTriggers(context.TODO(), appModel) + triggers, err := appService.ListApplicationTriggers(context.TODO(), appModel) Expect(err).Should(BeNil()) Expect(len(triggers)).Should(Equal(3)) }) It("Test DeleteTrigger function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) - triggers, err := appUsecase.ListApplicationTriggers(context.TODO(), appModel) + triggers, err := appService.ListApplicationTriggers(context.TODO(), appModel) Expect(err).Should(BeNil()) Expect(len(triggers)).Should(Equal(3)) var trigger *v1.ApplicationTriggerBase @@ -238,8 +239,8 @@ var _ = Describe("Test application usecase function", func() { } } Expect(trigger).ShouldNot(BeNil()) - Expect(appUsecase.DeleteApplicationTrigger(context.TODO(), appModel, trigger.Token)).Should(BeNil()) - triggers, err = appUsecase.ListApplicationTriggers(context.TODO(), appModel) + Expect(appService.DeleteApplicationTrigger(context.TODO(), appModel, trigger.Token)).Should(BeNil()) + triggers, err = appService.ListApplicationTriggers(context.TODO(), appModel) Expect(err).Should(BeNil()) Expect(len(triggers)).Should(Equal(2)) trigger = nil @@ -253,21 +254,21 @@ var _ = Describe("Test application usecase function", func() { }) It("Test ListComponents function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty()) - components, err := appUsecase.ListComponents(context.TODO(), appModel, v1.ListApplicationComponentOptions{}) + components, err := appService.ListComponents(context.TODO(), appModel, v1.ListApplicationComponentOptions{}) Expect(err).Should(BeNil()) Expect(cmp.Diff(len(components), 1)).Should(BeEmpty()) Expect(cmp.Diff(components[0].ComponentType, "webservice")).Should(BeEmpty()) }) It("Test CreateComponent function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) - base, err := appUsecase.CreateComponent(context.TODO(), appModel, v1.CreateComponentRequest{ + base, err := appService.CreateComponent(context.TODO(), appModel, v1.CreateComponentRequest{ Name: "test2", Description: "this is a test2 component", Labels: map[string]string{}, @@ -291,16 +292,16 @@ var _ = Describe("Test application usecase function", func() { Expect(err).Should(BeNil()) Expect(cmp.Diff(base.ComponentType, "webservice")).Should(BeEmpty()) - detailResponse, err := appUsecase.DetailComponent(context.TODO(), appModel, "test2") + detailResponse, err := appService.DetailComponent(context.TODO(), appModel, "test2") Expect(err).Should(BeNil()) Expect(cmp.Diff(len(detailResponse.Traits), 2)).Should(BeEmpty()) }) It("Test DetailComponent function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty()) - detailResponse, err := appUsecase.DetailComponent(context.TODO(), appModel, "test2") + detailResponse, err := appService.DetailComponent(context.TODO(), appModel, "test2") Expect(err).Should(BeNil()) Expect(cmp.Diff(detailResponse.DependsOn[0], "component-name")).Should(BeEmpty()) Expect(detailResponse.Properties).ShouldNot(BeNil()) @@ -308,10 +309,10 @@ var _ = Describe("Test application usecase function", func() { }) It("Test AddPolicy function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty()) - _, err = appUsecase.CreatePolicy(context.TODO(), appModel, v1.CreatePolicyRequest{ + _, err = appService.CreatePolicy(context.TODO(), appModel, v1.CreatePolicyRequest{ Name: overridePolicyName, Description: "this is a test2 policy", Type: "override", @@ -319,7 +320,7 @@ var _ = Describe("Test application usecase function", func() { }) Expect(err).Should(BeNil()) - _, err = appUsecase.CreatePolicy(context.TODO(), appModel, v1.CreatePolicyRequest{ + _, err = appService.CreatePolicy(context.TODO(), appModel, v1.CreatePolicyRequest{ Name: overridePolicyName, Description: "this is a test2 policy", Type: "override", @@ -329,11 +330,11 @@ var _ = Describe("Test application usecase function", func() { }) It("Test ListPolicies function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty()) - policies, err := appUsecase.ListPolicies(context.TODO(), appModel) + policies, err := appService.ListPolicies(context.TODO(), appModel) Expect(err).Should(BeNil()) var count int for _, p := range policies { @@ -345,20 +346,20 @@ var _ = Describe("Test application usecase function", func() { }) It("Test DetailPolicy function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty()) - detail, err := appUsecase.DetailPolicy(context.TODO(), appModel, overridePolicyName) + detail, err := appService.DetailPolicy(context.TODO(), appModel, overridePolicyName) Expect(err).Should(BeNil()) Expect(detail.Properties).ShouldNot(BeNil()) Expect((*detail.Properties)["components"]).ShouldNot(BeEmpty()) }) It("Test UpdatePolicy function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty()) - base, err := appUsecase.UpdatePolicy(context.TODO(), appModel, overridePolicyName, v1.UpdatePolicyRequest{ + base, err := appService.UpdatePolicy(context.TODO(), appModel, overridePolicyName, v1.UpdatePolicyRequest{ Type: "override", Properties: `{"components":{}}`, }) @@ -367,20 +368,20 @@ var _ = Describe("Test application usecase function", func() { Expect((*base.Properties)["components"]).Should(BeEmpty()) }) It("Test DeletePolicy function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty()) - err = appUsecase.DeletePolicy(context.TODO(), appModel, overridePolicyName) + err = appService.DeletePolicy(context.TODO(), appModel, overridePolicyName) Expect(err).Should(BeNil()) }) It("Test DeleteComponent function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty()) - component, err := appUsecase.GetApplicationComponent(context.TODO(), appModel, "test2") + component, err := appService.GetApplicationComponent(context.TODO(), appModel, "test2") Expect(err).Should(BeNil()) - err = appUsecase.DeleteComponent(context.TODO(), appModel, component) + err = appService.DeleteComponent(context.TODO(), appModel, component) Expect(err).Should(BeNil()) }) @@ -396,36 +397,36 @@ var _ = Describe("Test application usecase function", func() { if i == 0 { appModel.Status = model.RevisionStatusTerminated } - err := workflowUsecase.createTestApplicationRevision(context.TODO(), appModel) + err := workflowService.createTestApplicationRevision(context.TODO(), appModel) Expect(err).Should(BeNil()) } - revisions, err := appUsecase.ListRevisions(context.TODO(), "test-app-sadasd", "", "", 0, 10) + revisions, err := appService.ListRevisions(context.TODO(), "test-app-sadasd", "", "", 0, 10) Expect(err).Should(BeNil()) Expect(revisions.Total).Should(Equal(int64(3))) - revisions, err = appUsecase.ListRevisions(context.TODO(), "test-app-sadasd", "env-0", "", 0, 10) + revisions, err = appService.ListRevisions(context.TODO(), "test-app-sadasd", "env-0", "", 0, 10) Expect(err).Should(BeNil()) Expect(revisions.Total).Should(Equal(int64(1))) Expect(revisions.Revisions[0].DeployUser.Name).Should(Equal(model.DefaultAdminUserName)) Expect(revisions.Revisions[0].DeployUser.Alias).Should(Equal(model.DefaultAdminUserAlias)) - revisions, err = appUsecase.ListRevisions(context.TODO(), "test-app-sadasd", "", "terminated", 0, 10) + revisions, err = appService.ListRevisions(context.TODO(), "test-app-sadasd", "", "terminated", 0, 10) Expect(err).Should(BeNil()) Expect(revisions.Total).Should(Equal(int64(1))) - revisions, err = appUsecase.ListRevisions(context.TODO(), "test-app", "env-1", "terminated", 0, 10) + revisions, err = appService.ListRevisions(context.TODO(), "test-app", "env-1", "terminated", 0, 10) Expect(err).Should(BeNil()) Expect(revisions.Total).Should(Equal(int64(0))) }) It("Test DetailRevision function", func() { - err := workflowUsecase.createTestApplicationRevision(context.TODO(), &model.ApplicationRevision{ + err := workflowService.createTestApplicationRevision(context.TODO(), &model.ApplicationRevision{ AppPrimaryKey: "test-app", Version: "123", DeployUser: model.DefaultAdminUserName, }) Expect(err).Should(BeNil()) - revision, err := appUsecase.DetailRevision(context.TODO(), "test-app", "123") + revision, err := appService.DetailRevision(context.TODO(), "test-app", "123") Expect(err).Should(BeNil()) Expect(revision.Version).Should(Equal("123")) Expect(revision.DeployUser.Name).Should(Equal(model.DefaultAdminUserName)) @@ -433,15 +434,15 @@ var _ = Describe("Test application usecase function", func() { }) It("Test ApplicationEnvRecycle function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) - revision, err := appUsecase.Deploy( + revision, err := appService.Deploy( context.WithValue(context.TODO(), &v1.CtxKeyUser, model.DefaultAdminUserName), - appModel, v1.ApplicationDeployRequest{WorkflowName: convertWorkflowName("app-dev")}) + appModel, v1.ApplicationDeployRequest{WorkflowName: repository.ConvertWorkflowName("app-dev")}) Expect(err).Should(BeNil()) Expect(revision.DeployUser.Name).Should(Equal(model.DefaultAdminUserName)) Expect(revision.DeployUser.Alias).Should(Equal(model.DefaultAdminUserAlias)) - err = envBindingUsecase.ApplicationEnvRecycle(context.TODO(), &model.Application{ + err = envBindingService.ApplicationEnvRecycle(context.TODO(), &model.Application{ Name: testApp, }, &model.EnvBinding{Name: "app-dev"}) Expect(err).Should(BeNil()) @@ -451,7 +452,7 @@ var _ = Describe("Test application usecase function", func() { By("no running records in application") ctx := context.TODO() for i := 0; i < 2; i++ { - appUsecase.ds.Add(ctx, &model.WorkflowRecord{ + appService.Store.Add(ctx, &model.WorkflowRecord{ AppPrimaryKey: "app-records", Name: fmt.Sprintf("list-%d", i), Finished: "true", @@ -459,13 +460,13 @@ var _ = Describe("Test application usecase function", func() { }) } - resp, err := appUsecase.ListRecords(context.TODO(), "app-records") + resp, err := appService.ListRecords(context.TODO(), "app-records") Expect(err).Should(BeNil()) Expect(resp.Total).Should(Equal(int64(1))) By("3 running records in application") for i := 0; i < 3; i++ { - appUsecase.ds.Add(ctx, &model.WorkflowRecord{ + appService.Store.Add(ctx, &model.WorkflowRecord{ AppPrimaryKey: "app-records", Name: fmt.Sprintf("list-running-%d", i), Finished: "false", @@ -473,145 +474,145 @@ var _ = Describe("Test application usecase function", func() { }) } - resp, err = appUsecase.ListRecords(context.TODO(), "app-records") + resp, err = appService.ListRecords(context.TODO(), "app-records") Expect(err).Should(BeNil()) Expect(resp.Total).Should(Equal(int64(3))) }) It("Test CompareAppWithLatestRevision function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) - _, err = appUsecase.Deploy(context.TODO(), appModel, v1.ApplicationDeployRequest{WorkflowName: convertWorkflowName("app-dev")}) + _, err = appService.Deploy(context.TODO(), appModel, v1.ApplicationDeployRequest{WorkflowName: repository.ConvertWorkflowName("app-dev")}) Expect(err).Should(BeNil()) - component, err := appUsecase.GetApplicationComponent(context.TODO(), appModel, "component-name") + component, err := appService.GetApplicationComponent(context.TODO(), appModel, "component-name") Expect(err).Should(BeNil()) By("compare when app not change, should return false") - compareResponse, err := appUsecase.CompareAppWithLatestRevision(context.TODO(), appModel, v1.AppCompareReq{}) + compareResponse, err := appService.CompareAppWithLatestRevision(context.TODO(), appModel, v1.AppCompareReq{}) Expect(err).Should(BeNil()) Expect(cmp.Diff(compareResponse.IsDiff, false)).Should(BeEmpty()) By("compare when app not change and env not empty, should return false") - compareResponse, err = appUsecase.CompareAppWithLatestRevision(context.TODO(), appModel, v1.AppCompareReq{Env: "app-dev"}) + compareResponse, err = appService.CompareAppWithLatestRevision(context.TODO(), appModel, v1.AppCompareReq{Env: "app-dev"}) Expect(err).Should(BeNil()) Expect(cmp.Diff(compareResponse.IsDiff, false)).Should(BeEmpty()) By("compare when app add env, not change, should return false") - _, err = envUsecase.CreateEnv(context.TODO(), v1.CreateEnvRequest{Name: "app-prod", Namespace: "envnsprod", Targets: []string{defaultTarget}, Project: "app-prod"}) + _, err = envService.CreateEnv(context.TODO(), v1.CreateEnvRequest{Name: "app-prod", Namespace: "envnsprod", Targets: []string{defaultTarget}, Project: "app-prod"}) Expect(err).Should(BeNil()) - _, err = envBindingUsecase.CreateEnvBinding(context.TODO(), appModel, v1.CreateApplicationEnvbindingRequest{EnvBinding: v1.EnvBinding{Name: "app-prod"}}) + _, err = envBindingService.CreateEnvBinding(context.TODO(), appModel, v1.CreateApplicationEnvbindingRequest{EnvBinding: v1.EnvBinding{Name: "app-prod"}}) Expect(err).Should(BeNil()) - compareResponse, err = appUsecase.CompareAppWithLatestRevision(context.TODO(), appModel, v1.AppCompareReq{}) + compareResponse, err = appService.CompareAppWithLatestRevision(context.TODO(), appModel, v1.AppCompareReq{}) Expect(err).Should(BeNil()) Expect(cmp.Diff(compareResponse.IsDiff, false)).Should(BeEmpty()) By("compare when app's env add target, should return true") - _, err = targetUsecase.CreateTarget(context.TODO(), v1.CreateTargetRequest{Name: "dev-target1", Project: appModel.Project, Cluster: &v1.ClusterTarget{ClusterName: "local", Namespace: "dev-target1"}}) + _, err = targetService.CreateTarget(context.TODO(), v1.CreateTargetRequest{Name: "dev-target1", Project: appModel.Project, Cluster: &v1.ClusterTarget{ClusterName: "local", Namespace: "dev-target1"}}) Expect(err).Should(BeNil()) - _, err = envUsecase.UpdateEnv(context.TODO(), "app-dev", + _, err = envService.UpdateEnv(context.TODO(), "app-dev", v1.UpdateEnvRequest{ Description: "this is a env description update", Targets: []string{defaultTarget, "dev-target1"}, }) Expect(err).Should(BeNil()) - compareResponse, err = appUsecase.CompareAppWithLatestRevision(context.TODO(), appModel, v1.AppCompareReq{}) + compareResponse, err = appService.CompareAppWithLatestRevision(context.TODO(), appModel, v1.AppCompareReq{}) Expect(err).Should(BeNil()) Expect(cmp.Diff(compareResponse.IsDiff, true)).Should(BeEmpty()) By("compare when update app's trait, should return true") // reset app config - _, err = appUsecase.ResetAppToLatestRevision(context.TODO(), testApp) + _, err = appService.ResetAppToLatestRevision(context.TODO(), testApp) Expect(err).Should(BeNil()) - _, err = appUsecase.UpdateApplicationTrait(context.TODO(), appModel, &model.ApplicationComponent{Name: "component-name"}, "scaler", v1.UpdateApplicationTraitRequest{ + _, err = appService.UpdateApplicationTrait(context.TODO(), appModel, &model.ApplicationComponent{Name: "component-name"}, "scaler", v1.UpdateApplicationTraitRequest{ Properties: `{"replicas":2}`, Alias: "alias", Description: "description", }) Expect(err).Should(BeNil()) - compareResponse, err = appUsecase.CompareAppWithLatestRevision(context.TODO(), appModel, v1.AppCompareReq{}) + compareResponse, err = appService.CompareAppWithLatestRevision(context.TODO(), appModel, v1.AppCompareReq{}) Expect(err).Should(BeNil()) Expect(cmp.Diff(compareResponse.IsDiff, true)).Should(BeEmpty()) By("compare when update component's target after app deployed ,should return ture") // reset app config - _, err = appUsecase.ResetAppToLatestRevision(context.TODO(), testApp) + _, err = appService.ResetAppToLatestRevision(context.TODO(), testApp) Expect(err).Should(BeNil()) newProperties := "{\"exposeType\":\"NodePort\",\"image\":\"nginx\",\"imagePullPolicy\":\"Always\"}" - _, err = appUsecase.UpdateComponent(context.TODO(), + _, err = appService.UpdateComponent(context.TODO(), appModel, component, v1.UpdateApplicationComponentRequest{ Properties: &newProperties, }) Expect(err).Should(BeNil()) - compareResponse, err = appUsecase.CompareAppWithLatestRevision(context.TODO(), appModel, v1.AppCompareReq{}) + compareResponse, err = appService.CompareAppWithLatestRevision(context.TODO(), appModel, v1.AppCompareReq{}) Expect(err).Should(BeNil()) Expect(cmp.Diff(compareResponse.IsDiff, true)).Should(BeEmpty()) - err = envBindingUsecase.ApplicationEnvRecycle(context.TODO(), &model.Application{Name: testApp}, &model.EnvBinding{Name: "app-dev"}) + err = envBindingService.ApplicationEnvRecycle(context.TODO(), &model.Application{Name: testApp}, &model.EnvBinding{Name: "app-dev"}) Expect(err).Should(BeNil()) }) It("Test ResetAppToLatestRevision function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) - resetResponse, err := appUsecase.ResetAppToLatestRevision(context.TODO(), testApp) + resetResponse, err := appService.ResetAppToLatestRevision(context.TODO(), testApp) Expect(err).Should(BeNil()) Expect(cmp.Diff(resetResponse.IsReset, true)).Should(BeEmpty()) - component, err := appUsecase.GetApplicationComponent(context.TODO(), appModel, "component-name") + component, err := appService.GetApplicationComponent(context.TODO(), appModel, "component-name") Expect(err).Should(BeNil()) expectProperties := "{\"image\":\"nginx\"}" Expect(cmp.Diff(component.Properties.JSON(), expectProperties)).Should(BeEmpty()) }) It("Test DryRun with app function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) - resetResponse, err := appUsecase.DryRunAppOrRevision(context.TODO(), appModel, v1.AppDryRunReq{DryRunType: "APP"}) + resetResponse, err := appService.DryRunAppOrRevision(context.TODO(), appModel, v1.AppDryRunReq{DryRunType: "APP"}) Expect(err).Should(BeNil()) Expect(strings.Contains(resetResponse.YAML, "# Application(test-app)")).Should(BeTrue()) Expect(strings.Contains(resetResponse.YAML, "# Application(test-app) -- Component(component-name)")).Should(BeTrue()) }) It("Test DryRun with env revision function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) - resetResponse, err := appUsecase.DryRunAppOrRevision(context.TODO(), appModel, v1.AppDryRunReq{DryRunType: "Revision", Env: "app-dev"}) + resetResponse, err := appService.DryRunAppOrRevision(context.TODO(), appModel, v1.AppDryRunReq{DryRunType: "Revision", Env: "app-dev"}) Expect(err).Should(BeNil()) Expect(strings.Contains(resetResponse.YAML, "# Application(test-app)")).Should(BeTrue()) Expect(strings.Contains(resetResponse.YAML, "# Application(test-app) -- Component(component-name)")).Should(BeTrue()) }) It("Test DryRun with last revision function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) - resetResponse, err := appUsecase.DryRunAppOrRevision(context.TODO(), appModel, v1.AppDryRunReq{DryRunType: "Revision"}) + resetResponse, err := appService.DryRunAppOrRevision(context.TODO(), appModel, v1.AppDryRunReq{DryRunType: "Revision"}) Expect(err).Should(BeNil()) Expect(strings.Contains(resetResponse.YAML, "# Application(test-app)")).Should(BeTrue()) Expect(strings.Contains(resetResponse.YAML, "# Application(test-app) -- Component(component-name)")).Should(BeTrue()) }) It("Test DeleteApplication function", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) time.Sleep(time.Second * 3) - err = appUsecase.DeleteApplication(context.TODO(), appModel) + err = appService.DeleteApplication(context.TODO(), appModel) Expect(err).Should(BeNil()) - components, err := appUsecase.ListComponents(context.TODO(), appModel, v1.ListApplicationComponentOptions{}) + components, err := appService.ListComponents(context.TODO(), appModel, v1.ListApplicationComponentOptions{}) Expect(err).Should(BeNil()) Expect(cmp.Diff(len(components), 0)).Should(BeEmpty()) - policies, err := appUsecase.ListPolicies(context.TODO(), appModel) + policies, err := appService.ListPolicies(context.TODO(), appModel) Expect(err).Should(BeNil()) Expect(cmp.Diff(len(policies), 0)).Should(BeEmpty()) }) }) -var _ = Describe("Test application component usecase function", func() { +var _ = Describe("Test application component service function", func() { var ( - appUsecase *applicationUsecaseImpl - projectUsecase *projectUsecaseImpl - envUsecase *envUsecaseImpl + appService *applicationServiceImpl + projectService *projectServiceImpl + envService *envServiceImpl testApp string testProject string ) @@ -620,20 +621,20 @@ var _ = Describe("Test application component usecase function", func() { ds, err := NewDatastore(datastore.Config{Type: "kubeapi", Database: "app-test-kubevela"}) Expect(ds).ToNot(BeNil()) Expect(err).Should(BeNil()) - rbacUsecase := &rbacUsecaseImpl{ds: ds} - projectUsecase = &projectUsecaseImpl{ds: ds, k8sClient: k8sClient, rbacUsecase: rbacUsecase} - envUsecase = &envUsecaseImpl{ds: ds, kubeClient: k8sClient, projectUsecase: projectUsecase} - workflowUsecase := &workflowUsecaseImpl{ds: ds, envUsecase: envUsecase} - envBindingUsecase := &envBindingUsecaseImpl{ds: ds, envUsecase: envUsecase, workflowUsecase: workflowUsecase, kubeClient: k8sClient} + rbacService := &rbacServiceImpl{Store: ds} + projectService = &projectServiceImpl{Store: ds, K8sClient: k8sClient, RbacService: rbacService} + envService = &envServiceImpl{Store: ds, KubeClient: k8sClient, ProjectService: projectService} + workflowService := &workflowServiceImpl{Store: ds, EnvService: envService} + envBindingService := &envBindingServiceImpl{Store: ds, EnvService: envService, WorkflowService: workflowService, KubeClient: k8sClient} - appUsecase = &applicationUsecaseImpl{ - ds: ds, - apply: apply.NewAPIApplicator(k8sClient), - kubeClient: k8sClient, - projectUsecase: projectUsecase, - workflowUsecase: workflowUsecase, - envBindingUsecase: envBindingUsecase, - envUsecase: envUsecase, + appService = &applicationServiceImpl{ + Store: ds, + Apply: apply.NewAPIApplicator(k8sClient), + KubeClient: k8sClient, + ProjectService: projectService, + WorkflowService: workflowService, + EnvBindingService: envBindingService, + EnvService: envService, } testApp = "test-trait-app" testProject = "test-trait-project" @@ -641,17 +642,17 @@ var _ = Describe("Test application component usecase function", func() { }) It("Test add application trait", func() { - _, err := projectUsecase.CreateProject(context.TODO(), v1.CreateProjectRequest{Name: testProject}) + _, err := projectService.CreateProject(context.TODO(), v1.CreateProjectRequest{Name: testProject}) Expect(err).Should(BeNil()) - _, err = appUsecase.CreateApplication(context.TODO(), v1.CreateApplicationRequest{Name: testApp, Project: testProject}) + _, err = appService.CreateApplication(context.TODO(), v1.CreateApplicationRequest{Name: testApp, Project: testProject}) Expect(err).Should(BeNil()) - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) - _, err = appUsecase.CreateComponent(context.TODO(), appModel, v1.CreateComponentRequest{Name: "test2", ComponentType: "webservice"}) + _, err = appService.CreateComponent(context.TODO(), appModel, v1.CreateComponentRequest{Name: "test2", ComponentType: "webservice"}) Expect(err).Should(BeNil()) alias := "alias" description := "description" - res, err := appUsecase.CreateApplicationTrait(context.TODO(), appModel, &model.ApplicationComponent{Name: "test2"}, v1.CreateApplicationTraitRequest{ + res, err := appService.CreateApplicationTrait(context.TODO(), appModel, &model.ApplicationComponent{Name: "test2"}, v1.CreateApplicationTraitRequest{ Type: "Ingress", Properties: `{"domain":"www.test.com"}`, Alias: alias, @@ -659,7 +660,7 @@ var _ = Describe("Test application component usecase function", func() { }) Expect(err).Should(BeNil()) Expect(cmp.Diff(res.Type, "Ingress")).Should(BeEmpty()) - comp, err := appUsecase.DetailComponent(context.TODO(), appModel, "test2") + comp, err := appService.DetailComponent(context.TODO(), appModel, "test2") Expect(err).Should(BeNil()) Expect(comp).ShouldNot(BeNil()) // A scaler trait is automatically generated for the webservice component. @@ -669,7 +670,7 @@ var _ = Describe("Test application component usecase function", func() { Expect(comp.Traits[1].Description).Should(BeEquivalentTo(description)) Expect(err).Should(BeNil()) - _, err = appUsecase.CreateApplicationTrait(context.TODO(), appModel, &model.ApplicationComponent{Name: "test2"}, v1.CreateApplicationTraitRequest{ + _, err = appService.CreateApplicationTrait(context.TODO(), appModel, &model.ApplicationComponent{Name: "test2"}, v1.CreateApplicationTraitRequest{ Type: "Ingress", Properties: `{"domain":"www.dup.com"}`, }) @@ -677,18 +678,18 @@ var _ = Describe("Test application component usecase function", func() { }) It("Test update application trait", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) alias := "newAlias" description := "newDescription" - res, err := appUsecase.UpdateApplicationTrait(context.TODO(), appModel, &model.ApplicationComponent{Name: "test2"}, "Ingress", v1.UpdateApplicationTraitRequest{ + res, err := appService.UpdateApplicationTrait(context.TODO(), appModel, &model.ApplicationComponent{Name: "test2"}, "Ingress", v1.UpdateApplicationTraitRequest{ Properties: `{"domain":"www.test1.com"}`, Alias: alias, Description: description, }) Expect(err).Should(BeNil()) Expect(cmp.Diff(res.Type, "Ingress")).Should(BeEmpty()) - comp, err := appUsecase.DetailComponent(context.TODO(), appModel, "test2") + comp, err := appService.DetailComponent(context.TODO(), appModel, "test2") Expect(err).Should(BeNil()) Expect(comp).ShouldNot(BeNil()) Expect(len(comp.Traits)).Should(BeEquivalentTo(2)) @@ -698,20 +699,20 @@ var _ = Describe("Test application component usecase function", func() { }) It("Test update a not exist", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) - _, err = appUsecase.UpdateApplicationTrait(context.TODO(), appModel, &model.ApplicationComponent{Name: "test2"}, "Ingress-1-20", v1.UpdateApplicationTraitRequest{ + _, err = appService.UpdateApplicationTrait(context.TODO(), appModel, &model.ApplicationComponent{Name: "test2"}, "Ingress-1-20", v1.UpdateApplicationTraitRequest{ Properties: `{"domain":"www.test1.com"}`, }) Expect(err).ShouldNot(BeNil()) }) It("Test delete an exist trait", func() { - appModel, err := appUsecase.GetApplication(context.TODO(), testApp) + appModel, err := appService.GetApplication(context.TODO(), testApp) Expect(err).Should(BeNil()) - err = appUsecase.DeleteApplicationTrait(context.TODO(), appModel, &model.ApplicationComponent{Name: "test2"}, "Ingress") + err = appService.DeleteApplicationTrait(context.TODO(), appModel, &model.ApplicationComponent{Name: "test2"}, "Ingress") Expect(err).Should(BeNil()) - app, err := appUsecase.DetailComponent(context.TODO(), appModel, "test2") + app, err := appService.DetailComponent(context.TODO(), appModel, "test2") Expect(err).Should(BeNil()) Expect(app).ShouldNot(BeNil()) Expect(len(app.Traits)).Should(BeEquivalentTo(1)) diff --git a/pkg/apiserver/rest/usecase/authentication.go b/pkg/apiserver/domain/service/authentication.go similarity index 85% rename from pkg/apiserver/rest/usecase/authentication.go rename to pkg/apiserver/domain/service/authentication.go index 67a468402..434485dc4 100644 --- a/pkg/apiserver/rest/usecase/authentication.go +++ b/pkg/apiserver/domain/service/authentication.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -37,12 +37,11 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" velatypes "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" ) const ( @@ -60,33 +59,24 @@ const ( var signedKey = "" -// AuthenticationUsecase is the usecase of authentication -type AuthenticationUsecase interface { +// AuthenticationService is the service of authentication +type AuthenticationService interface { Login(ctx context.Context, loginReq apisv1.LoginRequest) (*apisv1.LoginResponse, error) RefreshToken(ctx context.Context, refreshToken string) (*apisv1.RefreshTokenResponse, error) GetDexConfig(ctx context.Context) (*apisv1.DexConfigResponse, error) GetLoginType(ctx context.Context) (*apisv1.GetLoginTypeResponse, error) } -type authenticationUsecaseImpl struct { - sysUsecase SystemInfoUsecase - userUsecase UserUsecase - ds datastore.DataStore - kubeClient client.Client +type authenticationServiceImpl struct { + SysService SystemInfoService `inject:""` + UserService UserService `inject:""` + Store datastore.DataStore `inject:"datastore"` + KubeClient client.Client `inject:"kubeClient"` } -// NewAuthenticationUsecase new authentication usecase -func NewAuthenticationUsecase(ds datastore.DataStore, sysUsecase SystemInfoUsecase, userUsecase UserUsecase) AuthenticationUsecase { - kubecli, err := clients.GetKubeClient() - if err != nil { - log.Logger.Fatalf("failed to get kube client: %s", err.Error()) - } - return &authenticationUsecaseImpl{ - sysUsecase: sysUsecase, - userUsecase: userUsecase, - ds: ds, - kubeClient: kubecli, - } +// NewAuthenticationService new authentication service +func NewAuthenticationService() AuthenticationService { + return &authenticationServiceImpl{} } type authHandler interface { @@ -95,17 +85,17 @@ type authHandler interface { type dexHandlerImpl struct { idToken *oidc.IDToken - ds datastore.DataStore + Store datastore.DataStore } type localHandlerImpl struct { ds datastore.DataStore - userUsecase UserUsecase + userService UserService username string password string } -func (a *authenticationUsecaseImpl) newDexHandler(ctx context.Context, req apisv1.LoginRequest) (*dexHandlerImpl, error) { +func (a *authenticationServiceImpl) newDexHandler(ctx context.Context, req apisv1.LoginRequest) (*dexHandlerImpl, error) { if req.Code == "" { return nil, bcode.ErrInvalidLoginRequest } @@ -135,26 +125,26 @@ func (a *authenticationUsecaseImpl) newDexHandler(ctx context.Context, req apisv } return &dexHandlerImpl{ idToken: idToken, - ds: a.ds, + Store: a.Store, }, nil } -func (a *authenticationUsecaseImpl) newLocalHandler(req apisv1.LoginRequest) (*localHandlerImpl, error) { +func (a *authenticationServiceImpl) newLocalHandler(req apisv1.LoginRequest) (*localHandlerImpl, error) { if req.Username == "" || req.Password == "" { return nil, bcode.ErrInvalidLoginRequest } return &localHandlerImpl{ - ds: a.ds, - userUsecase: a.userUsecase, + ds: a.Store, + userService: a.UserService, username: req.Username, password: req.Password, }, nil } -func (a *authenticationUsecaseImpl) Login(ctx context.Context, loginReq apisv1.LoginRequest) (*apisv1.LoginResponse, error) { +func (a *authenticationServiceImpl) Login(ctx context.Context, loginReq apisv1.LoginRequest) (*apisv1.LoginResponse, error) { var handler authHandler var err error - sysInfo, err := a.sysUsecase.Get(ctx) + sysInfo, err := a.SysService.Get(ctx) if err != nil { return nil, err } @@ -196,7 +186,7 @@ func (a *authenticationUsecaseImpl) Login(ctx context.Context, loginReq apisv1.L }, nil } -func (a *authenticationUsecaseImpl) generateJWTToken(username, grantType string, expireDuration time.Duration) (string, error) { +func (a *authenticationServiceImpl) generateJWTToken(username, grantType string, expireDuration time.Duration) (string, error) { expire := time.Now().Add(expireDuration) claims := model.CustomClaims{ StandardClaims: jwt.StandardClaims{ @@ -211,7 +201,7 @@ func (a *authenticationUsecaseImpl) generateJWTToken(username, grantType string, return token.SignedString([]byte(signedKey)) } -func (a *authenticationUsecaseImpl) RefreshToken(ctx context.Context, refreshToken string) (*apisv1.RefreshTokenResponse, error) { +func (a *authenticationServiceImpl) RefreshToken(ctx context.Context, refreshToken string) (*apisv1.RefreshTokenResponse, error) { claim, err := ParseToken(refreshToken) if err != nil { if errors.Is(err, bcode.ErrTokenExpired) { @@ -260,8 +250,8 @@ func ParseToken(tokenString string) (*model.CustomClaims, error) { return nil, bcode.ErrTokenInvalid } -func (a *authenticationUsecaseImpl) GetDexConfig(ctx context.Context) (*apisv1.DexConfigResponse, error) { - config, err := getDexConfig(ctx, a.kubeClient) +func (a *authenticationServiceImpl) GetDexConfig(ctx context.Context) (*apisv1.DexConfigResponse, error) { + config, err := getDexConfig(ctx, a.KubeClient) if err != nil { return nil, err } @@ -426,8 +416,8 @@ func getDexConfig(ctx context.Context, kubeClient client.Client) (*model.DexConf return config, nil } -func (a *authenticationUsecaseImpl) GetLoginType(ctx context.Context) (*apisv1.GetLoginTypeResponse, error) { - sysInfo, err := a.sysUsecase.Get(ctx) +func (a *authenticationServiceImpl) GetLoginType(ctx context.Context) (*apisv1.GetLoginTypeResponse, error) { + sysInfo, err := a.SysService.Get(ctx) if err != nil { return nil, err } @@ -451,18 +441,18 @@ func (d *dexHandlerImpl) login(ctx context.Context) (*apisv1.UserBase, error) { user := &model.User{Email: claims.Email} userBase := &apisv1.UserBase{Email: claims.Email, Name: claims.Name} - users, err := d.ds.List(ctx, user, &datastore.ListOptions{}) + users, err := d.Store.List(ctx, user, &datastore.ListOptions{}) if err != nil { return nil, err } if len(users) > 0 { u := users[0].(*model.User) u.LastLoginTime = time.Now() - if err := d.ds.Put(ctx, u); err != nil { + if err := d.Store.Put(ctx, u); err != nil { return nil, err } userBase.Name = u.Name - } else if err := d.ds.Add(ctx, &model.User{ + } else if err := d.Store.Add(ctx, &model.User{ Email: claims.Email, Name: claims.Name, LastLoginTime: time.Now(), @@ -474,7 +464,7 @@ func (d *dexHandlerImpl) login(ctx context.Context) (*apisv1.UserBase, error) { } func (l *localHandlerImpl) login(ctx context.Context) (*apisv1.UserBase, error) { - user, err := l.userUsecase.GetUser(ctx, l.username) + user, err := l.userService.GetUser(ctx, l.username) if err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil, bcode.ErrUsernameNotExist @@ -484,7 +474,7 @@ func (l *localHandlerImpl) login(ctx context.Context) (*apisv1.UserBase, error) if err := compareHashWithPassword(user.Password, l.password); err != nil { return nil, err } - if err := l.userUsecase.UpdateUserLoginTime(ctx, user); err != nil { + if err := l.userService.UpdateUserLoginTime(ctx, user); err != nil { return nil, err } return &apisv1.UserBase{ diff --git a/pkg/apiserver/rest/usecase/authentication_test.go b/pkg/apiserver/domain/service/authentication_test.go similarity index 85% rename from pkg/apiserver/rest/usecase/authentication_test.go rename to pkg/apiserver/domain/service/authentication_test.go index 69d7e45d8..45e7f92f2 100644 --- a/pkg/apiserver/rest/usecase/authentication_test.go +++ b/pkg/apiserver/domain/service/authentication_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -36,18 +36,18 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" "github.com/oam-dev/kubevela/pkg/oam/util" ) -var _ = Describe("Test authentication usecase functions", func() { +var _ = Describe("Test authentication service functions", func() { var ( - authUsecase *authenticationUsecaseImpl - userUsecase *userUsecaseImpl - sysUsecase *systemInfoUsecaseImpl + authService *authenticationServiceImpl + userService *userServiceImpl + sysService *systemInfoServiceImpl ds datastore.DataStore ) @@ -56,9 +56,9 @@ var _ = Describe("Test authentication usecase functions", func() { ds, err = NewDatastore(datastore.Config{Type: "kubeapi", Database: "auth-test-" + strconv.FormatInt(time.Now().UnixNano(), 10)}) Expect(ds).ToNot(BeNil()) Expect(err).Should(BeNil()) - authUsecase = &authenticationUsecaseImpl{kubeClient: k8sClient, ds: ds} - sysUsecase = &systemInfoUsecaseImpl{ds: ds, kubeClient: k8sClient} - userUsecase = &userUsecaseImpl{ds: ds, sysUsecase: sysUsecase} + authService = &authenticationServiceImpl{KubeClient: k8sClient, Store: ds} + sysService = &systemInfoServiceImpl{Store: ds, KubeClient: k8sClient} + userService = &userServiceImpl{Store: ds, SysService: sysService} }) It("Test Dex login", func() { testIDToken := &oidc.IDToken{} @@ -68,7 +68,7 @@ var _ = Describe("Test authentication usecase functions", func() { defer patch.Reset() dexHandler := dexHandlerImpl{ idToken: testIDToken, - ds: ds, + Store: ds, } resp, err := dexHandler.login(context.Background()) Expect(err).Should(BeNil()) @@ -98,14 +98,14 @@ var _ = Describe("Test authentication usecase functions", func() { }) It("Test local login", func() { - _, err := userUsecase.CreateUser(context.Background(), apisv1.CreateUserRequest{ + _, err := userService.CreateUser(context.Background(), apisv1.CreateUserRequest{ Name: "test-login", Email: "test@example.com", Password: "password1", }) Expect(err).Should(BeNil()) localHandler := localHandlerImpl{ - userUsecase: userUsecase, + userService: userService, ds: ds, username: "test-login", password: "password1", @@ -167,9 +167,9 @@ var _ = Describe("Test authentication usecase functions", func() { }) Expect(err).Should(BeNil()) By("try to update dex config without config secret") - connectors, err := utils.GetDexConnectors(context.Background(), authUsecase.kubeClient) + connectors, err := utils.GetDexConnectors(context.Background(), authService.KubeClient) Expect(err).Should(BeNil()) - err = generateDexConfig(context.Background(), authUsecase.kubeClient, &model.UpdateDexConfig{ + err = generateDexConfig(context.Background(), authService.KubeClient, &model.UpdateDexConfig{ Connectors: connectors, }) Expect(err).Should(BeNil()) @@ -181,19 +181,19 @@ var _ = Describe("Test authentication usecase functions", func() { Expect(err).Should(BeNil()) Expect(len(config.Connectors)).Should(Equal(1)) By("try to update dex config with config secret") - err = generateDexConfig(context.Background(), authUsecase.kubeClient, &model.UpdateDexConfig{}) + err = generateDexConfig(context.Background(), authService.KubeClient, &model.UpdateDexConfig{}) Expect(err).Should(BeNil()) }) It("Test get dex config", func() { err := ds.Add(context.Background(), &model.User{Name: "admin", Email: "test@test.com"}) Expect(err).Should(BeNil()) - _, err = sysUsecase.UpdateSystemInfo(context.Background(), apisv1.SystemInfoRequest{ + _, err = sysService.UpdateSystemInfo(context.Background(), apisv1.SystemInfoRequest{ LoginType: model.LoginTypeDex, VelaAddress: "http://velaux.com", }) Expect(err).Should(BeNil()) - config, err := authUsecase.GetDexConfig(context.Background()) + config, err := authService.GetDexConfig(context.Background()) Expect(err).Should(BeNil()) Expect(config.Issuer).Should(Equal("http://velaux.com/dex")) Expect(config.ClientID).Should(Equal("velaux")) diff --git a/pkg/apiserver/rest/usecase/cluster.go b/pkg/apiserver/domain/service/cluster.go similarity index 83% rename from pkg/apiserver/rest/usecase/cluster.go rename to pkg/apiserver/domain/service/cluster.go index 11e35596d..c209ce09f 100644 --- a/pkg/apiserver/rest/usecase/cluster.go +++ b/pkg/apiserver/domain/service/cluster.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -35,21 +35,21 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" velatypes "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - utils2 "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + utils2 "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/cloudprovider" "github.com/oam-dev/kubevela/pkg/multicluster" "github.com/oam-dev/kubevela/pkg/utils" "github.com/oam-dev/kubevela/pkg/utils/util" ) -// ClusterUsecase cluster manage -type ClusterUsecase interface { +// ClusterService cluster manage +type ClusterService interface { ListKubeClusters(context.Context, string, int, int) (*apis.ListClusterResponse, error) CreateKubeCluster(context.Context, apis.CreateClusterRequest) (*apis.ClusterBase, error) GetKubeCluster(context.Context, string) (*apis.DetailClusterResponse, error) @@ -64,27 +64,25 @@ type ClusterUsecase interface { GetCloudClusterCreationStatus(context.Context, string, string) (*apis.CreateCloudClusterResponse, error) ListCloudClusterCreation(context.Context, string) (*apis.ListCloudClusterCreationResponse, error) DeleteCloudClusterCreation(context.Context, string, string) (*apis.CreateCloudClusterResponse, error) + Init(ctx context.Context) error } -type clusterUsecaseImpl struct { - ds datastore.DataStore +type clusterServiceImpl struct { + Store datastore.DataStore `inject:"datastore"` + K8sClient client.Client `inject:"kubeClient"` caches *utils2.MemoryCacheStore - k8sClient client.Client } -// NewClusterUsecase new cluster usecase -func NewClusterUsecase(ds datastore.DataStore) ClusterUsecase { - k8sClient, err := clients.GetKubeClient() - if err != nil { - log.Logger.Fatalf("get k8sClient failure: %s", err.Error()) - } - c := &clusterUsecaseImpl{ds: ds, k8sClient: k8sClient, caches: utils2.NewMemoryCacheStore(context.Background())} - if err = c.preAddLocalCluster(context.Background()); err != nil { - log.Logger.Fatalf("preAdd local cluster failure: %s", err.Error()) - } +// NewClusterService new cluster service +func NewClusterService() ClusterService { + c := &clusterServiceImpl{caches: utils2.NewMemoryCacheStore(context.Background())} return c } +func (c *clusterServiceImpl) Init(ctx context.Context) error { + return c.preAddLocalCluster(ctx) +} + func _getClusterFromDataStore(ctx context.Context, ds datastore.DataStore, clusterName string) (*model.Cluster, error) { cluster := &model.Cluster{Name: clusterName} if err := ds.Get(ctx, cluster); err != nil { @@ -93,35 +91,35 @@ func _getClusterFromDataStore(ctx context.Context, ds datastore.DataStore, clust return cluster, nil } -func (c *clusterUsecaseImpl) getClusterFromDataStore(ctx context.Context, clusterName string) (*model.Cluster, error) { - return _getClusterFromDataStore(ctx, c.ds, clusterName) +func (c *clusterServiceImpl) getClusterFromDataStore(ctx context.Context, clusterName string) (*model.Cluster, error) { + return _getClusterFromDataStore(ctx, c.Store, clusterName) } -func (c *clusterUsecaseImpl) rollbackAddedClusterInDataStore(ctx context.Context, cluster *model.Cluster) { - if e := c.ds.Delete(ctx, cluster); e != nil { +func (c *clusterServiceImpl) rollbackAddedClusterInDataStore(ctx context.Context, cluster *model.Cluster) { + if e := c.Store.Delete(ctx, cluster); e != nil { log.Logger.Errorf("failed to rollback added cluster %s in data store: %s", utils.Sanitize(cluster.Name), e.Error()) } } -func (c *clusterUsecaseImpl) rollbackDeletedClusterInDataStore(ctx context.Context, cluster *model.Cluster) { - if e := c.ds.Add(ctx, cluster); e != nil { +func (c *clusterServiceImpl) rollbackDeletedClusterInDataStore(ctx context.Context, cluster *model.Cluster) { + if e := c.Store.Add(ctx, cluster); e != nil { log.Logger.Errorf("failed to rollback deleted cluster %s in data store: %s", utils.Sanitize(cluster.Name), e.Error()) } } -func (c *clusterUsecaseImpl) rollbackJoinedKubeCluster(ctx context.Context, cluster *model.Cluster) { - if e := multicluster.DetachCluster(ctx, c.k8sClient, cluster.Name); e != nil { +func (c *clusterServiceImpl) rollbackJoinedKubeCluster(ctx context.Context, cluster *model.Cluster) { + if e := multicluster.DetachCluster(ctx, c.K8sClient, cluster.Name); e != nil { log.Logger.Errorf("failed to rollback joined cluster %s in kubevela: %s", utils.Sanitize(cluster.Name), e.Error()) } } -func (c *clusterUsecaseImpl) rollbackDetachedKubeCluster(ctx context.Context, cluster *model.Cluster) { - if _, e := joinClusterByKubeConfigString(ctx, c.k8sClient, cluster.Name, cluster.KubeConfig); e != nil { +func (c *clusterServiceImpl) rollbackDetachedKubeCluster(ctx context.Context, cluster *model.Cluster) { + if _, e := joinClusterByKubeConfigString(ctx, c.K8sClient, cluster.Name, cluster.KubeConfig); e != nil { log.Logger.Errorf("failed to rollback detached cluster %s in kubevela: %s", utils.Sanitize(cluster.Name), e.Error()) } } -func (c *clusterUsecaseImpl) preAddLocalCluster(ctx context.Context) error { +func (c *clusterServiceImpl) preAddLocalCluster(ctx context.Context) error { cfg, err := clients.GetKubeConfig() if err != nil { return err @@ -132,10 +130,10 @@ func (c *clusterUsecaseImpl) preAddLocalCluster(ctx context.Context) error { Status: model.ClusterStatusHealthy, APIServerURL: cfg.Host + cfg.APIPath, } - if err = c.ds.Get(ctx, localCluster); err != nil { + if err = c.Store.Get(ctx, localCluster); err != nil { // no local cluster in datastore if errors.Is(err, datastore.ErrRecordNotExist) { - if err = c.ds.Add(ctx, localCluster); err != nil { + if err = c.Store.Add(ctx, localCluster); err != nil { // local cluster already added in datastore if errors.Is(err, datastore.ErrRecordExist) { return nil @@ -148,19 +146,19 @@ func (c *clusterUsecaseImpl) preAddLocalCluster(ctx context.Context) error { } if localCluster.CreateTime.Before(model.LocalClusterCreatedTime) { localCluster.CreateTime = model.LocalClusterCreatedTime - if err = c.ds.Put(ctx, localCluster); err != nil { + if err = c.Store.Put(ctx, localCluster); err != nil { return err } } return nil } -func (c *clusterUsecaseImpl) ListKubeClusters(ctx context.Context, query string, page int, pageSize int) (*apis.ListClusterResponse, error) { - clusters, err := prismclusterv1alpha1.NewClusterClient(c.k8sClient).List(ctx) +func (c *clusterServiceImpl) ListKubeClusters(ctx context.Context, query string, page int, pageSize int) (*apis.ListClusterResponse, error) { + clusters, err := prismclusterv1alpha1.NewClusterClient(c.K8sClient).List(ctx) if err != nil { return nil, errors.Wrapf(err, "failed to get clusters with ClusterClient") } - clustersInfo, err := c.ds.List(ctx, &model.Cluster{}, nil) + clustersInfo, err := c.Store.List(ctx, &model.Cluster{}, nil) if err != nil { return nil, errors.Wrapf(err, "failed to list cluster in data store") } @@ -230,7 +228,7 @@ func createClusterModelFromRequest(req apis.CreateClusterRequest, oldCluster *mo return newCluster } -func (c *clusterUsecaseImpl) createKubeCluster(ctx context.Context, req apis.CreateClusterRequest, providerCluster *cloudprovider.CloudCluster) (*apis.ClusterBase, error) { +func (c *clusterServiceImpl) createKubeCluster(ctx context.Context, req apis.CreateClusterRequest, providerCluster *cloudprovider.CloudCluster) (*apis.ClusterBase, error) { var err error cluster := createClusterModelFromRequest(req, nil) if cluster.Name == multicluster.ClusterLocalName { @@ -252,18 +250,18 @@ func (c *clusterUsecaseImpl) createKubeCluster(ctx context.Context, req apis.Cre } cluster.DashboardURL = providerCluster.DashBoardURL } - if err = c.ds.Get(ctx, cluster); err == nil { + if err = c.Store.Get(ctx, cluster); err == nil { return nil, bcode.ErrClusterAlreadyExistInDataStore } else if !errors.Is(err, datastore.ErrRecordNotExist) { return nil, err } if req.KubeConfig != "" { - cluster.APIServerURL, err = joinClusterByKubeConfigString(ctx, c.k8sClient, req.Name, req.KubeConfig) + cluster.APIServerURL, err = joinClusterByKubeConfigString(ctx, c.K8sClient, req.Name, req.KubeConfig) if err != nil { return nil, err } c.setClusterStatusAndResourceInfo(ctx, cluster) - if err = c.ds.Add(ctx, cluster); err != nil { + if err = c.Store.Add(ctx, cluster); err != nil { c.rollbackJoinedKubeCluster(ctx, cluster) if errors.Is(err, datastore.ErrRecordExist) { return nil, bcode.ErrClusterAlreadyExistInDataStore @@ -278,17 +276,17 @@ func (c *clusterUsecaseImpl) createKubeCluster(ctx context.Context, req apis.Cre return nil, bcode.ErrKubeConfigAndSecretIsNotSet } -func (c *clusterUsecaseImpl) CreateKubeCluster(ctx context.Context, req apis.CreateClusterRequest) (*apis.ClusterBase, error) { +func (c *clusterServiceImpl) CreateKubeCluster(ctx context.Context, req apis.CreateClusterRequest) (*apis.ClusterBase, error) { return c.createKubeCluster(ctx, req, nil) } -func (c *clusterUsecaseImpl) GetKubeCluster(ctx context.Context, clusterName string) (*apis.DetailClusterResponse, error) { +func (c *clusterServiceImpl) GetKubeCluster(ctx context.Context, clusterName string) (*apis.DetailClusterResponse, error) { cluster, err := c.getClusterFromDataStore(ctx, clusterName) if err != nil { if !errors.Is(err, datastore.ErrRecordNotExist) { return nil, errors.Wrapf(err, "failed to find cluster %s in data store", clusterName) } - prismCluster, err := prismclusterv1alpha1.NewClusterClient(c.k8sClient).Get(ctx, clusterName) + prismCluster, err := prismclusterv1alpha1.NewClusterClient(c.K8sClient).Get(ctx, clusterName) if err != nil { if kerrors.IsNotFound(err) { return nil, bcode.ErrClusterNotFoundInDataStore @@ -296,12 +294,12 @@ func (c *clusterUsecaseImpl) GetKubeCluster(ctx context.Context, clusterName str return nil, errors.Wrapf(err, "failed to find cluster %s in control plane", clusterName) } cluster = newClusterModelFromPrismCluster(prismCluster) - if err = c.ds.Add(ctx, cluster); err != nil { + if err = c.Store.Add(ctx, cluster); err != nil { return nil, errors.Wrapf(err, "failed to add cluster %s from existing prism cluster", clusterName) } } resourceInfo := c.setClusterStatusAndResourceInfo(ctx, cluster) - if err = c.ds.Put(ctx, cluster); err != nil { + if err = c.Store.Put(ctx, cluster); err != nil { return nil, errors.Wrapf(err, "failed to update cluster %s status info", clusterName) } return &apis.DetailClusterResponse{ @@ -310,7 +308,7 @@ func (c *clusterUsecaseImpl) GetKubeCluster(ctx context.Context, clusterName str }, nil } -func (c *clusterUsecaseImpl) ModifyKubeCluster(ctx context.Context, req apis.CreateClusterRequest, clusterName string) (*apis.ClusterBase, error) { +func (c *clusterServiceImpl) ModifyKubeCluster(ctx context.Context, req apis.CreateClusterRequest, clusterName string) (*apis.ClusterBase, error) { oldCluster, err := c.getClusterFromDataStore(ctx, clusterName) if err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { @@ -329,7 +327,7 @@ func (c *clusterUsecaseImpl) ModifyKubeCluster(ctx context.Context, req apis.Cre return nil, bcode.ErrKubeConfigSecretNotSupport } newClusterTempName := newCluster.Name + "_tmp_" + utils.RandomString(8) - newCluster.APIServerURL, err = joinClusterByKubeConfigString(ctx, c.k8sClient, newCluster.Name, newCluster.KubeConfig) + newCluster.APIServerURL, err = joinClusterByKubeConfigString(ctx, c.K8sClient, newCluster.Name, newCluster.KubeConfig) if err != nil { return nil, errors.Wrapf(err, "failed to join new cluster %s", newCluster.Name) } @@ -339,11 +337,11 @@ func (c *clusterUsecaseImpl) ModifyKubeCluster(ctx context.Context, req apis.Cre rollBackCluster.Name = newClusterTempName c.rollbackJoinedKubeCluster(ctx, rollBackCluster) } - if err = multicluster.DetachCluster(ctx, c.k8sClient, oldCluster.Name); err != nil { + if err = multicluster.DetachCluster(ctx, c.K8sClient, oldCluster.Name); err != nil { rollbackTempCluster() return nil, errors.Wrapf(err, "failed to detach old cluster %s", oldCluster.Name) } - if err = c.ds.Delete(ctx, oldCluster); err != nil { + if err = c.Store.Delete(ctx, oldCluster); err != nil { rollbackTempCluster() c.rollbackDetachedKubeCluster(ctx, oldCluster) if errors.Is(err, datastore.ErrRecordNotExist) { @@ -351,7 +349,7 @@ func (c *clusterUsecaseImpl) ModifyKubeCluster(ctx context.Context, req apis.Cre } return nil, errors.Wrapf(err, "failed to delete old cluster %s from datastore", oldCluster.Name) } - if err = c.ds.Add(ctx, newCluster); err != nil { + if err = c.Store.Add(ctx, newCluster); err != nil { rollbackTempCluster() c.rollbackDetachedKubeCluster(ctx, oldCluster) c.rollbackDeletedClusterInDataStore(ctx, oldCluster) @@ -360,7 +358,7 @@ func (c *clusterUsecaseImpl) ModifyKubeCluster(ctx context.Context, req apis.Cre } return nil, errors.Wrapf(err, "failed to add new cluster %s to datastore", newCluster.Name) } - if err = multicluster.RenameCluster(ctx, c.k8sClient, newClusterTempName, newCluster.Name); err != nil { + if err = multicluster.RenameCluster(ctx, c.K8sClient, newClusterTempName, newCluster.Name); err != nil { rollbackTempCluster() c.rollbackDetachedKubeCluster(ctx, oldCluster) c.rollbackDeletedClusterInDataStore(ctx, oldCluster) @@ -370,14 +368,14 @@ func (c *clusterUsecaseImpl) ModifyKubeCluster(ctx context.Context, req apis.Cre } else { newCluster.Status = oldCluster.Status newCluster.Reason = oldCluster.Reason - if err = c.ds.Put(ctx, newCluster); err != nil { + if err = c.Store.Put(ctx, newCluster); err != nil { return nil, errors.Wrapf(err, "failed to update cluster %s", newCluster.Name) } } return newClusterBaseFromCluster(newCluster), nil } -func (c *clusterUsecaseImpl) DeleteKubeCluster(ctx context.Context, clusterName string) (*apis.ClusterBase, error) { +func (c *clusterServiceImpl) DeleteKubeCluster(ctx context.Context, clusterName string) (*apis.ClusterBase, error) { if clusterName == multicluster.ClusterLocalName { return nil, bcode.ErrLocalClusterImmutable } @@ -388,20 +386,20 @@ func (c *clusterUsecaseImpl) DeleteKubeCluster(ctx context.Context, clusterName } return nil, errors.Wrapf(err, "failed to found cluster %s in data store", clusterName) } - if err = c.ds.Delete(ctx, cluster); err != nil { + if err = c.Store.Delete(ctx, cluster); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil, bcode.ErrClusterNotFoundInDataStore } return nil, errors.Wrapf(err, "failed to delete cluster %s in data store", clusterName) } - if err = multicluster.DetachCluster(ctx, c.k8sClient, clusterName); err != nil { + if err = multicluster.DetachCluster(ctx, c.K8sClient, clusterName); err != nil { c.rollbackDeletedClusterInDataStore(ctx, cluster) return nil, errors.Wrapf(err, "failed to delete cluster %s in kubernetes", clusterName) } return newClusterBaseFromCluster(cluster), nil } -func (c *clusterUsecaseImpl) CreateClusterNamespace(ctx context.Context, clusterName string, req apis.CreateClusterNamespaceRequest) (*apis.CreateClusterNamespaceResponse, error) { +func (c *clusterServiceImpl) CreateClusterNamespace(ctx context.Context, clusterName string, req apis.CreateClusterNamespaceRequest) (*apis.CreateClusterNamespaceResponse, error) { _, err := c.getClusterFromDataStore(ctx, clusterName) if err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { @@ -411,7 +409,7 @@ func (c *clusterUsecaseImpl) CreateClusterNamespace(ctx context.Context, cluster } ns := &v12.Namespace{} ns.Name = req.Namespace - if err = c.k8sClient.Create(multicluster.ContextWithClusterName(ctx, clusterName), ns); err != nil { + if err = c.K8sClient.Create(multicluster.ContextWithClusterName(ctx, clusterName), ns); err != nil { if kerrors.IsAlreadyExists(err) { return &apis.CreateClusterNamespaceResponse{Exists: true}, nil } @@ -423,7 +421,7 @@ func (c *clusterUsecaseImpl) CreateClusterNamespace(ctx context.Context, cluster return &apis.CreateClusterNamespaceResponse{Exists: false}, nil } -func (c *clusterUsecaseImpl) setClusterStatusAndResourceInfo(ctx context.Context, cluster *model.Cluster) apis.ClusterResourceInfo { +func (c *clusterServiceImpl) setClusterStatusAndResourceInfo(ctx context.Context, cluster *model.Cluster) apis.ClusterResourceInfo { resourceInfo, err := c.getClusterResourceInfoFromK8s(ctx, cluster.Name) if err != nil { cluster.Status = model.ClusterStatusUnhealthy @@ -435,16 +433,16 @@ func (c *clusterUsecaseImpl) setClusterStatusAndResourceInfo(ctx context.Context return resourceInfo } -func (c *clusterUsecaseImpl) getClusterResourceInfoCacheKey(clusterName string) string { +func (c *clusterServiceImpl) getClusterResourceInfoCacheKey(clusterName string) string { return "cluster-resource-info::" + clusterName } -func (c *clusterUsecaseImpl) getClusterResourceInfoFromK8s(ctx context.Context, clusterName string) (apis.ClusterResourceInfo, error) { +func (c *clusterServiceImpl) getClusterResourceInfoFromK8s(ctx context.Context, clusterName string) (apis.ClusterResourceInfo, error) { cacheKey := c.getClusterResourceInfoCacheKey(clusterName) if cache := c.caches.Get(cacheKey); cache != nil { return cache.(apis.ClusterResourceInfo), nil } - clusterInfo, err := multicluster.GetClusterInfo(ctx, c.k8sClient, clusterName) + clusterInfo, err := multicluster.GetClusterInfo(ctx, c.K8sClient, clusterName) if err != nil { return apis.ClusterResourceInfo{}, err } @@ -475,8 +473,8 @@ func (c *clusterUsecaseImpl) getClusterResourceInfoFromK8s(ctx context.Context, return clusterResourceInfo, nil } -func (c *clusterUsecaseImpl) ListCloudClusters(ctx context.Context, provider string, req apis.AccessKeyRequest, pageNumber int, pageSize int) (*apis.ListCloudClusterResponse, error) { - p, err := cloudprovider.GetClusterProvider(provider, req.AccessKeyID, req.AccessKeySecret, c.k8sClient) +func (c *clusterServiceImpl) ListCloudClusters(ctx context.Context, provider string, req apis.AccessKeyRequest, pageNumber int, pageSize int) (*apis.ListCloudClusterResponse, error) { + p, err := cloudprovider.GetClusterProvider(provider, req.AccessKeyID, req.AccessKeySecret, c.K8sClient) if err != nil { log.Logger.Errorf("failed to get cluster provider: %s", err.Error()) return nil, bcode.ErrInvalidCloudClusterProvider @@ -499,8 +497,8 @@ func (c *clusterUsecaseImpl) ListCloudClusters(ctx context.Context, provider str return resp, nil } -func (c *clusterUsecaseImpl) ConnectCloudCluster(ctx context.Context, provider string, req apis.ConnectCloudClusterRequest) (*apis.ClusterBase, error) { - p, err := cloudprovider.GetClusterProvider(provider, req.AccessKeyID, req.AccessKeySecret, c.k8sClient) +func (c *clusterServiceImpl) ConnectCloudCluster(ctx context.Context, provider string, req apis.ConnectCloudClusterRequest) (*apis.ClusterBase, error) { + p, err := cloudprovider.GetClusterProvider(provider, req.AccessKeyID, req.AccessKeySecret, c.K8sClient) if err != nil { log.Logger.Errorf("failed to get cluster provider: %s", err.Error()) return nil, bcode.ErrInvalidCloudClusterProvider @@ -529,8 +527,8 @@ func (c *clusterUsecaseImpl) ConnectCloudCluster(ctx context.Context, provider s return c.createKubeCluster(ctx, createReq, cluster) } -func (c *clusterUsecaseImpl) CreateCloudCluster(ctx context.Context, provider string, req apis.CreateCloudClusterRequest) (*apis.CreateCloudClusterResponse, error) { - p, err := cloudprovider.GetClusterProvider(provider, req.AccessKeyID, req.AccessKeySecret, c.k8sClient) +func (c *clusterServiceImpl) CreateCloudCluster(ctx context.Context, provider string, req apis.CreateCloudClusterRequest) (*apis.CreateCloudClusterResponse, error) { + p, err := cloudprovider.GetClusterProvider(provider, req.AccessKeyID, req.AccessKeySecret, c.K8sClient) if err != nil { log.Logger.Errorf("failed to get cluster provider: %s", err.Error()) return nil, bcode.ErrInvalidCloudClusterProvider @@ -546,7 +544,7 @@ func (c *clusterUsecaseImpl) CreateCloudCluster(ctx context.Context, provider st return c.GetCloudClusterCreationStatus(ctx, provider, req.Name) } -func (c *clusterUsecaseImpl) convertTerraformConfigurationStateIntoCloudClusterCreationStatus(cfg v1beta1.Configuration) (status string, clusterID string, err error) { +func (c *clusterServiceImpl) convertTerraformConfigurationStateIntoCloudClusterCreationStatus(cfg v1beta1.Configuration) (status string, clusterID string, err error) { status = string(cfg.Status.Apply.State) if status == "" { return "Initializing", "", nil @@ -565,7 +563,7 @@ func (c *clusterUsecaseImpl) convertTerraformConfigurationStateIntoCloudClusterC return status, "", nil } -func (c *clusterUsecaseImpl) getCloudClusterCreationStatus(ctx context.Context, provider string, cloudClusterName string) (*apis.CreateCloudClusterResponse, *v1beta1.Configuration, error) { +func (c *clusterServiceImpl) getCloudClusterCreationStatus(ctx context.Context, provider string, cloudClusterName string) (*apis.CreateCloudClusterResponse, *v1beta1.Configuration, error) { terraformConfigurationName := cloudprovider.GetCloudClusterFullName(provider, cloudClusterName) cfg := &v1beta1.Configuration{ ObjectMeta: v1.ObjectMeta{ @@ -573,7 +571,7 @@ func (c *clusterUsecaseImpl) getCloudClusterCreationStatus(ctx context.Context, Namespace: util.GetRuntimeNamespace(), }, } - if err := c.k8sClient.Get(ctx, client.ObjectKeyFromObject(cfg), cfg); err != nil { + if err := c.K8sClient.Get(ctx, client.ObjectKeyFromObject(cfg), cfg); err != nil { if kerrors.IsNotFound(err) { return nil, nil, bcode.ErrTerraformConfigurationNotFound } @@ -586,14 +584,14 @@ func (c *clusterUsecaseImpl) getCloudClusterCreationStatus(ctx context.Context, return &apis.CreateCloudClusterResponse{Name: cloudClusterName, Status: status, ClusterID: clusterID}, cfg, nil } -func (c *clusterUsecaseImpl) GetCloudClusterCreationStatus(ctx context.Context, provider string, cloudClusterName string) (*apis.CreateCloudClusterResponse, error) { +func (c *clusterServiceImpl) GetCloudClusterCreationStatus(ctx context.Context, provider string, cloudClusterName string) (*apis.CreateCloudClusterResponse, error) { resp, _, err := c.getCloudClusterCreationStatus(ctx, provider, cloudClusterName) return resp, err } -func (c *clusterUsecaseImpl) ListCloudClusterCreation(ctx context.Context, provider string) (*apis.ListCloudClusterCreationResponse, error) { +func (c *clusterServiceImpl) ListCloudClusterCreation(ctx context.Context, provider string) (*apis.ListCloudClusterCreationResponse, error) { cfgs := v1beta1.ConfigurationList{} - if err := c.k8sClient.List(ctx, &cfgs, client.HasLabels{cloudprovider.CloudClusterCreatorLabelKey}, client.InNamespace(util.GetRuntimeNamespace())); err != nil { + if err := c.K8sClient.List(ctx, &cfgs, client.HasLabels{cloudprovider.CloudClusterCreatorLabelKey}, client.InNamespace(util.GetRuntimeNamespace())); err != nil { return nil, err } var creations []apis.CreateCloudClusterResponse @@ -608,12 +606,12 @@ func (c *clusterUsecaseImpl) ListCloudClusterCreation(ctx context.Context, provi return &apis.ListCloudClusterCreationResponse{Creations: creations}, nil } -func (c *clusterUsecaseImpl) DeleteCloudClusterCreation(ctx context.Context, provider string, cloudClusterName string) (*apis.CreateCloudClusterResponse, error) { +func (c *clusterServiceImpl) DeleteCloudClusterCreation(ctx context.Context, provider string, cloudClusterName string) (*apis.CreateCloudClusterResponse, error) { resp, cfg, err := c.getCloudClusterCreationStatus(ctx, provider, cloudClusterName) if err != nil { return resp, err } - if err = c.k8sClient.Delete(ctx, cfg); err != nil { + if err = c.K8sClient.Delete(ctx, cfg); err != nil { if kerrors.IsNotFound(err) { return resp, nil } diff --git a/pkg/apiserver/rest/usecase/cluster_test.go b/pkg/apiserver/domain/service/cluster_test.go similarity index 85% rename from pkg/apiserver/rest/usecase/cluster_test.go rename to pkg/apiserver/domain/service/cluster_test.go index a5252635a..ec04783f0 100644 --- a/pkg/apiserver/rest/usecase/cluster_test.go +++ b/pkg/apiserver/domain/service/cluster_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -29,15 +29,15 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" "github.com/oam-dev/kubevela/pkg/oam/util" pkgutil "github.com/oam-dev/kubevela/pkg/utils" ) -var _ = Describe("Test cluster usecase function", func() { +var _ = Describe("Test cluster service function", func() { var ( ds datastore.DataStore cache *utils.MemoryCacheStore @@ -74,53 +74,53 @@ var _ = Describe("Test cluster usecase function", func() { }) It("Test get kube cluster", func() { - usecase := clusterUsecaseImpl{ - ds: ds, + service := clusterServiceImpl{ + Store: ds, caches: cache, - k8sClient: k8sClient, + K8sClient: k8sClient, } Expect(ds.Add(ctx, &model.Cluster{Name: "first", Alias: "first-alias", Icon: "first-icon"})).Should(Succeed()) - resp, err := usecase.GetKubeCluster(ctx, "first") + resp, err := service.GetKubeCluster(ctx, "first") Expect(err).Should(Succeed()) Expect(resp.Alias).Should(Equal("first-alias")) Expect(resp.Icon).Should(Equal("first-icon")) - _, err = usecase.GetKubeCluster(ctx, "prism-cluster") + _, err = service.GetKubeCluster(ctx, "prism-cluster") Expect(err).Should(Equal(bcode.ErrClusterNotFoundInDataStore)) Expect(createClusterSecret("prism-cluster", "prism-alias")).Should(Succeed()) - resp, err = usecase.GetKubeCluster(ctx, "prism-cluster") + resp, err = service.GetKubeCluster(ctx, "prism-cluster") Expect(err).Should(Succeed()) Expect(resp.Alias).Should(Equal("prism-alias")) - _, err = usecase.GetKubeCluster(ctx, "non-exist-cluster") + _, err = service.GetKubeCluster(ctx, "non-exist-cluster") Expect(err).Should(Equal(bcode.ErrClusterNotFoundInDataStore)) }) It("Test list kube clusters", func() { - usecase := clusterUsecaseImpl{ - ds: ds, + service := clusterServiceImpl{ + Store: ds, caches: cache, - k8sClient: k8sClient, + K8sClient: k8sClient, } Expect(createClusterSecret("prism-cluster1", "prism-alias1")).Should(Succeed()) Expect(ds.Add(ctx, &model.Cluster{Name: "prism-cluster1", Alias: "prism-alias1", Icon: "prism-icon1"})).Should(Succeed()) Expect(ds.Add(ctx, &model.Cluster{Name: "local"})).Should(Succeed()) - resp, err := usecase.ListKubeClusters(ctx, "", 1, 5) + resp, err := service.ListKubeClusters(ctx, "", 1, 5) Expect(err).Should(Succeed()) Expect(len(resp.Clusters)).Should(Equal(2)) Expect(resp.Clusters[0].Name).Should(Equal("local")) Expect(resp.Clusters[1].Name).Should(Equal("prism-cluster1")) Expect(createClusterSecret("prism-cluster2", "prism-alias2")).Should(Succeed()) Expect(createClusterSecret("cluster3", "prism-alias3")).Should(Succeed()) - resp, err = usecase.ListKubeClusters(ctx, "", 1, 5) + resp, err = service.ListKubeClusters(ctx, "", 1, 5) Expect(err).Should(Succeed()) Expect(len(resp.Clusters)).Should(Equal(4)) Expect(resp.Clusters[3].Icon).Should(Equal("prism-icon1")) - resp, err = usecase.ListKubeClusters(ctx, "prism-cluster", 1, 5) + resp, err = service.ListKubeClusters(ctx, "prism-cluster", 1, 5) Expect(err).Should(Succeed()) Expect(len(resp.Clusters)).Should(Equal(2)) - resp, err = usecase.ListKubeClusters(ctx, "", 2, 3) + resp, err = service.ListKubeClusters(ctx, "", 2, 3) Expect(err).Should(Succeed()) Expect(len(resp.Clusters)).Should(Equal(1)) - resp, err = usecase.ListKubeClusters(ctx, "", 3, 3) + resp, err = service.ListKubeClusters(ctx, "", 3, 3) Expect(err).Should(Succeed()) Expect(len(resp.Clusters)).Should(Equal(0)) }) diff --git a/pkg/apiserver/rest/usecase/config.go b/pkg/apiserver/domain/service/config.go similarity index 88% rename from pkg/apiserver/rest/usecase/config.go rename to pkg/apiserver/domain/service/config.go index 41c63cb97..94378cc78 100644 --- a/pkg/apiserver/rest/usecase/config.go +++ b/pkg/apiserver/domain/service/config.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -35,9 +35,8 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" "github.com/oam-dev/kubevela/pkg/definition" "github.com/oam-dev/kubevela/pkg/utils/config" ) @@ -52,8 +51,8 @@ const ( configSyncProjectPrefix = "config-sync" ) -// ConfigHandler handle CRUD of configs -type ConfigHandler interface { +// ConfigService handle CRUD of configs +type ConfigService interface { ListConfigTypes(ctx context.Context, query string) ([]*apis.ConfigType, error) GetConfigType(ctx context.Context, configType string) (*apis.ConfigType, error) CreateConfig(ctx context.Context, req apis.CreateConfigRequest) error @@ -62,27 +61,19 @@ type ConfigHandler interface { DeleteConfig(ctx context.Context, configType, name string) error } -// NewConfigUseCase returns a config use case -func NewConfigUseCase(authenticationUseCase AuthenticationUsecase) ConfigHandler { - k8sClient, err := clients.GetKubeClient() - if err != nil { - panic(err) - } - return &configUseCaseImpl{ - authenticationUseCase: authenticationUseCase, - kubeClient: k8sClient, - } +// NewConfigService returns a config use case +func NewConfigService() ConfigService { + return &configServiceImpl{} } -type configUseCaseImpl struct { - kubeClient client.Client - authenticationUseCase AuthenticationUsecase +type configServiceImpl struct { + KubeClient client.Client `inject:"kubeClient"` } // ListConfigTypes returns all config types -func (u *configUseCaseImpl) ListConfigTypes(ctx context.Context, query string) ([]*apis.ConfigType, error) { +func (u *configServiceImpl) ListConfigTypes(ctx context.Context, query string) ([]*apis.ConfigType, error) { defs := &v1beta1.ComponentDefinitionList{} - if err := u.kubeClient.List(ctx, defs, client.InNamespace(types.DefaultKubeVelaNS), + if err := u.KubeClient.List(ctx, defs, client.InNamespace(types.DefaultKubeVelaNS), client.MatchingLabels{definition.UserPrefix + "catalog.config.oam.dev": types.VelaCoreConfig}); err != nil { return nil, err } @@ -121,9 +112,9 @@ func (u *configUseCaseImpl) ListConfigTypes(ctx context.Context, query string) ( } // GetConfigType returns a config type -func (u *configUseCaseImpl) GetConfigType(ctx context.Context, configType string) (*apis.ConfigType, error) { +func (u *configServiceImpl) GetConfigType(ctx context.Context, configType string) (*apis.ConfigType, error) { d := &v1beta1.ComponentDefinition{} - if err := u.kubeClient.Get(ctx, client.ObjectKey{Namespace: types.DefaultKubeVelaNS, Name: configType}, d); err != nil { + if err := u.KubeClient.Get(ctx, client.ObjectKey{Namespace: types.DefaultKubeVelaNS, Name: configType}, d); err != nil { return nil, errors.Wrap(err, "failed to get config type") } @@ -135,7 +126,7 @@ func (u *configUseCaseImpl) GetConfigType(ctx context.Context, configType string return t, nil } -func (u *configUseCaseImpl) CreateConfig(ctx context.Context, req apis.CreateConfigRequest) error { +func (u *configServiceImpl) CreateConfig(ctx context.Context, req apis.CreateConfigRequest) error { p := req.Properties // If the component is Terraform type, set the provider name same as the application name and the component name if strings.HasPrefix(req.ComponentType, types.TerraformComponentPrefix) { @@ -155,20 +146,20 @@ func (u *configUseCaseImpl) CreateConfig(ctx context.Context, req apis.CreateCon Description: req.Description, Project: req.Project, } - return config.CreateApplication(ctx, u.kubeClient, req.Name, req.ComponentType, p, ui) + return config.CreateApplication(ctx, u.KubeClient, req.Name, req.ComponentType, p, ui) } -func (u *configUseCaseImpl) GetConfigs(ctx context.Context, configType string) ([]*apis.Config, error) { +func (u *configServiceImpl) GetConfigs(ctx context.Context, configType string) ([]*apis.Config, error) { switch configType { case types.TerraformProvider: - providers, err := config.ListTerraformProviders(ctx, u.kubeClient) + providers, err := config.ListTerraformProviders(ctx, u.KubeClient) if err != nil { return nil, err } configs := make([]*apis.Config, len(providers)) for i, p := range providers { var a v1beta1.Application - if err := u.kubeClient.Get(ctx, client.ObjectKey{Namespace: types.DefaultKubeVelaNS, Name: p.Name}, &a); err != nil { + if err := u.KubeClient.Get(ctx, client.ObjectKey{Namespace: types.DefaultKubeVelaNS, Name: p.Name}, &a); err != nil { if kerrors.IsNotFound(err) { t := p.CreationTimestamp.Time configs[i] = &apis.Config{ @@ -198,9 +189,9 @@ func (u *configUseCaseImpl) GetConfigs(ctx context.Context, configType string) ( } } -func (u *configUseCaseImpl) getConfigsByConfigType(ctx context.Context, configType string) ([]*apis.Config, error) { +func (u *configServiceImpl) getConfigsByConfigType(ctx context.Context, configType string) ([]*apis.Config, error) { var apps = &v1beta1.ApplicationList{} - if err := u.kubeClient.List(ctx, apps, client.InNamespace(types.DefaultKubeVelaNS), + if err := u.KubeClient.List(ctx, apps, client.InNamespace(types.DefaultKubeVelaNS), client.MatchingLabels{ model.LabelSourceOfTruth: model.FromInner, types.LabelConfigCatalog: types.VelaCoreConfig, @@ -216,9 +207,9 @@ func (u *configUseCaseImpl) getConfigsByConfigType(ctx context.Context, configTy return configs, nil } -func (u *configUseCaseImpl) GetConfig(ctx context.Context, configType, name string) (*apis.Config, error) { +func (u *configServiceImpl) GetConfig(ctx context.Context, configType, name string) (*apis.Config, error) { var a = &v1beta1.Application{} - if err := u.kubeClient.Get(ctx, client.ObjectKey{Namespace: types.DefaultKubeVelaNS, Name: name}, a); err != nil { + if err := u.KubeClient.Get(ctx, client.ObjectKey{Namespace: types.DefaultKubeVelaNS, Name: name}, a); err != nil { return nil, err } @@ -232,12 +223,12 @@ func (u *configUseCaseImpl) GetConfig(ctx context.Context, configType, name stri return config, nil } -func (u *configUseCaseImpl) DeleteConfig(ctx context.Context, configType, name string) error { +func (u *configServiceImpl) DeleteConfig(ctx context.Context, configType, name string) error { var isTerraformProvider bool if strings.HasPrefix(configType, types.TerraformComponentPrefix) { isTerraformProvider = true } - return config.DeleteApplication(ctx, u.kubeClient, name, isTerraformProvider) + return config.DeleteApplication(ctx, u.KubeClient, name, isTerraformProvider) } // ApplicationDeployTarget is the struct of application deploy target diff --git a/pkg/apiserver/rest/usecase/config_test.go b/pkg/apiserver/domain/service/config_test.go similarity index 96% rename from pkg/apiserver/rest/usecase/config_test.go rename to pkg/apiserver/domain/service/config_test.go index f087d8d67..fb633469e 100644 --- a/pkg/apiserver/rest/usecase/config_test.go +++ b/pkg/apiserver/domain/service/config_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -38,8 +38,8 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" "github.com/oam-dev/kubevela/pkg/definition" "github.com/oam-dev/kubevela/pkg/multicluster" ) @@ -85,10 +85,12 @@ func TestListConfigTypes(t *testing.T) { }) defer patches.Reset() - h := NewConfigUseCase(nil) + h := &configServiceImpl{ + KubeClient: k8sClient, + } type args struct { - h ConfigHandler + h ConfigService } type want struct { @@ -165,10 +167,10 @@ func TestGetConfigType(t *testing.T) { }) defer patches.Reset() - h := NewConfigUseCase(nil) + h := &configServiceImpl{KubeClient: k8sClient} type args struct { - h ConfigHandler + h ConfigService name string } @@ -227,10 +229,10 @@ func TestCreateConfig(t *testing.T) { k8sClient := fake.NewClientBuilder().WithScheme(s).Build() - h := &configUseCaseImpl{kubeClient: k8sClient} + h := &configServiceImpl{KubeClient: k8sClient} type args struct { - h ConfigHandler + h ConfigService req apis.CreateConfigRequest } @@ -337,11 +339,11 @@ func TestGetConfigs(t *testing.T) { k8sClient := fake.NewClientBuilder().WithScheme(s).WithObjects(provider1, provider2, provider3, app1).Build() - h := &configUseCaseImpl{kubeClient: k8sClient} + h := &configServiceImpl{KubeClient: k8sClient} type args struct { configType string - h ConfigHandler + h ConfigService } type want struct { @@ -698,12 +700,12 @@ func TestDeleteConfig(t *testing.T) { k8sClient := fake.NewClientBuilder().WithScheme(s).WithObjects(provider1, provider2, provider3, app1, app2, normalApp).Build() - h := &configUseCaseImpl{kubeClient: k8sClient} + h := &configServiceImpl{KubeClient: k8sClient} type args struct { configType string name string - h ConfigHandler + h ConfigService } type want struct { diff --git a/pkg/apiserver/rest/usecase/definition.go b/pkg/apiserver/domain/service/definition.go similarity index 89% rename from pkg/apiserver/rest/usecase/definition.go rename to pkg/apiserver/domain/service/definition.go index 57719bb8b..f98ca8584 100644 --- a/pkg/apiserver/rest/usecase/definition.go +++ b/pkg/apiserver/domain/service/definition.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -35,15 +35,14 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" ) -// DefinitionUsecase definition usecase, Implement the management of ComponentDefinition、TraitDefinition and WorkflowStepDefinition. -type DefinitionUsecase interface { +// DefinitionService definition service, Implement the management of ComponentDefinition、TraitDefinition and WorkflowStepDefinition. +type DefinitionService interface { // ListDefinitions list definition base info ListDefinitions(ctx context.Context, ops DefinitionQueryOption) ([]*apisv1.DefinitionBase, error) // DetailDefinition get definition detail @@ -54,8 +53,8 @@ type DefinitionUsecase interface { UpdateDefinitionStatus(ctx context.Context, name string, status apisv1.UpdateDefinitionStatusRequest) (*apisv1.DetailDefinitionResponse, error) } -type definitionUsecaseImpl struct { - kubeClient client.Client +type definitionServiceImpl struct { + KubeClient client.Client `inject:"kubeClient"` caches *utils.MemoryCacheStore } @@ -79,16 +78,12 @@ const ( kindPolicyDefinition = "PolicyDefinition" ) -// NewDefinitionUsecase new definition usecase -func NewDefinitionUsecase() DefinitionUsecase { - kubecli, err := clients.GetKubeClient() - if err != nil { - log.Logger.Fatalf("get kubeclient failure %s", err.Error()) - } - return &definitionUsecaseImpl{kubeClient: kubecli, caches: utils.NewMemoryCacheStore(context.Background())} +// NewDefinitionService new definition service +func NewDefinitionService() DefinitionService { + return &definitionServiceImpl{caches: utils.NewMemoryCacheStore(context.Background())} } -func (d *definitionUsecaseImpl) ListDefinitions(ctx context.Context, ops DefinitionQueryOption) ([]*apisv1.DefinitionBase, error) { +func (d *definitionServiceImpl) ListDefinitions(ctx context.Context, ops DefinitionQueryOption) ([]*apisv1.DefinitionBase, error) { defs := &unstructured.UnstructuredList{} version, kind, err := getKindAndVersion(ops.Type) if err != nil { @@ -99,7 +94,7 @@ func (d *definitionUsecaseImpl) ListDefinitions(ctx context.Context, ops Definit return d.listDefinitions(ctx, defs, kind, ops) } -func (d *definitionUsecaseImpl) listDefinitions(ctx context.Context, list *unstructured.UnstructuredList, kind string, ops DefinitionQueryOption) ([]*apisv1.DefinitionBase, error) { +func (d *definitionServiceImpl) listDefinitions(ctx context.Context, list *unstructured.UnstructuredList, kind string, ops DefinitionQueryOption) ([]*apisv1.DefinitionBase, error) { if mc := d.caches.Get(ops.String()); mc != nil { return mc.([]*apisv1.DefinitionBase), nil } @@ -121,7 +116,7 @@ func (d *definitionUsecaseImpl) listDefinitions(ctx context.Context, list *unstr if err != nil { return nil, err } - if err := d.kubeClient.List(ctx, list, &client.ListOptions{ + if err := d.KubeClient.List(ctx, list, &client.ListOptions{ LabelSelector: selector, }); err != nil { return nil, err @@ -223,7 +218,7 @@ func convertDefinitionBase(def unstructured.Unstructured, kind string) (*apisv1. } // DetailDefinition get definition detail -func (d *definitionUsecaseImpl) DetailDefinition(ctx context.Context, name, defType string) (*apisv1.DetailDefinitionResponse, error) { +func (d *definitionServiceImpl) DetailDefinition(ctx context.Context, name, defType string) (*apisv1.DetailDefinitionResponse, error) { def := &unstructured.Unstructured{} version, kind, err := getKindAndVersion(defType) if err != nil { @@ -231,7 +226,7 @@ func (d *definitionUsecaseImpl) DetailDefinition(ctx context.Context, name, defT } def.SetAPIVersion(version) def.SetKind(kind) - if err := d.kubeClient.Get(ctx, k8stypes.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: name}, def); err != nil { + if err := d.KubeClient.Get(ctx, k8stypes.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: name}, def); err != nil { if apierrors.IsNotFound(err) { return nil, bcode.ErrDefinitionNotFound } @@ -242,7 +237,7 @@ func (d *definitionUsecaseImpl) DetailDefinition(ctx context.Context, name, defT return nil, err } var cm v1.ConfigMap - if err := d.kubeClient.Get(ctx, k8stypes.NamespacedName{ + if err := d.KubeClient.Get(ctx, k8stypes.NamespacedName{ Namespace: types.DefaultKubeVelaNS, Name: fmt.Sprintf("%s-schema-%s", defType, name), }, &cm); err != nil { @@ -271,9 +266,9 @@ func (d *definitionUsecaseImpl) DetailDefinition(ctx context.Context, name, defT }, nil } -func (d *definitionUsecaseImpl) renderCustomUISchema(ctx context.Context, name, defType string, defaultSchema []*utils.UIParameter) []*utils.UIParameter { +func (d *definitionServiceImpl) renderCustomUISchema(ctx context.Context, name, defType string, defaultSchema []*utils.UIParameter) []*utils.UIParameter { var cm v1.ConfigMap - if err := d.kubeClient.Get(ctx, k8stypes.NamespacedName{ + if err := d.KubeClient.Get(ctx, k8stypes.NamespacedName{ Namespace: types.DefaultKubeVelaNS, Name: fmt.Sprintf("%s-uischema-%s", defType, name), }, &cm); err != nil { @@ -295,19 +290,19 @@ func (d *definitionUsecaseImpl) renderCustomUISchema(ctx context.Context, name, } // AddDefinitionUISchema add definition custom ui schema config -func (d *definitionUsecaseImpl) AddDefinitionUISchema(ctx context.Context, name, defType string, schema []*utils.UIParameter) ([]*utils.UIParameter, error) { +func (d *definitionServiceImpl) AddDefinitionUISchema(ctx context.Context, name, defType string, schema []*utils.UIParameter) ([]*utils.UIParameter, error) { dataBate, err := json.Marshal(schema) if err != nil { log.Logger.Errorf("json marshal failure %s", err.Error()) return nil, bcode.ErrInvalidDefinitionUISchema } var cm v1.ConfigMap - if err := d.kubeClient.Get(ctx, k8stypes.NamespacedName{ + if err := d.KubeClient.Get(ctx, k8stypes.NamespacedName{ Namespace: types.DefaultKubeVelaNS, Name: fmt.Sprintf("%s-uischema-%s", defType, name), }, &cm); err != nil { if apierrors.IsNotFound(err) { - err = d.kubeClient.Create(ctx, &v1.ConfigMap{ + err = d.KubeClient.Create(ctx, &v1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Namespace: types.DefaultKubeVelaNS, Name: fmt.Sprintf("%s-uischema-%s", defType, name), @@ -322,7 +317,7 @@ func (d *definitionUsecaseImpl) AddDefinitionUISchema(ctx context.Context, name, } } else { cm.Data[types.UISchema] = string(dataBate) - err := d.kubeClient.Update(ctx, &cm) + err := d.KubeClient.Update(ctx, &cm) if err != nil { return nil, err } @@ -335,7 +330,7 @@ func (d *definitionUsecaseImpl) AddDefinitionUISchema(ctx context.Context, name, } // UpdateDefinitionStatus update the status of the definition -func (d *definitionUsecaseImpl) UpdateDefinitionStatus(ctx context.Context, name string, update apisv1.UpdateDefinitionStatusRequest) (*apisv1.DetailDefinitionResponse, error) { +func (d *definitionServiceImpl) UpdateDefinitionStatus(ctx context.Context, name string, update apisv1.UpdateDefinitionStatusRequest) (*apisv1.DetailDefinitionResponse, error) { def := &unstructured.Unstructured{} version, kind, err := getKindAndVersion(update.DefinitionType) if err != nil { @@ -343,7 +338,7 @@ func (d *definitionUsecaseImpl) UpdateDefinitionStatus(ctx context.Context, name } def.SetAPIVersion(version) def.SetKind(kind) - if err := d.kubeClient.Get(ctx, k8stypes.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: name}, def); err != nil { + if err := d.KubeClient.Get(ctx, k8stypes.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: name}, def); err != nil { if apierrors.IsNotFound(err) { return nil, bcode.ErrDefinitionNotFound } @@ -354,7 +349,7 @@ func (d *definitionUsecaseImpl) UpdateDefinitionStatus(ctx context.Context, name labels := def.GetLabels() delete(labels, types.LabelDefinitionHidden) def.SetLabels(labels) - if err := d.kubeClient.Update(ctx, def); err != nil { + if err := d.KubeClient.Update(ctx, def); err != nil { return nil, err } } @@ -362,7 +357,7 @@ func (d *definitionUsecaseImpl) UpdateDefinitionStatus(ctx context.Context, name labels := def.GetLabels() labels[types.LabelDefinitionHidden] = "true" def.SetLabels(labels) - if err := d.kubeClient.Update(ctx, def); err != nil { + if err := d.KubeClient.Update(ctx, def); err != nil { return nil, err } } diff --git a/pkg/apiserver/rest/usecase/definition_test.go b/pkg/apiserver/domain/service/definition_test.go similarity index 92% rename from pkg/apiserver/rest/usecase/definition_test.go rename to pkg/apiserver/domain/service/definition_test.go index e1564059a..a7f738c8a 100644 --- a/pkg/apiserver/rest/usecase/definition_test.go +++ b/pkg/apiserver/domain/service/definition_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -33,18 +33,18 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" - v1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" + v1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" "github.com/oam-dev/kubevela/pkg/oam/util" ) -var _ = Describe("Test namespace usecase functions", func() { +var _ = Describe("Test namespace service functions", func() { var ( - definitionUsecase *definitionUsecaseImpl + definitionService *definitionServiceImpl ) BeforeEach(func() { - definitionUsecase = &definitionUsecaseImpl{kubeClient: k8sClient, caches: utils.NewMemoryCacheStore(context.TODO())} + definitionService = &definitionServiceImpl{KubeClient: k8sClient, caches: utils.NewMemoryCacheStore(context.TODO())} err := k8sClient.Create(context.Background(), &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: "vela-system", @@ -62,7 +62,7 @@ var _ = Describe("Test namespace usecase functions", func() { err = k8sClient.Create(context.Background(), &cd) Expect(err).Should(Succeed()) - definitions, err := definitionUsecase.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "component"}) + definitions, err := definitionService.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "component"}) Expect(err).Should(BeNil()) var selectDefinition *v1.DefinitionBase for i, definition := range definitions { @@ -83,7 +83,7 @@ var _ = Describe("Test namespace usecase functions", func() { Expect(err).Should(Succeed()) err = k8sClient.Create(context.Background(), &td) Expect(err).Should(Succeed()) - traits, err := definitionUsecase.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "trait"}) + traits, err := definitionService.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "trait"}) Expect(err).Should(BeNil()) // there is already a scaler trait definition in the test env Expect(cmp.Diff(len(traits), 2)).Should(BeEmpty()) @@ -101,7 +101,7 @@ var _ = Describe("Test namespace usecase functions", func() { err = k8sClient.Create(context.Background(), &sd) Expect(err).Should(Succeed()) - wfstep, err := definitionUsecase.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "workflowstep"}) + wfstep, err := definitionService.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "workflowstep"}) Expect(err).Should(BeNil()) // there is already a deploy workflow step definition in the test env Expect(cmp.Diff(len(wfstep), 2)).Should(BeEmpty()) @@ -118,7 +118,7 @@ var _ = Describe("Test namespace usecase functions", func() { err = k8sClient.Create(context.Background(), &sd2) Expect(err).Should(Succeed()) - allstep, err := definitionUsecase.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "workflowstep", QueryAll: true}) + allstep, err := definitionService.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "workflowstep", QueryAll: true}) Expect(err).Should(BeNil()) Expect(cmp.Diff(len(allstep), 3)).Should(BeEmpty()) @@ -138,7 +138,7 @@ var _ = Describe("Test namespace usecase functions", func() { } err = k8sClient.Create(context.Background(), &policy) Expect(err).Should(Succeed()) - policies, err := definitionUsecase.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "policy"}) + policies, err := definitionService.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "policy"}) Expect(err).Should(BeNil()) Expect(cmp.Diff(len(policies), 1)).Should(BeEmpty()) Expect(cmp.Diff(policies[0].Name, "health")).Should(BeEmpty()) @@ -167,7 +167,7 @@ var _ = Describe("Test namespace usecase functions", func() { } err = k8sClient.Create(context.Background(), cm) Expect(err).Should(Succeed()) - definitionDetail, err := definitionUsecase.DetailDefinition(context.TODO(), "apply-object", "workflowstep") + definitionDetail, err := definitionService.DetailDefinition(context.TODO(), "apply-object", "workflowstep") Expect(err).Should(Succeed()) schemaFromCM := &openapi3.Schema{} @@ -213,7 +213,10 @@ var _ = Describe("Test namespace usecase functions", func() { It("Test sortDefaultUISchema", testSortDefaultUISchema) It("Test update ui schema", func() { - du := NewDefinitionUsecase() + du := &definitionServiceImpl{ + KubeClient: k8sClient, + caches: utils.NewMemoryCacheStore(context.Background()), + } cdata, err := ioutil.ReadFile("./testdata/workflowstep-apply-object.yaml") Expect(err).Should(Succeed()) var schema utils.UISchema @@ -230,7 +233,10 @@ var _ = Describe("Test namespace usecase functions", func() { }) It("Test update status of the definition", func() { - du := NewDefinitionUsecase() + du := &definitionServiceImpl{ + KubeClient: k8sClient, + caches: utils.NewMemoryCacheStore(context.Background()), + } detail, err := du.UpdateDefinitionStatus(context.TODO(), "apply-object", v1.UpdateDefinitionStatusRequest{ DefinitionType: "workflowstep", HiddenInUI: true, diff --git a/pkg/apiserver/rest/usecase/env.go b/pkg/apiserver/domain/service/env.go similarity index 75% rename from pkg/apiserver/rest/usecase/env.go rename to pkg/apiserver/domain/service/env.go index debbb03dc..87cd43209 100644 --- a/pkg/apiserver/rest/usecase/env.go +++ b/pkg/apiserver/domain/service/env.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -25,18 +25,18 @@ import ( apierror "k8s.io/apimachinery/pkg/api/errors" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/repository" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/oam" util "github.com/oam-dev/kubevela/pkg/utils" ) -// EnvUsecase defines the API of Env. -type EnvUsecase interface { +// EnvService defines the API of Env. +type EnvService interface { GetEnv(ctx context.Context, envName string) (*model.Env, error) ListEnvs(ctx context.Context, page, pageSize int, listOption apisv1.ListEnvOptions) (*apisv1.ListEnvResponse, error) ListEnvCount(ctx context.Context, listOption apisv1.ListEnvOptions) (int64, error) @@ -45,41 +45,37 @@ type EnvUsecase interface { UpdateEnv(ctx context.Context, envName string, req apisv1.UpdateEnvRequest) (*apisv1.Env, error) } -type envUsecaseImpl struct { - ds datastore.DataStore - projectUsecase ProjectUsecase - kubeClient client.Client +type envServiceImpl struct { + Store datastore.DataStore `inject:"datastore"` + ProjectService ProjectService `inject:""` + KubeClient client.Client `inject:"kubeClient"` } -// NewEnvUsecase new env usecase -func NewEnvUsecase(ds datastore.DataStore, projectUsecase ProjectUsecase) EnvUsecase { - kubecli, err := clients.GetKubeClient() - if err != nil { - log.Logger.Fatalf("get kubeclient failure %s", err.Error()) - } - return &envUsecaseImpl{kubeClient: kubecli, ds: ds, projectUsecase: projectUsecase} +// NewEnvService new env service +func NewEnvService() EnvService { + return &envServiceImpl{} } // GetEnv get env -func (p *envUsecaseImpl) GetEnv(ctx context.Context, envName string) (*model.Env, error) { - return getEnv(ctx, p.ds, envName) +func (p *envServiceImpl) GetEnv(ctx context.Context, envName string) (*model.Env, error) { + return repository.GetEnv(ctx, p.Store, envName) } // DeleteEnv delete an env by name // the function assume applications contain in env already empty. // it won't delete the namespace created by the Env, but it will update the label -func (p *envUsecaseImpl) DeleteEnv(ctx context.Context, envName string) error { +func (p *envServiceImpl) DeleteEnv(ctx context.Context, envName string) error { env := &model.Env{} env.Name = envName - if err := p.ds.Get(ctx, env); err != nil { + if err := p.Store.Get(ctx, env); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil } return err } // reset the labels - err := util.UpdateNamespace(ctx, p.kubeClient, env.Namespace, util.MergeOverrideLabels(map[string]string{ + err := util.UpdateNamespace(ctx, p.KubeClient, env.Namespace, util.MergeOverrideLabels(map[string]string{ oam.LabelNamespaceOfEnvName: "", oam.LabelControlPlaneNamespaceUsage: "", })) @@ -87,7 +83,7 @@ func (p *envUsecaseImpl) DeleteEnv(ctx context.Context, envName string) error { return err } - if err = p.ds.Delete(ctx, env); err != nil { + if err = p.Store.Delete(ctx, env); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil } @@ -97,12 +93,12 @@ func (p *envUsecaseImpl) DeleteEnv(ctx context.Context, envName string) error { } // ListEnvs list envs -func (p *envUsecaseImpl) ListEnvs(ctx context.Context, page, pageSize int, listOption apisv1.ListEnvOptions) (*apisv1.ListEnvResponse, error) { +func (p *envServiceImpl) ListEnvs(ctx context.Context, page, pageSize int, listOption apisv1.ListEnvOptions) (*apisv1.ListEnvResponse, error) { userName, ok := ctx.Value(&apisv1.CtxKeyUser).(string) if !ok { return nil, bcode.ErrUnauthorized } - projects, err := p.projectUsecase.ListUserProjects(ctx, userName) + projects, err := p.ProjectService.ListUserProjects(ctx, userName) if err != nil { return nil, err } @@ -132,7 +128,7 @@ func (p *envUsecaseImpl) ListEnvs(ctx context.Context, page, pageSize int, listO }, }, } - entities, err := listEnvs(ctx, p.ds, &datastore.ListOptions{ + entities, err := repository.ListEnvs(ctx, p.Store, &datastore.ListOptions{ Page: page, PageSize: pageSize, SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}, @@ -142,7 +138,7 @@ func (p *envUsecaseImpl) ListEnvs(ctx context.Context, page, pageSize int, listO return nil, err } - targets, err := listTarget(ctx, p.ds, listOption.Project, nil) + targets, err := repository.ListTarget(ctx, p.Store, listOption.Project, nil) if err != nil { return nil, err } @@ -156,15 +152,15 @@ func (p *envUsecaseImpl) ListEnvs(ctx context.Context, page, pageSize int, listO envs[i].Project.Alias = projectNameAlias[envs[i].Project.Name] } - total, err := p.ds.Count(ctx, &model.Env{Project: listOption.Project}, &filter) + total, err := p.Store.Count(ctx, &model.Env{Project: listOption.Project}, &filter) if err != nil { return nil, err } return &apisv1.ListEnvResponse{Envs: envs, Total: total}, nil } -func (p *envUsecaseImpl) ListEnvCount(ctx context.Context, listOption apisv1.ListEnvOptions) (int64, error) { - return p.ds.Count(ctx, &model.Env{Project: listOption.Project}, nil) +func (p *envServiceImpl) ListEnvCount(ctx context.Context, listOption apisv1.ListEnvOptions) (int64, error) { + return p.Store.Count(ctx, &model.Env{Project: listOption.Project}, nil) } func checkEqual(old, new []string) bool { @@ -179,15 +175,15 @@ func checkEqual(old, new []string) bool { return reflect.DeepEqual(old, new) } -func (p *envUsecaseImpl) updateAppWithNewEnv(ctx context.Context, envName string, env *model.Env) error { +func (p *envServiceImpl) updateAppWithNewEnv(ctx context.Context, envName string, env *model.Env) error { // List all apps inside the env - apps, err := listApp(ctx, p.ds, apisv1.ListApplicationOptions{Env: envName}) + apps, err := listApp(ctx, p.Store, apisv1.ListApplicationOptions{Env: envName}) if err != nil { return err } for _, app := range apps { - err = UpdateEnvWorkflow(ctx, p.kubeClient, p.ds, app, env) + err = repository.UpdateEnvWorkflow(ctx, p.KubeClient, p.Store, app, env) if err != nil { return err } @@ -197,10 +193,10 @@ func (p *envUsecaseImpl) updateAppWithNewEnv(ctx context.Context, envName string } // UpdateEnv update an env for request -func (p *envUsecaseImpl) UpdateEnv(ctx context.Context, name string, req apisv1.UpdateEnvRequest) (*apisv1.Env, error) { +func (p *envServiceImpl) UpdateEnv(ctx context.Context, name string, req apisv1.UpdateEnvRequest) (*apisv1.Env, error) { env := &model.Env{} env.Name = name - err := p.ds.Get(ctx, env) + err := p.Store.Get(ctx, env) if err != nil { log.Logger.Errorf("check if env name exists failure %s", err.Error()) return nil, bcode.ErrEnvNotExisted @@ -223,7 +219,7 @@ func (p *envUsecaseImpl) UpdateEnv(ctx context.Context, name string, req apisv1. env.Targets = req.Targets } - targets, err := listTarget(ctx, p.ds, "", nil) + targets, err := repository.ListTarget(ctx, p.Store, "", nil) if err != nil { return nil, err } @@ -238,7 +234,7 @@ func (p *envUsecaseImpl) UpdateEnv(ctx context.Context, name string, req apisv1. } // create namespace at first - if err := p.ds.Put(ctx, env); err != nil { + if err := p.Store.Put(ctx, env); err != nil { return nil, err } @@ -254,7 +250,7 @@ func (p *envUsecaseImpl) UpdateEnv(ctx context.Context, name string, req apisv1. } // CreateEnv create an env for request -func (p *envUsecaseImpl) CreateEnv(ctx context.Context, req apisv1.CreateEnvRequest) (*apisv1.Env, error) { +func (p *envServiceImpl) CreateEnv(ctx context.Context, req apisv1.CreateEnvRequest) (*apisv1.Env, error) { newEnv := &model.Env{ Name: req.Name, Alias: req.Alias, @@ -269,7 +265,7 @@ func (p *envUsecaseImpl) CreateEnv(ctx context.Context, req apisv1.CreateEnvRequ return nil, bcode.ErrEnvTargetConflict } - targets, err := listTarget(ctx, p.ds, "", nil) + targets, err := repository.ListTarget(ctx, p.Store, "", nil) if err != nil { return nil, err } @@ -285,7 +281,7 @@ func (p *envUsecaseImpl) CreateEnv(ctx context.Context, req apisv1.CreateEnvRequ } } - err = createEnv(ctx, p.kubeClient, p.ds, newEnv) + err = repository.CreateEnv(ctx, p.KubeClient, p.Store, newEnv) if err != nil { return nil, err } @@ -295,11 +291,11 @@ func (p *envUsecaseImpl) CreateEnv(ctx context.Context, req apisv1.CreateEnvRequ } // checkEnvTarget In one project, a delivery target can only belong to one env. -func (p *envUsecaseImpl) checkEnvTarget(ctx context.Context, project string, envName string, targets []string) (bool, error) { +func (p *envServiceImpl) checkEnvTarget(ctx context.Context, project string, envName string, targets []string) (bool, error) { if len(targets) == 0 { return true, nil } - entitys, err := p.ds.List(ctx, &model.Env{Project: project}, &datastore.ListOptions{}) + entitys, err := p.Store.List(ctx, &model.Env{Project: project}, &datastore.ListOptions{}) if err != nil { return false, err } diff --git a/pkg/apiserver/rest/usecase/env_test.go b/pkg/apiserver/domain/service/env_test.go similarity index 76% rename from pkg/apiserver/rest/usecase/env_test.go rename to pkg/apiserver/domain/service/env_test.go index 41aee9497..fd8d24ca5 100644 --- a/pkg/apiserver/rest/usecase/env_test.go +++ b/pkg/apiserver/domain/service/env_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -26,16 +26,16 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" "github.com/oam-dev/kubevela/pkg/oam" ) -var _ = Describe("Test env usecase functions", func() { +var _ = Describe("Test env service functions", func() { var ( - envUsecase *envUsecaseImpl + envService *envServiceImpl ds datastore.DataStore ) BeforeEach(func() { @@ -43,9 +43,9 @@ var _ = Describe("Test env usecase functions", func() { ds, err = NewDatastore(datastore.Config{Type: "kubeapi", Database: "env-test-kubevela"}) Expect(ds).ToNot(BeNil()) Expect(err).Should(BeNil()) - rbacUsecase := &rbacUsecaseImpl{ds: ds} - projectUsecase := &projectUsecaseImpl{ds: ds, k8sClient: k8sClient, rbacUsecase: rbacUsecase} - envUsecase = &envUsecaseImpl{kubeClient: k8sClient, ds: ds, projectUsecase: projectUsecase} + rbacService := &rbacServiceImpl{Store: ds} + projectService := &projectServiceImpl{Store: ds, K8sClient: k8sClient, RbacService: rbacService} + envService = &envServiceImpl{KubeClient: k8sClient, Store: ds, ProjectService: projectService} }) It("Test Create/Get/Delete Env function", func() { // create target @@ -56,7 +56,7 @@ var _ = Describe("Test env usecase functions", func() { Name: "test-env", Description: "this is a env description", } - base, err := envUsecase.CreateEnv(context.TODO(), req) + base, err := envService.CreateEnv(context.TODO(), req) Expect(err).Should(BeNil()) Expect(cmp.Diff(base.Description, req.Description)).Should(BeEmpty()) Expect(cmp.Diff(base.Namespace, req.Name)).Should(BeEmpty()) @@ -67,7 +67,7 @@ var _ = Describe("Test env usecase functions", func() { Description: "this is a env description", Namespace: base.Namespace, } - _, err = envUsecase.CreateEnv(context.TODO(), req2) + _, err = envService.CreateEnv(context.TODO(), req2) equal := cmp.Equal(err, bcode.ErrEnvNamespaceAlreadyBound, cmpopts.EquateErrors()) Expect(equal).Should(BeTrue()) @@ -78,7 +78,7 @@ var _ = Describe("Test env usecase functions", func() { Project: "env-project", Targets: []string{"env-test"}, } - base, err = envUsecase.CreateEnv(context.TODO(), req3) + base, err = envService.CreateEnv(context.TODO(), req3) Expect(err).Should(BeNil()) Expect(cmp.Diff(base.Namespace, "default")).Should(BeEmpty()) var namespace corev1.Namespace @@ -94,7 +94,7 @@ var _ = Describe("Test env usecase functions", func() { Project: "env-project", Targets: []string{"env-test"}, } - _, err = envUsecase.CreateEnv(context.TODO(), req4) + _, err = envService.CreateEnv(context.TODO(), req4) Expect(cmp.Equal(err, bcode.ErrEnvTargetConflict, cmpopts.EquateErrors())).Should(BeTrue()) // test update env @@ -102,18 +102,18 @@ var _ = Describe("Test env usecase functions", func() { Description: "this is a env description update", Targets: []string{"env-test"}, } - env, err := envUsecase.UpdateEnv(context.TODO(), "test-env-2", req5) + env, err := envService.UpdateEnv(context.TODO(), "test-env-2", req5) Expect(err).Should(BeNil()) Expect(cmp.Diff(env.Description, req5.Description)).Should(BeEmpty()) // clean up the env - err = envUsecase.DeleteEnv(context.TODO(), "test-env") + err = envService.DeleteEnv(context.TODO(), "test-env") Expect(err).Should(BeNil()) - err = envUsecase.DeleteEnv(context.TODO(), "test-env-2") + err = envService.DeleteEnv(context.TODO(), "test-env-2") Expect(err).Should(BeNil()) By("Test ListEnvs function") - _, err = envUsecase.ListEnvs(context.WithValue(context.TODO(), &apisv1.CtxKeyUser, "admin"), 1, 1, apisv1.ListEnvOptions{}) + _, err = envService.ListEnvs(context.WithValue(context.TODO(), &apisv1.CtxKeyUser, "admin"), 1, 1, apisv1.ListEnvOptions{}) Expect(err).Should(BeNil()) }) diff --git a/pkg/apiserver/domain/service/envbinding.go b/pkg/apiserver/domain/service/envbinding.go new file mode 100644 index 000000000..c5486c39f --- /dev/null +++ b/pkg/apiserver/domain/service/envbinding.go @@ -0,0 +1,301 @@ +/* +Copyright 2021 The KubeVela 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 service + +import ( + "context" + "errors" + "fmt" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/repository" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + assembler "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/assembler/v1" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" + utils2 "github.com/oam-dev/kubevela/pkg/utils" +) + +// EnvBindingService envbinding service +type EnvBindingService interface { + GetEnvBindings(ctx context.Context, app *model.Application) ([]*apisv1.EnvBindingBase, error) + GetEnvBinding(ctx context.Context, app *model.Application, envName string) (*model.EnvBinding, error) + CreateEnvBinding(ctx context.Context, app *model.Application, env apisv1.CreateApplicationEnvbindingRequest) (*apisv1.EnvBinding, error) + BatchCreateEnvBinding(ctx context.Context, app *model.Application, env apisv1.EnvBindingList) error + UpdateEnvBinding(ctx context.Context, app *model.Application, envName string, diff apisv1.PutApplicationEnvBindingRequest) (*apisv1.DetailEnvBindingResponse, error) + DeleteEnvBinding(ctx context.Context, app *model.Application, envName string) error + BatchDeleteEnvBinding(ctx context.Context, app *model.Application) error + DetailEnvBinding(ctx context.Context, app *model.Application, envBinding *model.EnvBinding) (*apisv1.DetailEnvBindingResponse, error) + ApplicationEnvRecycle(ctx context.Context, appModel *model.Application, envBinding *model.EnvBinding) error +} + +type envBindingServiceImpl struct { + Store datastore.DataStore `inject:"datastore"` + WorkflowService WorkflowService `inject:""` + EnvService EnvService `inject:""` + DefinitionService DefinitionService `inject:""` + KubeClient client.Client `inject:"kubeClient"` +} + +// NewEnvBindingService new envBinding service +func NewEnvBindingService() EnvBindingService { + return &envBindingServiceImpl{} +} + +func (e *envBindingServiceImpl) GetEnvBindings(ctx context.Context, app *model.Application) ([]*apisv1.EnvBindingBase, error) { + full, err := repository.ListFullEnvBinding(ctx, e.Store, repository.EnvListOption{AppPrimaryKey: app.PrimaryKey(), ProjectName: app.Project}) + if err != nil { + log.Logger.Errorf("list envbinding for app %s err: %v\n", app.Name, err) + return nil, err + } + return full, nil +} + +func (e *envBindingServiceImpl) GetEnvBinding(ctx context.Context, app *model.Application, envName string) (*model.EnvBinding, error) { + envBinding, err := e.getBindingByEnv(ctx, app, envName) + if err != nil { + if errors.Is(err, datastore.ErrRecordNotExist) { + return nil, bcode.ErrEnvBindingsNotExist + } + return nil, err + } + return envBinding, nil +} + +// CheckAppEnvBindingsContainTarget check envbinding contain target +func CheckAppEnvBindingsContainTarget(envBindings []*apisv1.EnvBindingBase, targetName string) (bool, error) { + var filteredList []*apisv1.EnvBindingBase + for _, envBinding := range envBindings { + if utils.StringsContain(envBinding.TargetNames, targetName) { + filteredList = append(filteredList, envBinding) + } + } + return len(filteredList) > 0, nil +} + +func (e *envBindingServiceImpl) CreateEnvBinding(ctx context.Context, app *model.Application, envReq apisv1.CreateApplicationEnvbindingRequest) (*apisv1.EnvBinding, error) { + envBinding, err := e.getBindingByEnv(ctx, app, envReq.Name) + if err != nil { + if !errors.Is(err, datastore.ErrRecordNotExist) { + return nil, err + } + } + if envBinding != nil { + return nil, bcode.ErrEnvBindingExist + } + env, err := repository.GetEnv(ctx, e.Store, envReq.Name) + if err != nil { + return nil, err + } + envBindingModel := assembler.CreateEnvBindingModel(app, envReq) + err = e.createEnvWorkflow(ctx, app, env, false) + if err != nil { + return nil, err + } + if err := e.Store.Add(ctx, &envBindingModel); err != nil { + return nil, err + } + + return &envReq.EnvBinding, nil +} + +func (e *envBindingServiceImpl) BatchCreateEnvBinding(ctx context.Context, app *model.Application, envbindings apisv1.EnvBindingList) error { + for i := range envbindings { + envBindingModel := assembler.ConvertToEnvBindingModel(app, *envbindings[i]) + env, err := repository.GetEnv(ctx, e.Store, envBindingModel.Name) + if err != nil { + log.Logger.Errorf("get env failure %s", err.Error()) + continue + } + if err := e.Store.Add(ctx, envBindingModel); err != nil { + log.Logger.Errorf("add envbinding %s failure %s", utils2.Sanitize(envBindingModel.Name), err.Error()) + continue + } + err = e.createEnvWorkflow(ctx, app, env, i == 0) + if err != nil { + log.Logger.Errorf("create env workflow failure %s", err.Error()) + continue + } + } + return nil +} + +func (e *envBindingServiceImpl) getBindingByEnv(ctx context.Context, app *model.Application, envName string) (*model.EnvBinding, error) { + var envBinding = model.EnvBinding{ + AppPrimaryKey: app.PrimaryKey(), + Name: envName, + } + err := e.Store.Get(ctx, &envBinding) + if err != nil { + return nil, err + } + return &envBinding, nil +} + +func (e *envBindingServiceImpl) UpdateEnvBinding(ctx context.Context, app *model.Application, envName string, _ apisv1.PutApplicationEnvBindingRequest) (*apisv1.DetailEnvBindingResponse, error) { + envBinding, err := e.getBindingByEnv(ctx, app, envName) + if err != nil { + if errors.Is(err, datastore.ErrRecordNotExist) { + return nil, bcode.ErrEnvBindingNotExist + } + return nil, err + } + env, err := repository.GetEnv(ctx, e.Store, envName) + if err != nil { + return nil, err + } + // update env + if err := e.Store.Put(ctx, envBinding); err != nil { + return nil, err + } + // update env workflow + if err := repository.UpdateEnvWorkflow(ctx, e.KubeClient, e.Store, app, env); err != nil { + return nil, bcode.ErrEnvBindingUpdateWorkflow + } + return e.DetailEnvBinding(ctx, app, envBinding) +} + +func (e *envBindingServiceImpl) DeleteEnvBinding(ctx context.Context, appModel *model.Application, envName string) error { + envBinding, err := e.getBindingByEnv(ctx, appModel, envName) + if err != nil { + if errors.Is(err, datastore.ErrRecordNotExist) { + return bcode.ErrEnvBindingNotExist + } + return err + } + env, err := repository.GetEnv(ctx, e.Store, envName) + if err != nil && errors.Is(err, datastore.ErrRecordNotExist) { + return err + } + if env != nil { + var app v1beta1.Application + err = e.KubeClient.Get(ctx, types.NamespacedName{Namespace: env.Namespace, Name: appModel.Name}, &app) + if err == nil || !apierrors.IsNotFound(err) { + return bcode.ErrApplicationEnvRefusedDelete + } + if err := e.Store.Delete(ctx, &model.EnvBinding{AppPrimaryKey: appModel.PrimaryKey(), Name: envBinding.Name}); err != nil { + return err + } + } + // delete env workflow + if err := e.deleteEnvWorkflow(ctx, appModel, repository.ConvertWorkflowName(envBinding.Name)); err != nil { + return fmt.Errorf("fail to clear the workflow belong to the env %w", err) + } + + // delete the topology and env-bindings policies + if err := e.Store.Delete(ctx, &model.ApplicationPolicy{AppPrimaryKey: appModel.PrimaryKey(), EnvName: envName}); err != nil && !errors.Is(err, datastore.ErrRecordNotExist) { + return fmt.Errorf("fail to clear the policies belong to the env %w", err) + } + return nil +} + +func (e *envBindingServiceImpl) BatchDeleteEnvBinding(ctx context.Context, app *model.Application) error { + envBindings, err := e.GetEnvBindings(ctx, app) + if err != nil { + return err + } + for _, envBinding := range envBindings { + // delete env + if err := e.Store.Delete(ctx, &model.EnvBinding{AppPrimaryKey: app.PrimaryKey(), Name: envBinding.Name}); err != nil { + return err + } + // delete env workflow + err := e.deleteEnvWorkflow(ctx, app, repository.ConvertWorkflowName(envBinding.Name)) + if err != nil { + return err + } + } + return nil +} + +func (e *envBindingServiceImpl) createEnvWorkflow(ctx context.Context, app *model.Application, env *model.Env, isDefault bool) error { + steps, policies := repository.GenEnvWorkflowStepsAndPolicies(ctx, e.KubeClient, e.Store, env, app) + workflow := &model.Workflow{ + Steps: steps, + Name: repository.ConvertWorkflowName(env.Name), + Alias: fmt.Sprintf("%s Workflow", env.Alias), + Description: "Created automatically by envbinding.", + Default: &isDefault, + EnvName: env.Name, + AppPrimaryKey: app.PrimaryKey(), + } + log.Logger.Infof("create workflow %s for app %s", utils2.Sanitize(workflow.Name), utils2.Sanitize(app.PrimaryKey())) + if err := e.Store.Add(ctx, workflow); err != nil { + return err + } + err := e.Store.BatchAdd(ctx, policies) + if err != nil { + if err := e.WorkflowService.DeleteWorkflow(ctx, app, repository.ConvertWorkflowName(env.Name)); err != nil { + log.Logger.Errorf("fail to rollback the workflow after fail to create policies, %s", err.Error()) + } + return fmt.Errorf("fail to create policies %w", err) + } + return nil +} + +func (e *envBindingServiceImpl) deleteEnvWorkflow(ctx context.Context, app *model.Application, workflowName string) error { + if err := e.WorkflowService.DeleteWorkflow(ctx, app, workflowName); err != nil { + if !errors.Is(err, bcode.ErrWorkflowNotExist) { + return err + } + } + return nil +} + +func (e *envBindingServiceImpl) DetailEnvBinding(ctx context.Context, app *model.Application, envBinding *model.EnvBinding) (*apisv1.DetailEnvBindingResponse, error) { + targets, err := repository.ListTarget(ctx, e.Store, "", nil) + if err != nil { + return nil, err + } + env, err := repository.GetEnv(ctx, e.Store, envBinding.Name) + if err != nil { + return nil, err + } + return &apisv1.DetailEnvBindingResponse{ + EnvBindingBase: *assembler.ConvertEnvBindingModelToBase(envBinding, env, targets), + }, nil +} + +func (e *envBindingServiceImpl) ApplicationEnvRecycle(ctx context.Context, appModel *model.Application, envBinding *model.EnvBinding) error { + env, err := repository.GetEnv(ctx, e.Store, envBinding.Name) + if err != nil { + return err + } + var app v1beta1.Application + err = e.KubeClient.Get(ctx, types.NamespacedName{Namespace: env.Namespace, Name: appModel.Name}, &app) + if err != nil { + if apierrors.IsNotFound(err) { + return nil + } + return err + } + if err := e.KubeClient.Delete(ctx, &app); err != nil { + return err + } + + if err := resetRevisionsAndRecords(ctx, e.Store, appModel.Name, "", "", ""); err != nil { + return err + } + return nil +} diff --git a/pkg/apiserver/rest/usecase/envbinding_test.go b/pkg/apiserver/domain/service/envbinding_test.go similarity index 63% rename from pkg/apiserver/rest/usecase/envbinding_test.go rename to pkg/apiserver/domain/service/envbinding_test.go index feb92bd0e..8c524a71a 100644 --- a/pkg/apiserver/rest/usecase/envbinding_test.go +++ b/pkg/apiserver/domain/service/envbinding_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -23,18 +23,19 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/repository" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" ) -var _ = Describe("Test envBindingUsecase functions", func() { +var _ = Describe("Test envBindingService functions", func() { var ( - envUsecase *envUsecaseImpl - envBindingUsecase *envBindingUsecaseImpl - workflowUsecase *workflowUsecaseImpl - definitionUsecase DefinitionUsecase + envService *envServiceImpl + envBindingService *envBindingServiceImpl + workflowService *workflowServiceImpl + definitionService DefinitionService envBindingDemo1 apisv1.EnvBinding envBindingDemo2 apisv1.EnvBinding testApp *model.Application @@ -49,12 +50,12 @@ var _ = Describe("Test envBindingUsecase functions", func() { Name: "test-app-env", Project: "default", } - rbacUsecase := &rbacUsecaseImpl{ds: ds} - projectUsecase := &projectUsecaseImpl{ds: ds, k8sClient: k8sClient, rbacUsecase: rbacUsecase} - envUsecase = &envUsecaseImpl{ds: ds, kubeClient: k8sClient, projectUsecase: projectUsecase} - workflowUsecase = &workflowUsecaseImpl{ds: ds, kubeClient: k8sClient, envUsecase: envUsecase} - definitionUsecase = &definitionUsecaseImpl{kubeClient: k8sClient, caches: utils.NewMemoryCacheStore(context.TODO())} - envBindingUsecase = &envBindingUsecaseImpl{ds: ds, workflowUsecase: workflowUsecase, definitionUsecase: definitionUsecase, kubeClient: k8sClient, envUsecase: envUsecase} + rbacService := &rbacServiceImpl{Store: ds} + projectService := &projectServiceImpl{Store: ds, K8sClient: k8sClient, RbacService: rbacService} + envService = &envServiceImpl{Store: ds, KubeClient: k8sClient, ProjectService: projectService} + workflowService = &workflowServiceImpl{Store: ds, KubeClient: k8sClient, EnvService: envService} + definitionService = &definitionServiceImpl{KubeClient: k8sClient, caches: utils.NewMemoryCacheStore(context.TODO())} + envBindingService = &envBindingServiceImpl{Store: ds, WorkflowService: workflowService, DefinitionService: definitionService, KubeClient: k8sClient, EnvService: envService} envBindingDemo1 = apisv1.EnvBinding{ Name: "envbinding-dev", } @@ -78,69 +79,69 @@ var _ = Describe("Test envBindingUsecase functions", func() { Cluster: &model.ClusterTarget{ClusterName: "local", Namespace: "prod-target"}}) Expect(err).Should(BeNil()) - _, err = envUsecase.CreateEnv(context.TODO(), apisv1.CreateEnvRequest{ + _, err = envService.CreateEnv(context.TODO(), apisv1.CreateEnvRequest{ Project: "default", Name: "envbinding-dev", Targets: []string{"dev-target"}}) Expect(err).Should(BeNil()) - _, err = envUsecase.CreateEnv(context.TODO(), apisv1.CreateEnvRequest{ + _, err = envService.CreateEnv(context.TODO(), apisv1.CreateEnvRequest{ Project: "default", Name: "envbinding-prod", Targets: []string{"prod-target"}}) Expect(err).Should(BeNil()) By("create two envbinding") req := apisv1.CreateApplicationEnvbindingRequest{EnvBinding: envBindingDemo1} - base, err := envBindingUsecase.CreateEnvBinding(context.TODO(), testApp, req) + base, err := envBindingService.CreateEnvBinding(context.TODO(), testApp, req) Expect(err).Should(BeNil()) Expect(cmp.Diff(base.Name, req.Name)).Should(BeEmpty()) req = apisv1.CreateApplicationEnvbindingRequest{EnvBinding: envBindingDemo2} - base, err = envBindingUsecase.CreateEnvBinding(context.TODO(), testApp, req) + base, err = envBindingService.CreateEnvBinding(context.TODO(), testApp, req) Expect(err).Should(BeNil()) Expect(cmp.Diff(base.Name, req.Name)).Should(BeEmpty()) By("auto create two workflow") - workflow, err := workflowUsecase.GetWorkflow(context.TODO(), testApp, convertWorkflowName("envbinding-dev")) + workflow, err := workflowService.GetWorkflow(context.TODO(), testApp, repository.ConvertWorkflowName("envbinding-dev")) Expect(err).Should(BeNil()) Expect(cmp.Diff(workflow.Steps[0].Name, "dev-target")).Should(BeEmpty()) - workflow, err = workflowUsecase.GetWorkflow(context.TODO(), testApp, convertWorkflowName("envbinding-prod")) + workflow, err = workflowService.GetWorkflow(context.TODO(), testApp, repository.ConvertWorkflowName("envbinding-prod")) Expect(err).Should(BeNil()) Expect(cmp.Diff(workflow.Steps[0].Name, "prod-target")).Should(BeEmpty()) }) It("Test GetApplication Envs function", func() { - envBindings, err := envBindingUsecase.GetEnvBindings(context.TODO(), testApp) + envBindings, err := envBindingService.GetEnvBindings(context.TODO(), testApp) Expect(err).Should(BeNil()) Expect(envBindings).ShouldNot(BeNil()) Expect(cmp.Diff(len(envBindings), 2)).Should(BeEmpty()) }) It("Test GetApplication Env function", func() { - envBinding, err := envBindingUsecase.GetEnvBinding(context.TODO(), testApp, "envbinding-dev") + envBinding, err := envBindingService.GetEnvBinding(context.TODO(), testApp, "envbinding-dev") Expect(err).Should(BeNil()) Expect(envBinding).ShouldNot(BeNil()) Expect(cmp.Diff(envBinding.Name, "envbinding-dev")).Should(BeEmpty()) }) It("Test Application UpdateEnv function", func() { - envBinding, err := envBindingUsecase.UpdateEnvBinding(context.TODO(), testApp, "envbinding-prod", apisv1.PutApplicationEnvBindingRequest{}) + envBinding, err := envBindingService.UpdateEnvBinding(context.TODO(), testApp, "envbinding-prod", apisv1.PutApplicationEnvBindingRequest{}) Expect(err).Should(BeNil()) Expect(envBinding).ShouldNot(BeNil()) Expect(cmp.Diff(envBinding.TargetNames[0], "prod-target")).Should(BeEmpty()) - workflow, err := workflowUsecase.GetWorkflow(context.TODO(), testApp, "workflow-envbinding-prod") + workflow, err := workflowService.GetWorkflow(context.TODO(), testApp, "workflow-envbinding-prod") Expect(err).Should(BeNil()) Expect(len(workflow.Steps)).Should(Equal(1)) Expect(cmp.Diff(workflow.Steps[0].Name, "prod-target")).Should(BeEmpty()) }) It("Test Application DeleteEnv function", func() { - err := envBindingUsecase.DeleteEnvBinding(context.TODO(), testApp, "envbinding-dev") + err := envBindingService.DeleteEnvBinding(context.TODO(), testApp, "envbinding-dev") Expect(err).Should(BeNil()) - _, err = workflowUsecase.GetWorkflow(context.TODO(), testApp, convertWorkflowName("envbinding-dev")) + _, err = workflowService.GetWorkflow(context.TODO(), testApp, repository.ConvertWorkflowName("envbinding-dev")) Expect(err).ShouldNot(BeNil()) - err = envBindingUsecase.DeleteEnvBinding(context.TODO(), testApp, "envbinding-prod") + err = envBindingService.DeleteEnvBinding(context.TODO(), testApp, "envbinding-prod") Expect(err).Should(BeNil()) - _, err = workflowUsecase.GetWorkflow(context.TODO(), testApp, convertWorkflowName("envbinding-prod")) + _, err = workflowService.GetWorkflow(context.TODO(), testApp, repository.ConvertWorkflowName("envbinding-prod")) Expect(err).ShouldNot(BeNil()) }) @@ -148,20 +149,20 @@ var _ = Describe("Test envBindingUsecase functions", func() { testBatchApp := &model.Application{ Name: "test-batch-createt", } - err := envBindingUsecase.BatchCreateEnvBinding(context.TODO(), testBatchApp, apisv1.EnvBindingList{&envBindingDemo1, &envBindingDemo2}) + err := envBindingService.BatchCreateEnvBinding(context.TODO(), testBatchApp, apisv1.EnvBindingList{&envBindingDemo1, &envBindingDemo2}) Expect(err).Should(BeNil()) - envBindings, err := envBindingUsecase.GetEnvBindings(context.TODO(), testBatchApp) + envBindings, err := envBindingService.GetEnvBindings(context.TODO(), testBatchApp) Expect(err).Should(BeNil()) Expect(cmp.Diff(len(envBindings), 2)).Should(BeEmpty()) - workflows, err := workflowUsecase.ListApplicationWorkflow(context.TODO(), testBatchApp) + workflows, err := workflowService.ListApplicationWorkflow(context.TODO(), testBatchApp) Expect(err).Should(BeNil()) Expect(cmp.Diff(len(workflows), 2)).Should(BeEmpty()) }) It("Test BatchDeleteEnvBinding function", func() { - err := envBindingUsecase.BatchDeleteEnvBinding(context.TODO(), testApp) + err := envBindingService.BatchDeleteEnvBinding(context.TODO(), testApp) Expect(err).Should(BeNil()) - envBindings, err := envBindingUsecase.GetEnvBindings(context.TODO(), testApp) + envBindings, err := envBindingService.GetEnvBindings(context.TODO(), testApp) Expect(err).Should(BeNil()) Expect(cmp.Diff(len(envBindings), 0)).Should(BeEmpty()) }) diff --git a/pkg/apiserver/rest/usecase/helm.go b/pkg/apiserver/domain/service/helm.go similarity index 75% rename from pkg/apiserver/rest/usecase/helm.go rename to pkg/apiserver/domain/service/helm.go index 01aa422a8..6f070dbc5 100644 --- a/pkg/apiserver/rest/usecase/helm.go +++ b/pkg/apiserver/domain/service/helm.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -23,10 +23,9 @@ import ( "github.com/oam-dev/kubevela/pkg/utils/config" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - v1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + v1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/utils" "github.com/oam-dev/kubevela/pkg/utils/common" @@ -39,39 +38,34 @@ import ( "helm.sh/helm/v3/pkg/repo" ) -// NewHelmUsecase return a helmHandler -func NewHelmUsecase() HelmHandler { - c, err := clients.GetKubeClient() - if err != nil { - log.Logger.Fatalf("get kube client failure %s", err.Error()) - } - return defaultHelmHandler{ - helper: helm.NewHelperWithCache(), - k8sClient: c, +// NewHelmService return a helmHandler +func NewHelmService() HelmService { + return &defaultHelmImpl{ + helper: helm.NewHelperWithCache(), } } -// HelmHandler responsible handle helm related interface -type HelmHandler interface { +// HelmService responsible handle helm related interface +type HelmService interface { ListChartNames(ctx context.Context, url string, secretName string, skipCache bool) ([]string, error) ListChartVersions(ctx context.Context, url string, chartName string, secretName string, skipCache bool) (repo.ChartVersions, error) GetChartValues(ctx context.Context, url string, chartName string, version string, secretName string, skipCache bool) (map[string]interface{}, error) ListChartRepo(ctx context.Context, projectName string) (*v1.ChartRepoResponseList, error) } -type defaultHelmHandler struct { +type defaultHelmImpl struct { helper *helm.Helper - k8sClient client.Client + K8sClient client.Client `inject:"kubeClient"` } -func (d defaultHelmHandler) ListChartNames(ctx context.Context, repoURL string, secretName string, skipCache bool) ([]string, error) { +func (d defaultHelmImpl) ListChartNames(ctx context.Context, repoURL string, secretName string, skipCache bool) ([]string, error) { if !utils.IsValidURL(repoURL) { return nil, bcode.ErrRepoInvalidURL } var opts *common.HTTPOption var err error if len(secretName) != 0 { - opts, err = helm.SetBasicAuthInfo(ctx, d.k8sClient, types2.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: secretName}) + opts, err = helm.SetBasicAuthInfo(ctx, d.K8sClient, types2.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: secretName}) if err != nil { return nil, bcode.ErrRepoBasicAuth } @@ -84,14 +78,14 @@ func (d defaultHelmHandler) ListChartNames(ctx context.Context, repoURL string, return charts, nil } -func (d defaultHelmHandler) ListChartVersions(ctx context.Context, repoURL string, chartName string, secretName string, skipCache bool) (repo.ChartVersions, error) { +func (d defaultHelmImpl) ListChartVersions(ctx context.Context, repoURL string, chartName string, secretName string, skipCache bool) (repo.ChartVersions, error) { if !utils.IsValidURL(repoURL) { return nil, bcode.ErrRepoInvalidURL } var opts *common.HTTPOption var err error if len(secretName) != 0 { - opts, err = helm.SetBasicAuthInfo(ctx, d.k8sClient, types2.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: secretName}) + opts, err = helm.SetBasicAuthInfo(ctx, d.K8sClient, types2.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: secretName}) if err != nil { return nil, bcode.ErrRepoBasicAuth } @@ -108,14 +102,14 @@ func (d defaultHelmHandler) ListChartVersions(ctx context.Context, repoURL strin return chartVersions, nil } -func (d defaultHelmHandler) GetChartValues(ctx context.Context, repoURL string, chartName string, version string, secretName string, skipCache bool) (map[string]interface{}, error) { +func (d defaultHelmImpl) GetChartValues(ctx context.Context, repoURL string, chartName string, version string, secretName string, skipCache bool) (map[string]interface{}, error) { if !utils.IsValidURL(repoURL) { return nil, bcode.ErrRepoInvalidURL } var opts *common.HTTPOption var err error if len(secretName) != 0 { - opts, err = helm.SetBasicAuthInfo(ctx, d.k8sClient, types2.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: secretName}) + opts, err = helm.SetBasicAuthInfo(ctx, d.K8sClient, types2.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: secretName}) if err != nil { return nil, bcode.ErrRepoBasicAuth } @@ -130,7 +124,7 @@ func (d defaultHelmHandler) GetChartValues(ctx context.Context, repoURL string, return res, nil } -func (d defaultHelmHandler) ListChartRepo(ctx context.Context, projectName string) (*v1.ChartRepoResponseList, error) { +func (d defaultHelmImpl) ListChartRepo(ctx context.Context, projectName string) (*v1.ChartRepoResponseList, error) { var res []*v1.ChartRepoResponse var err error @@ -139,7 +133,7 @@ func (d defaultHelmHandler) ListChartRepo(ctx context.Context, projectName strin client.MatchingLabels{oam.LabelConfigType: "config-helm-repository"}, client.InNamespace(types.DefaultKubeVelaNS), } - err = d.k8sClient.List(ctx, &projectSecrets, opts...) + err = d.K8sClient.List(ctx, &projectSecrets, opts...) if err != nil { return nil, err } diff --git a/pkg/apiserver/rest/usecase/helm_test.go b/pkg/apiserver/domain/service/helm_test.go similarity index 95% rename from pkg/apiserver/rest/usecase/helm_test.go rename to pkg/apiserver/domain/service/helm_test.go index 767c53bb2..290957574 100644 --- a/pkg/apiserver/rest/usecase/helm_test.go +++ b/pkg/apiserver/domain/service/helm_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -29,6 +29,7 @@ import ( . "github.com/onsi/gomega" "github.com/oam-dev/kubevela/pkg/oam/util" + "github.com/oam-dev/kubevela/pkg/utils/helm" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -51,6 +52,14 @@ func TestFlattenKeyFunc(t *testing.T) { assert.Equal(t, dstMap, res) } +// NewTestHelmService new helm service for test +func NewTestHelmService() HelmService { + return &defaultHelmImpl{ + helper: helm.NewHelperWithCache(), + K8sClient: k8sClient, + } +} + var _ = Describe("Test helm repo list", func() { ctx := context.Background() var pSec, gSec v1.Secret @@ -71,7 +80,7 @@ var _ = Describe("Test helm repo list", func() { }) It("Test list with project ", func() { - u := NewHelmUsecase() + u := NewTestHelmService() list, err := u.ListChartRepo(ctx, "my-project") Expect(err).Should(BeNil()) Expect(len(list.ChartRepoResponse)).Should(BeEquivalentTo(2)) @@ -90,7 +99,7 @@ var _ = Describe("Test helm repo list", func() { }) It("Test list func with not exist project", func() { - u := NewHelmUsecase() + u := NewTestHelmService() list, err := u.ListChartRepo(ctx, "not-exist-project") Expect(err).Should(BeNil()) Expect(len(list.ChartRepoResponse)).Should(BeEquivalentTo(1)) @@ -99,7 +108,7 @@ var _ = Describe("Test helm repo list", func() { }) It("Test list func without project", func() { - u := NewHelmUsecase() + u := NewTestHelmService() list, err := u.ListChartRepo(ctx, "") Expect(err).Should(BeNil()) Expect(len(list.ChartRepoResponse)).Should(BeEquivalentTo(1)) @@ -124,7 +133,7 @@ var _ = Describe("test helm usecasae", func() { Expect(k8sClient.Delete(ctx, &repoSec)).Should(BeNil()) }) - It("helm associated usecase interface test", func() { + It("helm associated service interface test", func() { var mockServer *httptest.Server handler := http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { @@ -162,7 +171,7 @@ var _ = Describe("test helm usecasae", func() { defer mockServer.Close() - u := NewHelmUsecase() + u := NewTestHelmService() charts, err := u.ListChartNames(ctx, mockServer.URL, "repo-secret", false) Expect(err).Should(BeNil()) Expect(len(charts)).Should(BeEquivalentTo(1)) @@ -180,7 +189,7 @@ var _ = Describe("test helm usecasae", func() { }) It("coverage not secret notExist error", func() { - u := NewHelmUsecase() + u := NewTestHelmService() _, err := u.ListChartNames(ctx, "http://127.0.0.1:8080", "repo-secret-notExist", false) Expect(err).ShouldNot(BeNil()) diff --git a/pkg/apiserver/rest/usecase/oam_application.go b/pkg/apiserver/domain/service/oam_application.go similarity index 67% rename from pkg/apiserver/rest/usecase/oam_application.go rename to pkg/apiserver/domain/service/oam_application.go index 6005c9f3d..3bf955a1b 100644 --- a/pkg/apiserver/rest/usecase/oam_application.go +++ b/pkg/apiserver/domain/service/oam_application.go @@ -14,13 +14,11 @@ limitations under the License. */ -package usecase +package service import ( "context" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "k8s.io/api/core/v1" @@ -28,33 +26,32 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" ) -// OAMApplicationUsecase oam_application usecase -type OAMApplicationUsecase interface { +// OAMApplicationService oam_application service +type OAMApplicationService interface { CreateOrUpdateOAMApplication(context.Context, apisv1.ApplicationRequest, string, string) error GetOAMApplication(context.Context, string, string) (*apisv1.ApplicationResponse, error) DeleteOAMApplication(context.Context, string, string) error } -// NewOAMApplicationUsecase new oam_application usecase -func NewOAMApplicationUsecase() OAMApplicationUsecase { - kubeClient, _ := clients.GetKubeClient() - return &oamApplicationUsecaseImpl{kubeClient: kubeClient} +// NewOAMApplicationService new oam_application service +func NewOAMApplicationService() OAMApplicationService { + return &oamApplicationServiceImpl{} } -type oamApplicationUsecaseImpl struct { - kubeClient client.Client +type oamApplicationServiceImpl struct { + KubeClient client.Client `inject:"kubeClient"` } // CreateOrUpdateOAMApplication create or update application -func (o oamApplicationUsecaseImpl) CreateOrUpdateOAMApplication(ctx context.Context, request apisv1.ApplicationRequest, name, namespace string) error { +func (o oamApplicationServiceImpl) CreateOrUpdateOAMApplication(ctx context.Context, request apisv1.ApplicationRequest, name, namespace string) error { ns := new(v1.Namespace) - err := o.kubeClient.Get(ctx, client.ObjectKey{Name: namespace}, ns) + err := o.KubeClient.Get(ctx, client.ObjectKey{Name: namespace}, ns) if kerrors.IsNotFound(err) { ns.Name = namespace - if err = o.kubeClient.Create(ctx, ns); err != nil { + if err = o.KubeClient.Create(ctx, ns); err != nil { return err } } @@ -72,22 +69,22 @@ func (o oamApplicationUsecaseImpl) CreateOrUpdateOAMApplication(ctx context.Cont } existApp := new(v1beta1.Application) - err = o.kubeClient.Get(ctx, client.ObjectKey{Name: name, Namespace: namespace}, existApp) + err = o.KubeClient.Get(ctx, client.ObjectKey{Name: name, Namespace: namespace}, existApp) if err != nil { if kerrors.IsNotFound(err) { - return o.kubeClient.Create(ctx, app) + return o.KubeClient.Create(ctx, app) } return err } existApp.Spec = app.Spec - return o.kubeClient.Update(ctx, existApp) + return o.KubeClient.Update(ctx, existApp) } // GetOAMApplication get application -func (o oamApplicationUsecaseImpl) GetOAMApplication(ctx context.Context, name, namespace string) (*apisv1.ApplicationResponse, error) { +func (o oamApplicationServiceImpl) GetOAMApplication(ctx context.Context, name, namespace string) (*apisv1.ApplicationResponse, error) { app := new(v1beta1.Application) - if err := o.kubeClient.Get(ctx, client.ObjectKey{Name: name, Namespace: namespace}, app); err != nil { + if err := o.KubeClient.Get(ctx, client.ObjectKey{Name: name, Namespace: namespace}, app); err != nil { return nil, err } return &apisv1.ApplicationResponse{ @@ -99,8 +96,8 @@ func (o oamApplicationUsecaseImpl) GetOAMApplication(ctx context.Context, name, } // DeleteOAMApplication delete application -func (o oamApplicationUsecaseImpl) DeleteOAMApplication(ctx context.Context, name, namespace string) error { - return client.IgnoreNotFound(o.kubeClient.Delete(ctx, &v1beta1.Application{ +func (o oamApplicationServiceImpl) DeleteOAMApplication(ctx context.Context, name, namespace string) error { + return client.IgnoreNotFound(o.KubeClient.Delete(ctx, &v1beta1.Application{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, diff --git a/pkg/apiserver/rest/usecase/oam_application_test.go b/pkg/apiserver/domain/service/oam_application_test.go similarity index 88% rename from pkg/apiserver/rest/usecase/oam_application_test.go rename to pkg/apiserver/domain/service/oam_application_test.go index a8fff0087..533839c79 100644 --- a/pkg/apiserver/rest/usecase/oam_application_test.go +++ b/pkg/apiserver/domain/service/oam_application_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package usecase +package service import ( "context" @@ -29,13 +29,13 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - apiv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + apiv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" "github.com/oam-dev/kubevela/pkg/oam/util" "github.com/oam-dev/kubevela/pkg/utils/common" ) -var _ = Describe("Test oam application usecase function", func() { - var oamAppUsecase *oamApplicationUsecaseImpl +var _ = Describe("Test oam application service function", func() { + var oamAppService *oamApplicationServiceImpl var ctx context.Context var baseApp v1beta1.Application var ns corev1.Namespace @@ -45,8 +45,8 @@ var _ = Describe("Test oam application usecase function", func() { ctx = context.Background() namespace = randomNamespaceName("test-oam-app") ns = corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}} - oamAppUsecase = &oamApplicationUsecaseImpl{ - kubeClient: k8sClient, + oamAppService = &oamApplicationServiceImpl{ + KubeClient: k8sClient, } Expect(common.ReadYamlToObject("./testdata/example-app.yaml", &baseApp)).Should(BeNil()) @@ -77,7 +77,7 @@ var _ = Describe("Test oam application usecase function", func() { Policies: baseApp.Spec.Policies, Workflow: baseApp.Spec.Workflow, } - Expect(oamAppUsecase.CreateOrUpdateOAMApplication(ctx, req, appName, appNs)).Should(BeNil()) + Expect(oamAppService.CreateOrUpdateOAMApplication(ctx, req, appName, appNs)).Should(BeNil()) app := new(v1beta1.Application) Expect(k8sClient.Get(ctx, client.ObjectKey{Namespace: appNs, Name: appName}, app)).Should(BeNil()) @@ -89,7 +89,7 @@ var _ = Describe("Test oam application usecase function", func() { updateReq := apiv1.ApplicationRequest{ Components: baseApp.Spec.Components[1:], } - Expect(oamAppUsecase.CreateOrUpdateOAMApplication(ctx, updateReq, appName, appNs)).Should(BeNil()) + Expect(oamAppService.CreateOrUpdateOAMApplication(ctx, updateReq, appName, appNs)).Should(BeNil()) updatedApp := new(v1beta1.Application) Expect(k8sClient.Get(ctx, client.ObjectKey{Namespace: appNs, Name: appName}, updatedApp)).Should(BeNil()) @@ -100,7 +100,7 @@ var _ = Describe("Test oam application usecase function", func() { It("Test GetOAMApplication function", func() { By("test get an existed application") - resp, err := oamAppUsecase.GetOAMApplication(ctx, baseApp.Name, namespace) + resp, err := oamAppService.GetOAMApplication(ctx, baseApp.Name, namespace) Expect(err).Should(BeNil()) Expect(resp.Spec.Components).Should(Equal(baseApp.Spec.Components)) @@ -113,7 +113,7 @@ var _ = Describe("Test oam application usecase function", func() { app := new(v1beta1.Application) Expect(k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: baseApp.Name}, app)).Should(BeNil()) - Expect(oamAppUsecase.DeleteOAMApplication(ctx, baseApp.Name, namespace)).Should(BeNil()) + Expect(oamAppService.DeleteOAMApplication(ctx, baseApp.Name, namespace)).Should(BeNil()) err := k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: baseApp.Name}, app) Expect(kerrors.IsNotFound(err)).Should(BeTrue()) }) diff --git a/pkg/apiserver/rest/usecase/project.go b/pkg/apiserver/domain/service/project.go similarity index 80% rename from pkg/apiserver/rest/usecase/project.go rename to pkg/apiserver/domain/service/project.go index 9f4d5cf08..f86f14c01 100644 --- a/pkg/apiserver/rest/usecase/project.go +++ b/pkg/apiserver/domain/service/project.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -33,18 +33,18 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/repository" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/multicluster" image "github.com/oam-dev/kubevela/pkg/utils/imageregistry" ) -// ProjectUsecase project manage usecase. -type ProjectUsecase interface { +// ProjectService project manage service. +type ProjectService interface { GetProject(ctx context.Context, projectName string) (*model.Project, error) DetailProject(ctx context.Context, projectName string) (*apisv1.ProjectBase, error) ListProjects(ctx context.Context, page, pageSize int) (*apisv1.ListProjectResponse, error) @@ -61,32 +61,27 @@ type ProjectUsecase interface { ValidateImage(ctx context.Context, projectName, image string) (*apisv1.ImageResponse, error) } -type projectUsecaseImpl struct { - ds datastore.DataStore - k8sClient client.Client - rbacUsecase RBACUsecase +type projectServiceImpl struct { + Store datastore.DataStore `inject:"datastore"` + K8sClient client.Client `inject:"kubeClient"` + RbacService RBACService `inject:""` } -// NewProjectUsecase new project usecase -func NewProjectUsecase(ds datastore.DataStore, rbacUsecase RBACUsecase) ProjectUsecase { - k8sClient, err := clients.GetKubeClient() - if err != nil { - log.Logger.Fatalf("get k8sClient failure: %s", err.Error()) - } - p := &projectUsecaseImpl{ds: ds, k8sClient: k8sClient, rbacUsecase: rbacUsecase} - return p +// NewProjectService new project service +func NewProjectService() ProjectService { + return &projectServiceImpl{} } // Init init default data -func (p *projectUsecaseImpl) Init(ctx context.Context) error { +func (p *projectServiceImpl) Init(ctx context.Context) error { return p.InitDefaultProjectEnvTarget(ctx, model.DefaultInitNamespace) } // initDefaultProjectEnvTarget will initialize a default project with a default env that contain a default target // the default env and default target both using the `default` namespace in control plane cluster -func (p *projectUsecaseImpl) InitDefaultProjectEnvTarget(ctx context.Context, defaultNamespace string) error { +func (p *projectServiceImpl) InitDefaultProjectEnvTarget(ctx context.Context, defaultNamespace string) error { var project = model.Project{} - entities, err := p.ds.List(ctx, &project, &datastore.ListOptions{FilterOptions: datastore.FilterOptions{ + entities, err := p.Store.List(ctx, &project, &datastore.ListOptions{FilterOptions: datastore.FilterOptions{ IsNotExist: []datastore.IsNotExistQueryOption{ { Key: "owner", @@ -101,12 +96,12 @@ func (p *projectUsecaseImpl) InitDefaultProjectEnvTarget(ctx context.Context, de pro := project.(*model.Project) var init = pro.Owner == "" pro.Owner = model.DefaultAdminUserName - if err := p.ds.Put(ctx, pro); err != nil { + if err := p.Store.Put(ctx, pro); err != nil { return err } // owner is empty, it is old data if init { - if err := p.rbacUsecase.InitDefaultRoleAndUsersForProject(ctx, pro); err != nil { + if err := p.RbacService.InitDefaultRoleAndUsersForProject(ctx, pro); err != nil { return fmt.Errorf("init default role and users for project %s failure %w", pro.Name, err) } } @@ -114,17 +109,17 @@ func (p *projectUsecaseImpl) InitDefaultProjectEnvTarget(ctx context.Context, de return nil } - count, _ := p.ds.Count(ctx, &project, nil) + count, _ := p.Store.Count(ctx, &project, nil) if count > 0 { return nil } log.Logger.Info("no default project found, adding a default project with default env and target") - if err := createTargetNamespace(ctx, p.k8sClient, multicluster.ClusterLocalName, defaultNamespace, model.DefaultInitName); err != nil { + if err := repository.CreateTargetNamespace(ctx, p.K8sClient, multicluster.ClusterLocalName, defaultNamespace, model.DefaultInitName); err != nil { return fmt.Errorf("initialize default target namespace failed %w", err) } // initialize default target first - err = createTarget(ctx, p.ds, &model.Target{ + err = repository.CreateTarget(ctx, p.Store, &model.Target{ Name: model.DefaultInitName, Alias: "Default", Description: model.DefaultTargetDescription, @@ -139,7 +134,7 @@ func (p *projectUsecaseImpl) InitDefaultProjectEnvTarget(ctx context.Context, de } // initialize default target first - err = createEnv(ctx, p.k8sClient, p.ds, &model.Env{ + err = repository.CreateEnv(ctx, p.K8sClient, p.Store, &model.Env{ Name: model.DefaultInitName, Alias: "Default", Description: model.DefaultEnvDescription, @@ -149,7 +144,6 @@ func (p *projectUsecaseImpl) InitDefaultProjectEnvTarget(ctx context.Context, de }) // for idempotence, ignore default env already exist error if err != nil && errors.Is(err, bcode.ErrEnvAlreadyExists) { - return fmt.Errorf("initialize default environment failed %w", err) } @@ -166,9 +160,9 @@ func (p *projectUsecaseImpl) InitDefaultProjectEnvTarget(ctx context.Context, de } // GetProject get project -func (p *projectUsecaseImpl) GetProject(ctx context.Context, projectName string) (*model.Project, error) { +func (p *projectServiceImpl) GetProject(ctx context.Context, projectName string) (*model.Project, error) { project := &model.Project{Name: projectName} - if err := p.ds.Get(ctx, project); err != nil { + if err := p.Store.Get(ctx, project); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil, bcode.ErrProjectIsNotExist } @@ -177,14 +171,14 @@ func (p *projectUsecaseImpl) GetProject(ctx context.Context, projectName string) return project, nil } -func (p *projectUsecaseImpl) DetailProject(ctx context.Context, projectName string) (*apisv1.ProjectBase, error) { +func (p *projectServiceImpl) DetailProject(ctx context.Context, projectName string) (*apisv1.ProjectBase, error) { project, err := p.GetProject(ctx, projectName) if err != nil { return nil, err } var user = &model.User{Name: project.Owner} if project.Owner != "" { - if err := p.ds.Get(ctx, user); err != nil { + if err := p.Store.Get(ctx, user); err != nil { log.Logger.Warnf("get project owner %s info failure %s", project.Owner, err.Error()) } } @@ -215,11 +209,11 @@ func listProjects(ctx context.Context, ds datastore.DataStore, page, pageSize in return &apisv1.ListProjectResponse{Projects: projects, Total: total}, nil } -func (p *projectUsecaseImpl) ListUserProjects(ctx context.Context, userName string) ([]*apisv1.ProjectBase, error) { +func (p *projectServiceImpl) ListUserProjects(ctx context.Context, userName string) ([]*apisv1.ProjectBase, error) { var projectUser = model.ProjectUser{ Username: userName, } - entities, err := p.ds.List(ctx, &projectUser, nil) + entities, err := p.Store.List(ctx, &projectUser, nil) if err != nil { return nil, err } @@ -230,7 +224,7 @@ func (p *projectUsecaseImpl) ListUserProjects(ctx context.Context, userName stri if len(projectNames) == 0 { return []*apisv1.ProjectBase{}, nil } - projectEntities, err := p.ds.List(ctx, &model.Project{}, &datastore.ListOptions{FilterOptions: datastore.FilterOptions{In: []datastore.InQueryOption{{ + projectEntities, err := p.Store.List(ctx, &model.Project{}, &datastore.ListOptions{FilterOptions: datastore.FilterOptions{In: []datastore.InQueryOption{{ Key: "name", Values: projectNames, }}}}) @@ -245,18 +239,18 @@ func (p *projectUsecaseImpl) ListUserProjects(ctx context.Context, userName stri } // ListProjects list projects -func (p *projectUsecaseImpl) ListProjects(ctx context.Context, page, pageSize int) (*apisv1.ListProjectResponse, error) { - return listProjects(ctx, p.ds, page, pageSize) +func (p *projectServiceImpl) ListProjects(ctx context.Context, page, pageSize int) (*apisv1.ListProjectResponse, error) { + return listProjects(ctx, p.Store, page, pageSize) } // DeleteProject delete a project -func (p *projectUsecaseImpl) DeleteProject(ctx context.Context, name string) error { +func (p *projectServiceImpl) DeleteProject(ctx context.Context, name string) error { _, err := p.GetProject(ctx, name) if err != nil { return err } - count, err := p.ds.Count(ctx, &model.Application{Project: name}, nil) + count, err := p.Store.Count(ctx, &model.Application{Project: name}, nil) if err != nil { return err } @@ -264,7 +258,7 @@ func (p *projectUsecaseImpl) DeleteProject(ctx context.Context, name string) err return bcode.ErrProjectDenyDeleteByApplication } - count, err = p.ds.Count(ctx, &model.Target{Project: name}, nil) + count, err = p.Store.Count(ctx, &model.Target{Project: name}, nil) if err != nil { return err } @@ -272,7 +266,7 @@ func (p *projectUsecaseImpl) DeleteProject(ctx context.Context, name string) err return bcode.ErrProjectDenyDeleteByTarget } - count, err = p.ds.Count(ctx, &model.Env{Project: name}, nil) + count, err = p.Store.Count(ctx, &model.Env{Project: name}, nil) if err != nil { return err } @@ -288,32 +282,32 @@ func (p *projectUsecaseImpl) DeleteProject(ctx context.Context, name string) err } } - roles, _ := p.rbacUsecase.ListRole(ctx, name, 0, 0) + roles, _ := p.RbacService.ListRole(ctx, name, 0, 0) for _, role := range roles.Roles { - err := p.rbacUsecase.DeleteRole(ctx, name, role.Name) + err := p.RbacService.DeleteRole(ctx, name, role.Name) if err != nil { return err } } - permissions, _ := p.rbacUsecase.ListPermissions(ctx, name) + permissions, _ := p.RbacService.ListPermissions(ctx, name) for _, perm := range permissions { - err := p.rbacUsecase.DeletePermission(ctx, name, perm.Name) + err := p.RbacService.DeletePermission(ctx, name, perm.Name) if err != nil { return err } } - if err := p.ds.Delete(ctx, &model.Project{Name: name}); err != nil { + if err := p.Store.Delete(ctx, &model.Project{Name: name}); err != nil { return err } // delete config-sync application - return destroySyncConfigsApp(ctx, p.k8sClient, name) + return destroySyncConfigsApp(ctx, p.K8sClient, name) } // CreateProject create project -func (p *projectUsecaseImpl) CreateProject(ctx context.Context, req apisv1.CreateProjectRequest) (*apisv1.ProjectBase, error) { +func (p *projectServiceImpl) CreateProject(ctx context.Context, req apisv1.CreateProjectRequest) (*apisv1.ProjectBase, error) { - exist, err := p.ds.IsExist(ctx, &model.Project{Name: req.Name}) + exist, err := p.Store.IsExist(ctx, &model.Project{Name: req.Name}) if err != nil { log.Logger.Errorf("check project name is exist failure %s", err.Error()) return nil, bcode.ErrProjectIsExist @@ -330,7 +324,7 @@ func (p *projectUsecaseImpl) CreateProject(ctx context.Context, req apisv1.Creat } var user = &model.User{Name: owner} if owner != "" { - if err := p.ds.Get(ctx, user); err != nil { + if err := p.Store.Get(ctx, user); err != nil { return nil, bcode.ErrProjectOwnerIsNotExist } } @@ -342,11 +336,11 @@ func (p *projectUsecaseImpl) CreateProject(ctx context.Context, req apisv1.Creat Owner: owner, } - if err := p.ds.Add(ctx, newProject); err != nil { + if err := p.Store.Add(ctx, newProject); err != nil { return nil, err } - if err := p.rbacUsecase.InitDefaultRoleAndUsersForProject(ctx, newProject); err != nil { + if err := p.RbacService.InitDefaultRoleAndUsersForProject(ctx, newProject); err != nil { log.Logger.Errorf("init default role and users for project failure %s", err.Error()) } @@ -354,7 +348,7 @@ func (p *projectUsecaseImpl) CreateProject(ctx context.Context, req apisv1.Creat } // UpdateProject update project -func (p *projectUsecaseImpl) UpdateProject(ctx context.Context, projectName string, req apisv1.UpdateProjectRequest) (*apisv1.ProjectBase, error) { +func (p *projectServiceImpl) UpdateProject(ctx context.Context, projectName string, req apisv1.UpdateProjectRequest) (*apisv1.ProjectBase, error) { project, err := p.GetProject(ctx, projectName) if err != nil { return nil, err @@ -363,7 +357,7 @@ func (p *projectUsecaseImpl) UpdateProject(ctx context.Context, projectName stri project.Description = req.Description var user = &model.User{Name: req.Owner} if req.Owner != "" { - if err := p.ds.Get(ctx, user); err != nil { + if err := p.Store.Get(ctx, user); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil, bcode.ErrProjectOwnerIsNotExist } @@ -371,18 +365,18 @@ func (p *projectUsecaseImpl) UpdateProject(ctx context.Context, projectName stri } project.Owner = req.Owner } - err = p.ds.Put(ctx, project) + err = p.Store.Put(ctx, project) if err != nil { return nil, err } return ConvertProjectModel2Base(project, user), nil } -func (p *projectUsecaseImpl) ListProjectUser(ctx context.Context, projectName string, page, pageSize int) (*apisv1.ListProjectUsersResponse, error) { +func (p *projectServiceImpl) ListProjectUser(ctx context.Context, projectName string, page, pageSize int) (*apisv1.ListProjectUsersResponse, error) { var projectUser = model.ProjectUser{ ProjectName: projectName, } - entities, err := p.ds.List(ctx, &projectUser, &datastore.ListOptions{Page: page, PageSize: pageSize, SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}}) + entities, err := p.Store.List(ctx, &projectUser, &datastore.ListOptions{Page: page, PageSize: pageSize, SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}}) if err != nil { return nil, err } @@ -390,7 +384,7 @@ func (p *projectUsecaseImpl) ListProjectUser(ctx context.Context, projectName st for _, entity := range entities { res.Users = append(res.Users, ConvertProjectUserModel2Base(entity.(*model.ProjectUser))) } - count, err := p.ds.Count(ctx, &projectUser, nil) + count, err := p.Store.Count(ctx, &projectUser, nil) if err != nil { return nil, err } @@ -398,7 +392,7 @@ func (p *projectUsecaseImpl) ListProjectUser(ctx context.Context, projectName st return &res, nil } -func (p *projectUsecaseImpl) AddProjectUser(ctx context.Context, projectName string, req apisv1.AddProjectUserRequest) (*apisv1.ProjectUserBase, error) { +func (p *projectServiceImpl) AddProjectUser(ctx context.Context, projectName string, req apisv1.AddProjectUserRequest) (*apisv1.ProjectUserBase, error) { project, err := p.GetProject(ctx, projectName) if err != nil { return nil, err @@ -409,7 +403,7 @@ func (p *projectUsecaseImpl) AddProjectUser(ctx context.Context, projectName str Name: role, Project: projectName, } - if err := p.ds.Get(ctx, &projectUser); err != nil { + if err := p.Store.Get(ctx, &projectUser); err != nil { return nil, bcode.ErrProjectRoleCheckFailure } if projectUser.Project != "" && projectUser.Project != projectName { @@ -421,7 +415,7 @@ func (p *projectUsecaseImpl) AddProjectUser(ctx context.Context, projectName str ProjectName: project.Name, UserRoles: req.UserRoles, } - if err := p.ds.Add(ctx, &projectUser); err != nil { + if err := p.Store.Add(ctx, &projectUser); err != nil { if errors.Is(err, datastore.ErrRecordExist) { return nil, bcode.ErrProjectUserExist } @@ -430,7 +424,7 @@ func (p *projectUsecaseImpl) AddProjectUser(ctx context.Context, projectName str return ConvertProjectUserModel2Base(&projectUser), nil } -func (p *projectUsecaseImpl) DeleteProjectUser(ctx context.Context, projectName string, userName string) error { +func (p *projectServiceImpl) DeleteProjectUser(ctx context.Context, projectName string, userName string) error { project, err := p.GetProject(ctx, projectName) if err != nil { return err @@ -439,7 +433,7 @@ func (p *projectUsecaseImpl) DeleteProjectUser(ctx context.Context, projectName Username: userName, ProjectName: project.Name, } - if err := p.ds.Delete(ctx, &projectUser); err != nil { + if err := p.Store.Delete(ctx, &projectUser); err != nil { if errors.Is(err, datastore.ErrRecordExist) { return bcode.ErrProjectUserExist } @@ -448,7 +442,7 @@ func (p *projectUsecaseImpl) DeleteProjectUser(ctx context.Context, projectName return nil } -func (p *projectUsecaseImpl) UpdateProjectUser(ctx context.Context, projectName string, userName string, req apisv1.UpdateProjectUserRequest) (*apisv1.ProjectUserBase, error) { +func (p *projectServiceImpl) UpdateProjectUser(ctx context.Context, projectName string, userName string, req apisv1.UpdateProjectUserRequest) (*apisv1.ProjectUserBase, error) { project, err := p.GetProject(ctx, projectName) if err != nil { return nil, err @@ -459,7 +453,7 @@ func (p *projectUsecaseImpl) UpdateProjectUser(ctx context.Context, projectName Name: role, Project: projectName, } - if err := p.ds.Get(ctx, &projectUser); err != nil { + if err := p.Store.Get(ctx, &projectUser); err != nil { return nil, bcode.ErrProjectRoleCheckFailure } if projectUser.Project != "" && projectUser.Project != projectName { @@ -470,26 +464,26 @@ func (p *projectUsecaseImpl) UpdateProjectUser(ctx context.Context, projectName Username: userName, ProjectName: project.Name, } - if err := p.ds.Get(ctx, &projectUser); err != nil { + if err := p.Store.Get(ctx, &projectUser); err != nil { if errors.Is(err, datastore.ErrRecordExist) { return nil, bcode.ErrProjectUserExist } return nil, err } projectUser.UserRoles = req.UserRoles - if err := p.ds.Put(ctx, &projectUser); err != nil { + if err := p.Store.Put(ctx, &projectUser); err != nil { return nil, err } return ConvertProjectUserModel2Base(&projectUser), nil } -func (p *projectUsecaseImpl) GetConfigs(ctx context.Context, projectName, configType string) ([]*apisv1.Config, error) { +func (p *projectServiceImpl) GetConfigs(ctx context.Context, projectName, configType string) ([]*apisv1.Config, error) { var ( configs []*apisv1.Config legacyTerraformProviders []*apisv1.Config apps = &v1beta1.ApplicationList{} ) - if err := p.k8sClient.List(ctx, apps, client.InNamespace(types.DefaultKubeVelaNS), + if err := p.K8sClient.List(ctx, apps, client.InNamespace(types.DefaultKubeVelaNS), client.MatchingLabels{ model.LabelSourceOfTruth: model.FromInner, types.LabelConfigCatalog: types.VelaCoreConfig, @@ -500,7 +494,7 @@ func (p *projectUsecaseImpl) GetConfigs(ctx context.Context, projectName, config if configType == types.TerraformProvider || configType == "" { // legacy providers var providers = &terraformapi.ProviderList{} - if err := p.k8sClient.List(ctx, providers, client.InNamespace(types.DefaultAppNamespace)); err != nil { + if err := p.K8sClient.List(ctx, providers, client.InNamespace(types.DefaultAppNamespace)); err != nil { return nil, err } for _, p := range providers.Items { @@ -559,7 +553,7 @@ func (p *projectUsecaseImpl) GetConfigs(ctx context.Context, projectName, config for i, c := range configs { if c.ConfigType != "" { d := &v1beta1.ComponentDefinition{} - err := p.k8sClient.Get(ctx, client.ObjectKey{Namespace: types.DefaultKubeVelaNS, Name: c.ConfigType}, d) + err := p.K8sClient.Get(ctx, client.ObjectKey{Namespace: types.DefaultKubeVelaNS, Name: c.ConfigType}, d) if err != nil { klog.InfoS("failed to get component definition", "ComponentDefinition", configType, "err", err) } else { @@ -619,8 +613,8 @@ func retrieveConfigFromApplication(a v1beta1.Application, project string) *apisv } } -func (p *projectUsecaseImpl) ValidateImage(ctx context.Context, projectName, image string) (*apisv1.ImageResponse, error) { - return validateImage(ctx, p.k8sClient, projectName, image) +func (p *projectServiceImpl) ValidateImage(ctx context.Context, projectName, image string) (*apisv1.ImageResponse, error) { + return validateImage(ctx, p.K8sClient, projectName, image) } func validateImage(ctx context.Context, k8sClient client.Client, project, imageName string) (*apisv1.ImageResponse, error) { diff --git a/pkg/apiserver/rest/usecase/project_test.go b/pkg/apiserver/domain/service/project_test.go similarity index 86% rename from pkg/apiserver/rest/usecase/project_test.go rename to pkg/apiserver/domain/service/project_test.go index 4a7fb55fa..04768cc39 100644 --- a/pkg/apiserver/rest/usecase/project_test.go +++ b/pkg/apiserver/domain/service/project_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -36,42 +36,42 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" velatypes "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" "github.com/oam-dev/kubevela/pkg/multicluster" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/util" ) -var _ = Describe("Test project usecase functions", func() { +var _ = Describe("Test project service functions", func() { var ( - projectUsecase *projectUsecaseImpl - envImpl *envUsecaseImpl - userUsecase *userUsecaseImpl - targetImpl *targetUsecaseImpl + projectService *projectServiceImpl + envImpl *envServiceImpl + userService *userServiceImpl + targetImpl *targetServiceImpl defaultNamespace = "project-default-ns1-test" ) BeforeEach(func() { ds, err := NewDatastore(datastore.Config{Type: "kubeapi", Database: "target-test-kubevela"}) Expect(ds).ToNot(BeNil()) Expect(err).Should(BeNil()) - userUsecase = &userUsecaseImpl{ds: ds, k8sClient: k8sClient} + userService = &userServiceImpl{Store: ds, K8sClient: k8sClient} var ns = corev1.Namespace{} ns.Name = defaultNamespace err = k8sClient.Create(context.TODO(), &ns) Expect(err).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) - projectUsecase = &projectUsecaseImpl{k8sClient: k8sClient, ds: ds, rbacUsecase: &rbacUsecaseImpl{ds: ds}} - pp, err := projectUsecase.ListProjects(context.TODO(), 0, 0) + projectService = &projectServiceImpl{K8sClient: k8sClient, Store: ds, RbacService: &rbacServiceImpl{Store: ds}} + pp, err := projectService.ListProjects(context.TODO(), 0, 0) Expect(err).Should(BeNil()) // reset all projects for _, p := range pp.Projects { - _ = projectUsecase.DeleteProject(context.TODO(), p.Name) + _ = projectService.DeleteProject(context.TODO(), p.Name) } - envImpl = &envUsecaseImpl{kubeClient: k8sClient, ds: ds, projectUsecase: projectUsecase} + envImpl = &envServiceImpl{KubeClient: k8sClient, Store: ds, ProjectService: projectService} ctx := context.WithValue(context.TODO(), &apisv1.CtxKeyUser, "admin") envs, err := envImpl.ListEnvs(ctx, 0, 0, apisv1.ListEnvOptions{}) Expect(err).Should(BeNil()) @@ -79,7 +79,7 @@ var _ = Describe("Test project usecase functions", func() { for _, e := range envs.Envs { _ = envImpl.DeleteEnv(context.TODO(), e.Name) } - targetImpl = &targetUsecaseImpl{k8sClient: k8sClient, ds: ds} + targetImpl = &targetServiceImpl{K8sClient: k8sClient, Store: ds} targets, err := targetImpl.ListTargets(context.TODO(), 0, 0, "") Expect(err).Should(BeNil()) // reset all projects @@ -94,11 +94,11 @@ var _ = Describe("Test project usecase functions", func() { ns.Name = velatypes.DefaultKubeVelaNS err := k8sClient.Create(context.TODO(), &ns) Expect(err).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) - err = userUsecase.Init(context.TODO()) + err = userService.Init(context.TODO()) Expect(err).Should(BeNil()) // init default project - err = projectUsecase.InitDefaultProjectEnvTarget(context.WithValue(context.TODO(), &apisv1.CtxKeyUser, model.DefaultAdminUserName), defaultNamespace) + err = projectService.InitDefaultProjectEnvTarget(context.WithValue(context.TODO(), &apisv1.CtxKeyUser, model.DefaultAdminUserName), defaultNamespace) Expect(err).Should(BeNil()) By("test env created") var namespace corev1.Namespace @@ -112,7 +112,7 @@ var _ = Describe("Test project usecase functions", func() { Expect(cmp.Diff(namespace.Labels[oam.LabelRuntimeNamespaceUsage], oam.VelaNamespaceUsageTarget)).Should(BeEmpty()) By("check project created") - dp, err := projectUsecase.GetProject(context.TODO(), model.DefaultInitName) + dp, err := projectService.GetProject(context.TODO(), model.DefaultInitName) Expect(err).Should(BeNil()) Expect(dp.Alias).Should(BeEquivalentTo("Default")) Expect(dp.Description).Should(BeEquivalentTo(model.DefaultProjectDescription)) @@ -151,12 +151,12 @@ var _ = Describe("Test project usecase functions", func() { Name: "test-project", Description: "this is a project description", } - base, err := projectUsecase.CreateProject(context.TODO(), req) + base, err := projectService.CreateProject(context.TODO(), req) Expect(err).Should(BeNil()) Expect(cmp.Diff(base.Description, req.Description)).Should(BeEmpty()) - _, err = projectUsecase.ListProjects(context.TODO(), 0, 0) + _, err = projectService.ListProjects(context.TODO(), 0, 0) Expect(err).Should(BeNil()) - projectUsecase.DeleteProject(context.TODO(), "test-project") + projectService.DeleteProject(context.TODO(), "test-project") }) It("Test Update project function", func() { @@ -176,10 +176,10 @@ var _ = Describe("Test project usecase functions", func() { }, } Expect(k8sClient.Create(context.TODO(), app1)).Should(BeNil()) - _, err := projectUsecase.CreateProject(context.TODO(), req) + _, err := projectService.CreateProject(context.TODO(), req) Expect(err).Should(BeNil()) - base, err := projectUsecase.UpdateProject(context.TODO(), "test-project", apisv1.UpdateProjectRequest{ + base, err := projectService.UpdateProject(context.TODO(), "test-project", apisv1.UpdateProjectRequest{ Alias: "Change alias", Description: "Change description", Owner: "admin", @@ -189,13 +189,13 @@ var _ = Describe("Test project usecase functions", func() { Expect(base.Description).Should(BeEquivalentTo("Change description")) Expect(base.Owner.Alias).Should(BeEquivalentTo("Administrator")) - _, err = projectUsecase.UpdateProject(context.TODO(), "test-project", apisv1.UpdateProjectRequest{ + _, err = projectService.UpdateProject(context.TODO(), "test-project", apisv1.UpdateProjectRequest{ Alias: "Change alias", Description: "Change description", Owner: "admin-error", }) Expect(err).Should(BeEquivalentTo(bcode.ErrProjectOwnerIsNotExist)) - err = projectUsecase.DeleteProject(context.TODO(), "test-project") + err = projectService.DeleteProject(context.TODO(), "test-project") Expect(err).Should(BeNil()) }) @@ -204,10 +204,10 @@ var _ = Describe("Test project usecase functions", func() { Name: "test-project", Description: "this is a project description", } - _, err := projectUsecase.CreateProject(context.TODO(), req) + _, err := projectService.CreateProject(context.TODO(), req) Expect(err).Should(BeNil()) - _, err = projectUsecase.AddProjectUser(context.TODO(), "test-project", apisv1.AddProjectUserRequest{ + _, err = projectService.AddProjectUser(context.TODO(), "test-project", apisv1.AddProjectUserRequest{ UserName: "admin", UserRoles: []string{"project-admin"}, }) @@ -219,21 +219,21 @@ var _ = Describe("Test project usecase functions", func() { Name: "test-project", Description: "this is a project description", } - _, err := projectUsecase.CreateProject(context.TODO(), req) + _, err := projectService.CreateProject(context.TODO(), req) Expect(err).Should(BeNil()) - _, err = projectUsecase.AddProjectUser(context.TODO(), "test-project", apisv1.AddProjectUserRequest{ + _, err = projectService.AddProjectUser(context.TODO(), "test-project", apisv1.AddProjectUserRequest{ UserName: "admin", UserRoles: []string{"project-admin"}, }) Expect(err).Should(BeNil()) - _, err = projectUsecase.UpdateProjectUser(context.TODO(), "test-project", "admin", apisv1.UpdateProjectUserRequest{ + _, err = projectService.UpdateProjectUser(context.TODO(), "test-project", "admin", apisv1.UpdateProjectUserRequest{ UserRoles: []string{"project-admin", "app-developer"}, }) Expect(err).Should(BeNil()) - _, err = projectUsecase.UpdateProjectUser(context.TODO(), "test-project", "admin", apisv1.UpdateProjectUserRequest{ + _, err = projectService.UpdateProjectUser(context.TODO(), "test-project", "admin", apisv1.UpdateProjectUserRequest{ UserRoles: []string{"project-admin", "app-developer", "xxx"}, }) Expect(err).Should(BeEquivalentTo(bcode.ErrProjectRoleCheckFailure)) @@ -257,23 +257,23 @@ var _ = Describe("Test project usecase functions", func() { } Expect(k8sClient.Create(context.TODO(), app1)).Should(BeNil()) - _, err := projectUsecase.CreateProject(context.TODO(), req) + _, err := projectService.CreateProject(context.TODO(), req) Expect(err).Should(BeNil()) - _, err = projectUsecase.AddProjectUser(context.TODO(), "test-project", apisv1.AddProjectUserRequest{ + _, err = projectService.AddProjectUser(context.TODO(), "test-project", apisv1.AddProjectUserRequest{ UserName: "admin", UserRoles: []string{"project-admin"}, }) Expect(err).Should(BeNil()) - err = projectUsecase.DeleteProjectUser(context.TODO(), "test-project", "admin") + err = projectService.DeleteProjectUser(context.TODO(), "test-project", "admin") Expect(err).Should(BeNil()) - err = projectUsecase.DeleteProject(context.TODO(), "test-project") + err = projectService.DeleteProject(context.TODO(), "test-project") Expect(err).Should(BeNil()) - perms, err := projectUsecase.rbacUsecase.ListPermissions(context.TODO(), "test-project") + perms, err := projectService.RbacService.ListPermissions(context.TODO(), "test-project") Expect(err).Should(BeNil()) Expect(len(perms)).Should(BeEquivalentTo(0)) - roles, err := projectUsecase.rbacUsecase.ListRole(context.TODO(), "test-project", 0, 0) + roles, err := projectService.RbacService.ListRole(context.TODO(), "test-project", 0, 0) Expect(err).Should(BeNil()) Expect(roles.Total).Should(BeEquivalentTo(0)) }) @@ -357,12 +357,12 @@ func TestProjectGetConfigs(t *testing.T) { k8sClient := fake.NewClientBuilder().WithScheme(s).WithObjects(app1, app2, app3, provider1, provider2).Build() - h := &projectUsecaseImpl{k8sClient: k8sClient} + h := &projectServiceImpl{K8sClient: k8sClient} type args struct { projectName string configType string - h ProjectUsecase + h ProjectService } type want struct { @@ -520,7 +520,7 @@ func TestValidateImage(t *testing.T) { }, } k8sClient1 := fake.NewClientBuilder().WithScheme(s).WithObjects(s1).Build() - h1 := &projectUsecaseImpl{k8sClient: k8sClient1} + h1 := &projectServiceImpl{K8sClient: k8sClient1} s2 := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ @@ -539,12 +539,12 @@ func TestValidateImage(t *testing.T) { } k8sClient2 := fake.NewClientBuilder().WithScheme(s).WithObjects(s2).Build() - h2 := &projectUsecaseImpl{k8sClient: k8sClient2} + h2 := &projectServiceImpl{K8sClient: k8sClient2} type args struct { project string imageName string - h ProjectUsecase + h ProjectService } type want struct { diff --git a/pkg/apiserver/rest/usecase/rbac.go b/pkg/apiserver/domain/service/rbac.go similarity index 88% rename from pkg/apiserver/rest/usecase/rbac.go rename to pkg/apiserver/domain/service/rbac.go index 1d73fa99d..11c65812d 100644 --- a/pkg/apiserver/rest/usecase/rbac.go +++ b/pkg/apiserver/domain/service/rbac.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -26,11 +26,11 @@ import ( "github.com/emicklei/go-restful/v3" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/utils" ) @@ -311,12 +311,12 @@ func registerResourceAction(resource string, actions ...string) { } } -type rbacUsecaseImpl struct { - ds datastore.DataStore +type rbacServiceImpl struct { + Store datastore.DataStore `inject:"datastore"` } -// RBACUsecase implement RBAC-related business logic. -type RBACUsecase interface { +// RBACService implement RBAC-related business logic. +type RBACService interface { CheckPerm(resource string, actions ...string) func(req *restful.Request, res *restful.Response, chain *restful.FilterChain) GetUserPermissions(ctx context.Context, user *model.User, projectName string, withPlatform bool) ([]*model.Permission, error) CreateRole(ctx context.Context, projectName string, req apisv1.CreateRoleRequest) (*apisv1.RoleBase, error) @@ -330,16 +330,14 @@ type RBACUsecase interface { Init(ctx context.Context) error } -// NewRBACUsecase is the usecase service of RBAC -func NewRBACUsecase(ds datastore.DataStore) RBACUsecase { - rbacUsecase := &rbacUsecaseImpl{ - ds: ds, - } - return rbacUsecase +// NewRBACService is the service service of RBAC +func NewRBACService() RBACService { + rbacService := &rbacServiceImpl{} + return rbacService } -func (p *rbacUsecaseImpl) Init(ctx context.Context) error { - count, _ := p.ds.Count(ctx, &model.Permission{}, &datastore.FilterOptions{ +func (p *rbacServiceImpl) Init(ctx context.Context) error { + count, _ := p.Store.Count(ctx, &model.Permission{}, &datastore.FilterOptions{ IsNotExist: []datastore.IsNotExistQueryOption{ { Key: "project", @@ -364,18 +362,18 @@ func (p *rbacUsecaseImpl) Init(ctx context.Context) error { Alias: "Admin", Permissions: []string{"admin"}, }) - if err := p.ds.BatchAdd(context.Background(), batchData); err != nil { + if err := p.Store.BatchAdd(ctx, batchData); err != nil { return fmt.Errorf("init the platform perm policies failure %w", err) } return nil } // GetUserPermissions get user permission policies, if projectName is empty, will only get the platform permission policies -func (p *rbacUsecaseImpl) GetUserPermissions(ctx context.Context, user *model.User, projectName string, withPlatform bool) ([]*model.Permission, error) { +func (p *rbacServiceImpl) GetUserPermissions(ctx context.Context, user *model.User, projectName string, withPlatform bool) ([]*model.Permission, error) { var permissionNames []string var perms []*model.Permission if withPlatform && len(user.UserRoles) > 0 { - entities, err := p.ds.List(ctx, &model.Role{}, &datastore.ListOptions{FilterOptions: datastore.FilterOptions{ + entities, err := p.Store.List(ctx, &model.Role{}, &datastore.ListOptions{FilterOptions: datastore.FilterOptions{ In: []datastore.InQueryOption{ { Key: "name", @@ -405,11 +403,11 @@ func (p *rbacUsecaseImpl) GetUserPermissions(ctx context.Context, user *model.Us Username: user.Name, } var roles []string - if err := p.ds.Get(ctx, &projectUser); err == nil { + if err := p.Store.Get(ctx, &projectUser); err == nil { roles = append(roles, projectUser.UserRoles...) } if len(roles) > 0 { - entities, err := p.ds.List(ctx, &model.Role{Project: projectName}, &datastore.ListOptions{FilterOptions: datastore.FilterOptions{In: []datastore.InQueryOption{ + entities, err := p.Store.List(ctx, &model.Role{Project: projectName}, &datastore.ListOptions{FilterOptions: datastore.FilterOptions{In: []datastore.InQueryOption{ { Key: "name", Values: roles, @@ -431,12 +429,12 @@ func (p *rbacUsecaseImpl) GetUserPermissions(ctx context.Context, user *model.Us return perms, nil } -func (p *rbacUsecaseImpl) UpdatePermission(ctx context.Context, projetName string, permissionName string, req *apisv1.UpdatePermissionRequest) (*apisv1.PermissionBase, error) { +func (p *rbacServiceImpl) UpdatePermission(ctx context.Context, projetName string, permissionName string, req *apisv1.UpdatePermissionRequest) (*apisv1.PermissionBase, error) { perm := &model.Permission{ Project: projetName, Name: permissionName, } - err := p.ds.Get(ctx, perm) + err := p.Store.Get(ctx, perm) if err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil, bcode.ErrPermissionNotExist @@ -447,7 +445,7 @@ func (p *rbacUsecaseImpl) UpdatePermission(ctx context.Context, projetName strin perm.Alias = req.Alias perm.Resources = req.Resources perm.Effect = req.Effect - if err := p.ds.Put(ctx, perm); err != nil { + if err := p.Store.Put(ctx, perm); err != nil { return nil, err } return &apisv1.PermissionBase{ @@ -461,7 +459,7 @@ func (p *rbacUsecaseImpl) UpdatePermission(ctx context.Context, projetName strin }, nil } -func (p *rbacUsecaseImpl) listPermPolices(ctx context.Context, projectName string, permissionNames []string) ([]*model.Permission, error) { +func (p *rbacServiceImpl) listPermPolices(ctx context.Context, projectName string, permissionNames []string) ([]*model.Permission, error) { if len(permissionNames) == 0 { return []*model.Permission{}, nil } @@ -476,7 +474,7 @@ func (p *rbacUsecaseImpl) listPermPolices(ctx context.Context, projectName strin Key: "project", }) } - permEntities, err := p.ds.List(ctx, &model.Permission{Project: projectName}, &datastore.ListOptions{FilterOptions: filter}) + permEntities, err := p.Store.List(ctx, &model.Permission{Project: projectName}, &datastore.ListOptions{FilterOptions: filter}) if err != nil { return nil, err } @@ -487,7 +485,7 @@ func (p *rbacUsecaseImpl) listPermPolices(ctx context.Context, projectName strin return perms, nil } -func (p *rbacUsecaseImpl) CheckPerm(resource string, actions ...string) func(req *restful.Request, res *restful.Response, chain *restful.FilterChain) { +func (p *rbacServiceImpl) CheckPerm(resource string, actions ...string) func(req *restful.Request, res *restful.Response, chain *restful.FilterChain) { registerResourceAction(resource, actions...) f := func(req *restful.Request, res *restful.Response, chain *restful.FilterChain) { // get login user info @@ -497,7 +495,7 @@ func (p *rbacUsecaseImpl) CheckPerm(resource string, actions ...string) func(req return } user := &model.User{Name: userName} - if err := p.ds.Get(req.Request.Context(), user); err != nil { + if err := p.Store.Get(req.Request.Context(), user); err != nil { bcode.ReturnError(req, res, bcode.ErrUnauthorized) return } @@ -521,13 +519,13 @@ func (p *rbacUsecaseImpl) CheckPerm(resource string, actions ...string) func(req } if appName := req.PathParameter(ResourceMaps["project"].subResources["application"].pathName); appName != "" { app := &model.Application{Name: appName} - if err := p.ds.Get(req.Request.Context(), app); err == nil { + if err := p.Store.Get(req.Request.Context(), app); err == nil { return app.Project } } if envName := req.PathParameter(ResourceMaps["project"].subResources["environment"].pathName); envName != "" { env := &model.Env{Name: envName} - if err := p.ds.Get(req.Request.Context(), env); err == nil { + if err := p.Store.Get(req.Request.Context(), env); err == nil { return env.Project } } @@ -559,12 +557,12 @@ func (p *rbacUsecaseImpl) CheckPerm(resource string, actions ...string) func(req return f } -func (p *rbacUsecaseImpl) CreateRole(ctx context.Context, projectName string, req apisv1.CreateRoleRequest) (*apisv1.RoleBase, error) { +func (p *rbacServiceImpl) CreateRole(ctx context.Context, projectName string, req apisv1.CreateRoleRequest) (*apisv1.RoleBase, error) { if projectName != "" { var project = model.Project{ Name: projectName, } - if err := p.ds.Get(ctx, &project); err != nil { + if err := p.Store.Get(ctx, &project); err != nil { return nil, bcode.ErrProjectIsNotExist } } @@ -581,7 +579,7 @@ func (p *rbacUsecaseImpl) CreateRole(ctx context.Context, projectName string, re Project: projectName, Permissions: req.Permissions, } - if err := p.ds.Add(ctx, &role); err != nil { + if err := p.Store.Add(ctx, &role); err != nil { if errors.Is(err, datastore.ErrRecordExist) { return nil, bcode.ErrRoleIsExist } @@ -590,12 +588,12 @@ func (p *rbacUsecaseImpl) CreateRole(ctx context.Context, projectName string, re return ConvertRole2Model(&role, policies), nil } -func (p *rbacUsecaseImpl) DeleteRole(ctx context.Context, projectName, roleName string) error { +func (p *rbacServiceImpl) DeleteRole(ctx context.Context, projectName, roleName string) error { var role = model.Role{ Name: roleName, Project: projectName, } - if err := p.ds.Delete(ctx, &role); err != nil { + if err := p.Store.Delete(ctx, &role); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return bcode.ErrRoleIsNotExist } @@ -604,12 +602,12 @@ func (p *rbacUsecaseImpl) DeleteRole(ctx context.Context, projectName, roleName return nil } -func (p *rbacUsecaseImpl) DeletePermission(ctx context.Context, projectName, permName string) error { +func (p *rbacServiceImpl) DeletePermission(ctx context.Context, projectName, permName string) error { var perm = model.Permission{ Name: permName, Project: projectName, } - if err := p.ds.Delete(ctx, &perm); err != nil { + if err := p.Store.Delete(ctx, &perm); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return bcode.ErrRoleIsNotExist } @@ -618,12 +616,12 @@ func (p *rbacUsecaseImpl) DeletePermission(ctx context.Context, projectName, per return nil } -func (p *rbacUsecaseImpl) UpdateRole(ctx context.Context, projectName, roleName string, req apisv1.UpdateRoleRequest) (*apisv1.RoleBase, error) { +func (p *rbacServiceImpl) UpdateRole(ctx context.Context, projectName, roleName string, req apisv1.UpdateRoleRequest) (*apisv1.RoleBase, error) { if projectName != "" { var project = model.Project{ Name: projectName, } - if err := p.ds.Get(ctx, &project); err != nil { + if err := p.Store.Get(ctx, &project); err != nil { return nil, bcode.ErrProjectIsNotExist } } @@ -638,7 +636,7 @@ func (p *rbacUsecaseImpl) UpdateRole(ctx context.Context, projectName, roleName Name: roleName, Project: projectName, } - if err := p.ds.Get(ctx, &role); err != nil { + if err := p.Store.Get(ctx, &role); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil, bcode.ErrRoleIsNotExist } @@ -646,13 +644,13 @@ func (p *rbacUsecaseImpl) UpdateRole(ctx context.Context, projectName, roleName } role.Alias = req.Alias role.Permissions = req.Permissions - if err := p.ds.Put(ctx, &role); err != nil { + if err := p.Store.Put(ctx, &role); err != nil { return nil, err } return ConvertRole2Model(&role, policies), nil } -func (p *rbacUsecaseImpl) ListRole(ctx context.Context, projectName string, page, pageSize int) (*apisv1.ListRolesResponse, error) { +func (p *rbacServiceImpl) ListRole(ctx context.Context, projectName string, page, pageSize int) (*apisv1.ListRolesResponse, error) { var role = model.Role{ Project: projectName, } @@ -662,7 +660,7 @@ func (p *rbacUsecaseImpl) ListRole(ctx context.Context, projectName string, page Key: "project", }) } - entities, err := p.ds.List(ctx, &role, &datastore.ListOptions{FilterOptions: filter, Page: page, PageSize: pageSize, SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}}) + entities, err := p.Store.List(ctx, &role, &datastore.ListOptions{FilterOptions: filter, Page: page, PageSize: pageSize, SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}}) if err != nil { return nil, err } @@ -690,7 +688,7 @@ func (p *rbacUsecaseImpl) ListRole(ctx context.Context, projectName string, page } res.Roles = append(res.Roles, ConvertRole2Model(entity.(*model.Role), rolePolicies)) } - count, err := p.ds.Count(ctx, &role, &filter) + count, err := p.Store.Count(ctx, &role, &filter) if err != nil { return nil, err } @@ -699,18 +697,18 @@ func (p *rbacUsecaseImpl) ListRole(ctx context.Context, projectName string, page } // ListPermissionTemplate TODO: -func (p *rbacUsecaseImpl) ListPermissionTemplate(ctx context.Context, projectName string) ([]apisv1.PermissionTemplateBase, error) { +func (p *rbacServiceImpl) ListPermissionTemplate(ctx context.Context, projectName string) ([]apisv1.PermissionTemplateBase, error) { return nil, nil } -func (p *rbacUsecaseImpl) ListPermissions(ctx context.Context, projectName string) ([]apisv1.PermissionBase, error) { +func (p *rbacServiceImpl) ListPermissions(ctx context.Context, projectName string) ([]apisv1.PermissionBase, error) { var filter datastore.FilterOptions if projectName == "" { filter.IsNotExist = append(filter.IsNotExist, datastore.IsNotExistQueryOption{ Key: "project", }) } - permEntities, err := p.ds.List(ctx, &model.Permission{Project: projectName}, &datastore.ListOptions{FilterOptions: filter}) + permEntities, err := p.Store.List(ctx, &model.Permission{Project: projectName}, &datastore.ListOptions{FilterOptions: filter}) if err != nil { return nil, err } @@ -730,7 +728,7 @@ func (p *rbacUsecaseImpl) ListPermissions(ctx context.Context, projectName strin return perms, nil } -func (p *rbacUsecaseImpl) InitDefaultRoleAndUsersForProject(ctx context.Context, project *model.Project) error { +func (p *rbacServiceImpl) InitDefaultRoleAndUsersForProject(ctx context.Context, project *model.Project) error { var batchData []datastore.Entity for _, permissionTemp := range defaultProjectPermissionTemplate { var rra = RequestResourceAction{} @@ -772,7 +770,7 @@ func (p *rbacUsecaseImpl) InitDefaultRoleAndUsersForProject(ctx context.Context, } batchData = append(batchData, projectUser) } - return p.ds.BatchAdd(ctx, batchData) + return p.Store.BatchAdd(ctx, batchData) } // ConvertRole2Model convert role model to role base struct diff --git a/pkg/apiserver/rest/usecase/rbac_test.go b/pkg/apiserver/domain/service/rbac_test.go similarity index 91% rename from pkg/apiserver/rest/usecase/rbac_test.go rename to pkg/apiserver/domain/service/rbac_test.go index 9b99183ba..b706ec7a3 100644 --- a/pkg/apiserver/rest/usecase/rbac_test.go +++ b/pkg/apiserver/domain/service/rbac_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -28,10 +28,10 @@ import ( . "github.com/onsi/gomega" "github.com/stretchr/testify/assert" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" ) var _ = Describe("Test rbac service", func() { @@ -89,10 +89,10 @@ var _ = Describe("Test rbac service", func() { }) It("Test init and list platform permissions", func() { - rbacUsecase := rbacUsecaseImpl{ds: ds} - err := rbacUsecase.Init(context.TODO()) + rbacService := rbacServiceImpl{Store: ds} + err := rbacService.Init(context.TODO()) Expect(err).Should(BeNil()) - policies, err := rbacUsecase.ListPermissions(context.TODO(), "") + policies, err := rbacService.ListPermissions(context.TODO(), "") Expect(err).Should(BeNil()) Expect(len(policies)).Should(BeEquivalentTo(int64(7))) }) @@ -102,7 +102,7 @@ var _ = Describe("Test rbac service", func() { err := ds.Add(context.TODO(), &model.User{Name: "admin", UserRoles: []string{"admin"}}) Expect(err).Should(BeNil()) - rbac := rbacUsecaseImpl{ds: ds} + rbac := rbacServiceImpl{Store: ds} req := &http.Request{} req = req.WithContext(context.WithValue(req.Context(), &apisv1.CtxKeyUser, "admin")) res := &restful.Response{} @@ -137,7 +137,7 @@ var _ = Describe("Test rbac service", func() { err = ds.Add(context.TODO(), &model.Permission{Project: projectName, Name: "application-manage", Resources: []string{"project:test-app-project/application:*"}, Actions: []string{"*"}}) Expect(err).Should(BeNil()) - rbac := rbacUsecaseImpl{ds: ds} + rbac := rbacServiceImpl{Store: ds} header := http.Header{} header.Set("Accept", "application/json") header.Set("Content-Type", "application/json") @@ -165,7 +165,7 @@ var _ = Describe("Test rbac service", func() { Expect(res.StatusCode()).Should(Equal(int(bcode.ErrForbidden.HTTPCode))) // add list application permission to role - // err = ds.Add(context.TODO(), &model.Permission{Project: projectName, Name: "application-list", Resources: []string{"project:*/application:*"}, Actions: []string{"list"}}) + // err = Store.Add(context.TODO(), &model.Permission{Project: projectName, Name: "application-list", Resources: []string{"project:*/application:*"}, Actions: []string{"list"}}) // Expect(err).Should(BeNil()) // _, err = rbac.UpdateRole(context.TODO(), projectName, "application-admin", apisv1.UpdateRoleRequest{ // Permissions: []string{"application-list", "application-manage"}, @@ -179,27 +179,27 @@ var _ = Describe("Test rbac service", func() { }) It("Test initDefaultRoleAndUsersForProject", func() { - rbacUsecase := rbacUsecaseImpl{ds: ds} + rbacService := rbacServiceImpl{Store: ds} err := ds.Add(context.TODO(), &model.User{Name: "test-user"}) Expect(err).Should(BeNil()) err = ds.Add(context.TODO(), &model.Project{Name: "init-test", Owner: "test-user"}) Expect(err).Should(BeNil()) - err = rbacUsecase.InitDefaultRoleAndUsersForProject(context.TODO(), &model.Project{Name: "init-test"}) + err = rbacService.InitDefaultRoleAndUsersForProject(context.TODO(), &model.Project{Name: "init-test"}) Expect(err).Should(BeNil()) - roles, err := rbacUsecase.ListRole(context.TODO(), "init-test", 0, 0) + roles, err := rbacService.ListRole(context.TODO(), "init-test", 0, 0) Expect(err).Should(BeNil()) Expect(roles.Total).Should(BeEquivalentTo(int64(2))) - policies, err := rbacUsecase.ListPermissions(context.TODO(), "init-test") + policies, err := rbacService.ListPermissions(context.TODO(), "init-test") Expect(err).Should(BeNil()) Expect(len(policies)).Should(BeEquivalentTo(int64(4))) }) It("Test UpdatePermission", func() { - rbacUsecase := rbacUsecaseImpl{ds: ds} - base, err := rbacUsecase.UpdatePermission(context.TODO(), "test-app-project", "application-manage", &apisv1.UpdatePermissionRequest{ + rbacService := rbacServiceImpl{Store: ds} + base, err := rbacService.UpdatePermission(context.TODO(), "test-app-project", "application-manage", &apisv1.UpdatePermissionRequest{ Resources: []string{"project:{projectName}/application:*/*"}, Actions: []string{"*"}, Alias: "App Management Update", diff --git a/pkg/apiserver/domain/service/service.go b/pkg/apiserver/domain/service/service.go new file mode 100644 index 000000000..90fa584f1 --- /dev/null +++ b/pkg/apiserver/domain/service/service.go @@ -0,0 +1,70 @@ +/* +Copyright 2022 The KubeVela 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 service + +import ( + "context" + "fmt" + + "github.com/oam-dev/kubevela/pkg/apiserver/config" +) + +// needInitData register the service that need to init data +var needInitData []DataInit + +// InitServiceBean init all service instance +func InitServiceBean(c config.Config) []interface{} { + clusterService := NewClusterService() + rbacService := NewRBACService() + projectService := NewProjectService() + envService := NewEnvService() + targetService := NewTargetService() + workflowService := NewWorkflowService() + oamApplicationService := NewOAMApplicationService() + velaQLService := NewVelaQLService() + definitionService := NewDefinitionService() + addonService := NewAddonService(c.AddonCacheTime) + envBindingService := NewEnvBindingService() + systemInfoService := NewSystemInfoService() + helmService := NewHelmService() + userService := NewUserService() + authenticationService := NewAuthenticationService() + configService := NewConfigService() + applicationService := NewApplicationService() + webhookService := NewWebhookService() + needInitData = []DataInit{clusterService, userService, rbacService, projectService, targetService, systemInfoService} + return []interface{}{ + clusterService, rbacService, projectService, envService, targetService, workflowService, oamApplicationService, + velaQLService, definitionService, addonService, envBindingService, systemInfoService, helmService, userService, + authenticationService, configService, applicationService, webhookService, + } +} + +// DataInit the service set that needs init data +type DataInit interface { + Init(ctx context.Context) error +} + +// InitData init data +func InitData(ctx context.Context) error { + for _, init := range needInitData { + if err := init.Init(ctx); err != nil { + return fmt.Errorf("database init failure %w", err) + } + } + return nil +} diff --git a/pkg/apiserver/rest/usecase/suite_test.go b/pkg/apiserver/domain/service/suite_test.go similarity index 91% rename from pkg/apiserver/rest/usecase/suite_test.go rename to pkg/apiserver/domain/service/suite_test.go index 1c3b1fb76..8a2e9f909 100644 --- a/pkg/apiserver/rest/usecase/suite_test.go +++ b/pkg/apiserver/domain/service/suite_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -39,10 +39,10 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore/kubeapi" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore/mongodb" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore/kubeapi" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore/mongodb" "github.com/oam-dev/kubevela/pkg/utils/common" ) @@ -50,9 +50,9 @@ var cfg *rest.Config var k8sClient client.Client var testEnv *envtest.Environment -func TestUsecase(t *testing.T) { +func TestService(t *testing.T) { RegisterFailHandler(Fail) - RunSpecs(t, "Usecase Suite") + RunSpecs(t, "Service Suite") } var _ = BeforeSuite(func(done Done) { diff --git a/pkg/apiserver/rest/usecase/system_info.go b/pkg/apiserver/domain/service/system_info.go similarity index 73% rename from pkg/apiserver/rest/usecase/system_info.go rename to pkg/apiserver/domain/service/system_info.go index 6390b69ee..f8acafe08 100644 --- a/pkg/apiserver/rest/usecase/system_info.go +++ b/pkg/apiserver/domain/service/system_info.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -23,42 +23,36 @@ import ( "k8s.io/apimachinery/pkg/util/rand" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - v1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + v1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" "github.com/oam-dev/kubevela/version" ) -// SystemInfoUsecase is usecase for systemInfoCollection -type SystemInfoUsecase interface { +// SystemInfoService is service for systemInfoCollection +type SystemInfoService interface { Get(ctx context.Context) (*model.SystemInfo, error) GetSystemInfo(ctx context.Context) (*v1.SystemInfoResponse, error) UpdateSystemInfo(ctx context.Context, sysInfo v1.SystemInfoRequest) (*v1.SystemInfoResponse, error) Init(ctx context.Context) error } -type systemInfoUsecaseImpl struct { - ds datastore.DataStore - kubeClient client.Client +type systemInfoServiceImpl struct { + Store datastore.DataStore `inject:"datastore"` + KubeClient client.Client `inject:"kubeClient"` } -// NewSystemInfoUsecase return a systemInfoCollectionUsecase -func NewSystemInfoUsecase(ds datastore.DataStore) SystemInfoUsecase { - kubecli, err := clients.GetKubeClient() - if err != nil { - log.Logger.Fatalf("failed to get kube client: %s", err.Error()) - } - return &systemInfoUsecaseImpl{ds: ds, kubeClient: kubecli} +// NewSystemInfoService return a systemInfoCollectionService +func NewSystemInfoService() SystemInfoService { + return &systemInfoServiceImpl{} } -func (u systemInfoUsecaseImpl) Get(ctx context.Context) (*model.SystemInfo, error) { +func (u systemInfoServiceImpl) Get(ctx context.Context) (*model.SystemInfo, error) { // first get request will init systemInfoCollection{installId: {random}, enableCollection: true} info := &model.SystemInfo{} - entities, err := u.ds.List(ctx, info, &datastore.ListOptions{}) + entities, err := u.Store.List(ctx, info, &datastore.ListOptions{}) if err != nil { return nil, err } @@ -74,14 +68,14 @@ func (u systemInfoUsecaseImpl) Get(ctx context.Context) (*model.SystemInfo, erro info.EnableCollection = true info.LoginType = model.LoginTypeLocal info.BaseModel = model.BaseModel{CreateTime: time.Now()} - err = u.ds.Add(ctx, info) + err = u.Store.Add(ctx, info) if err != nil { return nil, err } return info, nil } -func (u systemInfoUsecaseImpl) GetSystemInfo(ctx context.Context) (*v1.SystemInfoResponse, error) { +func (u systemInfoServiceImpl) GetSystemInfo(ctx context.Context) (*v1.SystemInfoResponse, error) { // first get request will init systemInfoCollection{installId: {random}, enableCollection: true} info, err := u.Get(ctx) if err != nil { @@ -106,7 +100,7 @@ func (u systemInfoUsecaseImpl) GetSystemInfo(ctx context.Context) (*v1.SystemInf }, nil } -func (u systemInfoUsecaseImpl) UpdateSystemInfo(ctx context.Context, sysInfo v1.SystemInfoRequest) (*v1.SystemInfoResponse, error) { +func (u systemInfoServiceImpl) UpdateSystemInfo(ctx context.Context, sysInfo v1.SystemInfoRequest) (*v1.SystemInfoResponse, error) { info, err := u.Get(ctx) if err != nil { return nil, err @@ -124,27 +118,27 @@ func (u systemInfoUsecaseImpl) UpdateSystemInfo(ctx context.Context, sysInfo v1. if sysInfo.LoginType == model.LoginTypeDex { admin := &model.User{Name: model.DefaultAdminUserName} - if err := u.ds.Get(ctx, admin); err != nil { + if err := u.Store.Get(ctx, admin); err != nil { return nil, err } if admin.Email == "" { return nil, bcode.ErrEmptyAdminEmail } - connectors, err := utils.GetDexConnectors(ctx, u.kubeClient) + connectors, err := utils.GetDexConnectors(ctx, u.KubeClient) if err != nil { return nil, err } if len(connectors) < 1 { return nil, bcode.ErrNoDexConnector } - if err := generateDexConfig(ctx, u.kubeClient, &model.UpdateDexConfig{ + if err := generateDexConfig(ctx, u.KubeClient, &model.UpdateDexConfig{ VelaAddress: sysInfo.VelaAddress, Connectors: connectors, }); err != nil { return nil, err } } - err = u.ds.Put(ctx, &modifiedInfo) + err = u.Store.Put(ctx, &modifiedInfo) if err != nil { return nil, err } @@ -160,13 +154,13 @@ func (u systemInfoUsecaseImpl) UpdateSystemInfo(ctx context.Context, sysInfo v1. }, nil } -func (u systemInfoUsecaseImpl) Init(ctx context.Context) error { +func (u systemInfoServiceImpl) Init(ctx context.Context) error { info, err := u.Get(ctx) if err != nil { return err } signedKey = info.InstallID - _, err = initDexConfig(ctx, u.kubeClient, "http://velaux.com") + _, err = initDexConfig(ctx, u.KubeClient, "http://velaux.com") return err } diff --git a/pkg/apiserver/rest/usecase/target.go b/pkg/apiserver/domain/service/target.go similarity index 69% rename from pkg/apiserver/rest/usecase/target.go rename to pkg/apiserver/domain/service/target.go index 28a8ca7c9..2bbadb707 100644 --- a/pkg/apiserver/rest/usecase/target.go +++ b/pkg/apiserver/domain/service/target.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -23,17 +23,17 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/repository" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/multicluster" ) -// TargetUsecase Target manage api -type TargetUsecase interface { +// TargetService Target manage api +type TargetService interface { GetTarget(ctx context.Context, TargetName string) (*model.Target, error) DetailTarget(ctx context.Context, Target *model.Target) (*apisv1.DetailTargetResponse, error) DeleteTarget(ctx context.Context, TargetName string) error @@ -44,24 +44,18 @@ type TargetUsecase interface { Init(ctx context.Context) error } -type targetUsecaseImpl struct { - ds datastore.DataStore - k8sClient client.Client +type targetServiceImpl struct { + Store datastore.DataStore `inject:"datastore"` + K8sClient client.Client `inject:"kubeClient"` } -// NewTargetUsecase new Target usecase -func NewTargetUsecase(ds datastore.DataStore) TargetUsecase { - k8sClient, err := clients.GetKubeClient() - if err != nil { - log.Logger.Fatalf("get k8sClient failure: %s", err.Error()) - } - return &targetUsecaseImpl{ - k8sClient: k8sClient, - ds: ds, - } +// NewTargetService new Target service +func NewTargetService() TargetService { + return &targetServiceImpl{} } -func (dt *targetUsecaseImpl) Init(ctx context.Context) error { - targets, err := dt.ds.List(ctx, &model.Target{}, &datastore.ListOptions{FilterOptions: datastore.FilterOptions{ + +func (dt *targetServiceImpl) Init(ctx context.Context) error { + targets, err := dt.Store.List(ctx, &model.Target{}, &datastore.ListOptions{FilterOptions: datastore.FilterOptions{ IsNotExist: []datastore.IsNotExistQueryOption{ { Key: "project", @@ -74,14 +68,14 @@ func (dt *targetUsecaseImpl) Init(ctx context.Context) error { for _, target := range targets { t := target.(*model.Target) t.Project = model.DefaultInitName - if err := dt.ds.Put(ctx, t); err != nil { + if err := dt.Store.Put(ctx, t); err != nil { return err } } return nil } -func (dt *targetUsecaseImpl) ListTargets(ctx context.Context, page, pageSize int, projectName string) (*apisv1.ListTargetResponse, error) { - targets, err := listTarget(ctx, dt.ds, projectName, &datastore.ListOptions{ +func (dt *targetServiceImpl) ListTargets(ctx context.Context, page, pageSize int, projectName string) (*apisv1.ListTargetResponse, error) { + targets, err := repository.ListTarget(ctx, dt.Store, projectName, &datastore.ListOptions{ Page: page, PageSize: pageSize, SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}, @@ -95,7 +89,7 @@ func (dt *targetUsecaseImpl) ListTargets(ctx context.Context, page, pageSize int for _, raw := range targets { resp.Targets = append(resp.Targets, *(dt.convertFromTargetModel(ctx, raw))) } - count, err := dt.ds.Count(ctx, &model.Target{Project: projectName}, nil) + count, err := dt.Store.Count(ctx, &model.Target{Project: projectName}, nil) if err != nil { return nil, err } @@ -104,12 +98,12 @@ func (dt *targetUsecaseImpl) ListTargets(ctx context.Context, page, pageSize int return resp, nil } -func (dt *targetUsecaseImpl) ListTargetCount(ctx context.Context, projectName string) (int64, error) { - return dt.ds.Count(ctx, &model.Target{Project: projectName}, nil) +func (dt *targetServiceImpl) ListTargetCount(ctx context.Context, projectName string) (int64, error) { + return dt.Store.Count(ctx, &model.Target{Project: projectName}, nil) } // DeleteTarget delete application Target -func (dt *targetUsecaseImpl) DeleteTarget(ctx context.Context, targetName string) error { +func (dt *targetServiceImpl) DeleteTarget(ctx context.Context, targetName string) error { target := &model.Target{ Name: targetName, } @@ -120,10 +114,10 @@ func (dt *targetUsecaseImpl) DeleteTarget(ctx context.Context, targetName string if err != nil { return err } - if err = deleteTargetNamespace(ctx, dt.k8sClient, ddt.Cluster.ClusterName, ddt.Cluster.Namespace, targetName); err != nil { + if err = repository.DeleteTargetNamespace(ctx, dt.K8sClient, ddt.Cluster.ClusterName, ddt.Cluster.Namespace, targetName); err != nil { return err } - if err = dt.ds.Delete(ctx, target); err != nil { + if err = dt.Store.Delete(ctx, target); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return bcode.ErrTargetNotExist } @@ -134,48 +128,48 @@ func (dt *targetUsecaseImpl) DeleteTarget(ctx context.Context, targetName string // CreateTarget will create a delivery target binding with a cluster and namespace, by default, it will use local cluster and namespace align with targetName // TODO(@wonderflow): we should support empty target in the future which only delivery cloud resources -func (dt *targetUsecaseImpl) CreateTarget(ctx context.Context, req apisv1.CreateTargetRequest) (*apisv1.DetailTargetResponse, error) { +func (dt *targetServiceImpl) CreateTarget(ctx context.Context, req apisv1.CreateTargetRequest) (*apisv1.DetailTargetResponse, error) { var project = model.Project{ Name: req.Project, } - if err := dt.ds.Get(ctx, &project); err != nil { + if err := dt.Store.Get(ctx, &project); err != nil { return nil, bcode.ErrProjectIsNotExist } target := convertCreateReqToTargetModel(req) if req.Cluster == nil { req.Cluster = &apisv1.ClusterTarget{ClusterName: multicluster.ClusterLocalName, Namespace: req.Name} } - if err := createTargetNamespace(ctx, dt.k8sClient, req.Cluster.ClusterName, req.Cluster.Namespace, req.Name); err != nil { + if err := repository.CreateTargetNamespace(ctx, dt.K8sClient, req.Cluster.ClusterName, req.Cluster.Namespace, req.Name); err != nil { return nil, err } - err := createTarget(ctx, dt.ds, &target) + err := repository.CreateTarget(ctx, dt.Store, &target) if err != nil { return nil, err } return dt.DetailTarget(ctx, &target) } -func (dt *targetUsecaseImpl) UpdateTarget(ctx context.Context, target *model.Target, req apisv1.UpdateTargetRequest) (*apisv1.DetailTargetResponse, error) { +func (dt *targetServiceImpl) UpdateTarget(ctx context.Context, target *model.Target, req apisv1.UpdateTargetRequest) (*apisv1.DetailTargetResponse, error) { targetModel := convertUpdateReqToTargetModel(target, req) - if err := dt.ds.Put(ctx, targetModel); err != nil { + if err := dt.Store.Put(ctx, targetModel); err != nil { return nil, err } return dt.DetailTarget(ctx, targetModel) } // DetailTarget detail Target -func (dt *targetUsecaseImpl) DetailTarget(ctx context.Context, target *model.Target) (*apisv1.DetailTargetResponse, error) { +func (dt *targetServiceImpl) DetailTarget(ctx context.Context, target *model.Target) (*apisv1.DetailTargetResponse, error) { return &apisv1.DetailTargetResponse{ TargetBase: *dt.convertFromTargetModel(ctx, target), }, nil } // GetTarget get Target model -func (dt *targetUsecaseImpl) GetTarget(ctx context.Context, targetName string) (*model.Target, error) { +func (dt *targetServiceImpl) GetTarget(ctx context.Context, targetName string) (*model.Target, error) { Target := &model.Target{ Name: targetName, } - if err := dt.ds.Get(ctx, Target); err != nil { + if err := dt.Store.Get(ctx, Target); err != nil { return nil, err } return Target, nil @@ -200,7 +194,7 @@ func convertCreateReqToTargetModel(req apisv1.CreateTargetRequest) model.Target return target } -func (dt *targetUsecaseImpl) convertFromTargetModel(ctx context.Context, target *model.Target) *apisv1.TargetBase { +func (dt *targetServiceImpl) convertFromTargetModel(ctx context.Context, target *model.Target) *apisv1.TargetBase { var appNum int64 = 0 // TODO: query app num in target targetBase := &apisv1.TargetBase{ @@ -217,13 +211,13 @@ func (dt *targetUsecaseImpl) convertFromTargetModel(ctx context.Context, target var project = model.Project{ Name: target.Project, } - if err := dt.ds.Get(ctx, &project); err != nil { + if err := dt.Store.Get(ctx, &project); err != nil { log.Logger.Errorf("get project failure %s", err.Error()) } targetBase.Project = apisv1.NameAlias{Name: project.Name, Alias: project.Alias} } if targetBase.Cluster != nil && targetBase.Cluster.ClusterName != "" { - cluster, err := _getClusterFromDataStore(ctx, dt.ds, target.Cluster.ClusterName) + cluster, err := _getClusterFromDataStore(ctx, dt.Store, target.Cluster.ClusterName) if err != nil { log.Logger.Errorf("query cluster info failure %s", err.Error()) } diff --git a/pkg/apiserver/rest/usecase/target_test.go b/pkg/apiserver/domain/service/target_test.go similarity index 67% rename from pkg/apiserver/rest/usecase/target_test.go rename to pkg/apiserver/domain/service/target_test.go index 0428b5c56..fc9dc0f6e 100644 --- a/pkg/apiserver/rest/usecase/target_test.go +++ b/pkg/apiserver/domain/service/target_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -23,27 +23,27 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" ) -var _ = Describe("Test target usecase functions", func() { +var _ = Describe("Test target service functions", func() { var ( - targetUsecase *targetUsecaseImpl - projectUsecase *projectUsecaseImpl + targetService *targetServiceImpl + projectService *projectServiceImpl testProject = "target-project" ) BeforeEach(func() { ds, err := NewDatastore(datastore.Config{Type: "kubeapi", Database: "target-test-kubevela"}) Expect(ds).ToNot(BeNil()) Expect(err).Should(BeNil()) - rbacUsecase := &rbacUsecaseImpl{ds: ds} - projectUsecase = &projectUsecaseImpl{ds: ds, k8sClient: k8sClient, rbacUsecase: rbacUsecase} - targetUsecase = &targetUsecaseImpl{ds: ds, k8sClient: k8sClient} + rbacService := &rbacServiceImpl{Store: ds} + projectService = &projectServiceImpl{Store: ds, K8sClient: k8sClient, RbacService: rbacService} + targetService = &targetServiceImpl{Store: ds, K8sClient: k8sClient} }) It("Test CreateTarget function", func() { - _, err := projectUsecase.CreateProject(context.TODO(), apisv1.CreateProjectRequest{Name: testProject}) + _, err := projectService.CreateProject(context.TODO(), apisv1.CreateProjectRequest{Name: testProject}) Expect(err).Should(BeNil()) req := apisv1.CreateTargetRequest{ @@ -54,25 +54,25 @@ var _ = Describe("Test target usecase functions", func() { Cluster: &apisv1.ClusterTarget{ClusterName: "cluster-dev", Namespace: "dev"}, Variable: map[string]interface{}{"terraform-provider": "provider", "region": "us-1"}, } - base, err := targetUsecase.CreateTarget(context.TODO(), req) + base, err := targetService.CreateTarget(context.TODO(), req) Expect(err).Should(BeNil()) Expect(cmp.Diff(base.Name, req.Name)).Should(BeEmpty()) - Expect(targetUsecase.ds.Add(context.TODO(), &model.Cluster{Name: "cluster-dev", Alias: "dev-alias"})).Should(Succeed()) + Expect(targetService.Store.Add(context.TODO(), &model.Cluster{Name: "cluster-dev", Alias: "dev-alias"})).Should(Succeed()) By("Test GetTarget function") - Target, err := targetUsecase.GetTarget(context.TODO(), "test--target") + Target, err := targetService.GetTarget(context.TODO(), "test--target") Expect(err).Should(BeNil()) Expect(Target).ShouldNot(BeNil()) Expect(cmp.Diff(Target.Name, "test--target")).Should(BeEmpty()) By("Test ListTargets function") - resp, err := targetUsecase.ListTargets(context.TODO(), 1, 1, "") + resp, err := targetService.ListTargets(context.TODO(), 1, 1, "") Expect(err).Should(BeNil()) Expect(resp.Targets[0].ClusterAlias).Should(Equal("dev-alias")) By("Test DetailTarget function") - detail, err := targetUsecase.DetailTarget(context.TODO(), + detail, err := targetService.DetailTarget(context.TODO(), &model.Target{ Name: "test--target", Alias: "test-alias", @@ -83,7 +83,7 @@ var _ = Describe("Test target usecase functions", func() { Expect(detail.Name).Should(Equal("test--target")) By("Test Delete target") - err = targetUsecase.DeleteTarget(context.TODO(), "test--target") + err = targetService.DeleteTarget(context.TODO(), "test--target") Expect(err).Should(BeNil()) }) }) diff --git a/pkg/apiserver/rest/usecase/testdata/addon-uischema-test.yaml b/pkg/apiserver/domain/service/testdata/addon-uischema-test.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/addon-uischema-test.yaml rename to pkg/apiserver/domain/service/testdata/addon-uischema-test.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/api-schema.json b/pkg/apiserver/domain/service/testdata/api-schema.json similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/api-schema.json rename to pkg/apiserver/domain/service/testdata/api-schema.json diff --git a/pkg/apiserver/rest/usecase/testdata/apply-application-hide.yaml b/pkg/apiserver/domain/service/testdata/apply-application-hide.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/apply-application-hide.yaml rename to pkg/apiserver/domain/service/testdata/apply-application-hide.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/apply-object.yaml b/pkg/apiserver/domain/service/testdata/apply-object.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/apply-object.yaml rename to pkg/apiserver/domain/service/testdata/apply-object.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/applyapplication-sd.yaml b/pkg/apiserver/domain/service/testdata/applyapplication-sd.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/applyapplication-sd.yaml rename to pkg/apiserver/domain/service/testdata/applyapplication-sd.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/deploy.yaml b/pkg/apiserver/domain/service/testdata/deploy.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/deploy.yaml rename to pkg/apiserver/domain/service/testdata/deploy.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/dex-config-def.yaml b/pkg/apiserver/domain/service/testdata/dex-config-def.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/dex-config-def.yaml rename to pkg/apiserver/domain/service/testdata/dex-config-def.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/example-app-error.yaml b/pkg/apiserver/domain/service/testdata/example-app-error.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/example-app-error.yaml rename to pkg/apiserver/domain/service/testdata/example-app-error.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/example-app.yaml b/pkg/apiserver/domain/service/testdata/example-app.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/example-app.yaml rename to pkg/apiserver/domain/service/testdata/example-app.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/helm/index.yaml b/pkg/apiserver/domain/service/testdata/helm/index.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/helm/index.yaml rename to pkg/apiserver/domain/service/testdata/helm/index.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/helm/mysql-8.8.23.tgz b/pkg/apiserver/domain/service/testdata/helm/mysql-8.8.23.tgz similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/helm/mysql-8.8.23.tgz rename to pkg/apiserver/domain/service/testdata/helm/mysql-8.8.23.tgz diff --git a/pkg/apiserver/rest/usecase/testdata/myingress-td.yaml b/pkg/apiserver/domain/service/testdata/myingress-td.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/myingress-td.yaml rename to pkg/apiserver/domain/service/testdata/myingress-td.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/scaler.yaml b/pkg/apiserver/domain/service/testdata/scaler.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/scaler.yaml rename to pkg/apiserver/domain/service/testdata/scaler.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/terraform-alibaba-rds.yaml b/pkg/apiserver/domain/service/testdata/terraform-alibaba-rds.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/terraform-alibaba-rds.yaml rename to pkg/apiserver/domain/service/testdata/terraform-alibaba-rds.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/ui-custom-schema.yaml b/pkg/apiserver/domain/service/testdata/ui-custom-schema.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/ui-custom-schema.yaml rename to pkg/apiserver/domain/service/testdata/ui-custom-schema.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/ui-default-schema.yaml b/pkg/apiserver/domain/service/testdata/ui-default-schema.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/ui-default-schema.yaml rename to pkg/apiserver/domain/service/testdata/ui-default-schema.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/ui-schema.yaml b/pkg/apiserver/domain/service/testdata/ui-schema.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/ui-schema.yaml rename to pkg/apiserver/domain/service/testdata/ui-schema.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/webserver-cd.yaml b/pkg/apiserver/domain/service/testdata/webserver-cd.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/webserver-cd.yaml rename to pkg/apiserver/domain/service/testdata/webserver-cd.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/webservice.yaml b/pkg/apiserver/domain/service/testdata/webservice.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/webservice.yaml rename to pkg/apiserver/domain/service/testdata/webservice.yaml diff --git a/pkg/apiserver/rest/usecase/testdata/workflowstep-apply-object.yaml b/pkg/apiserver/domain/service/testdata/workflowstep-apply-object.yaml similarity index 100% rename from pkg/apiserver/rest/usecase/testdata/workflowstep-apply-object.yaml rename to pkg/apiserver/domain/service/testdata/workflowstep-apply-object.yaml diff --git a/pkg/apiserver/rest/usecase/user.go b/pkg/apiserver/domain/service/user.go similarity index 76% rename from pkg/apiserver/rest/usecase/user.go rename to pkg/apiserver/domain/service/user.go index 1431bf88c..a1fa92e95 100644 --- a/pkg/apiserver/rest/usecase/user.go +++ b/pkg/apiserver/domain/service/user.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -24,12 +24,11 @@ import ( "helm.sh/helm/v3/pkg/time" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" utils2 "github.com/oam-dev/kubevela/pkg/utils" ) @@ -37,8 +36,8 @@ const ( initAdminPassword = "VelaUX12345" ) -// UserUsecase User manage api -type UserUsecase interface { +// UserService User manage api +type UserService interface { GetUser(ctx context.Context, username string) (*model.User, error) DetailUser(ctx context.Context, user *model.User) (*apisv1.DetailUserResponse, error) DeleteUser(ctx context.Context, username string) error @@ -52,32 +51,22 @@ type UserUsecase interface { Init(ctx context.Context) error } -type userUsecaseImpl struct { - ds datastore.DataStore - k8sClient client.Client - projectUsecase ProjectUsecase - rbacUsecase RBACUsecase - sysUsecase SystemInfoUsecase +type userServiceImpl struct { + Store datastore.DataStore `inject:"datastore"` + K8sClient client.Client `inject:"kubeClient"` + ProjectService ProjectService `inject:""` + RbacService RBACService `inject:""` + SysService SystemInfoService `inject:""` } -// NewUserUsecase new User usecase -func NewUserUsecase(ds datastore.DataStore, projectUsecase ProjectUsecase, sysUsecase SystemInfoUsecase, rbacUsecase RBACUsecase) UserUsecase { - k8sClient, err := clients.GetKubeClient() - if err != nil { - log.Logger.Fatalf("get k8sClient failure: %s", err.Error()) - } - return &userUsecaseImpl{ - k8sClient: k8sClient, - ds: ds, - projectUsecase: projectUsecase, - sysUsecase: sysUsecase, - rbacUsecase: rbacUsecase, - } +// NewUserService new User service +func NewUserService() UserService { + return &userServiceImpl{} } -func (u *userUsecaseImpl) Init(ctx context.Context) error { +func (u *userServiceImpl) Init(ctx context.Context) error { admin := model.DefaultAdminUserName - if err := u.ds.Get(ctx, &model.User{ + if err := u.Store.Get(ctx, &model.User{ Name: admin, }); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { @@ -85,7 +74,7 @@ func (u *userUsecaseImpl) Init(ctx context.Context) error { if err != nil { return err } - if err := u.ds.Add(ctx, &model.User{ + if err := u.Store.Add(ctx, &model.User{ Name: admin, Alias: model.DefaultAdminUserAlias, Password: encrypted, @@ -104,19 +93,19 @@ func (u *userUsecaseImpl) Init(ctx context.Context) error { } // GetUser get user -func (u *userUsecaseImpl) GetUser(ctx context.Context, username string) (*model.User, error) { +func (u *userServiceImpl) GetUser(ctx context.Context, username string) (*model.User, error) { user := &model.User{ Name: username, } - if err := u.ds.Get(ctx, user); err != nil { + if err := u.Store.Get(ctx, user); err != nil { return nil, err } return user, nil } // DetailUser return user detail -func (u *userUsecaseImpl) DetailUser(ctx context.Context, user *model.User) (*apisv1.DetailUserResponse, error) { - roles, err := u.rbacUsecase.ListRole(ctx, "", 0, 0) +func (u *userServiceImpl) DetailUser(ctx context.Context, user *model.User) (*apisv1.DetailUserResponse, error) { + roles, err := u.RbacService.ListRole(ctx, "", 0, 0) if err != nil { log.Logger.Warnf("list platform roles failure %s", err.Error()) } @@ -124,7 +113,7 @@ func (u *userUsecaseImpl) DetailUser(ctx context.Context, user *model.User) (*ap pUser := &model.ProjectUser{ Username: user.Name, } - projectUsers, err := u.ds.List(ctx, pUser, &datastore.ListOptions{ + projectUsers, err := u.Store.List(ctx, pUser, &datastore.ListOptions{ SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}, }) if err != nil { @@ -133,7 +122,7 @@ func (u *userUsecaseImpl) DetailUser(ctx context.Context, user *model.User) (*ap for _, v := range projectUsers { pu, ok := v.(*model.ProjectUser) if ok { - project, err := u.projectUsecase.DetailProject(ctx, pu.ProjectName) + project, err := u.ProjectService.DetailProject(ctx, pu.ProjectName) if err != nil { log.Logger.Errorf("failed to delete project(%s) info: %s", pu.ProjectName, err.Error()) continue @@ -145,22 +134,22 @@ func (u *userUsecaseImpl) DetailUser(ctx context.Context, user *model.User) (*ap } // DeleteUser delete user -func (u *userUsecaseImpl) DeleteUser(ctx context.Context, username string) error { +func (u *userServiceImpl) DeleteUser(ctx context.Context, username string) error { pUser := &model.ProjectUser{ Username: username, } - projectUsers, err := u.ds.List(ctx, pUser, &datastore.ListOptions{}) + projectUsers, err := u.Store.List(ctx, pUser, &datastore.ListOptions{}) if err != nil { return err } for _, v := range projectUsers { pu := v.(*model.ProjectUser) - if err := u.ds.Delete(ctx, pu); err != nil { + if err := u.Store.Delete(ctx, pu); err != nil { log.Logger.Errorf("failed to delete project user %s: %s", pu.PrimaryKey(), err.Error()) } } - if err := u.ds.Delete(ctx, &model.User{Name: username}); err != nil { + if err := u.Store.Delete(ctx, &model.User{Name: username}); err != nil { log.Logger.Errorf("failed to delete user %s %v", utils2.Sanitize(username), err.Error()) return err } @@ -168,8 +157,8 @@ func (u *userUsecaseImpl) DeleteUser(ctx context.Context, username string) error } // CreateUser create user -func (u *userUsecaseImpl) CreateUser(ctx context.Context, req apisv1.CreateUserRequest) (*apisv1.UserBase, error) { - sysInfo, err := u.sysUsecase.Get(ctx) +func (u *userServiceImpl) CreateUser(ctx context.Context, req apisv1.CreateUserRequest) (*apisv1.UserBase, error) { + sysInfo, err := u.SysService.Get(ctx) if err != nil { return nil, err } @@ -189,15 +178,15 @@ func (u *userUsecaseImpl) CreateUser(ctx context.Context, req apisv1.CreateUserR Password: hash, Disabled: false, } - if err := u.ds.Add(ctx, user); err != nil { + if err := u.Store.Add(ctx, user); err != nil { return nil, err } return convertUserBase(user), nil } // UpdateUser update user -func (u *userUsecaseImpl) UpdateUser(ctx context.Context, user *model.User, req apisv1.UpdateUserRequest) (*apisv1.UserBase, error) { - sysInfo, err := u.sysUsecase.Get(ctx) +func (u *userServiceImpl) UpdateUser(ctx context.Context, user *model.User, req apisv1.UpdateUserRequest) (*apisv1.UserBase, error) { + sysInfo, err := u.SysService.Get(ctx) if err != nil { return nil, err } @@ -224,11 +213,11 @@ func (u *userUsecaseImpl) UpdateUser(ctx context.Context, user *model.User, req if req.Roles != nil { user.UserRoles = *req.Roles } - if err := u.ds.Put(ctx, user); err != nil { + if err := u.Store.Put(ctx, user); err != nil { return nil, err } if user.Name == model.DefaultAdminUserName { - if err := generateDexConfig(ctx, u.k8sClient, &model.UpdateDexConfig{ + if err := generateDexConfig(ctx, u.K8sClient, &model.UpdateDexConfig{ StaticPasswords: []model.StaticPassword{ { Email: user.Email, @@ -244,7 +233,7 @@ func (u *userUsecaseImpl) UpdateUser(ctx context.Context, user *model.User, req } // ListUsers list users -func (u *userUsecaseImpl) ListUsers(ctx context.Context, page, pageSize int, listOptions apisv1.ListUserOptions) (*apisv1.ListUserResponse, error) { +func (u *userServiceImpl) ListUsers(ctx context.Context, page, pageSize int, listOptions apisv1.ListUserOptions) (*apisv1.ListUserResponse, error) { user := &model.User{} var queries []datastore.FuzzyQueryOption if listOptions.Name != "" { @@ -259,7 +248,7 @@ func (u *userUsecaseImpl) ListUsers(ctx context.Context, page, pageSize int, lis fo := datastore.FilterOptions{Queries: queries} var userList []*apisv1.DetailUserResponse - users, err := u.ds.List(ctx, user, &datastore.ListOptions{ + users, err := u.Store.List(ctx, user, &datastore.ListOptions{ Page: page, PageSize: pageSize, SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}, @@ -268,7 +257,7 @@ func (u *userUsecaseImpl) ListUsers(ctx context.Context, page, pageSize int, lis if err != nil { return nil, err } - roles, err := u.rbacUsecase.ListRole(ctx, "", 0, 0) + roles, err := u.RbacService.ListRole(ctx, "", 0, 0) if err != nil { log.Logger.Warnf("list platform roles failure %s", err.Error()) } @@ -278,7 +267,7 @@ func (u *userUsecaseImpl) ListUsers(ctx context.Context, page, pageSize int, lis userList = append(userList, convertUserModel(user, roles)) } } - count, err := u.ds.Count(ctx, user, &fo) + count, err := u.Store.Count(ctx, user, &fo) if err != nil { return nil, err } @@ -290,31 +279,31 @@ func (u *userUsecaseImpl) ListUsers(ctx context.Context, page, pageSize int, lis } // DisableUser disable user -func (u *userUsecaseImpl) DisableUser(ctx context.Context, user *model.User) error { +func (u *userServiceImpl) DisableUser(ctx context.Context, user *model.User) error { if user.Disabled { return bcode.ErrUserAlreadyDisabled } user.Disabled = true - return u.ds.Put(ctx, user) + return u.Store.Put(ctx, user) } // EnableUser disable user -func (u *userUsecaseImpl) EnableUser(ctx context.Context, user *model.User) error { +func (u *userServiceImpl) EnableUser(ctx context.Context, user *model.User) error { if !user.Disabled { return bcode.ErrUserAlreadyEnabled } user.Disabled = false - return u.ds.Put(ctx, user) + return u.Store.Put(ctx, user) } // UpdateUserLoginTime update user login time -func (u *userUsecaseImpl) UpdateUserLoginTime(ctx context.Context, user *model.User) error { +func (u *userServiceImpl) UpdateUserLoginTime(ctx context.Context, user *model.User) error { user.LastLoginTime = time.Now().Time - return u.ds.Put(ctx, user) + return u.Store.Put(ctx, user) } // DetailLoginUserInfo get projects and permission policies of login user -func (u *userUsecaseImpl) DetailLoginUserInfo(ctx context.Context) (*apisv1.LoginUserInfoResponse, error) { +func (u *userServiceImpl) DetailLoginUserInfo(ctx context.Context) (*apisv1.LoginUserInfoResponse, error) { userName, ok := ctx.Value(&apisv1.CtxKeyUser).(string) if !ok { return nil, bcode.ErrUnauthorized @@ -324,13 +313,13 @@ func (u *userUsecaseImpl) DetailLoginUserInfo(ctx context.Context) (*apisv1.Logi log.Logger.Errorf("get login user model failure %s", err.Error()) return nil, bcode.ErrUnauthorized } - projects, err := u.projectUsecase.ListUserProjects(ctx, userName) + projects, err := u.ProjectService.ListUserProjects(ctx, userName) if err != nil { return nil, err } var projectPermissions = make(map[string][]apisv1.PermissionBase) for _, project := range projects { - perms, err := u.rbacUsecase.GetUserPermissions(ctx, user, project.Name, false) + perms, err := u.RbacService.GetUserPermissions(ctx, user, project.Name, false) if err != nil { log.Logger.Errorf("list user %s perm policies from project %s failure %s", user.Name, project.Name, err.Error()) continue @@ -350,7 +339,7 @@ func (u *userUsecaseImpl) DetailLoginUserInfo(ctx context.Context) (*apisv1.Logi return }() } - perms, err := u.rbacUsecase.GetUserPermissions(ctx, user, "", true) + perms, err := u.RbacService.GetUserPermissions(ctx, user, "", true) if err != nil { log.Logger.Errorf("list user %s platform perm policies failure %s", user.Name, err.Error()) } diff --git a/pkg/apiserver/rest/usecase/user_test.go b/pkg/apiserver/domain/service/user_test.go similarity index 81% rename from pkg/apiserver/rest/usecase/user_test.go rename to pkg/apiserver/domain/service/user_test.go index 6cf07fa19..f3b83dab6 100644 --- a/pkg/apiserver/rest/usecase/user_test.go +++ b/pkg/apiserver/domain/service/user_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -29,16 +29,16 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/yaml" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" "github.com/oam-dev/kubevela/pkg/oam/util" ) -var _ = Describe("Test authentication usecase functions", func() { +var _ = Describe("Test authentication service functions", func() { var ( - userUsecase *userUsecaseImpl + userService *userServiceImpl ds datastore.DataStore db string ) @@ -49,17 +49,17 @@ var _ = Describe("Test authentication usecase functions", func() { ds, err = NewDatastore(datastore.Config{Type: "kubeapi", Database: db}) Expect(ds).ToNot(BeNil()) Expect(err).Should(BeNil()) - rbacUsecase := &rbacUsecaseImpl{ds: ds} - projectUsecase := &projectUsecaseImpl{k8sClient: k8sClient, ds: ds, rbacUsecase: rbacUsecase} - sysUsecase := &systemInfoUsecaseImpl{ds: ds} - userUsecase = &userUsecaseImpl{ds: ds, k8sClient: k8sClient, projectUsecase: projectUsecase, sysUsecase: sysUsecase, rbacUsecase: rbacUsecase} + rbacService := &rbacServiceImpl{Store: ds} + projectService := &projectServiceImpl{K8sClient: k8sClient, Store: ds, RbacService: rbacService} + sysService := &systemInfoServiceImpl{Store: ds} + userService = &userServiceImpl{Store: ds, K8sClient: k8sClient, ProjectService: projectService, SysService: sysService, RbacService: rbacService} }) AfterEach(func() { err := k8sClient.Delete(context.Background(), &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: db}}) Expect(err).Should(BeNil()) }) It("Test create user", func() { - user, err := userUsecase.CreateUser(context.Background(), apisv1.CreateUserRequest{ + user, err := userService.CreateUser(context.Background(), apisv1.CreateUserRequest{ Name: "name", Alias: "alias", Email: "email@example.com", @@ -110,7 +110,7 @@ var _ = Describe("Test authentication usecase functions", func() { } err = ds.Get(ctx, userModel) Expect(err).Should(BeNil()) - user, err := userUsecase.DetailUser(ctx, userModel) + user, err := userService.DetailUser(ctx, userModel) Expect(err).Should(BeNil()) Expect(user.Name).Should(Equal("name")) Expect(user.Alias).Should(Equal("alias")) @@ -126,11 +126,11 @@ var _ = Describe("Test authentication usecase functions", func() { }) Expect(err).Should(BeNil()) } - users, err := userUsecase.ListUsers(ctx, 0, 10, apisv1.ListUserOptions{Name: "1"}) + users, err := userService.ListUsers(ctx, 0, 10, apisv1.ListUserOptions{Name: "1"}) Expect(err).Should(BeNil()) Expect(users.Total).Should(Equal(int64(1))) - users, err = userUsecase.ListUsers(ctx, 0, 10, apisv1.ListUserOptions{}) + users, err = userService.ListUsers(ctx, 0, 10, apisv1.ListUserOptions{}) Expect(err).Should(BeNil()) Expect(users.Total).Should(Equal(int64(2))) }) @@ -144,13 +144,13 @@ var _ = Describe("Test authentication usecase functions", func() { Password: "password", }) Expect(err).Should(BeNil()) - users, err := userUsecase.ListUsers(ctx, 0, 10, apisv1.ListUserOptions{}) + users, err := userService.ListUsers(ctx, 0, 10, apisv1.ListUserOptions{}) Expect(err).Should(BeNil()) Expect(users.Total).Should(Equal(int64(1))) - err = userUsecase.DeleteUser(ctx, "name") + err = userService.DeleteUser(ctx, "name") Expect(err).Should(BeNil()) - users, err = userUsecase.ListUsers(ctx, 0, 10, apisv1.ListUserOptions{}) + users, err = userService.ListUsers(ctx, 0, 10, apisv1.ListUserOptions{}) Expect(err).Should(BeNil()) Expect(users.Total).Should(Equal(int64(0))) }) @@ -172,7 +172,7 @@ var _ = Describe("Test authentication usecase functions", func() { }, }) Expect(err).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) - _, err = userUsecase.UpdateUser(ctx, userModel, apisv1.UpdateUserRequest{ + _, err = userService.UpdateUser(ctx, userModel, apisv1.UpdateUserRequest{ Alias: "new-alias", Password: "new-password", }) @@ -205,13 +205,13 @@ var _ = Describe("Test authentication usecase functions", func() { err := ds.Add(ctx, userModel) Expect(err).Should(BeNil()) - err = userUsecase.DisableUser(ctx, userModel) + err = userService.DisableUser(ctx, userModel) Expect(err).Should(Equal(bcode.ErrUserAlreadyDisabled)) userModel.Disabled = false err = ds.Put(ctx, userModel) Expect(err).Should(BeNil()) - err = userUsecase.DisableUser(ctx, userModel) + err = userService.DisableUser(ctx, userModel) Expect(err).Should(BeNil()) newUser := &model.User{ @@ -231,13 +231,13 @@ var _ = Describe("Test authentication usecase functions", func() { err := ds.Add(ctx, userModel) Expect(err).Should(BeNil()) - err = userUsecase.EnableUser(ctx, userModel) + err = userService.EnableUser(ctx, userModel) Expect(err).Should(Equal(bcode.ErrUserAlreadyEnabled)) userModel.Disabled = true err = ds.Put(ctx, userModel) Expect(err).Should(BeNil()) - err = userUsecase.EnableUser(ctx, userModel) + err = userService.EnableUser(ctx, userModel) Expect(err).Should(BeNil()) newUser := &model.User{ diff --git a/pkg/apiserver/rest/usecase/velaql.go b/pkg/apiserver/domain/service/velaql.go similarity index 80% rename from pkg/apiserver/rest/usecase/velaql.go rename to pkg/apiserver/domain/service/velaql.go index 166fc7852..826aa47fc 100644 --- a/pkg/apiserver/rest/usecase/velaql.go +++ b/pkg/apiserver/domain/service/velaql.go @@ -14,7 +14,7 @@ limitations under the License. */ -package usecase +package service import ( "context" @@ -22,29 +22,29 @@ import ( "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/cue/packages" "github.com/oam-dev/kubevela/pkg/oam/discoverymapper" "github.com/oam-dev/kubevela/pkg/velaql" ) -// VelaQLUsecase velaQL usecase -type VelaQLUsecase interface { +// VelaQLService velaQL service +type VelaQLService interface { QueryView(context.Context, string) (*apis.VelaQLViewResponse, error) } -type velaQLUsecaseImpl struct { +type velaQLServiceImpl struct { kubeClient client.Client kubeConfig *rest.Config dm discoverymapper.DiscoveryMapper pd *packages.PackageDiscover } -// NewVelaQLUsecase new velaQL usecase -func NewVelaQLUsecase() VelaQLUsecase { +// NewVelaQLService new velaQL service +func NewVelaQLService() VelaQLService { k8sClient, err := clients.GetKubeClient() if err != nil { log.Logger.Fatalf("get kubeclient failure %s", err.Error()) @@ -64,7 +64,7 @@ func NewVelaQLUsecase() VelaQLUsecase { if err != nil { log.Logger.Fatalf("get package discover failure %s", err.Error()) } - return &velaQLUsecaseImpl{ + return &velaQLServiceImpl{ kubeClient: k8sClient, kubeConfig: kubeConfig, dm: dm, @@ -73,7 +73,7 @@ func NewVelaQLUsecase() VelaQLUsecase { } // QueryView get the view query results -func (v *velaQLUsecaseImpl) QueryView(ctx context.Context, velaQL string) (*apis.VelaQLViewResponse, error) { +func (v *velaQLServiceImpl) QueryView(ctx context.Context, velaQL string) (*apis.VelaQLViewResponse, error) { query, err := velaql.ParseVelaQL(velaQL) if err != nil { return nil, bcode.ErrParseVelaQL diff --git a/pkg/apiserver/rest/usecase/webhook.go b/pkg/apiserver/domain/service/webhook.go similarity index 86% rename from pkg/apiserver/rest/usecase/webhook.go rename to pkg/apiserver/domain/service/webhook.go index 8ba2159be..3976cff7e 100644 --- a/pkg/apiserver/rest/usecase/webhook.go +++ b/pkg/apiserver/domain/service/webhook.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -25,36 +25,31 @@ import ( "github.com/emicklei/go-restful/v3" "k8s.io/apimachinery/pkg/runtime" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/policy/envbinding" ) -// WebhookUsecase webhook usecase -type WebhookUsecase interface { +// WebhookService webhook service +type WebhookService interface { HandleApplicationWebhook(ctx context.Context, token string, req *restful.Request) (interface{}, error) } -type webhookUsecaseImpl struct { - ds datastore.DataStore - applicationUsecase ApplicationUsecase +type webhookServiceImpl struct { + Store datastore.DataStore `inject:"datastore"` + ApplicationService ApplicationService `inject:""` } // WebhookHandlers is the webhook handlers var WebhookHandlers []string -// NewWebhookUsecase new webhook usecase -func NewWebhookUsecase(ds datastore.DataStore, - applicationUsecase ApplicationUsecase, -) WebhookUsecase { +// NewWebhookService new webhook service +func NewWebhookService() WebhookService { registerHandlers() - return &webhookUsecaseImpl{ - ds: ds, - applicationUsecase: applicationUsecase, - } + return &webhookServiceImpl{} } func registerHandlers() { @@ -72,20 +67,20 @@ type webhookHandler interface { type customHandlerImpl struct { req apisv1.HandleApplicationTriggerWebhookRequest - w *webhookUsecaseImpl + w *webhookServiceImpl } type acrHandlerImpl struct { req apisv1.HandleApplicationTriggerACRRequest - w *webhookUsecaseImpl + w *webhookServiceImpl } type dockerHubHandlerImpl struct { req apisv1.HandleApplicationTriggerDockerHubRequest - w *webhookUsecaseImpl + w *webhookServiceImpl } -func (c *webhookUsecaseImpl) newCustomHandler(req *restful.Request) (webhookHandler, error) { +func (c *webhookServiceImpl) newCustomHandler(req *restful.Request) (webhookHandler, error) { var webhookReq apisv1.HandleApplicationTriggerWebhookRequest if err := req.ReadEntity(&webhookReq); err != nil { return nil, bcode.ErrInvalidWebhookPayloadBody @@ -96,7 +91,7 @@ func (c *webhookUsecaseImpl) newCustomHandler(req *restful.Request) (webhookHand }, nil } -func (c *webhookUsecaseImpl) newACRHandler(req *restful.Request) (webhookHandler, error) { +func (c *webhookServiceImpl) newACRHandler(req *restful.Request) (webhookHandler, error) { var acrReq apisv1.HandleApplicationTriggerACRRequest if err := req.ReadEntity(&acrReq); err != nil { return nil, bcode.ErrInvalidWebhookPayloadBody @@ -107,7 +102,7 @@ func (c *webhookUsecaseImpl) newACRHandler(req *restful.Request) (webhookHandler }, nil } -func (c *webhookUsecaseImpl) newDockerHubHandler(req *restful.Request) (webhookHandler, error) { +func (c *webhookServiceImpl) newDockerHubHandler(req *restful.Request) (webhookHandler, error) { var dockerHubReq apisv1.HandleApplicationTriggerDockerHubRequest if err := req.ReadEntity(&dockerHubReq); err != nil { return nil, bcode.ErrInvalidWebhookPayloadBody @@ -118,11 +113,11 @@ func (c *webhookUsecaseImpl) newDockerHubHandler(req *restful.Request) (webhookH }, nil } -func (c *webhookUsecaseImpl) HandleApplicationWebhook(ctx context.Context, token string, req *restful.Request) (interface{}, error) { +func (c *webhookServiceImpl) HandleApplicationWebhook(ctx context.Context, token string, req *restful.Request) (interface{}, error) { webhookTrigger := &model.ApplicationTrigger{ Token: token, } - if err := c.ds.Get(ctx, webhookTrigger); err != nil { + if err := c.Store.Get(ctx, webhookTrigger); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil, bcode.ErrInvalidWebhookToken } @@ -131,7 +126,7 @@ func (c *webhookUsecaseImpl) HandleApplicationWebhook(ctx context.Context, token app := &model.Application{ Name: webhookTrigger.AppPrimaryKey, } - if err := c.ds.Get(ctx, app); err != nil { + if err := c.Store.Get(ctx, app); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil, bcode.ErrApplicationNotExist } @@ -173,7 +168,7 @@ func (c *webhookUsecaseImpl) HandleApplicationWebhook(ctx context.Context, token return handler.handle(ctx, webhookTrigger, app) } -func (c *webhookUsecaseImpl) patchComponentProperties(ctx context.Context, component *model.ApplicationComponent, patch *runtime.RawExtension) error { +func (c *webhookServiceImpl) patchComponentProperties(ctx context.Context, component *model.ApplicationComponent, patch *runtime.RawExtension) error { merge, err := envbinding.MergeRawExtension(component.Properties.RawExtension(), patch) if err != nil { return err @@ -183,7 +178,7 @@ func (c *webhookUsecaseImpl) patchComponentProperties(ctx context.Context, compo return err } component.Properties = prop - if err := c.ds.Put(ctx, component); err != nil { + if err := c.Store.Put(ctx, component); err != nil { return err } return nil @@ -195,7 +190,7 @@ func (c *customHandlerImpl) handle(ctx context.Context, webhookTrigger *model.Ap AppPrimaryKey: webhookTrigger.AppPrimaryKey, Name: comp, } - if err := c.w.ds.Get(ctx, component); err != nil { + if err := c.w.Store.Get(ctx, component); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil, bcode.ErrApplicationComponentNotExist } @@ -205,7 +200,7 @@ func (c *customHandlerImpl) handle(ctx context.Context, webhookTrigger *model.Ap return nil, err } } - return c.w.applicationUsecase.Deploy(ctx, app, apisv1.ApplicationDeployRequest{ + return c.w.ApplicationService.Deploy(ctx, app, apisv1.ApplicationDeployRequest{ WorkflowName: webhookTrigger.WorkflowName, Note: "triggered by webhook custom", TriggerType: apisv1.TriggerTypeWebhook, @@ -220,7 +215,7 @@ func (c *customHandlerImpl) install() { func (c *acrHandlerImpl) handle(ctx context.Context, webhookTrigger *model.ApplicationTrigger, app *model.Application) (interface{}, error) { - component, err := getComponent(ctx, c.w.ds, webhookTrigger) + component, err := getComponent(ctx, c.w.Store, webhookTrigger) if err != nil { return nil, err } @@ -232,7 +227,7 @@ func (c *acrHandlerImpl) handle(ctx context.Context, webhookTrigger *model.Appli return nil, err } - return c.w.applicationUsecase.Deploy(ctx, app, apisv1.ApplicationDeployRequest{ + return c.w.ApplicationService.Deploy(ctx, app, apisv1.ApplicationDeployRequest{ WorkflowName: webhookTrigger.WorkflowName, Note: "triggered by webhook acr", TriggerType: apisv1.TriggerTypeWebhook, @@ -270,7 +265,7 @@ func (c dockerHubHandlerImpl) handle(ctx context.Context, trigger *model.Applica Description: "not create event", }, nil } - component, err := getComponent(ctx, c.w.ds, trigger) + component, err := getComponent(ctx, c.w.Store, trigger) if err != nil { return nil, err } @@ -286,7 +281,7 @@ func (c dockerHubHandlerImpl) handle(ctx context.Context, trigger *model.Applica repositoryType = "private" } - if _, err = c.w.applicationUsecase.Deploy(ctx, app, apisv1.ApplicationDeployRequest{ + if _, err = c.w.ApplicationService.Deploy(ctx, app, apisv1.ApplicationDeployRequest{ WorkflowName: trigger.WorkflowName, Note: "triggered by webhook dockerhub", TriggerType: apisv1.TriggerTypeWebhook, @@ -340,10 +335,10 @@ func parseTimeString(t string) time.Time { type harborHandlerImpl struct { req apisv1.HandleApplicationHarborReq - w *webhookUsecaseImpl + w *webhookServiceImpl } -func (c *webhookUsecaseImpl) newHarborHandler(req *restful.Request) (webhookHandler, error) { +func (c *webhookServiceImpl) newHarborHandler(req *restful.Request) (webhookHandler, error) { var harborReq apisv1.HandleApplicationHarborReq if err := req.ReadEntity(&harborReq); err != nil { return nil, bcode.ErrInvalidWebhookPayloadBody @@ -369,7 +364,7 @@ func (c *harborHandlerImpl) handle(ctx context.Context, webhookTrigger *model.Ap imageURL := resources[0].ResourceURL digest := resources[0].Digest tag := resources[0].Tag - component, err := getComponent(ctx, c.w.ds, webhookTrigger) + component, err := getComponent(ctx, c.w.Store, webhookTrigger) if err != nil { return nil, err } @@ -379,7 +374,7 @@ func (c *harborHandlerImpl) handle(ctx context.Context, webhookTrigger *model.Ap }); err != nil { return nil, err } - return c.w.applicationUsecase.Deploy(ctx, app, apisv1.ApplicationDeployRequest{ + return c.w.ApplicationService.Deploy(ctx, app, apisv1.ApplicationDeployRequest{ WorkflowName: webhookTrigger.WorkflowName, Note: "triggered by webhook harbor", TriggerType: apisv1.TriggerTypeWebhook, @@ -405,10 +400,10 @@ func (c *harborHandlerImpl) handle(ctx context.Context, webhookTrigger *model.Ap type jfrogHandlerImpl struct { req apisv1.HandleApplicationTriggerJFrogRequest - w *webhookUsecaseImpl + w *webhookServiceImpl } -func (c *webhookUsecaseImpl) newJFrogHandler(req *restful.Request) (webhookHandler, error) { +func (c *webhookServiceImpl) newJFrogHandler(req *restful.Request) (webhookHandler, error) { var jfrogReq apisv1.HandleApplicationTriggerJFrogRequest if err := req.ReadEntity(&jfrogReq); err != nil { return nil, bcode.ErrInvalidWebhookPayloadBody @@ -426,7 +421,7 @@ func (c *webhookUsecaseImpl) newJFrogHandler(req *restful.Request) (webhookHandl func (j *jfrogHandlerImpl) handle(ctx context.Context, webhookTrigger *model.ApplicationTrigger, app *model.Application) (interface{}, error) { jfrogReq := j.req - component, err := getComponent(ctx, j.w.ds, webhookTrigger) + component, err := getComponent(ctx, j.w.Store, webhookTrigger) if err != nil { return nil, err } @@ -440,7 +435,7 @@ func (j *jfrogHandlerImpl) handle(ctx context.Context, webhookTrigger *model.App return nil, err } - return j.w.applicationUsecase.Deploy(ctx, app, apisv1.ApplicationDeployRequest{ + return j.w.ApplicationService.Deploy(ctx, app, apisv1.ApplicationDeployRequest{ WorkflowName: webhookTrigger.WorkflowName, Note: "triggered by webhook jfrog", TriggerType: apisv1.TriggerTypeWebhook, diff --git a/pkg/apiserver/rest/usecase/webhook_test.go b/pkg/apiserver/domain/service/webhook_test.go similarity index 73% rename from pkg/apiserver/rest/usecase/webhook_test.go rename to pkg/apiserver/domain/service/webhook_test.go index ffb952053..62669054a 100644 --- a/pkg/apiserver/rest/usecase/webhook_test.go +++ b/pkg/apiserver/domain/service/webhook_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "bytes" @@ -28,51 +28,51 @@ import ( corev1 "k8s.io/api/core/v1" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" "github.com/oam-dev/kubevela/pkg/oam/util" "github.com/oam-dev/kubevela/pkg/utils/apply" ) -var _ = Describe("Test application usecase function", func() { +var _ = Describe("Test application service function", func() { var ( - appUsecase *applicationUsecaseImpl - workflowUsecase *workflowUsecaseImpl - envUsecase *envUsecaseImpl - envBindingUsecase *envBindingUsecaseImpl - targetUsecase *targetUsecaseImpl - definitionUsecase *definitionUsecaseImpl - projectUsecase *projectUsecaseImpl - webhookUsecase *webhookUsecaseImpl + appService *applicationServiceImpl + workflowService *workflowServiceImpl + envService *envServiceImpl + envBindingService *envBindingServiceImpl + targetService *targetServiceImpl + definitionService *definitionServiceImpl + projectService *projectServiceImpl + webhookService *webhookServiceImpl ) BeforeEach(func() { ds, err := NewDatastore(datastore.Config{Type: "kubeapi", Database: "app-test-kubevela"}) Expect(ds).ToNot(BeNil()) Expect(err).Should(BeNil()) - workflowUsecase = &workflowUsecaseImpl{ds: ds, envUsecase: envUsecase} - definitionUsecase = &definitionUsecaseImpl{kubeClient: k8sClient} - envBindingUsecase = &envBindingUsecaseImpl{ds: ds, envUsecase: envUsecase, workflowUsecase: workflowUsecase, kubeClient: k8sClient, definitionUsecase: definitionUsecase} - targetUsecase = &targetUsecaseImpl{ds: ds, k8sClient: k8sClient} - rbacUsecase := &rbacUsecaseImpl{ds: ds} - projectUsecase = &projectUsecaseImpl{ds: ds, k8sClient: k8sClient, rbacUsecase: rbacUsecase} - envUsecase = &envUsecaseImpl{ds: ds, kubeClient: k8sClient, projectUsecase: projectUsecase} - appUsecase = &applicationUsecaseImpl{ - ds: ds, - workflowUsecase: workflowUsecase, - apply: apply.NewAPIApplicator(k8sClient), - kubeClient: k8sClient, - envBindingUsecase: envBindingUsecase, - envUsecase: envUsecase, - definitionUsecase: definitionUsecase, - targetUsecase: targetUsecase, - projectUsecase: projectUsecase, + workflowService = &workflowServiceImpl{Store: ds, EnvService: envService} + definitionService = &definitionServiceImpl{KubeClient: k8sClient} + envBindingService = &envBindingServiceImpl{Store: ds, EnvService: envService, WorkflowService: workflowService, KubeClient: k8sClient, DefinitionService: definitionService} + targetService = &targetServiceImpl{Store: ds, K8sClient: k8sClient} + rbacService := &rbacServiceImpl{Store: ds} + projectService = &projectServiceImpl{Store: ds, K8sClient: k8sClient, RbacService: rbacService} + envService = &envServiceImpl{Store: ds, KubeClient: k8sClient, ProjectService: projectService} + appService = &applicationServiceImpl{ + Store: ds, + WorkflowService: workflowService, + Apply: apply.NewAPIApplicator(k8sClient), + KubeClient: k8sClient, + EnvBindingService: envBindingService, + EnvService: envService, + DefinitionService: definitionService, + TargetService: targetService, + ProjectService: projectService, } - webhookUsecase = &webhookUsecaseImpl{ - ds: ds, - applicationUsecase: appUsecase, + webhookService = &webhookServiceImpl{ + Store: ds, + ApplicationService: appService, } }) @@ -82,13 +82,13 @@ var _ = Describe("Test application usecase function", func() { err := k8sClient.Create(context.TODO(), &ns) Expect(err).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) - _, err = projectUsecase.CreateProject(context.TODO(), apisv1.CreateProjectRequest{Name: "project-webhook"}) + _, err = projectService.CreateProject(context.TODO(), apisv1.CreateProjectRequest{Name: "project-webhook"}) Expect(err).Should(BeNil()) - _, err = targetUsecase.CreateTarget(context.TODO(), apisv1.CreateTargetRequest{Name: "dev-target-webhook", Project: "project-webhook"}) + _, err = targetService.CreateTarget(context.TODO(), apisv1.CreateTargetRequest{Name: "dev-target-webhook", Project: "project-webhook"}) Expect(err).Should(BeNil()) - _, err = envUsecase.CreateEnv(context.TODO(), apisv1.CreateEnvRequest{Name: "webhook-dev", Namespace: "webhook-dev", Targets: []string{"dev-target-webhook"}, Project: "project-webhook"}) + _, err = envService.CreateEnv(context.TODO(), apisv1.CreateEnvRequest{Name: "webhook-dev", Namespace: "webhook-dev", Targets: []string{"dev-target-webhook"}, Project: "project-webhook"}) Expect(err).Should(BeNil()) Expect(err).Should(BeNil()) @@ -104,22 +104,22 @@ var _ = Describe("Test application usecase function", func() { ComponentType: "webservice", }, } - _, err = appUsecase.CreateApplication(context.TODO(), req) + _, err = appService.CreateApplication(context.TODO(), req) Expect(err).Should(BeNil()) - appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-webhook") + appModel, err := appService.GetApplication(context.TODO(), "test-app-webhook") Expect(err).Should(BeNil()) - _, err = webhookUsecase.HandleApplicationWebhook(context.TODO(), "invalid-token", nil) + _, err = webhookService.HandleApplicationWebhook(context.TODO(), "invalid-token", nil) Expect(err).Should(Equal(bcode.ErrInvalidWebhookToken)) - triggers, err := appUsecase.ListApplicationTriggers(context.TODO(), appModel) + triggers, err := appService.ListApplicationTriggers(context.TODO(), appModel) Expect(err).Should(BeNil()) invalidReq, err := http.NewRequest("post", "/", bytes.NewBuffer([]byte(`{"upgrade": "test"}`))) invalidReq.Header.Add(restful.HEADER_ContentType, "application/json") Expect(err).Should(BeNil()) - _, err = webhookUsecase.HandleApplicationWebhook(context.TODO(), triggers[0].Token, restful.NewRequest(invalidReq)) + _, err = webhookService.HandleApplicationWebhook(context.TODO(), triggers[0].Token, restful.NewRequest(invalidReq)) Expect(err).Should(Equal(bcode.ErrInvalidWebhookPayloadBody)) By("Test HandleApplicationWebhook function with custom payload") @@ -143,10 +143,10 @@ var _ = Describe("Test application usecase function", func() { httpreq, err := http.NewRequest("post", "/", bytes.NewBuffer(body)) httpreq.Header.Add(restful.HEADER_ContentType, "application/json") Expect(err).Should(BeNil()) - res, err := webhookUsecase.HandleApplicationWebhook(context.TODO(), triggers[0].Token, restful.NewRequest(httpreq)) + res, err := webhookService.HandleApplicationWebhook(context.TODO(), triggers[0].Token, restful.NewRequest(httpreq)) Expect(err).Should(BeNil()) appDeployRes := res.(*apisv1.ApplicationDeployResponse) - comp, err := appUsecase.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook") + comp, err := appService.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook") Expect(err).Should(BeNil()) Expect((*comp.Properties)["image"]).Should(Equal("test-image")) Expect((*comp.Properties)["test1"]).Should(Equal(map[string]interface{}{ @@ -157,14 +157,14 @@ var _ = Describe("Test application usecase function", func() { AppPrimaryKey: "test-app-webhook", Version: appDeployRes.Version, } - err = webhookUsecase.ds.Get(context.TODO(), revision) + err = webhookService.Store.Get(context.TODO(), revision) Expect(err).Should(BeNil()) Expect(revision.CodeInfo.Commit).Should(Equal("test-commit")) Expect(revision.CodeInfo.Branch).Should(Equal("test-branch")) Expect(revision.CodeInfo.User).Should(Equal("test-user")) By("Test HandleApplicationWebhook function with ACR payload") - acrTrigger, err := appUsecase.CreateApplicationTrigger(context.TODO(), appModel, apisv1.CreateApplicationTriggerRequest{ + acrTrigger, err := appService.CreateApplicationTrigger(context.TODO(), appModel, apisv1.CreateApplicationTriggerRequest{ Name: "test-acr", PayloadType: "acr", Type: "webhook", @@ -190,14 +190,14 @@ var _ = Describe("Test application usecase function", func() { httpreq, err = http.NewRequest("post", "/", bytes.NewBuffer(body)) httpreq.Header.Add(restful.HEADER_ContentType, "application/json") Expect(err).Should(BeNil()) - _, err = webhookUsecase.HandleApplicationWebhook(context.TODO(), acrTrigger.Token, restful.NewRequest(httpreq)) + _, err = webhookService.HandleApplicationWebhook(context.TODO(), acrTrigger.Token, restful.NewRequest(httpreq)) Expect(err).Should(BeNil()) - comp, err = appUsecase.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook") + comp, err = appService.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook") Expect(err).Should(BeNil()) Expect((*comp.Properties)["image"]).Should(Equal("registry.test-region.aliyuncs.com/test-namespace/test-repo:test-tag")) By("Test HandleApplicationWebhook function with harbor payload") - harborTrigger, err := appUsecase.CreateApplicationTrigger(context.TODO(), appModel, apisv1.CreateApplicationTriggerRequest{ + harborTrigger, err := appService.CreateApplicationTrigger(context.TODO(), appModel, apisv1.CreateApplicationTriggerRequest{ Name: "test-harbor", PayloadType: "harbor", Type: "webhook", @@ -228,14 +228,14 @@ var _ = Describe("Test application usecase function", func() { httpreq, err = http.NewRequest("post", "/", bytes.NewBuffer(body)) httpreq.Header.Add(restful.HEADER_ContentType, "application/json") Expect(err).Should(BeNil()) - _, err = webhookUsecase.HandleApplicationWebhook(context.TODO(), harborTrigger.Token, restful.NewRequest(httpreq)) + _, err = webhookService.HandleApplicationWebhook(context.TODO(), harborTrigger.Token, restful.NewRequest(httpreq)) Expect(err).Should(BeNil()) - comp, err = appUsecase.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook") + comp, err = appService.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook") Expect(err).Should(BeNil()) Expect((*comp.Properties)["image"]).Should(Equal("harbor.server/test-pro/test-repo:test-tag")) By("Test HandleApplicationWebhook function with dockerhub payload") - dockerhubTrigger, err := appUsecase.CreateApplicationTrigger(context.TODO(), appModel, apisv1.CreateApplicationTriggerRequest{ + dockerhubTrigger, err := appService.CreateApplicationTrigger(context.TODO(), appModel, apisv1.CreateApplicationTriggerRequest{ Name: "test-dockerhub", PayloadType: "dockerhub", Type: "webhook", @@ -260,14 +260,14 @@ var _ = Describe("Test application usecase function", func() { httpreq, err = http.NewRequest("post", "/", bytes.NewBuffer(body)) httpreq.Header.Add(restful.HEADER_ContentType, "application/json") Expect(err).Should(BeNil()) - _, err = webhookUsecase.HandleApplicationWebhook(context.TODO(), dockerhubTrigger.Token, restful.NewRequest(httpreq)) + _, err = webhookService.HandleApplicationWebhook(context.TODO(), dockerhubTrigger.Token, restful.NewRequest(httpreq)) Expect(err).Should(BeNil()) - comp, err = appUsecase.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook") + comp, err = appService.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook") Expect(err).Should(BeNil()) Expect((*comp.Properties)["image"]).Should(Equal("docker.io/test-namespace/test-repo:test-tag")) By("Test HandleApplicationWebhook function with jfrog payload without header of X-JFrogURL") - jfrogTrigger, err := appUsecase.CreateApplicationTrigger(context.TODO(), appModel, apisv1.CreateApplicationTriggerRequest{ + jfrogTrigger, err := appService.CreateApplicationTrigger(context.TODO(), appModel, apisv1.CreateApplicationTriggerRequest{ Name: "test-jfrog", PayloadType: "jfrog", Type: "webhook", @@ -289,9 +289,9 @@ var _ = Describe("Test application usecase function", func() { httpreq, err = http.NewRequest("post", "/", bytes.NewBuffer(body)) httpreq.Header.Add(restful.HEADER_ContentType, "application/json") Expect(err).Should(BeNil()) - _, err = webhookUsecase.HandleApplicationWebhook(context.TODO(), jfrogTrigger.Token, restful.NewRequest(httpreq)) + _, err = webhookService.HandleApplicationWebhook(context.TODO(), jfrogTrigger.Token, restful.NewRequest(httpreq)) Expect(err).Should(BeNil()) - comp, err = appUsecase.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook") + comp, err = appService.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook") Expect(err).Should(BeNil()) Expect((*comp.Properties)["image"]).Should(Equal("test-repo/test-image:test-tag")) @@ -300,9 +300,9 @@ var _ = Describe("Test application usecase function", func() { Expect(err).Should(BeNil()) httpreq.Header.Add(restful.HEADER_ContentType, "application/json") httpreq.Header.Add("X-JFrogURL", "test-addr") - _, err = webhookUsecase.HandleApplicationWebhook(context.TODO(), jfrogTrigger.Token, restful.NewRequest(httpreq)) + _, err = webhookService.HandleApplicationWebhook(context.TODO(), jfrogTrigger.Token, restful.NewRequest(httpreq)) Expect(err).Should(BeNil()) - comp, err = appUsecase.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook") + comp, err = appService.GetApplicationComponent(context.TODO(), appModel, "component-name-webhook") Expect(err).Should(BeNil()) Expect((*comp.Properties)["image"]).Should(Equal("test-addr/test-repo/test-image:test-tag")) }) diff --git a/pkg/apiserver/rest/usecase/workflow.go b/pkg/apiserver/domain/service/workflow.go similarity index 76% rename from pkg/apiserver/rest/usecase/workflow.go rename to pkg/apiserver/domain/service/workflow.go index 42101393b..9befe37ed 100644 --- a/pkg/apiserver/rest/usecase/workflow.go +++ b/pkg/apiserver/domain/service/workflow.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -31,21 +31,22 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/repository" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + assembler "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/assembler/v1" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/util" utils2 "github.com/oam-dev/kubevela/pkg/utils" "github.com/oam-dev/kubevela/pkg/utils/apply" ) -// WorkflowUsecase workflow manage api -type WorkflowUsecase interface { +// WorkflowService workflow manage api +type WorkflowService interface { ListApplicationWorkflow(ctx context.Context, app *model.Application) ([]*apisv1.WorkflowBase, error) GetWorkflow(ctx context.Context, app *model.Application, workflowName string) (*model.Workflow, error) DetailWorkflow(ctx context.Context, workflow *model.Workflow) (*apisv1.DetailWorkflowResponse, error) @@ -64,29 +65,20 @@ type WorkflowUsecase interface { CountWorkflow(ctx context.Context, app *model.Application) int64 } -// NewWorkflowUsecase new workflow usecase -func NewWorkflowUsecase(ds datastore.DataStore, envUsecase EnvUsecase) WorkflowUsecase { - kubecli, err := clients.GetKubeClient() - if err != nil { - log.Logger.Fatalf("get kubeclient failure %s", err.Error()) - } - return &workflowUsecaseImpl{ - ds: ds, - kubeClient: kubecli, - apply: apply.NewAPIApplicator(kubecli), - envUsecase: envUsecase, - } +// NewWorkflowService new workflow service +func NewWorkflowService() WorkflowService { + return &workflowServiceImpl{} } -type workflowUsecaseImpl struct { - ds datastore.DataStore - kubeClient client.Client - apply apply.Applicator - envUsecase EnvUsecase +type workflowServiceImpl struct { + Store datastore.DataStore `inject:"datastore"` + KubeClient client.Client `inject:"kubeClient"` + Apply apply.Applicator `inject:"apply"` + EnvService EnvService `inject:""` } // DeleteWorkflow delete application workflow -func (w *workflowUsecaseImpl) DeleteWorkflow(ctx context.Context, app *model.Application, workflowName string) error { +func (w *workflowServiceImpl) DeleteWorkflow(ctx context.Context, app *model.Application, workflowName string) error { var workflow = &model.Workflow{ Name: workflowName, AppPrimaryKey: app.PrimaryKey(), @@ -95,16 +87,16 @@ func (w *workflowUsecaseImpl) DeleteWorkflow(ctx context.Context, app *model.App AppPrimaryKey: workflow.AppPrimaryKey, WorkflowName: workflow.Name, } - records, err := w.ds.List(ctx, &record, &datastore.ListOptions{}) + records, err := w.Store.List(ctx, &record, &datastore.ListOptions{}) if err != nil { log.Logger.Errorf("list workflow %s record failure %s", utils2.Sanitize(workflow.PrimaryKey()), err.Error()) } for _, record := range records { - if err := w.ds.Delete(ctx, record); err != nil { + if err := w.Store.Delete(ctx, record); err != nil { log.Logger.Errorf("delete workflow record %s failure %s", record.PrimaryKey(), err.Error()) } } - if err := w.ds.Delete(ctx, workflow); err != nil { + if err := w.Store.Delete(ctx, workflow); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return bcode.ErrWorkflowNotExist } @@ -113,12 +105,12 @@ func (w *workflowUsecaseImpl) DeleteWorkflow(ctx context.Context, app *model.App return nil } -func (w *workflowUsecaseImpl) DeleteWorkflowByApp(ctx context.Context, app *model.Application) error { +func (w *workflowServiceImpl) DeleteWorkflowByApp(ctx context.Context, app *model.Application) error { var workflow = &model.Workflow{ AppPrimaryKey: app.PrimaryKey(), } - workflows, err := w.ds.List(ctx, workflow, &datastore.ListOptions{}) + workflows, err := w.Store.List(ctx, workflow, &datastore.ListOptions{}) if err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil @@ -131,23 +123,23 @@ func (w *workflowUsecaseImpl) DeleteWorkflowByApp(ctx context.Context, app *mode AppPrimaryKey: workflow.AppPrimaryKey, WorkflowName: workflow.Name, } - records, err := w.ds.List(ctx, &record, &datastore.ListOptions{}) + records, err := w.Store.List(ctx, &record, &datastore.ListOptions{}) if err != nil { log.Logger.Errorf("list workflow %s record failure %s", workflow.PrimaryKey(), err.Error()) } for _, record := range records { - if err := w.ds.Delete(ctx, record); err != nil { + if err := w.Store.Delete(ctx, record); err != nil { log.Logger.Errorf("delete workflow record %s failure %s", record.PrimaryKey(), err.Error()) } } - if err := w.ds.Delete(ctx, workflow); err != nil { + if err := w.Store.Delete(ctx, workflow); err != nil { log.Logger.Errorf("delete workflow %s failure %s", workflow.PrimaryKey(), err.Error()) } } return nil } -func (w *workflowUsecaseImpl) CreateOrUpdateWorkflow(ctx context.Context, app *model.Application, req apisv1.CreateWorkflowRequest) (*apisv1.DetailWorkflowResponse, error) { +func (w *workflowServiceImpl) CreateOrUpdateWorkflow(ctx context.Context, app *model.Application, req apisv1.CreateWorkflowRequest) (*apisv1.DetailWorkflowResponse, error) { if req.EnvName == "" { return nil, bcode.ErrWorkflowNoEnv } @@ -178,7 +170,7 @@ func (w *workflowUsecaseImpl) CreateOrUpdateWorkflow(ctx context.Context, app *m workflow.Alias = req.Alias workflow.Description = req.Description workflow.Default = req.Default - if err := w.ds.Put(ctx, workflow); err != nil { + if err := w.Store.Put(ctx, workflow); err != nil { return nil, err } } else { @@ -193,21 +185,15 @@ func (w *workflowUsecaseImpl) CreateOrUpdateWorkflow(ctx context.Context, app *m AppPrimaryKey: app.PrimaryKey(), } log.Logger.Infof("create workflow %s for app %s", utils2.Sanitize(req.Name), utils2.Sanitize(app.PrimaryKey())) - if err := w.ds.Add(ctx, workflow); err != nil { + if err := w.Store.Add(ctx, workflow); err != nil { return nil, err } } return w.DetailWorkflow(ctx, workflow) } -// updateWorkflowSteps will update workflow with new steps -func updateWorkflowSteps(ctx context.Context, ds datastore.DataStore, workflow *model.Workflow, steps []model.WorkflowStep) error { - workflow.Steps = steps - return ds.Put(ctx, workflow) -} - -func (w *workflowUsecaseImpl) UpdateWorkflow(ctx context.Context, workflow *model.Workflow, req apisv1.UpdateWorkflowRequest) (*apisv1.DetailWorkflowResponse, error) { - modeSteps, err := convertAPIStep2ModelStep(req.Steps) +func (w *workflowServiceImpl) UpdateWorkflow(ctx context.Context, workflow *model.Workflow, req apisv1.UpdateWorkflowRequest) (*apisv1.DetailWorkflowResponse, error) { + modeSteps, err := assembler.CreateWorkflowStepModel(req.Steps) if err != nil { return nil, err } @@ -216,50 +202,50 @@ func (w *workflowUsecaseImpl) UpdateWorkflow(ctx context.Context, workflow *mode if req.Default != nil { workflow.Default = req.Default } - if err := updateWorkflowSteps(ctx, w.ds, workflow, modeSteps); err != nil { + if err := repository.UpdateWorkflowSteps(ctx, w.Store, workflow, modeSteps); err != nil { return nil, err } return w.DetailWorkflow(ctx, workflow) } // DetailWorkflow detail workflow -func (w *workflowUsecaseImpl) DetailWorkflow(ctx context.Context, workflow *model.Workflow) (*apisv1.DetailWorkflowResponse, error) { +func (w *workflowServiceImpl) DetailWorkflow(ctx context.Context, workflow *model.Workflow) (*apisv1.DetailWorkflowResponse, error) { return &apisv1.DetailWorkflowResponse{ - WorkflowBase: convertWorkflowBase(workflow), + WorkflowBase: assembler.ConvertWorkflowBase(workflow), }, nil } // GetWorkflow get workflow model -func (w *workflowUsecaseImpl) GetWorkflow(ctx context.Context, app *model.Application, workflowName string) (*model.Workflow, error) { - return getWorkflowForApp(ctx, w.ds, app, workflowName) +func (w *workflowServiceImpl) GetWorkflow(ctx context.Context, app *model.Application, workflowName string) (*model.Workflow, error) { + return repository.GetWorkflowForApp(ctx, w.Store, app, workflowName) } // ListApplicationWorkflow list application workflows -func (w *workflowUsecaseImpl) ListApplicationWorkflow(ctx context.Context, app *model.Application) ([]*apisv1.WorkflowBase, error) { +func (w *workflowServiceImpl) ListApplicationWorkflow(ctx context.Context, app *model.Application) ([]*apisv1.WorkflowBase, error) { var workflow = model.Workflow{ AppPrimaryKey: app.PrimaryKey(), } - workflows, err := w.ds.List(ctx, &workflow, &datastore.ListOptions{}) + workflows, err := w.Store.List(ctx, &workflow, &datastore.ListOptions{}) if err != nil { return nil, err } var list []*apisv1.WorkflowBase for _, workflow := range workflows { wm := workflow.(*model.Workflow) - base := convertWorkflowBase(wm) + base := assembler.ConvertWorkflowBase(wm) list = append(list, &base) } return list, nil } // GetApplicationDefaultWorkflow get application default workflow -func (w *workflowUsecaseImpl) GetApplicationDefaultWorkflow(ctx context.Context, app *model.Application) (*model.Workflow, error) { +func (w *workflowServiceImpl) GetApplicationDefaultWorkflow(ctx context.Context, app *model.Application) (*model.Workflow, error) { var defaultEnable = true var workflow = model.Workflow{ AppPrimaryKey: app.PrimaryKey(), Default: &defaultEnable, } - workflows, err := w.ds.List(ctx, &workflow, &datastore.ListOptions{}) + workflows, err := w.Store.List(ctx, &workflow, &datastore.ListOptions{}) if err != nil { return nil, err } @@ -270,12 +256,12 @@ func (w *workflowUsecaseImpl) GetApplicationDefaultWorkflow(ctx context.Context, } // ListWorkflowRecords list workflow record -func (w *workflowUsecaseImpl) ListWorkflowRecords(ctx context.Context, workflow *model.Workflow, page, pageSize int) (*apisv1.ListWorkflowRecordsResponse, error) { +func (w *workflowServiceImpl) ListWorkflowRecords(ctx context.Context, workflow *model.Workflow, page, pageSize int) (*apisv1.ListWorkflowRecordsResponse, error) { var record = model.WorkflowRecord{ AppPrimaryKey: workflow.AppPrimaryKey, WorkflowName: workflow.Name, } - records, err := w.ds.List(ctx, &record, &datastore.ListOptions{Page: page, PageSize: pageSize}) + records, err := w.Store.List(ctx, &record, &datastore.ListOptions{Page: page, PageSize: pageSize}) if err != nil { return nil, err } @@ -286,10 +272,10 @@ func (w *workflowUsecaseImpl) ListWorkflowRecords(ctx context.Context, workflow for _, raw := range records { record, ok := raw.(*model.WorkflowRecord) if ok { - resp.Records = append(resp.Records, *convertFromRecordModel(record)) + resp.Records = append(resp.Records, *assembler.ConvertFromRecordModel(record)) } } - count, err := w.ds.Count(ctx, &record, nil) + count, err := w.Store.Count(ctx, &record, nil) if err != nil { return nil, err } @@ -299,13 +285,13 @@ func (w *workflowUsecaseImpl) ListWorkflowRecords(ctx context.Context, workflow } // DetailWorkflowRecord get workflow record detail with name -func (w *workflowUsecaseImpl) DetailWorkflowRecord(ctx context.Context, workflow *model.Workflow, recordName string) (*apisv1.DetailWorkflowRecordResponse, error) { +func (w *workflowServiceImpl) DetailWorkflowRecord(ctx context.Context, workflow *model.Workflow, recordName string) (*apisv1.DetailWorkflowRecordResponse, error) { var record = model.WorkflowRecord{ AppPrimaryKey: workflow.AppPrimaryKey, WorkflowName: workflow.Name, Name: recordName, } - err := w.ds.Get(ctx, &record) + err := w.Store.Get(ctx, &record) if err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil, bcode.ErrWorkflowRecordNotExist @@ -317,7 +303,7 @@ func (w *workflowUsecaseImpl) DetailWorkflowRecord(ctx context.Context, workflow AppPrimaryKey: record.AppPrimaryKey, Version: record.RevisionPrimaryKey, } - err = w.ds.Get(ctx, &revision) + err = w.Store.Get(ctx, &revision) if err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return nil, bcode.ErrApplicationRevisionNotExist @@ -326,7 +312,7 @@ func (w *workflowUsecaseImpl) DetailWorkflowRecord(ctx context.Context, workflow } return &apisv1.DetailWorkflowRecordResponse{ - WorkflowRecord: *convertFromRecordModel(&record), + WorkflowRecord: *assembler.ConvertFromRecordModel(&record), DeployTime: revision.CreateTime, DeployUser: revision.DeployUser, Note: revision.Note, @@ -334,12 +320,12 @@ func (w *workflowUsecaseImpl) DetailWorkflowRecord(ctx context.Context, workflow }, nil } -func (w *workflowUsecaseImpl) SyncWorkflowRecord(ctx context.Context) error { +func (w *workflowServiceImpl) SyncWorkflowRecord(ctx context.Context) error { var record = model.WorkflowRecord{ Finished: "false", } // list all unfinished workflow records - records, err := w.ds.List(ctx, &record, &datastore.ListOptions{}) + records, err := w.Store.List(ctx, &record, &datastore.ListOptions{}) if err != nil { return err } @@ -351,12 +337,12 @@ func (w *workflowUsecaseImpl) SyncWorkflowRecord(ctx context.Context) error { Name: record.WorkflowName, AppPrimaryKey: record.AppPrimaryKey, } - if err := w.ds.Get(ctx, workflow); err != nil { + if err := w.Store.Get(ctx, workflow); err != nil { klog.ErrorS(err, "failed to get workflow", "app name", record.AppPrimaryKey, "workflow name", record.WorkflowName, "record name", record.Name) continue } appName := record.AppPrimaryKey - if err := w.kubeClient.Get(ctx, types.NamespacedName{ + if err := w.KubeClient.Get(ctx, types.NamespacedName{ Name: appName, Namespace: record.Namespace, }, app); err != nil { @@ -374,7 +360,7 @@ func (w *workflowUsecaseImpl) SyncWorkflowRecord(ctx context.Context) error { // try to sync the status from the controller revision cr := &appsv1.ControllerRevision{} - if err := w.kubeClient.Get(ctx, types.NamespacedName{ + if err := w.KubeClient.Get(ctx, types.NamespacedName{ Name: fmt.Sprintf("record-%s-%s", appName, record.Name), Namespace: record.Namespace, }, cr); err != nil { @@ -396,12 +382,12 @@ func (w *workflowUsecaseImpl) SyncWorkflowRecord(ctx context.Context) error { return nil } -func (w *workflowUsecaseImpl) syncWorkflowStatus(ctx context.Context, app *v1beta1.Application, recordName, source string) error { +func (w *workflowServiceImpl) syncWorkflowStatus(ctx context.Context, app *v1beta1.Application, recordName, source string) error { var record = &model.WorkflowRecord{ AppPrimaryKey: app.Annotations[oam.AnnotationAppName], Name: recordName, } - if err := w.ds.Get(ctx, record); err != nil { + if err := w.Store.Get(ctx, record); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return bcode.ErrWorkflowRecordNotExist } @@ -412,7 +398,7 @@ func (w *workflowUsecaseImpl) syncWorkflowStatus(ctx context.Context, app *v1bet Version: record.RevisionPrimaryKey, } - if err := w.ds.Get(ctx, revision); err != nil { + if err := w.Store.Get(ctx, revision); err != nil { if errors.Is(err, datastore.ErrRecordNotExist) { return bcode.ErrApplicationRevisionNotExist } @@ -445,12 +431,12 @@ func (w *workflowUsecaseImpl) syncWorkflowStatus(ctx context.Context, app *v1bet } record.Finished = strconv.FormatBool(status.Finished) - if err := w.ds.Put(ctx, record); err != nil { + if err := w.Store.Put(ctx, record); err != nil { return err } revision.Status = summaryStatus - if err := w.ds.Put(ctx, revision); err != nil { + if err := w.Store.Put(ctx, revision); err != nil { return err } } @@ -462,7 +448,7 @@ func (w *workflowUsecaseImpl) syncWorkflowStatus(ctx context.Context, app *v1bet return nil } -func (w *workflowUsecaseImpl) CreateWorkflowRecord(ctx context.Context, appModel *model.Application, app *v1beta1.Application, workflow *model.Workflow) error { +func (w *workflowServiceImpl) CreateWorkflowRecord(ctx context.Context, appModel *model.Application, app *v1beta1.Application, workflow *model.Workflow) error { if app.Annotations == nil { return fmt.Errorf("empty annotations in application") } @@ -481,7 +467,7 @@ func (w *workflowUsecaseImpl) CreateWorkflowRecord(ctx context.Context, appModel } } - if err := w.ds.Add(ctx, &model.WorkflowRecord{ + if err := w.Store.Add(ctx, &model.WorkflowRecord{ WorkflowName: workflow.Name, WorkflowAlias: workflow.Alias, AppPrimaryKey: appModel.PrimaryKey(), @@ -496,7 +482,7 @@ func (w *workflowUsecaseImpl) CreateWorkflowRecord(ctx context.Context, appModel return err } - if err := resetRevisionsAndRecords(ctx, w.ds, appModel.PrimaryKey(), workflow.Name, app.Annotations[oam.AnnotationDeployVersion], app.Annotations[oam.AnnotationPublishVersion]); err != nil { + if err := resetRevisionsAndRecords(ctx, w.Store, appModel.PrimaryKey(), workflow.Name, app.Annotations[oam.AnnotationDeployVersion], app.Annotations[oam.AnnotationPublishVersion]); err != nil { return err } @@ -560,22 +546,22 @@ func resetRevisionsAndRecords(ctx context.Context, ds datastore.DataStore, appNa return nil } -func (w *workflowUsecaseImpl) CountWorkflow(ctx context.Context, app *model.Application) int64 { - count, err := w.ds.Count(ctx, &model.Workflow{AppPrimaryKey: app.PrimaryKey()}, &datastore.FilterOptions{}) +func (w *workflowServiceImpl) CountWorkflow(ctx context.Context, app *model.Application) int64 { + count, err := w.Store.Count(ctx, &model.Workflow{AppPrimaryKey: app.PrimaryKey()}, &datastore.FilterOptions{}) if err != nil { log.Logger.Errorf("count app %s workflow failure %s", app.PrimaryKey(), err.Error()) } return count } -func (w *workflowUsecaseImpl) ResumeRecord(ctx context.Context, appModel *model.Application, workflow *model.Workflow, recordName string) error { +func (w *workflowServiceImpl) ResumeRecord(ctx context.Context, appModel *model.Application, workflow *model.Workflow, recordName string) error { oamApp, err := w.checkRecordRunning(ctx, appModel, workflow.EnvName) if err != nil { return err } oamApp.Status.Workflow.Suspend = false - if err := w.kubeClient.Status().Patch(ctx, oamApp, client.Merge); err != nil { + if err := w.KubeClient.Status().Patch(ctx, oamApp, client.Merge); err != nil { return err } if err := w.syncWorkflowStatus(ctx, oamApp, recordName, oamApp.Name); err != nil { @@ -585,14 +571,14 @@ func (w *workflowUsecaseImpl) ResumeRecord(ctx context.Context, appModel *model. return nil } -func (w *workflowUsecaseImpl) TerminateRecord(ctx context.Context, appModel *model.Application, workflow *model.Workflow, recordName string) error { +func (w *workflowServiceImpl) TerminateRecord(ctx context.Context, appModel *model.Application, workflow *model.Workflow, recordName string) error { oamApp, err := w.checkRecordRunning(ctx, appModel, workflow.EnvName) if err != nil { return err } oamApp.Status.Workflow.Terminated = true - if err := w.kubeClient.Status().Patch(ctx, oamApp, client.Merge); err != nil { + if err := w.KubeClient.Status().Patch(ctx, oamApp, client.Merge); err != nil { return err } if err := w.syncWorkflowStatus(ctx, oamApp, recordName, oamApp.Name); err != nil { @@ -602,7 +588,7 @@ func (w *workflowUsecaseImpl) TerminateRecord(ctx context.Context, appModel *mod return nil } -func (w *workflowUsecaseImpl) RollbackRecord(ctx context.Context, appModel *model.Application, workflow *model.Workflow, recordName, revisionVersion string) error { +func (w *workflowServiceImpl) RollbackRecord(ctx context.Context, appModel *model.Application, workflow *model.Workflow, recordName, revisionVersion string) error { if revisionVersion == "" { // find the latest complete revision version var revision = model.ApplicationRevision{ @@ -611,7 +597,7 @@ func (w *workflowUsecaseImpl) RollbackRecord(ctx context.Context, appModel *mode WorkflowName: workflow.Name, EnvName: workflow.EnvName, } - revisions, err := w.ds.List(ctx, &revision, &datastore.ListOptions{ + revisions, err := w.Store.List(ctx, &revision, &datastore.ListOptions{ Page: 1, PageSize: 1, SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}, @@ -630,7 +616,7 @@ func (w *workflowUsecaseImpl) RollbackRecord(ctx context.Context, appModel *mode AppPrimaryKey: appModel.PrimaryKey(), Name: recordName, } - if err := w.ds.Get(ctx, record); err != nil { + if err := w.Store.Get(ctx, record); err != nil { return err } @@ -643,7 +629,7 @@ func (w *workflowUsecaseImpl) RollbackRecord(ctx context.Context, appModel *mode AppPrimaryKey: appModel.Name, Version: record.RevisionPrimaryKey, } - if err := w.ds.Get(ctx, originalRevision); err != nil { + if err := w.Store.Get(ctx, originalRevision); err != nil { return err } @@ -651,7 +637,7 @@ func (w *workflowUsecaseImpl) RollbackRecord(ctx context.Context, appModel *mode AppPrimaryKey: appModel.Name, Version: revisionVersion, } - if err := w.ds.Get(ctx, rollbackRevision); err != nil { + if err := w.Store.Get(ctx, rollbackRevision); err != nil { return err } @@ -659,7 +645,7 @@ func (w *workflowUsecaseImpl) RollbackRecord(ctx context.Context, appModel *mode originalRevision.Status = model.RevisionStatusRollback originalRevision.RollbackVersion = revisionVersion originalRevision.UpdateTime = time.Now().Time - if err := w.ds.Put(ctx, originalRevision); err != nil { + if err := w.Store.Put(ctx, originalRevision); err != nil { return err } @@ -681,9 +667,9 @@ func (w *workflowUsecaseImpl) RollbackRecord(ctx context.Context, appModel *mode return err } - if err := w.apply.Apply(ctx, oamApp); err != nil { + if err := w.Apply.Apply(ctx, oamApp); err != nil { // rollback error case - if err := w.ds.Delete(ctx, &model.WorkflowRecord{Name: newRecordName}); err != nil { + if err := w.Store.Delete(ctx, &model.WorkflowRecord{Name: newRecordName}); err != nil { klog.Error(err, "failed to delete record", newRecordName) } return err @@ -692,13 +678,13 @@ func (w *workflowUsecaseImpl) RollbackRecord(ctx context.Context, appModel *mode return nil } -func (w *workflowUsecaseImpl) checkRecordRunning(ctx context.Context, appModel *model.Application, envName string) (*v1beta1.Application, error) { +func (w *workflowServiceImpl) checkRecordRunning(ctx context.Context, appModel *model.Application, envName string) (*v1beta1.Application, error) { oamApp := &v1beta1.Application{} - env, err := w.envUsecase.GetEnv(ctx, envName) + env, err := w.EnvService.GetEnv(ctx, envName) if err != nil { return nil, err } - if err := w.kubeClient.Get(ctx, types.NamespacedName{Name: appModel.Name, Namespace: env.Namespace}, oamApp); err != nil { + if err := w.KubeClient.Get(ctx, types.NamespacedName{Name: appModel.Name, Namespace: env.Namespace}, oamApp); err != nil { return nil, err } if oamApp.Status.Workflow != nil && !oamApp.Status.Workflow.Suspend && !oamApp.Status.Workflow.Terminated && !oamApp.Status.Workflow.Finished { @@ -708,40 +694,3 @@ func (w *workflowUsecaseImpl) checkRecordRunning(ctx context.Context, appModel * oamApp.SetGroupVersionKind(v1beta1.ApplicationKindVersionKind) return oamApp, nil } - -func convertFromRecordModel(record *model.WorkflowRecord) *apisv1.WorkflowRecord { - return &apisv1.WorkflowRecord{ - Name: record.Name, - Namespace: record.Namespace, - WorkflowName: record.WorkflowName, - WorkflowAlias: record.WorkflowAlias, - ApplicationRevision: record.RevisionPrimaryKey, - StartTime: record.StartTime, - Status: record.Status, - Steps: record.Steps, - } -} - -func convertFromWorkflowStepModel(step model.WorkflowStep) apisv1.WorkflowStep { - apiStep := apisv1.WorkflowStep{ - Name: step.Name, - Type: step.Type, - Alias: step.Alias, - Description: step.Description, - Inputs: step.Inputs, - Outputs: step.Outputs, - Properties: step.Properties.JSON(), - DependsOn: step.DependsOn, - } - if step.Properties != nil { - apiStep.Properties = step.Properties.JSON() - } - return apiStep -} - -func convertBool(b *bool) bool { - if b == nil { - return false - } - return *b -} diff --git a/pkg/apiserver/rest/usecase/workflow_test.go b/pkg/apiserver/domain/service/workflow_test.go similarity index 76% rename from pkg/apiserver/rest/usecase/workflow_test.go rename to pkg/apiserver/domain/service/workflow_test.go index ff0b05486..cd8b7ffac 100644 --- a/pkg/apiserver/rest/usecase/workflow_test.go +++ b/pkg/apiserver/domain/service/workflow_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package usecase +package service import ( "context" @@ -34,20 +34,20 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/utils/apply" ) var appName = "app-workflow" -var _ = Describe("Test workflow usecase functions", func() { +var _ = Describe("Test workflow service functions", func() { var ( - workflowUsecase *workflowUsecaseImpl - appUsecase *applicationUsecaseImpl - projectUsecase *projectUsecaseImpl - envUsecase *envUsecaseImpl + workflowService *workflowServiceImpl + appService *applicationServiceImpl + projectService *projectServiceImpl + envService *envServiceImpl testProject = "workflow-project" ds datastore.DataStore ) @@ -57,26 +57,26 @@ var _ = Describe("Test workflow usecase functions", func() { ds, err = NewDatastore(datastore.Config{Type: "kubeapi", Database: "workflow-test-" + strconv.FormatInt(time.Now().UnixNano(), 10)}) Expect(ds).ToNot(BeNil()) Expect(err).Should(BeNil()) - rbacUsecase := &rbacUsecaseImpl{ds: ds} - projectUsecase = &projectUsecaseImpl{ds: ds, rbacUsecase: rbacUsecase} - envUsecase = &envUsecaseImpl{ds: ds, kubeClient: k8sClient, projectUsecase: projectUsecase} - workflowUsecase = &workflowUsecaseImpl{ - ds: ds, - kubeClient: k8sClient, - apply: apply.NewAPIApplicator(k8sClient), - envUsecase: envUsecase} - appUsecase = &applicationUsecaseImpl{ds: ds, kubeClient: k8sClient, - apply: apply.NewAPIApplicator(k8sClient), - projectUsecase: projectUsecase, - envUsecase: envUsecase, - envBindingUsecase: &envBindingUsecaseImpl{ - ds: ds, - workflowUsecase: workflowUsecase, - envUsecase: envUsecase, + rbacService := &rbacServiceImpl{Store: ds} + projectService = &projectServiceImpl{Store: ds, RbacService: rbacService} + envService = &envServiceImpl{Store: ds, KubeClient: k8sClient, ProjectService: projectService} + workflowService = &workflowServiceImpl{ + Store: ds, + KubeClient: k8sClient, + Apply: apply.NewAPIApplicator(k8sClient), + EnvService: envService} + appService = &applicationServiceImpl{Store: ds, KubeClient: k8sClient, + Apply: apply.NewAPIApplicator(k8sClient), + ProjectService: projectService, + EnvService: envService, + EnvBindingService: &envBindingServiceImpl{ + Store: ds, + WorkflowService: workflowService, + EnvService: envService, }} }) It("Test CreateWorkflow function", func() { - _, err := projectUsecase.CreateProject(context.TODO(), apisv1.CreateProjectRequest{Name: testProject}) + _, err := projectService.CreateProject(context.TODO(), apisv1.CreateProjectRequest{Name: testProject}) Expect(err).Should(BeNil()) reqApp := apisv1.CreateApplicationRequest{ Name: appName, @@ -86,7 +86,7 @@ var _ = Describe("Test workflow usecase functions", func() { Name: "dev", }}, } - _, err = appUsecase.CreateApplication(context.TODO(), reqApp) + _, err = appService.CreateApplication(context.TODO(), reqApp) Expect(err).Should(BeNil()) req := apisv1.CreateWorkflowRequest{ Name: "test-workflow-1", @@ -94,7 +94,7 @@ var _ = Describe("Test workflow usecase functions", func() { EnvName: "dev", } - base, err := workflowUsecase.CreateOrUpdateWorkflow(context.TODO(), &model.Application{ + base, err := workflowService.CreateOrUpdateWorkflow(context.TODO(), &model.Application{ Name: appName, }, req) Expect(err).Should(BeNil()) @@ -106,7 +106,7 @@ var _ = Describe("Test workflow usecase functions", func() { EnvName: "dev2", } - base, err = workflowUsecase.CreateOrUpdateWorkflow(context.TODO(), &model.Application{ + base, err = workflowService.CreateOrUpdateWorkflow(context.TODO(), &model.Application{ Name: appName, }, req2) Expect(err).Should(BeNil()) @@ -129,14 +129,14 @@ var _ = Describe("Test workflow usecase functions", func() { }, Default: &defaultW, } - base, err = workflowUsecase.CreateOrUpdateWorkflow(context.TODO(), &model.Application{ + base, err = workflowService.CreateOrUpdateWorkflow(context.TODO(), &model.Application{ Name: appName, }, req) Expect(err).Should(BeNil()) Expect(cmp.Diff(base.Name, req.Name)).Should(BeEmpty()) By("Test GetApplicationDefaultWorkflow function") - workflow, err := workflowUsecase.GetApplicationDefaultWorkflow(context.TODO(), &model.Application{ + workflow, err := workflowService.GetApplicationDefaultWorkflow(context.TODO(), &model.Application{ Name: appName, }) Expect(err).Should(BeNil()) @@ -150,20 +150,20 @@ var _ = Describe("Test workflow usecase functions", func() { err = json.Unmarshal(raw, app) Expect(err).Should(BeNil()) app.Annotations[oam.AnnotationWorkflowName] = "test-workflow-2" - workflow, err = workflowUsecase.GetWorkflow(context.TODO(), &model.Application{ + workflow, err = workflowService.GetWorkflow(context.TODO(), &model.Application{ Name: appName, }, "test-workflow-2") Expect(err).Should(BeNil()) for i := 0; i < 3; i++ { app.Annotations[oam.AnnotationPublishVersion] = fmt.Sprintf("list-workflow-name-%d", i) app.Status.Workflow.AppRevision = fmt.Sprintf("list-workflow-name-%d", i) - err = workflowUsecase.CreateWorkflowRecord(context.TODO(), &model.Application{ + err = workflowService.CreateWorkflowRecord(context.TODO(), &model.Application{ Name: appName, }, app, workflow) Expect(err).Should(BeNil()) } - resp, err := workflowUsecase.ListWorkflowRecords(context.TODO(), workflow, 0, 10) + resp, err := workflowService.ListWorkflowRecords(context.TODO(), workflow, 0, 10) Expect(err).Should(BeNil()) Expect(resp.Total).Should(Equal(int64(3))) @@ -176,11 +176,11 @@ var _ = Describe("Test workflow usecase functions", func() { app.Annotations[oam.AnnotationPublishVersion] = "test-workflow-2-123" app.Status.Workflow.AppRevision = "test-workflow-2-123" app.Annotations[oam.AnnotationDeployVersion] = "1234" - workflow, err = workflowUsecase.GetWorkflow(context.TODO(), &model.Application{ + workflow, err = workflowService.GetWorkflow(context.TODO(), &model.Application{ Name: appName, }, "test-workflow-2") Expect(err).Should(BeNil()) - err = workflowUsecase.CreateWorkflowRecord(context.TODO(), &model.Application{ + err = workflowService.CreateWorkflowRecord(context.TODO(), &model.Application{ Name: appName, }, app, workflow) Expect(err).Should(BeNil()) @@ -195,10 +195,10 @@ var _ = Describe("Test workflow usecase functions", func() { WorkflowName: "test-workflow-2", } - err = workflowUsecase.createTestApplicationRevision(context.TODO(), revision) + err = workflowService.createTestApplicationRevision(context.TODO(), revision) Expect(err).Should(BeNil()) - detail, err := workflowUsecase.DetailWorkflowRecord(context.TODO(), workflow, "test-workflow-2-123") + detail, err := workflowService.DetailWorkflowRecord(context.TODO(), workflow, "test-workflow-2-123") Expect(err).Should(BeNil()) Expect(detail.WorkflowRecord.Name).Should(Equal("test-workflow-2-123")) Expect(detail.DeployUser).Should(Equal("test-user")) @@ -214,11 +214,11 @@ var _ = Describe("Test workflow usecase functions", func() { app.Annotations[oam.AnnotationPublishVersion] = "test-workflow-2-233" app.Status.Workflow.AppRevision = "test-workflow-2-233" app.Annotations[oam.AnnotationDeployVersion] = "4321" - workflow, err = workflowUsecase.GetWorkflow(context.TODO(), &model.Application{ + workflow, err = workflowService.GetWorkflow(context.TODO(), &model.Application{ Name: appName, }, "test-workflow-2") Expect(err).Should(BeNil()) - err = workflowUsecase.CreateWorkflowRecord(context.TODO(), &model.Application{ + err = workflowService.CreateWorkflowRecord(context.TODO(), &model.Application{ Name: appName, }, app, workflow) Expect(err).Should(BeNil()) @@ -231,25 +231,25 @@ var _ = Describe("Test workflow usecase functions", func() { DeployUser: "test-user", WorkflowName: "test-workflow-2", } - err = workflowUsecase.createTestApplicationRevision(context.TODO(), revision) + err = workflowService.createTestApplicationRevision(context.TODO(), revision) Expect(err).Should(BeNil()) By("create the application to sync") ctx := context.Background() app.Status.Workflow.Finished = true - err = workflowUsecase.kubeClient.Create(ctx, app.DeepCopy()) + err = workflowService.KubeClient.Create(ctx, app.DeepCopy()) Expect(err).Should(BeNil()) - err = workflowUsecase.kubeClient.Status().Patch(ctx, app, client.Merge) + err = workflowService.KubeClient.Status().Patch(ctx, app, client.Merge) Expect(err).Should(BeNil()) - err = workflowUsecase.SyncWorkflowRecord(ctx) + err = workflowService.SyncWorkflowRecord(ctx) Expect(err).Should(BeNil()) - workflow, err = workflowUsecase.GetWorkflow(context.TODO(), &model.Application{ + workflow, err = workflowService.GetWorkflow(context.TODO(), &model.Application{ Name: appName, }, "test-workflow-2") Expect(err).Should(BeNil()) By("check the record") - record, err := workflowUsecase.DetailWorkflowRecord(context.TODO(), workflow, "test-workflow-2-233") + record, err := workflowService.DetailWorkflowRecord(context.TODO(), workflow, "test-workflow-2-233") Expect(err).Should(BeNil()) Expect(record.Status).Should(Equal(model.RevisionStatusComplete)) Expect(record.Steps[0].Alias).Should(Equal("step-alias-1")) @@ -258,7 +258,7 @@ var _ = Describe("Test workflow usecase functions", func() { Expect(record.Steps[1].Phase).Should(Equal(common.WorkflowStepPhaseSucceeded)) By("check the application revision") - err = workflowUsecase.ds.Get(ctx, revision) + err = workflowService.Store.Get(ctx, revision) Expect(err).Should(BeNil()) Expect(revision.Status).Should(Equal(model.RevisionStatusComplete)) @@ -267,7 +267,7 @@ var _ = Describe("Test workflow usecase functions", func() { app.Annotations[oam.AnnotationPublishVersion] = "test-workflow-2-111" app.Status.Workflow.AppRevision = "test-workflow-2-111" app.Annotations[oam.AnnotationDeployVersion] = "1111" - err = workflowUsecase.CreateWorkflowRecord(context.TODO(), &model.Application{ + err = workflowService.CreateWorkflowRecord(context.TODO(), &model.Application{ Name: appName, }, app, workflow) Expect(err).Should(BeNil()) @@ -280,7 +280,7 @@ var _ = Describe("Test workflow usecase functions", func() { DeployUser: "test-user", WorkflowName: "test-workflow-2", } - err = workflowUsecase.createTestApplicationRevision(context.TODO(), anotherRevision) + err = workflowService.createTestApplicationRevision(context.TODO(), anotherRevision) Expect(err).Should(BeNil()) By("create one controller revision to test sync workflow record") @@ -293,19 +293,19 @@ var _ = Describe("Test workflow usecase functions", func() { }, Data: runtime.RawExtension{Raw: raw}, } - err = workflowUsecase.kubeClient.Create(ctx, cr) + err = workflowService.KubeClient.Create(ctx, cr) Expect(err).Should(BeNil()) - err = workflowUsecase.SyncWorkflowRecord(ctx) + err = workflowService.SyncWorkflowRecord(ctx) Expect(err).Should(BeNil()) By("check the record") - anotherRecord, err := workflowUsecase.DetailWorkflowRecord(context.TODO(), workflow, "test-workflow-2-111") + anotherRecord, err := workflowService.DetailWorkflowRecord(context.TODO(), workflow, "test-workflow-2-111") Expect(err).Should(BeNil()) Expect(anotherRecord.Status).Should(Equal(model.RevisionStatusComplete)) By("check the application revision") - err = workflowUsecase.ds.Get(ctx, anotherRevision) + err = workflowService.Store.Get(ctx, anotherRevision) Expect(err).Should(BeNil()) Expect(anotherRevision.Status).Should(Equal(model.RevisionStatusComplete)) }) @@ -313,7 +313,7 @@ var _ = Describe("Test workflow usecase functions", func() { It("Test CreateRecord function", func() { ctx := context.TODO() for i := 0; i < 3; i++ { - workflowUsecase.ds.Add(ctx, &model.WorkflowRecord{ + workflowService.Store.Add(ctx, &model.WorkflowRecord{ AppPrimaryKey: "record-app", Name: fmt.Sprintf("test-record-%d", i), WorkflowName: "test-workflow", @@ -321,10 +321,10 @@ var _ = Describe("Test workflow usecase functions", func() { }) } - app, err := createTestSuspendApp(ctx, "record-app", "default", "revision-123", "test-workflow", "test-record-3", workflowUsecase.kubeClient) + app, err := createTestSuspendApp(ctx, "record-app", "default", "revision-123", "test-workflow", "test-record-3", workflowService.KubeClient) Expect(err).Should(BeNil()) - err = workflowUsecase.CreateWorkflowRecord(ctx, &model.Application{ + err = workflowService.CreateWorkflowRecord(ctx, &model.Application{ Name: "record-app", }, app, &model.Workflow{Name: "test-workflow"}) Expect(err).Should(BeNil()) @@ -334,7 +334,7 @@ var _ = Describe("Test workflow usecase functions", func() { AppPrimaryKey: "record-app", WorkflowName: "test-workflow", } - err = workflowUsecase.ds.Get(ctx, record) + err = workflowService.Store.Get(ctx, record) Expect(err).Should(BeNil()) Expect(record.Status).Should(Equal(model.RevisionStatusRunning)) }) @@ -342,7 +342,7 @@ var _ = Describe("Test workflow usecase functions", func() { It("Test ResumeRecord function", func() { ctx := context.TODO() - _, err := envUsecase.CreateEnv(context.TODO(), apisv1.CreateEnvRequest{Name: "resume"}) + _, err := envService.CreateEnv(context.TODO(), apisv1.CreateEnvRequest{Name: "resume"}) Expect(err).Should(BeNil()) ResumeWorkflow := "resume-workflow" req := apisv1.CreateWorkflowRequest{ @@ -351,33 +351,33 @@ var _ = Describe("Test workflow usecase functions", func() { EnvName: "resume", } - base, err := workflowUsecase.CreateOrUpdateWorkflow(context.TODO(), &model.Application{ + base, err := workflowService.CreateOrUpdateWorkflow(context.TODO(), &model.Application{ Name: appName, }, req) Expect(err).Should(BeNil()) Expect(cmp.Diff(base.Name, req.Name)).Should(BeEmpty()) - app, err := createTestSuspendApp(ctx, appName, "resume", "revision-resume1", ResumeWorkflow, "workflow-resume-1", workflowUsecase.kubeClient) + app, err := createTestSuspendApp(ctx, appName, "resume", "revision-resume1", ResumeWorkflow, "workflow-resume-1", workflowService.KubeClient) Expect(err).Should(BeNil()) - err = workflowUsecase.CreateWorkflowRecord(context.TODO(), &model.Application{ + err = workflowService.CreateWorkflowRecord(context.TODO(), &model.Application{ Name: appName, }, app, &model.Workflow{Name: ResumeWorkflow}) Expect(err).Should(BeNil()) - err = workflowUsecase.createTestApplicationRevision(ctx, &model.ApplicationRevision{ + err = workflowService.createTestApplicationRevision(ctx, &model.ApplicationRevision{ AppPrimaryKey: appName, Version: "revision-resume1", Status: model.RevisionStatusRunning, }) Expect(err).Should(BeNil()) - err = workflowUsecase.ResumeRecord(ctx, &model.Application{ + err = workflowService.ResumeRecord(ctx, &model.Application{ Name: appName, }, &model.Workflow{Name: ResumeWorkflow, EnvName: "resume"}, "workflow-resume-1") Expect(err).Should(BeNil()) - record, err := workflowUsecase.DetailWorkflowRecord(ctx, &model.Workflow{Name: ResumeWorkflow, AppPrimaryKey: appName}, "workflow-resume-1") + record, err := workflowService.DetailWorkflowRecord(ctx, &model.Workflow{Name: ResumeWorkflow, AppPrimaryKey: appName}, "workflow-resume-1") Expect(err).Should(BeNil()) Expect(record.Status).Should(Equal(model.RevisionStatusRunning)) }) @@ -385,7 +385,7 @@ var _ = Describe("Test workflow usecase functions", func() { It("Test TerminateRecord function", func() { ctx := context.TODO() - _, err := envUsecase.CreateEnv(context.TODO(), apisv1.CreateEnvRequest{Name: "terminate"}) + _, err := envService.CreateEnv(context.TODO(), apisv1.CreateEnvRequest{Name: "terminate"}) Expect(err).Should(BeNil()) workflowName := "terminate-workflow" req := apisv1.CreateWorkflowRequest{ @@ -394,40 +394,40 @@ var _ = Describe("Test workflow usecase functions", func() { EnvName: "terminate", } workflow := &model.Workflow{Name: workflowName, EnvName: "terminate"} - base, err := workflowUsecase.CreateOrUpdateWorkflow(context.TODO(), &model.Application{ + base, err := workflowService.CreateOrUpdateWorkflow(context.TODO(), &model.Application{ Name: appName, }, req) Expect(err).Should(BeNil()) Expect(cmp.Diff(base.Name, req.Name)).Should(BeEmpty()) - app, err := createTestSuspendApp(ctx, appName, "terminate", "revision-terminate1", workflow.Name, "test-workflow-2-1", workflowUsecase.kubeClient) + app, err := createTestSuspendApp(ctx, appName, "terminate", "revision-terminate1", workflow.Name, "test-workflow-2-1", workflowService.KubeClient) Expect(err).Should(BeNil()) - err = workflowUsecase.CreateWorkflowRecord(context.TODO(), &model.Application{ + err = workflowService.CreateWorkflowRecord(context.TODO(), &model.Application{ Name: appName, }, app, workflow) Expect(err).Should(BeNil()) - err = workflowUsecase.createTestApplicationRevision(ctx, &model.ApplicationRevision{ + err = workflowService.createTestApplicationRevision(ctx, &model.ApplicationRevision{ AppPrimaryKey: appName, Version: "revision-terminate1", Status: model.RevisionStatusRunning, }) Expect(err).Should(BeNil()) - err = workflowUsecase.TerminateRecord(ctx, &model.Application{ + err = workflowService.TerminateRecord(ctx, &model.Application{ Name: appName, }, workflow, "test-workflow-2-1") Expect(err).Should(BeNil()) - record, err := workflowUsecase.DetailWorkflowRecord(ctx, workflow, "test-workflow-2-1") + record, err := workflowService.DetailWorkflowRecord(ctx, workflow, "test-workflow-2-1") Expect(err).Should(BeNil()) Expect(record.Status).Should(Equal(model.RevisionStatusTerminated)) }) It("Test RollbackRecord function", func() { ctx := context.TODO() - _, err := envUsecase.CreateEnv(context.TODO(), apisv1.CreateEnvRequest{Name: "rollback"}) + _, err := envService.CreateEnv(context.TODO(), apisv1.CreateEnvRequest{Name: "rollback"}) Expect(err).Should(BeNil()) workflowName := "rollback-workflow" req := apisv1.CreateWorkflowRequest{ @@ -436,21 +436,21 @@ var _ = Describe("Test workflow usecase functions", func() { EnvName: "rollback", } workflow := &model.Workflow{Name: workflowName, EnvName: "rollback"} - base, err := workflowUsecase.CreateOrUpdateWorkflow(context.TODO(), &model.Application{ + base, err := workflowService.CreateOrUpdateWorkflow(context.TODO(), &model.Application{ Name: appName, }, req) Expect(err).Should(BeNil()) Expect(cmp.Diff(base.Name, req.Name)).Should(BeEmpty()) - app, err := createTestSuspendApp(ctx, appName, "rollback", "revision-rollback1", workflow.Name, "test-workflow-2-2", workflowUsecase.kubeClient) + app, err := createTestSuspendApp(ctx, appName, "rollback", "revision-rollback1", workflow.Name, "test-workflow-2-2", workflowService.KubeClient) Expect(err).Should(BeNil()) - err = workflowUsecase.CreateWorkflowRecord(context.TODO(), &model.Application{ + err = workflowService.CreateWorkflowRecord(context.TODO(), &model.Application{ Name: appName, }, app, workflow) Expect(err).Should(BeNil()) - err = workflowUsecase.createTestApplicationRevision(ctx, &model.ApplicationRevision{ + err = workflowService.createTestApplicationRevision(ctx, &model.ApplicationRevision{ AppPrimaryKey: appName, Version: "revision-rollback1", Status: model.RevisionStatusRunning, @@ -458,7 +458,7 @@ var _ = Describe("Test workflow usecase functions", func() { EnvName: "rollback", }) Expect(err).Should(BeNil()) - err = workflowUsecase.createTestApplicationRevision(ctx, &model.ApplicationRevision{ + err = workflowService.createTestApplicationRevision(ctx, &model.ApplicationRevision{ AppPrimaryKey: appName, Version: "revision-rollback0", ApplyAppConfig: `{"apiVersion":"core.oam.dev/v1beta1","kind":"Application","metadata":{"annotations":{"app.oam.dev/workflowName":"test-workflow-2-2","app.oam.dev/deployVersion":"revision-rollback1","vela.io/publish-version":"workflow-rollback1"},"name":"first-vela-app","namespace":"default"},"spec":{"components":[{"name":"express-server","properties":{"image":"crccheck/hello-world","port":8000},"traits":[{"properties":{"domain":"testsvc.example.com","http":{"/":8000}},"type":"ingress-1-20"}],"type":"webservice"}]}}`, @@ -468,12 +468,12 @@ var _ = Describe("Test workflow usecase functions", func() { }) Expect(err).Should(BeNil()) - err = workflowUsecase.RollbackRecord(ctx, &model.Application{ + err = workflowService.RollbackRecord(ctx, &model.Application{ Name: appName, }, workflow, "test-workflow-2-2", "revision-rollback0") Expect(err).Should(BeNil()) - recordsNum, err := workflowUsecase.ds.Count(ctx, &model.WorkflowRecord{ + recordsNum, err := workflowService.Store.Count(ctx, &model.WorkflowRecord{ AppPrimaryKey: appName, WorkflowName: workflow.Name, RevisionPrimaryKey: "revision-rollback0", @@ -484,17 +484,17 @@ var _ = Describe("Test workflow usecase functions", func() { By("rollback application without revision version") app.Annotations[oam.AnnotationPublishVersion] = "workflow-rollback-2" app.Status.Workflow.AppRevision = "workflow-rollback-2" - err = workflowUsecase.CreateWorkflowRecord(context.TODO(), &model.Application{ + err = workflowService.CreateWorkflowRecord(context.TODO(), &model.Application{ Name: appName, }, app, workflow) Expect(err).Should(BeNil()) - err = workflowUsecase.RollbackRecord(ctx, &model.Application{ + err = workflowService.RollbackRecord(ctx, &model.Application{ Name: appName, }, workflow, "workflow-rollback-2", "") Expect(err).Should(BeNil()) - recordsNum, err = workflowUsecase.ds.Count(ctx, &model.WorkflowRecord{ + recordsNum, err = workflowService.Store.Count(ctx, &model.WorkflowRecord{ AppPrimaryKey: appName, WorkflowName: workflow.Name, RevisionPrimaryKey: "revision-rollback0", @@ -506,7 +506,7 @@ var _ = Describe("Test workflow usecase functions", func() { AppPrimaryKey: appName, Version: "revision-rollback1", } - err = workflowUsecase.ds.Get(ctx, originalRevision) + err = workflowService.Store.Get(ctx, originalRevision) Expect(err).Should(BeNil()) Expect(originalRevision.Status).Should(Equal(model.RevisionStatusRollback)) Expect(originalRevision.RollbackVersion).Should(Equal("revision-rollback0")) @@ -515,7 +515,7 @@ var _ = Describe("Test workflow usecase functions", func() { It("Test resetRevisionsAndRecords function", func() { ctx := context.TODO() - err := workflowUsecase.ds.Add(ctx, &model.WorkflowRecord{ + err := workflowService.Store.Add(ctx, &model.WorkflowRecord{ AppPrimaryKey: "reset-app", WorkflowName: "reset-workflow", Name: "reset-record", @@ -531,7 +531,7 @@ var _ = Describe("Test workflow usecase functions", func() { }) Expect(err).Should(BeNil()) - err = resetRevisionsAndRecords(ctx, workflowUsecase.ds, "reset-app", "reset-workflow", "", "") + err = resetRevisionsAndRecords(ctx, workflowService.Store, "reset-app", "reset-workflow", "", "") Expect(err).Should(BeNil()) record := &model.WorkflowRecord{ @@ -539,7 +539,7 @@ var _ = Describe("Test workflow usecase functions", func() { WorkflowName: "reset-workflow", Name: "reset-record", } - err = workflowUsecase.ds.Get(ctx, record) + err = workflowService.Store.Get(ctx, record) Expect(err).Should(BeNil()) Expect(record.Status).Should(Equal(model.RevisionStatusTerminated)) Expect(record.Finished).Should(Equal("true")) @@ -590,8 +590,8 @@ status: finished: true appRevision: "test-workflow-name-111"` -func (w *workflowUsecaseImpl) createTestApplicationRevision(ctx context.Context, revision *model.ApplicationRevision) error { - if err := w.ds.Add(ctx, revision); err != nil { +func (w *workflowServiceImpl) createTestApplicationRevision(ctx context.Context, revision *model.ApplicationRevision) error { + if err := w.Store.Add(ctx, revision); err != nil { return err } return nil diff --git a/pkg/apiserver/collect/suit_test.go b/pkg/apiserver/event/collect/suit_test.go similarity index 87% rename from pkg/apiserver/collect/suit_test.go rename to pkg/apiserver/event/collect/suit_test.go index 0e1c42c2f..a891908c9 100644 --- a/pkg/apiserver/collect/suit_test.go +++ b/pkg/apiserver/event/collect/suit_test.go @@ -31,10 +31,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore/kubeapi" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore/mongodb" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore/kubeapi" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore/mongodb" "github.com/oam-dev/kubevela/pkg/utils/common" ) @@ -55,7 +55,7 @@ var _ = BeforeSuite(func(done Done) { ControlPlaneStartTimeout: time.Minute * 3, ControlPlaneStopTimeout: time.Minute, UseExistingCluster: pointer.BoolPtr(false), - CRDDirectoryPaths: []string{"../../../charts/vela-core/crds"}, + CRDDirectoryPaths: []string{"../../../../charts/vela-core/crds"}, } By("start kube test env") diff --git a/pkg/apiserver/collect/system_info_collect.go b/pkg/apiserver/event/collect/system_info_collect.go similarity index 88% rename from pkg/apiserver/collect/system_info_collect.go rename to pkg/apiserver/event/collect/system_info_collect.go index 2a2dea6bb..4859c083a 100644 --- a/pkg/apiserver/collect/system_info_collect.go +++ b/pkg/apiserver/event/collect/system_info_collect.go @@ -28,12 +28,12 @@ import ( "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/oam" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" "github.com/oam-dev/kubevela/pkg/multicluster" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/robfig/cron/v3" "k8s.io/apimachinery/pkg/util/wait" @@ -56,25 +56,22 @@ var waitBackOff = wait.Backoff{ // InfoCalculateCronJob is the cronJob to calculate the system info store in db type InfoCalculateCronJob struct { - ds datastore.DataStore + Store datastore.DataStore `inject:"datastore"` + cron *cron.Cron } -// StartCalculatingInfoCronJob will start the system info calculating job. -func StartCalculatingInfoCronJob(ds datastore.DataStore) { - i := InfoCalculateCronJob{ - ds: ds, - } - - // run calculate job in 0:00 of every day +// Start start the worker +func (i *InfoCalculateCronJob) Start(ctx context.Context, errChan chan error) { i.start(CrontabSpec) + defer i.cron.Stop() + <-ctx.Done() } -func (i InfoCalculateCronJob) start(cronSpec string) { +func (i *InfoCalculateCronJob) start(cronSpec string) { c := cron.New(cron.WithChain( // don't let job panic crash whole api-server process cron.Recover(cron.DefaultLogger), )) - // ignore the entityId and error, the cron spec is defined by hard code, mustn't generate error _, _ = c.AddFunc(cronSpec, func() { @@ -94,14 +91,14 @@ func (i InfoCalculateCronJob) start(cronSpec string) { log.Logger.Errorf("After 5 tries the calculating cronJob failed: %v", err) } }) - + i.cron = c c.Start() } func (i InfoCalculateCronJob) run() error { ctx := context.Background() systemInfo := model.SystemInfo{} - e, err := i.ds.List(ctx, &systemInfo, &datastore.ListOptions{}) + e, err := i.Store.List(ctx, &systemInfo, &datastore.ListOptions{}) if err != nil { return err } @@ -153,7 +150,7 @@ func (i InfoCalculateCronJob) calculateAndUpdate(ctx context.Context, systemInfo } systemInfo.StatisticInfo = statisticInfo - if err := i.ds.Put(ctx, &systemInfo); err != nil { + if err := i.Store.Put(ctx, &systemInfo); err != nil { return err } return nil @@ -168,7 +165,7 @@ func (i InfoCalculateCronJob) calculateAppInfo(ctx context.Context) (int, []stri policyDef := map[string]int{} var app = model.Application{} - entities, err := i.ds.List(ctx, &app, &datastore.ListOptions{}) + entities, err := i.Store.List(ctx, &app, &datastore.ListOptions{}) if err != nil { return 0, nil, nil, nil, nil, err } @@ -181,7 +178,7 @@ func (i InfoCalculateCronJob) calculateAppInfo(ctx context.Context) (int, []stri comp := model.ApplicationComponent{ AppPrimaryKey: appModel.Name, } - comps, err := i.ds.List(ctx, &comp, &datastore.ListOptions{}) + comps, err := i.Store.List(ctx, &comp, &datastore.ListOptions{}) if err != nil { return 0, nil, nil, nil, nil, err } @@ -199,7 +196,7 @@ func (i InfoCalculateCronJob) calculateAppInfo(ctx context.Context) (int, []stri workflow := model.Workflow{ AppPrimaryKey: app.PrimaryKey(), } - workflows, err := i.ds.List(ctx, &workflow, &datastore.ListOptions{}) + workflows, err := i.Store.List(ctx, &workflow, &datastore.ListOptions{}) if err != nil { return 0, nil, nil, nil, nil, err } @@ -216,7 +213,7 @@ func (i InfoCalculateCronJob) calculateAppInfo(ctx context.Context) (int, []stri policy := model.ApplicationPolicy{ AppPrimaryKey: app.PrimaryKey(), } - policies, err := i.ds.List(ctx, &policy, &datastore.ListOptions{}) + policies, err := i.Store.List(ctx, &policy, &datastore.ListOptions{}) if err != nil { return 0, nil, nil, nil, nil, err } diff --git a/pkg/apiserver/collect/system_info_collect_test.go b/pkg/apiserver/event/collect/system_info_collect_test.go similarity index 98% rename from pkg/apiserver/collect/system_info_collect_test.go rename to pkg/apiserver/event/collect/system_info_collect_test.go index 161c65432..bdc584089 100644 --- a/pkg/apiserver/collect/system_info_collect_test.go +++ b/pkg/apiserver/event/collect/system_info_collect_test.go @@ -34,8 +34,8 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/util" ) @@ -83,7 +83,7 @@ var _ = Describe("Test calculate cronJob", func() { testProject = "test-cronjob-project" mockDataInDs() i = InfoCalculateCronJob{ - ds: ds, + Store: ds, } systemInfo := model.SystemInfo{InstallID: "test-id", EnableCollection: true} Expect(ds.Add(ctx, &systemInfo)).Should(SatisfyAny(BeNil(), DataExistMatcher{})) diff --git a/pkg/apiserver/event/event.go b/pkg/apiserver/event/event.go new file mode 100644 index 000000000..33173804e --- /dev/null +++ b/pkg/apiserver/event/event.go @@ -0,0 +1,50 @@ +/* +Copyright 2022 The KubeVela 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 event + +import ( + "context" + + "github.com/oam-dev/kubevela/pkg/apiserver/config" + "github.com/oam-dev/kubevela/pkg/apiserver/event/collect" + "github.com/oam-dev/kubevela/pkg/apiserver/event/sync" +) + +var workers []Worker + +// Worker handle events through rotation training, listener and crontab. +type Worker interface { + Start(ctx context.Context, errChan chan error) +} + +// InitEvent init all event worker +func InitEvent(cfg config.Config) []interface{} { + workflow := &sync.WorkflowRecordSync{ + Duration: cfg.LeaderConfig.Duration, + } + application := &sync.ApplicationSync{} + collect := &collect.InfoCalculateCronJob{} + workers = append(workers, workflow, application, collect) + return []interface{}{workflow, application, collect} +} + +// StartEventWorker start all event worker +func StartEventWorker(ctx context.Context, errChan chan error) { + for i := range workers { + go workers[i].Start(ctx, errChan) + } +} diff --git a/pkg/apiserver/event/event_test.go b/pkg/apiserver/event/event_test.go new file mode 100644 index 000000000..ec2b2536d --- /dev/null +++ b/pkg/apiserver/event/event_test.go @@ -0,0 +1,30 @@ +/* +Copyright 2022 The KubeVela 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 event + +import ( + "testing" + + "gotest.tools/assert" + + "github.com/oam-dev/kubevela/pkg/apiserver/config" +) + +func TestInitEvent(t *testing.T) { + InitEvent(config.Config{}) + assert.Equal(t, len(workers), 3) +} diff --git a/pkg/apiserver/sync/cache.go b/pkg/apiserver/event/sync/cache.go similarity index 96% rename from pkg/apiserver/sync/cache.go rename to pkg/apiserver/event/sync/cache.go index c6bd7e4f5..e6638252e 100644 --- a/pkg/apiserver/sync/cache.go +++ b/pkg/apiserver/event/sync/cache.go @@ -25,8 +25,8 @@ import ( "github.com/sirupsen/logrus" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" ) type cached struct { diff --git a/pkg/apiserver/sync/cache_test.go b/pkg/apiserver/event/sync/cache_test.go similarity index 96% rename from pkg/apiserver/sync/cache_test.go rename to pkg/apiserver/event/sync/cache_test.go index 9e1148b07..2e9573632 100644 --- a/pkg/apiserver/sync/cache_test.go +++ b/pkg/apiserver/event/sync/cache_test.go @@ -27,8 +27,8 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" "github.com/oam-dev/kubevela/pkg/oam/util" ) diff --git a/pkg/apiserver/sync/convert.go b/pkg/apiserver/event/sync/convert.go similarity index 96% rename from pkg/apiserver/sync/convert.go rename to pkg/apiserver/event/sync/convert.go index fd20caad6..cb3de2434 100644 --- a/pkg/apiserver/sync/convert.go +++ b/pkg/apiserver/event/sync/convert.go @@ -23,8 +23,8 @@ import ( "time" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - "github.com/oam-dev/kubevela/pkg/apiserver/sync/convert" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/event/sync/convert" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/workflow/step" ) diff --git a/pkg/apiserver/sync/convert/convert.go b/pkg/apiserver/event/sync/convert/convert.go similarity index 98% rename from pkg/apiserver/sync/convert/convert.go rename to pkg/apiserver/event/sync/convert/convert.go index 29e877b63..ad6438211 100644 --- a/pkg/apiserver/sync/convert/convert.go +++ b/pkg/apiserver/event/sync/convert/convert.go @@ -26,7 +26,7 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/apiserver/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" "github.com/oam-dev/kubevela/pkg/multicluster" "github.com/oam-dev/kubevela/pkg/workflow/step" ) diff --git a/pkg/apiserver/sync/cr2ux.go b/pkg/apiserver/event/sync/cr2ux.go similarity index 91% rename from pkg/apiserver/sync/cr2ux.go rename to pkg/apiserver/event/sync/cr2ux.go index 14f962a93..fae279c89 100644 --- a/pkg/apiserver/sync/cr2ux.go +++ b/pkg/apiserver/event/sync/cr2ux.go @@ -23,10 +23,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/oam" ) @@ -80,10 +80,10 @@ func (c *CR2UX) getApp(ctx context.Context, name, namespace string) (*model.Appl // CR2UX provides the Add/Update/Delete method type CR2UX struct { - ds datastore.DataStore - cli client.Client - cache sync.Map - usecases map[string]interface{} + ds datastore.DataStore + cli client.Client + cache sync.Map + projectService service.ProjectService } func formatAppComposedName(name, namespace string) string { @@ -108,11 +108,7 @@ func (c *CR2UX) AddOrUpdate(ctx context.Context, targetApp *v1beta1.Application) log.Logger.Errorf("Convert App to data store err %v", err) return err } - pu, ok := c.usecases["project"].(usecase.ProjectUsecase) - if !ok { - log.Logger.Warnf("not provide project usecase instance") - } - if err = StoreProject(ctx, dsApp.AppMeta.Project, ds, pu); err != nil { + if err = StoreProject(ctx, dsApp.AppMeta.Project, ds, c.projectService); err != nil { log.Logger.Errorf("get or create project for sync process err %v", err) return err } diff --git a/pkg/apiserver/sync/cr2ux_test.go b/pkg/apiserver/event/sync/cr2ux_test.go similarity index 98% rename from pkg/apiserver/sync/cr2ux_test.go rename to pkg/apiserver/event/sync/cr2ux_test.go index e2e3fd489..62a27d2b2 100644 --- a/pkg/apiserver/sync/cr2ux_test.go +++ b/pkg/apiserver/event/sync/cr2ux_test.go @@ -27,8 +27,8 @@ import ( corev1 "k8s.io/api/core/v1" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" "github.com/oam-dev/kubevela/pkg/oam/util" common2 "github.com/oam-dev/kubevela/pkg/utils/common" ) diff --git a/pkg/apiserver/sync/store.go b/pkg/apiserver/event/sync/store.go similarity index 94% rename from pkg/apiserver/sync/store.go rename to pkg/apiserver/event/sync/store.go index 0f740ed28..fccbe531b 100644 --- a/pkg/apiserver/sync/store.go +++ b/pkg/apiserver/event/sync/store.go @@ -21,16 +21,16 @@ import ( "errors" "strings" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - v1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + v1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/utils" ) // StoreProject will create project for synced application -func StoreProject(ctx context.Context, name string, ds datastore.DataStore, projectUsecase usecase.ProjectUsecase) error { +func StoreProject(ctx context.Context, name string, ds datastore.DataStore, projectService service.ProjectService) error { err := ds.Get(ctx, &model.Project{Name: name}) if err == nil { // it means the record already exists, don't need to add anything @@ -40,8 +40,8 @@ func StoreProject(ctx context.Context, name string, ds datastore.DataStore, proj // other database error, return it return err } - if projectUsecase != nil { - _, err := projectUsecase.CreateProject(ctx, v1.CreateProjectRequest{ + if projectService != nil { + _, err := projectService.CreateProject(ctx, v1.CreateProjectRequest{ Name: name, Alias: strings.Title(name), Owner: model.DefaultAdminUserName, diff --git a/pkg/apiserver/sync/suit_test.go b/pkg/apiserver/event/sync/suit_test.go similarity index 87% rename from pkg/apiserver/sync/suit_test.go rename to pkg/apiserver/event/sync/suit_test.go index 34f59eaa9..a5af9195e 100644 --- a/pkg/apiserver/sync/suit_test.go +++ b/pkg/apiserver/event/sync/suit_test.go @@ -30,10 +30,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore/kubeapi" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore/mongodb" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore/kubeapi" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore/mongodb" "github.com/oam-dev/kubevela/pkg/utils/common" ) @@ -54,7 +54,7 @@ var _ = BeforeSuite(func(done Done) { ControlPlaneStartTimeout: time.Minute * 3, ControlPlaneStopTimeout: time.Minute, UseExistingCluster: pointer.BoolPtr(false), - CRDDirectoryPaths: []string{"../../../charts/vela-core/crds"}, + CRDDirectoryPaths: []string{"../../../../charts/vela-core/crds"}, } By("start kube test env") diff --git a/pkg/apiserver/sync/testdata/test-app1.yaml b/pkg/apiserver/event/sync/testdata/test-app1.yaml similarity index 100% rename from pkg/apiserver/sync/testdata/test-app1.yaml rename to pkg/apiserver/event/sync/testdata/test-app1.yaml diff --git a/pkg/apiserver/sync/testdata/test-app2.yaml b/pkg/apiserver/event/sync/testdata/test-app2.yaml similarity index 100% rename from pkg/apiserver/sync/testdata/test-app2.yaml rename to pkg/apiserver/event/sync/testdata/test-app2.yaml diff --git a/pkg/apiserver/sync/testdata/test-app3.yaml b/pkg/apiserver/event/sync/testdata/test-app3.yaml similarity index 100% rename from pkg/apiserver/sync/testdata/test-app3.yaml rename to pkg/apiserver/event/sync/testdata/test-app3.yaml diff --git a/pkg/apiserver/sync/worker.go b/pkg/apiserver/event/sync/worker.go similarity index 57% rename from pkg/apiserver/sync/worker.go rename to pkg/apiserver/event/sync/worker.go index 295e9aefc..b439dc44f 100644 --- a/pkg/apiserver/sync/worker.go +++ b/pkg/apiserver/event/sync/worker.go @@ -22,57 +22,55 @@ import ( "sync" "github.com/fatih/color" - "github.com/sirupsen/logrus" v1 "k8s.io/api/core/v1" "k8s.io/client-go/dynamic" - "k8s.io/client-go/dynamic/dynamicinformer" + dynamicInformer "k8s.io/client-go/dynamic/dynamicinformer" "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" ) -// Start prepares watchers and run their controllers, then waits for process termination signals -func Start(ctx context.Context, ds datastore.DataStore, cfg *rest.Config, usecases map[string]interface{}) { - k8sClient, err := clients.GetKubeClient() - if err != nil { - logrus.Fatal(err) - } - - dynamicClient, err := dynamic.NewForConfig(cfg) - if err != nil { - logrus.Fatal(err) - } - - f := dynamicinformer.NewFilteredDynamicSharedInformerFactory(dynamicClient, 0, v1.NamespaceAll, nil) - - startAppSyncing(ctx, f, ds, k8sClient, usecases) +// ApplicationSync sync application from cluster to database +type ApplicationSync struct { + KubeClient client.Client `inject:"kubeClient"` + KubeConfig *rest.Config `inject:"kubeConfig"` + Store datastore.DataStore `inject:"datastore"` + ProjectService service.ProjectService `inject:""` } -func startAppSyncing(ctx context.Context, factory dynamicinformer.DynamicSharedInformerFactory, ds datastore.DataStore, cli client.Client, usecases map[string]interface{}) { - var err error +// Start prepares watchers and run their controllers, then waits for process termination signals +func (a *ApplicationSync) Start(ctx context.Context, errorChan chan error) { + dynamicClient, err := dynamic.NewForConfig(a.KubeConfig) + if err != nil { + errorChan <- err + } + + factory := dynamicInformer.NewFilteredDynamicSharedInformerFactory(dynamicClient, 0, v1.NamespaceAll, nil) informer := factory.ForResource(v1beta1.SchemeGroupVersion.WithResource("applications")).Informer() getApp := func(obj interface{}) *v1beta1.Application { app := &v1beta1.Application{} - bs, _ := json.Marshal(obj) + bs, err := json.Marshal(obj) + if err != nil { + log.Logger.Errorf("decode the application failure %s", err.Error()) + return app + } _ = json.Unmarshal(bs, app) return app } - if usecases == nil { - usecases = make(map[string]interface{}) - } cu := &CR2UX{ - ds: ds, - cli: cli, - cache: sync.Map{}, - usecases: usecases, + ds: a.Store, + cli: a.KubeClient, + cache: sync.Map{}, + projectService: a.ProjectService, } if err = cu.initCache(ctx); err != nil { - klog.Fatal("sync app init err", err) + errorChan <- err } handlers := cache.ResourceEventHandlerFuncs{ @@ -81,7 +79,7 @@ func startAppSyncing(ctx context.Context, factory dynamicinformer.DynamicSharedI klog.Infof("watched add app event, namespace: %s, name: %s", app.Namespace, app.Name) err = cu.AddOrUpdate(ctx, app) if err != nil { - logrus.Errorf("Application %-30s Create Sync to db err %v", color.WhiteString(app.Namespace+"/"+app.Name), err) + log.Logger.Errorf("Application %-30s Create Sync to db err %v", color.WhiteString(app.Namespace+"/"+app.Name), err) } }, UpdateFunc: func(oldObj, obj interface{}) { @@ -89,7 +87,7 @@ func startAppSyncing(ctx context.Context, factory dynamicinformer.DynamicSharedI klog.Infof("watched update app event, namespace: %s, name: %s", app.Namespace, app.Name) err = cu.AddOrUpdate(ctx, app) if err != nil { - klog.Errorf("Application %-30s Update Sync to db err %v", color.WhiteString(app.Namespace+"/"+app.Name), err) + log.Logger.Errorf("Application %-30s Update Sync to db err %v", color.WhiteString(app.Namespace+"/"+app.Name), err) } }, DeleteFunc: func(obj interface{}) { @@ -97,11 +95,11 @@ func startAppSyncing(ctx context.Context, factory dynamicinformer.DynamicSharedI klog.Infof("watched delete app event, namespace: %s, name: %s", app.Namespace, app.Name) err = cu.DeleteApp(ctx, app) if err != nil { - klog.Errorf("Application %-30s Deleted Sync to db err %v", color.WhiteString(app.Namespace+"/"+app.Name), err) + log.Logger.Errorf("Application %-30s Deleted Sync to db err %v", color.WhiteString(app.Namespace+"/"+app.Name), err) } }, } informer.AddEventHandler(handlers) - klog.Info("app syncing started") + log.Logger.Info("app syncing started") informer.Run(ctx.Done()) } diff --git a/pkg/apiserver/sync/worker_test.go b/pkg/apiserver/event/sync/worker_test.go similarity index 94% rename from pkg/apiserver/sync/worker_test.go rename to pkg/apiserver/event/sync/worker_test.go index 8be05cf79..f5df64f59 100644 --- a/pkg/apiserver/sync/worker_test.go +++ b/pkg/apiserver/event/sync/worker_test.go @@ -26,8 +26,8 @@ import ( corev1 "k8s.io/api/core/v1" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" "github.com/oam-dev/kubevela/pkg/oam/util" common2 "github.com/oam-dev/kubevela/pkg/utils/common" ) @@ -61,7 +61,13 @@ var _ = Describe("Test Worker CR sync to datastore", func() { By("Start syncing") ctx, cancel := context.WithCancel(context.Background()) defer cancel() - go Start(ctx, ds, cfg, nil) + + appSync := &ApplicationSync{ + KubeClient: k8sClient, + KubeConfig: cfg, + Store: ds, + } + go appSync.Start(ctx, make(chan error)) By("create test app1 and check the syncing results") app1 := &v1beta1.Application{} diff --git a/pkg/apiserver/event/sync/workflow_record.go b/pkg/apiserver/event/sync/workflow_record.go new file mode 100644 index 000000000..b50a4f5b2 --- /dev/null +++ b/pkg/apiserver/event/sync/workflow_record.go @@ -0,0 +1,49 @@ +/* +Copyright 2022 The KubeVela 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 sync + +import ( + "context" + "time" + + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" +) + +// WorkflowRecordSync sync workflow record from cluster to database +type WorkflowRecordSync struct { + Duration time.Duration + WorkflowService service.WorkflowService `inject:""` +} + +// Start sync workflow record data +func (w *WorkflowRecordSync) Start(ctx context.Context, errorChan chan error) { + log.Logger.Infof("workflow record syncing worker started") + defer log.Logger.Infof("workflow record syncing worker closed") + t := time.NewTicker(w.Duration) + defer t.Stop() + for { + select { + case <-t.C: + if err := w.WorkflowService.SyncWorkflowRecord(ctx); err != nil { + log.Logger.Errorf("syncWorkflowRecordError: %s", err.Error()) + } + case <-ctx.Done(): + return + } + } +} diff --git a/pkg/apiserver/clients/kubeclient.go b/pkg/apiserver/infrastructure/clients/kubeclient.go similarity index 100% rename from pkg/apiserver/clients/kubeclient.go rename to pkg/apiserver/infrastructure/clients/kubeclient.go diff --git a/pkg/apiserver/datastore/datastore.go b/pkg/apiserver/infrastructure/datastore/datastore.go similarity index 100% rename from pkg/apiserver/datastore/datastore.go rename to pkg/apiserver/infrastructure/datastore/datastore.go diff --git a/pkg/apiserver/datastore/datastore_suite_test.go b/pkg/apiserver/infrastructure/datastore/datastore_suite_test.go similarity index 100% rename from pkg/apiserver/datastore/datastore_suite_test.go rename to pkg/apiserver/infrastructure/datastore/datastore_suite_test.go diff --git a/pkg/apiserver/datastore/datastore_test.go b/pkg/apiserver/infrastructure/datastore/datastore_test.go similarity index 96% rename from pkg/apiserver/datastore/datastore_test.go rename to pkg/apiserver/infrastructure/datastore/datastore_test.go index 26feeff76..09fd65a55 100644 --- a/pkg/apiserver/datastore/datastore_test.go +++ b/pkg/apiserver/infrastructure/datastore/datastore_test.go @@ -24,7 +24,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/oam-dev/kubevela/pkg/apiserver/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" ) var _ = Describe("Test new entity function", func() { diff --git a/pkg/apiserver/datastore/kubeapi/kubeapi.go b/pkg/apiserver/infrastructure/datastore/kubeapi/kubeapi.go similarity index 94% rename from pkg/apiserver/datastore/kubeapi/kubeapi.go rename to pkg/apiserver/infrastructure/datastore/kubeapi/kubeapi.go index 4bea92d30..60f0260f7 100644 --- a/pkg/apiserver/datastore/kubeapi/kubeapi.go +++ b/pkg/apiserver/infrastructure/datastore/kubeapi/kubeapi.go @@ -34,13 +34,13 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" ) type kubeapi struct { - kubeclient client.Client + kubeClient client.Client namespace string } @@ -66,7 +66,7 @@ func New(ctx context.Context, cfg datastore.Config) (datastore.DataStore, error) } migrate(cfg.Database) return &kubeapi{ - kubeclient: kubeClient, + kubeClient: kubeClient, namespace: cfg.Database, }, nil } @@ -110,7 +110,7 @@ func (m *kubeapi) Add(ctx context.Context, entity datastore.Entity) error { entity.SetCreateTime(time.Now()) entity.SetUpdateTime(time.Now()) configMap := m.generateConfigMap(entity) - if err := m.kubeclient.Create(ctx, configMap); err != nil { + if err := m.kubeClient.Create(ctx, configMap); err != nil { if apierrors.IsAlreadyExists(err) { return datastore.ErrRecordExist } @@ -151,7 +151,7 @@ func (m *kubeapi) Get(ctx context.Context, entity datastore.Entity) error { return datastore.ErrTableNameEmpty } var configMap corev1.ConfigMap - if err := m.kubeclient.Get(ctx, types.NamespacedName{Namespace: m.namespace, Name: generateName(entity)}, &configMap); err != nil { + if err := m.kubeClient.Get(ctx, types.NamespacedName{Namespace: m.namespace, Name: generateName(entity)}, &configMap); err != nil { if apierrors.IsNotFound(err) { return datastore.ErrRecordNotExist } @@ -180,7 +180,7 @@ func (m *kubeapi) Put(ctx context.Context, entity datastore.Entity) error { labels["primaryKey"] = entity.PrimaryKey() entity.SetUpdateTime(time.Now()) var configMap corev1.ConfigMap - if err := m.kubeclient.Get(ctx, types.NamespacedName{Namespace: m.namespace, Name: generateName(entity)}, &configMap); err != nil { + if err := m.kubeClient.Get(ctx, types.NamespacedName{Namespace: m.namespace, Name: generateName(entity)}, &configMap); err != nil { if apierrors.IsNotFound(err) { return datastore.ErrRecordNotExist } @@ -192,7 +192,7 @@ func (m *kubeapi) Put(ctx context.Context, entity datastore.Entity) error { } configMap.BinaryData["data"] = data configMap.Labels = labels - if err := m.kubeclient.Update(ctx, &configMap); err != nil { + if err := m.kubeClient.Update(ctx, &configMap); err != nil { return datastore.NewDBError(err) } return nil @@ -207,7 +207,7 @@ func (m *kubeapi) IsExist(ctx context.Context, entity datastore.Entity) (bool, e return false, datastore.ErrTableNameEmpty } var configMap corev1.ConfigMap - if err := m.kubeclient.Get(ctx, types.NamespacedName{Namespace: m.namespace, Name: generateName(entity)}, &configMap); err != nil { + if err := m.kubeClient.Get(ctx, types.NamespacedName{Namespace: m.namespace, Name: generateName(entity)}, &configMap); err != nil { if apierrors.IsNotFound(err) { return false, nil } @@ -224,7 +224,7 @@ func (m *kubeapi) Delete(ctx context.Context, entity datastore.Entity) error { if entity.TableName() == "" { return datastore.ErrTableNameEmpty } - if err := m.kubeclient.Delete(ctx, m.generateConfigMap(entity)); err != nil { + if err := m.kubeClient.Delete(ctx, m.generateConfigMap(entity)); err != nil { if apierrors.IsNotFound(err) { return datastore.ErrRecordNotExist } @@ -382,7 +382,7 @@ func (m *kubeapi) List(ctx context.Context, entity datastore.Entity, op *datasto } } var configMaps corev1.ConfigMapList - if err := m.kubeclient.List(ctx, &configMaps, options); err != nil { + if err := m.kubeClient.List(ctx, &configMaps, options); err != nil { if apierrors.IsNotFound(err) { return nil, nil } @@ -461,7 +461,7 @@ func (m *kubeapi) Count(ctx context.Context, entity datastore.Entity, filterOpti } var configMaps corev1.ConfigMapList - if err := m.kubeclient.List(ctx, &configMaps, options); err != nil { + if err := m.kubeClient.List(ctx, &configMaps, options); err != nil { if apierrors.IsNotFound(err) { return 0, nil } diff --git a/pkg/apiserver/infrastructure/datastore/kubeapi/kubeapi_suite_test.go b/pkg/apiserver/infrastructure/datastore/kubeapi/kubeapi_suite_test.go new file mode 100644 index 000000000..32407fe70 --- /dev/null +++ b/pkg/apiserver/infrastructure/datastore/kubeapi/kubeapi_suite_test.go @@ -0,0 +1,86 @@ +/* +Copyright 2021 The KubeVela 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 kubeapi + +import ( + "context" + "math/rand" + "testing" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "k8s.io/utils/pointer" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" +) + +func TestKubeapi(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Kubeapi Suite") +} + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment +var testScheme = runtime.NewScheme() +var kubeStore datastore.DataStore + +var _ = BeforeSuite(func(done Done) { + rand.Seed(time.Now().UnixNano()) + By("bootstrapping test environment") + + testEnv = &envtest.Environment{ + ControlPlaneStartTimeout: time.Minute * 3, + ControlPlaneStopTimeout: time.Minute, + UseExistingCluster: pointer.BoolPtr(false), + } + + By("start kube test env") + var err error + cfg, err = testEnv.Start() + Expect(err).ShouldNot(HaveOccurred()) + Expect(cfg).ToNot(BeNil()) + + err = scheme.AddToScheme(testScheme) + Expect(err).NotTo(HaveOccurred()) + + By("new kube client") + cfg.Timeout = time.Minute * 2 + k8sClient, err = client.New(cfg, client.Options{Scheme: testScheme}) + Expect(err).Should(BeNil()) + Expect(k8sClient).ToNot(BeNil()) + By("new kube client success") + + clients.SetKubeClient(k8sClient) + kubeStore, err = New(context.TODO(), datastore.Config{Database: "test"}) + Expect(err).Should(BeNil()) + Expect(kubeStore).ToNot(BeNil()) + close(done) +}, 240) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).ToNot(HaveOccurred()) +}) diff --git a/pkg/apiserver/datastore/kubeapi/kubeapi_test.go b/pkg/apiserver/infrastructure/datastore/kubeapi/kubeapi_test.go similarity index 82% rename from pkg/apiserver/datastore/kubeapi/kubeapi_test.go rename to pkg/apiserver/infrastructure/datastore/kubeapi/kubeapi_test.go index 07c82ee27..29df5e6dd 100644 --- a/pkg/apiserver/datastore/kubeapi/kubeapi_test.go +++ b/pkg/apiserver/infrastructure/datastore/kubeapi/kubeapi_test.go @@ -19,7 +19,6 @@ package kubeapi import ( "context" "fmt" - "math/rand" "strings" "time" @@ -28,84 +27,33 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/selection" - "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" - "k8s.io/utils/pointer" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/envtest" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" ) -var cfg *rest.Config -var k8sClient client.Client -var testEnv *envtest.Environment -var testScheme = runtime.NewScheme() - -var _ = BeforeSuite(func(done Done) { - rand.Seed(time.Now().UnixNano()) - By("bootstrapping test environment") - - testEnv = &envtest.Environment{ - ControlPlaneStartTimeout: time.Minute * 3, - ControlPlaneStopTimeout: time.Minute, - UseExistingCluster: pointer.BoolPtr(false), - } - - By("start kube test env") - var err error - cfg, err = testEnv.Start() - Expect(err).ShouldNot(HaveOccurred()) - Expect(cfg).ToNot(BeNil()) - - err = scheme.AddToScheme(testScheme) - Expect(err).NotTo(HaveOccurred()) - - By("new kube client") - cfg.Timeout = time.Minute * 2 - k8sClient, err = client.New(cfg, client.Options{Scheme: testScheme}) - Expect(err).Should(BeNil()) - Expect(k8sClient).ToNot(BeNil()) - By("new kube client success") - close(done) -}, 240) - -var _ = AfterSuite(func() { - By("tearing down the test environment") - err := testEnv.Stop() - Expect(err).ToNot(HaveOccurred()) -}) - var _ = Describe("Test kubeapi datastore driver", func() { - clients.SetKubeClient(k8sClient) - kubeStore, err := New(context.TODO(), datastore.Config{Database: "test"}) - Expect(err).Should(BeNil()) - Expect(kubeStore).ToNot(BeNil()) - It("Test add function", func() { err := kubeStore.Add(context.TODO(), &model.Application{Name: "kubevela-app", Description: "default"}) Expect(err).ToNot(HaveOccurred()) }) It("Test batch add function", func() { - var datas = []datastore.Entity{ + var entities = []datastore.Entity{ &model.Application{Name: "kubevela-app-2", Description: "this is demo 2"}, &model.Application{Name: "kubevela-app-3", Description: "this is demo 3"}, &model.Application{Name: "kubevela-app-4", Project: "testProject", Description: "this is demo 4"}, } - err := kubeStore.BatchAdd(context.TODO(), datas) + err := kubeStore.BatchAdd(context.TODO(), entities) Expect(err).ToNot(HaveOccurred()) - var datas2 = []datastore.Entity{ + var entities2 = []datastore.Entity{ &model.Application{Name: "can-delete", Description: "this is demo can-delete"}, &model.Application{Name: "kubevela-app-2", Description: "this is demo 2"}, } - err = kubeStore.BatchAdd(context.TODO(), datas2) + err = kubeStore.BatchAdd(context.TODO(), entities2) equal := cmp.Diff(strings.Contains(err.Error(), "save entities occur error"), true) Expect(equal).To(BeEmpty()) }) @@ -269,9 +217,9 @@ var _ = Describe("Test kubeapi datastore driver", func() { Expect(diff).Should(BeEmpty()) app.Name = "kubevela-app-5" - notexist, err := kubeStore.IsExist(context.TODO(), &app) + notExist, err := kubeStore.IsExist(context.TODO(), &app) Expect(err).ShouldNot(HaveOccurred()) - diff = cmp.Diff(notexist, false) + diff = cmp.Diff(notExist, false) Expect(diff).Should(BeEmpty()) }) diff --git a/pkg/apiserver/datastore/kubeapi/migrate.go b/pkg/apiserver/infrastructure/datastore/kubeapi/migrate.go similarity index 95% rename from pkg/apiserver/datastore/kubeapi/migrate.go rename to pkg/apiserver/infrastructure/datastore/kubeapi/migrate.go index 9243c26b4..f058ef3f1 100644 --- a/pkg/apiserver/datastore/kubeapi/migrate.go +++ b/pkg/apiserver/infrastructure/datastore/kubeapi/migrate.go @@ -26,8 +26,8 @@ import ( "k8s.io/klog" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" ) // MigrateKey marks the label key of the migrated data diff --git a/pkg/apiserver/datastore/kubeapi/migrate_test.go b/pkg/apiserver/infrastructure/datastore/kubeapi/migrate_test.go similarity index 86% rename from pkg/apiserver/datastore/kubeapi/migrate_test.go rename to pkg/apiserver/infrastructure/datastore/kubeapi/migrate_test.go index 628b474a7..302af0322 100644 --- a/pkg/apiserver/datastore/kubeapi/migrate_test.go +++ b/pkg/apiserver/infrastructure/datastore/kubeapi/migrate_test.go @@ -26,8 +26,8 @@ import ( v1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" ) var _ = Describe("Test Migrate", func() { @@ -36,7 +36,7 @@ var _ = Describe("Test Migrate", func() { clients.SetKubeClient(k8sClient) nsName := "test-migrate" - ds := &kubeapi{kubeclient: k8sClient, namespace: nsName} + ds := &kubeapi{kubeClient: k8sClient, namespace: nsName} ns := &v1.Namespace{} ns.Name = nsName Expect(k8sClient.Create(context.Background(), ns)).Should(BeNil()) @@ -45,7 +45,7 @@ var _ = Describe("Test Migrate", func() { name := fmt.Sprintf("veladatabase-%s-%s", entity.TableName(), entity.PrimaryKey()) cm.Name = strings.ReplaceAll(name, "_", "-") cm.Namespace = nsName - Expect(ds.kubeclient.Create(context.Background(), cm)).Should(BeNil()) + Expect(ds.kubeClient.Create(context.Background(), cm)).Should(BeNil()) migrate(nsName) cmList := v1.ConfigMapList{} diff --git a/pkg/apiserver/datastore/mongodb/iterator.go b/pkg/apiserver/infrastructure/datastore/mongodb/iterator.go similarity index 100% rename from pkg/apiserver/datastore/mongodb/iterator.go rename to pkg/apiserver/infrastructure/datastore/mongodb/iterator.go diff --git a/pkg/apiserver/datastore/mongodb/mongodb.go b/pkg/apiserver/infrastructure/datastore/mongodb/mongodb.go similarity index 98% rename from pkg/apiserver/datastore/mongodb/mongodb.go rename to pkg/apiserver/infrastructure/datastore/mongodb/mongodb.go index 28f5d2e59..705e1dedd 100644 --- a/pkg/apiserver/datastore/mongodb/mongodb.go +++ b/pkg/apiserver/infrastructure/datastore/mongodb/mongodb.go @@ -28,8 +28,8 @@ import ( "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/x/bsonx" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" ) type mongodb struct { diff --git a/pkg/apiserver/datastore/mongodb/mongodb_suite_test.go b/pkg/apiserver/infrastructure/datastore/mongodb/mongodb_suite_test.go similarity index 92% rename from pkg/apiserver/datastore/mongodb/mongodb_suite_test.go rename to pkg/apiserver/infrastructure/datastore/mongodb/mongodb_suite_test.go index afa23b62e..9d77fd2ce 100644 --- a/pkg/apiserver/datastore/mongodb/mongodb_suite_test.go +++ b/pkg/apiserver/infrastructure/datastore/mongodb/mongodb_suite_test.go @@ -23,7 +23,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" ) func TestMongodb(t *testing.T) { diff --git a/pkg/apiserver/datastore/mongodb/mongodb_test.go b/pkg/apiserver/infrastructure/datastore/mongodb/mongodb_test.go similarity index 98% rename from pkg/apiserver/datastore/mongodb/mongodb_test.go rename to pkg/apiserver/infrastructure/datastore/mongodb/mongodb_test.go index 630287076..93b97933d 100644 --- a/pkg/apiserver/datastore/mongodb/mongodb_test.go +++ b/pkg/apiserver/infrastructure/datastore/mongodb/mongodb_test.go @@ -29,8 +29,8 @@ import ( "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" ) var mongodbDriver datastore.DataStore diff --git a/pkg/apiserver/rest/webservice/addon.go b/pkg/apiserver/interfaces/api/addon.go similarity index 73% rename from pkg/apiserver/rest/webservice/addon.go rename to pkg/apiserver/interfaces/api/addon.go index 806d57c8e..524dc77c5 100644 --- a/pkg/apiserver/rest/webservice/addon.go +++ b/pkg/apiserver/interfaces/api/addon.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( "strconv" @@ -23,35 +23,28 @@ import ( "github.com/emicklei/go-restful/v3" "github.com/oam-dev/kubevela/apis/types" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" ) -// NewAddonWebService returns addon web service -func NewAddonWebService(u usecase.AddonHandler, rbacUsecase usecase.RBACUsecase, cluster usecase.ClusterUsecase) WebService { - return &addonWebService{ - handler: u, - rbacUsecase: rbacUsecase, - clusterHandler: cluster, - } +// NewAddonAPIInterface returns addon web service +func NewAddonAPIInterface() Interface { + return &addonAPIInterface{} } -// NewEnabledAddonWebService returns enabled addon web service -func NewEnabledAddonWebService(u usecase.AddonHandler, rbacUsecase usecase.RBACUsecase) WebService { - return &enabledAddonWebService{ - addonUsecase: u, - rbacUsecase: rbacUsecase, - } +// NewEnabledAddonAPIInterface returns enabled addon web service +func NewEnabledAddonAPIInterface() Interface { + return &enabledAddonAPIInterface{} } -type addonWebService struct { - rbacUsecase usecase.RBACUsecase - handler usecase.AddonHandler - clusterHandler usecase.ClusterUsecase +type addonAPIInterface struct { + RbacService service.RBACService `inject:""` + AddonService service.AddonService `inject:""` + ClusterService service.ClusterService `inject:""` } -func (s *addonWebService) GetWebService() *restful.WebService { +func (s *addonAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/addons"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -64,7 +57,7 @@ func (s *addonWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/").To(s.listAddons). Doc("list all addons"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(s.rbacUsecase.CheckPerm("addon", "list")). + Filter(s.RbacService.CheckPerm("addon", "list")). Param(ws.QueryParameter("registry", "filter addons from given registry").DataType("string")). Param(ws.QueryParameter("query", "Fuzzy search based on name and description.").DataType("string")). Returns(200, "OK", apis.ListAddonResponse{}). @@ -76,7 +69,7 @@ func (s *addonWebService) GetWebService() *restful.WebService { Doc("show details of an addon"). Metadata(restfulspec.KeyOpenAPITags, tags). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(s.rbacUsecase.CheckPerm("addon", "detail")). + Filter(s.RbacService.CheckPerm("addon", "detail")). Returns(200, "OK", apis.DetailAddonResponse{}). Returns(400, "Bad Request", bcode.Bcode{}). Param(ws.PathParameter("name", "addon name to query detail").DataType("string").Required(true)). @@ -89,7 +82,7 @@ func (s *addonWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{addonName}/status").To(s.statusAddon). Doc("show status of an addon"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(s.rbacUsecase.CheckPerm("addon", "detail")). + Filter(s.RbacService.CheckPerm("addon", "detail")). Returns(200, "OK", apis.AddonStatusResponse{}). Returns(400, "Bad Request", bcode.Bcode{}). Param(ws.PathParameter("addonName", "addon name to query status").DataType("string").Required(true)). @@ -100,7 +93,7 @@ func (s *addonWebService) GetWebService() *restful.WebService { Doc("enable an addon"). Metadata(restfulspec.KeyOpenAPITags, tags). Reads(apis.EnableAddonRequest{}). - Filter(s.rbacUsecase.CheckPerm("addon", "enable")). + Filter(s.RbacService.CheckPerm("addon", "enable")). Returns(200, "OK", apis.AddonStatusResponse{}). Returns(400, "Bad Request", bcode.Bcode{}). Param(ws.PathParameter("addonName", "addon name to enable").DataType("string").Required(true)). @@ -111,7 +104,7 @@ func (s *addonWebService) GetWebService() *restful.WebService { Doc("disable an addon"). Metadata(restfulspec.KeyOpenAPITags, tags). Returns(200, "OK", apis.AddonStatusResponse{}). - Filter(s.rbacUsecase.CheckPerm("addon", "disable")). + Filter(s.RbacService.CheckPerm("addon", "disable")). Returns(400, "Bad Request", bcode.Bcode{}). Param(ws.PathParameter("addonName", "addon name to enable").DataType("string").Required(true)). Param(ws.QueryParameter("force", "force disable an addon").DataType("boolean").Required(false)). @@ -123,7 +116,7 @@ func (s *addonWebService) GetWebService() *restful.WebService { Metadata(restfulspec.KeyOpenAPITags, tags). Reads(apis.EnableAddonRequest{}). Returns(200, "OK", apis.AddonStatusResponse{}). - Filter(s.rbacUsecase.CheckPerm("addon", "update")). + Filter(s.RbacService.CheckPerm("addon", "update")). Returns(400, "Bad Request", bcode.Bcode{}). Param(ws.PathParameter("addonName", "addon name to update").DataType("string").Required(true)). Writes(apis.AddonStatusResponse{})) @@ -132,8 +125,8 @@ func (s *addonWebService) GetWebService() *restful.WebService { return ws } -func (s *addonWebService) listAddons(req *restful.Request, res *restful.Response) { - detailAddons, err := s.handler.ListAddons(req.Request.Context(), req.QueryParameter("registry"), req.QueryParameter("query")) +func (s *addonAPIInterface) listAddons(req *restful.Request, res *restful.Response) { + detailAddons, err := s.AddonService.ListAddons(req.Request.Context(), req.QueryParameter("registry"), req.QueryParameter("query")) if len(detailAddons) == 0 && err != nil { bcode.ReturnError(req, res, err) return @@ -156,9 +149,9 @@ func (s *addonWebService) listAddons(req *restful.Request, res *restful.Response } } -func (s *addonWebService) detailAddon(req *restful.Request, res *restful.Response) { +func (s *addonAPIInterface) detailAddon(req *restful.Request, res *restful.Response) { name := req.PathParameter("addonName") - addon, err := s.handler.GetAddon(req.Request.Context(), name, req.QueryParameter("registry"), req.QueryParameter("version")) + addon, err := s.AddonService.GetAddon(req.Request.Context(), name, req.QueryParameter("registry"), req.QueryParameter("version")) if err != nil { bcode.ReturnError(req, res, err) return @@ -172,7 +165,7 @@ func (s *addonWebService) detailAddon(req *restful.Request, res *restful.Respons } -func (s *addonWebService) enableAddon(req *restful.Request, res *restful.Response) { +func (s *addonAPIInterface) enableAddon(req *restful.Request, res *restful.Response) { var createReq apis.EnableAddonRequest var args []byte _, err := req.Request.Body.Read(args) @@ -195,7 +188,7 @@ func (s *addonWebService) enableAddon(req *restful.Request, res *restful.Respons } name := req.PathParameter("addonName") - err = s.handler.EnableAddon(req.Request.Context(), name, createReq) + err = s.AddonService.EnableAddon(req.Request.Context(), name, createReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -204,11 +197,11 @@ func (s *addonWebService) enableAddon(req *restful.Request, res *restful.Respons s.statusAddon(req, res) } -func (s *addonWebService) disableAddon(req *restful.Request, res *restful.Response) { +func (s *addonAPIInterface) disableAddon(req *restful.Request, res *restful.Response) { name := req.PathParameter("addonName") forceParam := req.QueryParameter("force") force, _ := strconv.ParseBool(forceParam) - err := s.handler.DisableAddon(req.Request.Context(), name, force) + err := s.AddonService.DisableAddon(req.Request.Context(), name, force) if err != nil { bcode.ReturnError(req, res, err) return @@ -216,14 +209,14 @@ func (s *addonWebService) disableAddon(req *restful.Request, res *restful.Respon s.statusAddon(req, res) } -func (s *addonWebService) statusAddon(req *restful.Request, res *restful.Response) { +func (s *addonAPIInterface) statusAddon(req *restful.Request, res *restful.Response) { name := req.PathParameter("addonName") - status, err := s.handler.StatusAddon(req.Request.Context(), name) + status, err := s.AddonService.StatusAddon(req.Request.Context(), name) if err != nil { bcode.ReturnError(req, res, err) return } - clusters, err := s.clusterHandler.ListKubeClusters(req.Request.Context(), "", 0, 0) + clusters, err := s.ClusterService.ListKubeClusters(req.Request.Context(), "", 0, 0) if err == nil { // align the alias here for _, c := range clusters.Clusters { @@ -243,7 +236,7 @@ func (s *addonWebService) statusAddon(req *restful.Request, res *restful.Respons } } -func (s *addonWebService) updateAddon(req *restful.Request, res *restful.Response) { +func (s *addonAPIInterface) updateAddon(req *restful.Request, res *restful.Response) { var createReq apis.EnableAddonRequest var args []byte _, err := req.Request.Body.Read(args) @@ -266,7 +259,7 @@ func (s *addonWebService) updateAddon(req *restful.Request, res *restful.Respons } name := req.PathParameter("addonName") - err = s.handler.UpdateAddon(req.Request.Context(), name, createReq) + err = s.AddonService.UpdateAddon(req.Request.Context(), name, createReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -275,12 +268,12 @@ func (s *addonWebService) updateAddon(req *restful.Request, res *restful.Respons s.statusAddon(req, res) } -type enabledAddonWebService struct { - addonUsecase usecase.AddonHandler - rbacUsecase usecase.RBACUsecase +type enabledAddonAPIInterface struct { + AddonService service.AddonService `inject:""` + RbacService service.RBACService `inject:""` } -func (s *enabledAddonWebService) GetWebService() *restful.WebService { +func (s *enabledAddonAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/enabled_addon"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -293,7 +286,7 @@ func (s *enabledAddonWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/").To(s.list). Doc("list all enabled addons"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(s.rbacUsecase.CheckPerm("addon", "list")). + Filter(s.RbacService.CheckPerm("addon", "list")). Param(ws.QueryParameter("registry", "filter addons from given registry").DataType("string")). Param(ws.QueryParameter("query", "Fuzzy search based on name and description.").DataType("string")). Returns(200, "OK", apis.ListEnabledAddonResponse{}). @@ -304,8 +297,8 @@ func (s *enabledAddonWebService) GetWebService() *restful.WebService { return ws } -func (s *enabledAddonWebService) list(req *restful.Request, res *restful.Response) { - enabledAddons, err := s.addonUsecase.ListEnabledAddon(req.Request.Context()) +func (s *enabledAddonAPIInterface) list(req *restful.Request, res *restful.Response) { + enabledAddons, err := s.AddonService.ListEnabledAddon(req.Request.Context()) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/rest/webservice/addon_registry.go b/pkg/apiserver/interfaces/api/addon_registry.go similarity index 70% rename from pkg/apiserver/rest/webservice/addon_registry.go rename to pkg/apiserver/interfaces/api/addon_registry.go index 379b276b4..96de657bb 100644 --- a/pkg/apiserver/rest/webservice/addon_registry.go +++ b/pkg/apiserver/interfaces/api/addon_registry.go @@ -14,31 +14,28 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( restfulspec "github.com/emicklei/go-restful-openapi/v2" "github.com/emicklei/go-restful/v3" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" ) -// NewAddonRegistryWebService returns addon registry web service -func NewAddonRegistryWebService(u usecase.AddonHandler, rbacUsecase usecase.RBACUsecase) WebService { - return &addonRegistryWebService{ - addonUsecase: u, - rbacUsecase: rbacUsecase, - } +// NewAddonRegistryAPIInterface returns addon registry web service +func NewAddonRegistryAPIInterface() Interface { + return &addonRegistryAPIInterface{} } -type addonRegistryWebService struct { - addonUsecase usecase.AddonHandler - rbacUsecase usecase.RBACUsecase +type addonRegistryAPIInterface struct { + AddonService service.AddonService `inject:""` + RbacService service.RBACService `inject:""` } -func (s *addonRegistryWebService) GetWebService() *restful.WebService { +func (s *addonRegistryAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/addon_registries"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -52,7 +49,7 @@ func (s *addonRegistryWebService) GetWebService() *restful.WebService { Doc("create an addon registry"). Metadata(restfulspec.KeyOpenAPITags, tags). Reads(apis.CreateAddonRegistryRequest{}). - Filter(s.rbacUsecase.CheckPerm("addonRegistry", "create")). + Filter(s.RbacService.CheckPerm("addonRegistry", "create")). Returns(200, "OK", apis.AddonRegistry{}). Returns(400, "Bad Request", bcode.Bcode{}). Writes(apis.AddonRegistry{})) @@ -60,7 +57,7 @@ func (s *addonRegistryWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/").To(s.listAddonRegistry). Doc("list all addon registry"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(s.rbacUsecase.CheckPerm("addonRegistry", "list")). + Filter(s.RbacService.CheckPerm("addonRegistry", "list")). Returns(200, "OK", apis.ListAddonRegistryResponse{}). Returns(400, "Bad Request", bcode.Bcode{}). Writes(apis.ListAddonRegistryResponse{})) @@ -71,7 +68,7 @@ func (s *addonRegistryWebService) GetWebService() *restful.WebService { Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.PathParameter("addonRegName", "identifier of the addon registry").DataType("string")). Returns(200, "OK", apis.AddonRegistry{}). - Filter(s.rbacUsecase.CheckPerm("addonRegistry", "delete")). + Filter(s.RbacService.CheckPerm("addonRegistry", "delete")). Returns(400, "Bad Request", bcode.Bcode{}). Writes(apis.AddonRegistry{})) @@ -79,7 +76,7 @@ func (s *addonRegistryWebService) GetWebService() *restful.WebService { Doc("update an addon registry"). Metadata(restfulspec.KeyOpenAPITags, tags). Reads(apis.UpdateAddonRegistryRequest{}). - Filter(s.rbacUsecase.CheckPerm("addonRegistry", "update")). + Filter(s.RbacService.CheckPerm("addonRegistry", "update")). Param(ws.PathParameter("addonRegName", "identifier of the addon registry").DataType("string")). Returns(200, "OK", apis.AddonRegistry{}). Returns(400, "Bad Request", bcode.Bcode{}). @@ -89,7 +86,7 @@ func (s *addonRegistryWebService) GetWebService() *restful.WebService { return ws } -func (s *addonRegistryWebService) createAddonRegistry(req *restful.Request, res *restful.Response) { +func (s *addonRegistryAPIInterface) createAddonRegistry(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var createReq apis.CreateAddonRegistryRequest if err := req.ReadEntity(&createReq); err != nil { @@ -101,8 +98,8 @@ func (s *addonRegistryWebService) createAddonRegistry(req *restful.Request, res return } - // Call the usecase layer code - meta, err := s.addonUsecase.CreateAddonRegistry(req.Request.Context(), createReq) + // Call the domain layer code + meta, err := s.AddonService.CreateAddonRegistry(req.Request.Context(), createReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -115,13 +112,13 @@ func (s *addonRegistryWebService) createAddonRegistry(req *restful.Request, res } } -func (s *addonRegistryWebService) deleteAddonRegistry(req *restful.Request, res *restful.Response) { - r, err := s.addonUsecase.GetAddonRegistry(req.Request.Context(), req.PathParameter("addonRegName")) +func (s *addonRegistryAPIInterface) deleteAddonRegistry(req *restful.Request, res *restful.Response) { + r, err := s.AddonService.GetAddonRegistry(req.Request.Context(), req.PathParameter("addonRegName")) if err != nil { bcode.ReturnError(req, res, err) return } - err = s.addonUsecase.DeleteAddonRegistry(req.Request.Context(), r.Name) + err = s.AddonService.DeleteAddonRegistry(req.Request.Context(), r.Name) if err != nil { bcode.ReturnError(req, res, err) return @@ -133,8 +130,8 @@ func (s *addonRegistryWebService) deleteAddonRegistry(req *restful.Request, res } } -func (s *addonRegistryWebService) listAddonRegistry(req *restful.Request, res *restful.Response) { - registries, err := s.addonUsecase.ListAddonRegistries(req.Request.Context()) +func (s *addonRegistryAPIInterface) listAddonRegistry(req *restful.Request, res *restful.Response) { + registries, err := s.AddonService.ListAddonRegistries(req.Request.Context()) if err != nil { bcode.ReturnError(req, res, err) return @@ -145,7 +142,7 @@ func (s *addonRegistryWebService) listAddonRegistry(req *restful.Request, res *r } } -func (s *addonRegistryWebService) updateAddonRegistry(req *restful.Request, res *restful.Response) { +func (s *addonRegistryAPIInterface) updateAddonRegistry(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var updateReq apis.UpdateAddonRegistryRequest if err := req.ReadEntity(&updateReq); err != nil { @@ -156,8 +153,8 @@ func (s *addonRegistryWebService) updateAddonRegistry(req *restful.Request, res bcode.ReturnError(req, res, err) return } - // Call the usecase layer code - meta, err := s.addonUsecase.UpdateAddonRegistry(req.Request.Context(), req.PathParameter("addonRegName"), updateReq) + // Call the domain layer code + meta, err := s.AddonService.UpdateAddonRegistry(req.Request.Context(), req.PathParameter("addonRegName"), updateReq) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/rest/webservice/webservice_suite_test.go b/pkg/apiserver/interfaces/api/api_suite_test.go similarity index 86% rename from pkg/apiserver/rest/webservice/webservice_suite_test.go rename to pkg/apiserver/interfaces/api/api_suite_test.go index 9857d5565..d86719d40 100644 --- a/pkg/apiserver/rest/webservice/webservice_suite_test.go +++ b/pkg/apiserver/interfaces/api/api_suite_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( "context" @@ -31,10 +31,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore/kubeapi" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore/mongodb" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore/kubeapi" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore/mongodb" "github.com/oam-dev/kubevela/pkg/utils/common" ) @@ -42,9 +42,9 @@ var cfg *rest.Config var k8sClient client.Client var testEnv *envtest.Environment -func TestWebservice(t *testing.T) { +func TestAPIInterface(t *testing.T) { RegisterFailHandler(Fail) - RunSpecs(t, "Webservice Suite") + RunSpecs(t, "APIInterface Suite") } var _ = BeforeSuite(func(done Done) { diff --git a/pkg/apiserver/rest/webservice/application.go b/pkg/apiserver/interfaces/api/application.go similarity index 79% rename from pkg/apiserver/rest/webservice/application.go rename to pkg/apiserver/interfaces/api/application.go index bfd993f00..907b8aa02 100644 --- a/pkg/apiserver/rest/webservice/application.go +++ b/pkg/apiserver/interfaces/api/application.go @@ -14,44 +14,36 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( "context" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" restfulspec "github.com/emicklei/go-restful-openapi/v2" "github.com/emicklei/go-restful/v3" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" ) -type applicationWebService struct { - workflowWebService - rbacUsecase usecase.RBACUsecase - applicationUsecase usecase.ApplicationUsecase - envBindingUsecase usecase.EnvBindingUsecase +type applicationAPIInterface struct { + WorkflowAPI WorkflowAPIInterface `inject:"inline"` + RbacService service.RBACService `inject:""` + ApplicationService service.ApplicationService `inject:""` + EnvBindingService service.EnvBindingService `inject:""` } -// NewApplicationWebService new application manage webservice -func NewApplicationWebService(applicationUsecase usecase.ApplicationUsecase, envBindingUsecase usecase.EnvBindingUsecase, workflowUsecase usecase.WorkflowUsecase, rbacUsecase usecase.RBACUsecase) WebService { - return &applicationWebService{ - workflowWebService: workflowWebService{ - workflowUsecase: workflowUsecase, - applicationUsecase: applicationUsecase, - }, - rbacUsecase: rbacUsecase, - applicationUsecase: applicationUsecase, - envBindingUsecase: envBindingUsecase, - } +// NewApplicationAPIInterface new application manage APIInterface +func NewApplicationAPIInterface() Interface { + return &applicationAPIInterface{} } -func (c *applicationWebService) GetWebService() *restful.WebService { +func (c *applicationAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/applications"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -68,7 +60,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { Param(ws.QueryParameter("env", "search base on env name").DataType("string")). Param(ws.QueryParameter("targetName", "Name of the application delivery target").DataType("string")). // This api will filter the app by user's permissions - // Filter(c.rbacUsecase.CheckPerm("application", "list")). + // Filter(c.RbacService.CheckPerm("application", "list")). Returns(200, "OK", apis.ListApplicationResponse{}). Returns(400, "Bad Request", bcode.Bcode{}). Writes(apis.ListApplicationResponse{})) @@ -77,7 +69,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { Doc("create one application "). Metadata(restfulspec.KeyOpenAPITags, tags). Reads(apis.CreateApplicationRequest{}). - Filter(c.rbacUsecase.CheckPerm("application", "create")). + Filter(c.RbacService.CheckPerm("application", "create")). Returns(200, "OK", apis.ApplicationBase{}). Returns(400, "Bad Request", bcode.Bcode{}). Writes(apis.ApplicationBase{})) @@ -85,7 +77,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.DELETE("/{appName}").To(c.deleteApplication). Doc("delete one application"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("application", "delete")). + Filter(c.RbacService.CheckPerm("application", "delete")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Returns(200, "OK", apis.EmptyResponse{}). @@ -95,7 +87,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{appName}").To(c.detailApplication). Doc("detail one application "). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("application", "detail")). + Filter(c.RbacService.CheckPerm("application", "detail")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Returns(200, "OK", apis.DetailApplicationResponse{}). @@ -105,7 +97,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.PUT("/{appName}").To(c.updateApplication). Doc("update one application "). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("application", "update")). + Filter(c.RbacService.CheckPerm("application", "update")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Reads(apis.UpdateApplicationRequest{}). @@ -116,7 +108,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{appName}/statistics").To(c.applicationStatistics). Doc("detail one application "). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("application", "detail")). + Filter(c.RbacService.CheckPerm("application", "detail")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Returns(200, "OK", apis.ApplicationStatisticsResponse{}). @@ -126,7 +118,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/{appName}/triggers").To(c.createApplicationTrigger). Doc("create one application trigger"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("trigger", "create")). + Filter(c.RbacService.CheckPerm("trigger", "create")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Reads(apis.CreateApplicationTriggerRequest{}). @@ -137,7 +129,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.DELETE("/{appName}/triggers/{token}").To(c.deleteApplicationTrigger). Doc("delete one application trigger"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("trigger", "delete")). + Filter(c.RbacService.CheckPerm("trigger", "delete")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Param(ws.PathParameter("token", "identifier of the trigger").DataType("string")). @@ -148,7 +140,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{appName}/triggers").To(c.listApplicationTriggers). Doc("list application triggers"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("trigger", "list")). + Filter(c.RbacService.CheckPerm("trigger", "list")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Returns(200, "OK", apis.ListApplicationTriggerResponse{}). @@ -158,7 +150,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/{appName}/template").To(c.publishApplicationTemplate). Doc("create one application template"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("applicationTemplate", "create")). + Filter(c.RbacService.CheckPerm("applicationTemplate", "create")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Reads(apis.CreateApplicationTemplateRequest{}). @@ -169,7 +161,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/{appName}/deploy").To(c.deployApplication). Doc("deploy or upgrade the application"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("application", "deploy")). + Filter(c.RbacService.CheckPerm("application", "deploy")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Reads(apis.ApplicationDeployRequest{}). @@ -179,7 +171,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{appName}/components").To(c.listApplicationComponents). Doc("gets the list of application components"). - Filter(c.rbacUsecase.CheckPerm("component", "list")). + Filter(c.RbacService.CheckPerm("component", "list")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Param(ws.QueryParameter("envName", "list components that deployed in define env").DataType("string")). @@ -190,7 +182,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/{appName}/components").To(c.createComponent). Doc("create component for application "). - Filter(c.rbacUsecase.CheckPerm("component", "create")). + Filter(c.RbacService.CheckPerm("component", "create")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Metadata(restfulspec.KeyOpenAPITags, tags). @@ -201,7 +193,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{appName}/components/{compName}").To(c.detailComponent). Doc("detail component for application "). - Filter(c.rbacUsecase.CheckPerm("component", "detail")). + Filter(c.RbacService.CheckPerm("component", "detail")). Filter(c.appCheckFilter). Filter(c.componentCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). @@ -213,7 +205,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.PUT("/{appName}/components/{compName}").To(c.updateComponent). Doc("update component config"). - Filter(c.rbacUsecase.CheckPerm("component", "update")). + Filter(c.RbacService.CheckPerm("component", "update")). Filter(c.appCheckFilter). Filter(c.componentCheckFilter). Param(ws.PathParameter("appName", "identifier of the application").DataType("string")). @@ -226,7 +218,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.DELETE("/{appName}/components/{compName}").To(c.deleteComponent). Doc("delete a component"). - Filter(c.rbacUsecase.CheckPerm("component", "delete")). + Filter(c.RbacService.CheckPerm("component", "delete")). Filter(c.appCheckFilter). Filter(c.componentCheckFilter). Param(ws.PathParameter("appName", "identifier of the application").DataType("string")). @@ -239,7 +231,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{appName}/policies").To(c.listApplicationPolicies). Doc("list policy for application"). - Filter(c.rbacUsecase.CheckPerm("policy", "list")). + Filter(c.RbacService.CheckPerm("policy", "list")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Metadata(restfulspec.KeyOpenAPITags, tags). @@ -249,7 +241,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/{appName}/policies").To(c.createApplicationPolicy). Doc("create policy for application"). - Filter(c.rbacUsecase.CheckPerm("policy", "create")). + Filter(c.RbacService.CheckPerm("policy", "create")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application").DataType("string")). Metadata(restfulspec.KeyOpenAPITags, tags). @@ -260,7 +252,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{appName}/policies/{policyName}").To(c.detailApplicationPolicy). Doc("detail policy for application"). - Filter(c.rbacUsecase.CheckPerm("policy", "detail")). + Filter(c.RbacService.CheckPerm("policy", "detail")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application").DataType("string")). Param(ws.PathParameter("policyName", "identifier of the application policy").DataType("string")). @@ -271,7 +263,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.DELETE("/{appName}/policies/{policyName}").To(c.deleteApplicationPolicy). Doc("detail policy for application"). - Filter(c.rbacUsecase.CheckPerm("policy", "delete")). + Filter(c.RbacService.CheckPerm("policy", "delete")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application").DataType("string")). Param(ws.PathParameter("policyName", "identifier of the application policy").DataType("string")). @@ -282,7 +274,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.PUT("/{appName}/policies/{policyName}").To(c.updateApplicationPolicy). Doc("update policy for application"). - Filter(c.rbacUsecase.CheckPerm("policy", "update")). + Filter(c.RbacService.CheckPerm("policy", "update")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application").DataType("string")). Param(ws.PathParameter("policyName", "identifier of the application policy").DataType("string")). @@ -294,7 +286,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/{appName}/components/{compName}/traits").To(c.addApplicationTrait). Doc("add trait for a component"). - Filter(c.rbacUsecase.CheckPerm("trait", "create")). + Filter(c.RbacService.CheckPerm("trait", "create")). Filter(c.appCheckFilter). Filter(c.componentCheckFilter). Param(ws.PathParameter("appName", "identifier of the application").DataType("string")). @@ -307,7 +299,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.PUT("/{appName}/components/{compName}/traits/{traitType}").To(c.updateApplicationTrait). Doc("update trait from a component"). - Filter(c.rbacUsecase.CheckPerm("trait", "update")). + Filter(c.RbacService.CheckPerm("trait", "update")). Filter(c.appCheckFilter). Filter(c.componentCheckFilter). Param(ws.PathParameter("appName", "identifier of the application").DataType("string")). @@ -321,7 +313,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.DELETE("/{appName}/components/{compName}/traits/{traitType}").To(c.deleteApplicationTrait). Doc("delete trait from a component"). - Filter(c.rbacUsecase.CheckPerm("trait", "delete")). + Filter(c.RbacService.CheckPerm("trait", "delete")). Filter(c.appCheckFilter). Filter(c.componentCheckFilter). Param(ws.PathParameter("appName", "identifier of the application").DataType("string")). @@ -334,7 +326,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{appName}/revisions").To(c.listApplicationRevisions). Doc("list revisions for application"). - Filter(c.rbacUsecase.CheckPerm("revision", "list")). + Filter(c.RbacService.CheckPerm("revision", "list")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Param(ws.QueryParameter("envName", "query identifier of the env").DataType("string")). @@ -348,7 +340,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{appName}/revisions/{revision}").To(c.detailApplicationRevision). Doc("detail revision for application"). - Filter(c.rbacUsecase.CheckPerm("revision", "detail")). + Filter(c.RbacService.CheckPerm("revision", "detail")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application").DataType("string")). Param(ws.PathParameter("revision", "identifier of the application revision").DataType("string")). @@ -359,7 +351,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{appName}/envs").To(c.listApplicationEnvs). Doc("list policy for application"). - Filter(c.rbacUsecase.CheckPerm("envBinding", "list")). + Filter(c.RbacService.CheckPerm("envBinding", "list")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Metadata(restfulspec.KeyOpenAPITags, tags). @@ -369,7 +361,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/{appName}/envs").To(c.createApplicationEnv). Doc("creating an application environment "). - Filter(c.rbacUsecase.CheckPerm("envBinding", "create")). + Filter(c.RbacService.CheckPerm("envBinding", "create")). Metadata(restfulspec.KeyOpenAPITags, tags). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). @@ -381,7 +373,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.PUT("/{appName}/envs/{envName}").To(c.updateApplicationEnv). Doc("set application differences in the specified environment"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("envBinding", "update")). + Filter(c.RbacService.CheckPerm("envBinding", "update")). Filter(c.appCheckFilter). Filter(c.envCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). @@ -394,7 +386,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.DELETE("/{appName}/envs/{envName}").To(c.deleteApplicationEnv). Doc("delete an application environment "). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("envBinding", "delete")). + Filter(c.RbacService.CheckPerm("envBinding", "delete")). Filter(c.appCheckFilter). Filter(c.envCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). @@ -406,7 +398,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{appName}/envs/{envName}/status").To(c.getApplicationStatus). Doc("get application status"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("envBinding", "detail")). + Filter(c.RbacService.CheckPerm("envBinding", "detail")). Filter(c.appCheckFilter). Filter(c.envCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). @@ -418,7 +410,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/{appName}/envs/{envName}/recycle").To(c.recycleApplicationEnv). Doc("get application status"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("envBinding", "recycle")). + Filter(c.RbacService.CheckPerm("envBinding", "recycle")). Filter(c.appCheckFilter). Filter(c.envCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string").Required(true)). @@ -427,18 +419,18 @@ func (c *applicationWebService) GetWebService() *restful.WebService { Returns(400, "Bad Request", bcode.Bcode{}). Writes(apis.EmptyResponse{})) - ws.Route(ws.GET("/{appName}/workflows").To(c.listApplicationWorkflows). + ws.Route(ws.GET("/{appName}/workflows").To(c.WorkflowAPI.listApplicationWorkflows). Doc("list application workflow"). - Filter(c.rbacUsecase.CheckPerm("application/workflow", "list")). + Filter(c.RbacService.CheckPerm("application/workflow", "list")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application.").DataType("string").Required(true)). Metadata(restfulspec.KeyOpenAPITags, tags). Returns(200, "OK", apis.ListWorkflowResponse{}). Writes(apis.ListWorkflowResponse{}).Do(returns200, returns500)) - ws.Route(ws.POST("/{appName}/workflows").To(c.createOrUpdateApplicationWorkflow). + ws.Route(ws.POST("/{appName}/workflows").To(c.WorkflowAPI.createOrUpdateApplicationWorkflow). Doc("create application workflow"). - Filter(c.rbacUsecase.CheckPerm("application/workflow", "create")). + Filter(c.RbacService.CheckPerm("application/workflow", "create")). Metadata(restfulspec.KeyOpenAPITags, tags). Reads(apis.CreateWorkflowRequest{}). Filter(c.appCheckFilter). @@ -447,109 +439,109 @@ func (c *applicationWebService) GetWebService() *restful.WebService { Returns(400, "create failure", bcode.Bcode{}). Writes(apis.DetailWorkflowResponse{}).Do(returns200, returns500)) - ws.Route(ws.GET("/{appName}/workflows/{workflowName}").To(c.detailWorkflow). + ws.Route(ws.GET("/{appName}/workflows/{workflowName}").To(c.WorkflowAPI.detailWorkflow). Doc("detail application workflow"). - Filter(c.rbacUsecase.CheckPerm("application/workflow", "detail")). + Filter(c.RbacService.CheckPerm("application/workflow", "detail")). Filter(c.appCheckFilter). - Filter(c.workflowCheckFilter). + Filter(c.WorkflowAPI.workflowCheckFilter). Param(ws.PathParameter("appName", "identifier of the application.").DataType("string").Required(true)). Param(ws.PathParameter("workflowName", "identifier of the workfloc.").DataType("string")). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.workflowCheckFilter). + Filter(c.WorkflowAPI.workflowCheckFilter). Returns(200, "create success", apis.DetailWorkflowResponse{}). Writes(apis.DetailWorkflowResponse{}).Do(returns200, returns500)) - ws.Route(ws.PUT("/{appName}/workflows/{workflowName}").To(c.updateWorkflow). + ws.Route(ws.PUT("/{appName}/workflows/{workflowName}").To(c.WorkflowAPI.updateWorkflow). Doc("update application workflow config"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("application/workflow", "update")). + Filter(c.RbacService.CheckPerm("application/workflow", "update")). Filter(c.appCheckFilter). - Filter(c.workflowCheckFilter). + Filter(c.WorkflowAPI.workflowCheckFilter). Param(ws.PathParameter("appName", "identifier of the application.").DataType("string").Required(true)). Param(ws.PathParameter("workflowName", "identifier of the workflow").DataType("string")). Reads(apis.UpdateWorkflowRequest{}). Returns(200, "OK", apis.DetailWorkflowResponse{}). Writes(apis.DetailWorkflowResponse{}).Do(returns200, returns500)) - ws.Route(ws.DELETE("/{appName}/workflows/{workflowName}").To(c.deleteWorkflow). + ws.Route(ws.DELETE("/{appName}/workflows/{workflowName}").To(c.WorkflowAPI.deleteWorkflow). Doc("deletet workflow"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("application/workflow", "delete")). + Filter(c.RbacService.CheckPerm("application/workflow", "delete")). Filter(c.appCheckFilter). - Filter(c.workflowCheckFilter). + Filter(c.WorkflowAPI.workflowCheckFilter). Param(ws.PathParameter("appName", "identifier of the application.").DataType("string").Required(true)). Param(ws.PathParameter("workflowName", "identifier of the workflow").DataType("string")). Returns(200, "OK", apis.EmptyResponse{}). Writes(apis.EmptyResponse{}).Do(returns200, returns500)) - ws.Route(ws.GET("/{appName}/workflows/{workflowName}/records").To(c.listWorkflowRecords). + ws.Route(ws.GET("/{appName}/workflows/{workflowName}/records").To(c.WorkflowAPI.listWorkflowRecords). Doc("query application workflow execution record"). Param(ws.PathParameter("appName", "identifier of the application.").DataType("string").Required(true)). Param(ws.PathParameter("workflowName", "identifier of the workflow").DataType("string")). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("application/workflow/record", "list")). + Filter(c.RbacService.CheckPerm("application/workflow/record", "list")). Filter(c.appCheckFilter). - Filter(c.workflowCheckFilter). + Filter(c.WorkflowAPI.workflowCheckFilter). Param(ws.QueryParameter("page", "query the page number").DataType("integer")). Param(ws.QueryParameter("pageSize", "query the page size number").DataType("integer")). Returns(200, "OK", apis.ListWorkflowRecordsResponse{}). Writes(apis.ListWorkflowRecordsResponse{}).Do(returns200, returns500)) - ws.Route(ws.GET("/{appName}/workflows/{workflowName}/records/{record}").To(c.detailWorkflowRecord). + ws.Route(ws.GET("/{appName}/workflows/{workflowName}/records/{record}").To(c.WorkflowAPI.detailWorkflowRecord). Doc("query application workflow execution record detail"). - Filter(c.rbacUsecase.CheckPerm("application/workflow/record", "detail")). + Filter(c.RbacService.CheckPerm("application/workflow/record", "detail")). Param(ws.PathParameter("appName", "identifier of the application.").DataType("string").Required(true)). Param(ws.PathParameter("workflowName", "identifier of the workflow").DataType("string")). Param(ws.PathParameter("record", "identifier of the workflow record").DataType("string")). Metadata(restfulspec.KeyOpenAPITags, tags). Filter(c.appCheckFilter). - Filter(c.workflowCheckFilter). + Filter(c.WorkflowAPI.workflowCheckFilter). Returns(200, "OK", apis.DetailWorkflowRecordResponse{}). Writes(apis.DetailWorkflowRecordResponse{}).Do(returns200, returns500)) - ws.Route(ws.GET("/{appName}/workflows/{workflowName}/records/{record}/resume").To(c.resumeWorkflowRecord). + ws.Route(ws.GET("/{appName}/workflows/{workflowName}/records/{record}/resume").To(c.WorkflowAPI.resumeWorkflowRecord). Doc("resume suspend workflow record"). - Filter(c.rbacUsecase.CheckPerm("application/workflow/record", "resume")). + Filter(c.RbacService.CheckPerm("application/workflow/record", "resume")). Param(ws.PathParameter("appName", "identifier of the application.").DataType("string").Required(true)). Param(ws.PathParameter("workflowName", "identifier of the workflow").DataType("string")). Param(ws.PathParameter("record", "identifier of the workflow record").DataType("string")). Metadata(restfulspec.KeyOpenAPITags, tags). Filter(c.appCheckFilter). - Filter(c.workflowCheckFilter). + Filter(c.WorkflowAPI.workflowCheckFilter). Returns(200, "OK", nil). Returns(400, "Bad Request", bcode.Bcode{}). Writes(apis.DetailWorkflowRecordResponse{})) - ws.Route(ws.GET("/{appName}/workflows/{workflowName}/records/{record}/terminate").To(c.terminateWorkflowRecord). + ws.Route(ws.GET("/{appName}/workflows/{workflowName}/records/{record}/terminate").To(c.WorkflowAPI.terminateWorkflowRecord). Doc("terminate suspend workflow record"). - Filter(c.rbacUsecase.CheckPerm("application/workflow/record", "terminate")). + Filter(c.RbacService.CheckPerm("application/workflow/record", "terminate")). Param(ws.PathParameter("appName", "identifier of the application.").DataType("string").Required(true)). Param(ws.PathParameter("workflowName", "identifier of the workflow").DataType("string")). Param(ws.PathParameter("record", "identifier of the workflow record").DataType("string")). Metadata(restfulspec.KeyOpenAPITags, tags). Filter(c.appCheckFilter). - Filter(c.workflowCheckFilter). + Filter(c.WorkflowAPI.workflowCheckFilter). Returns(200, "OK", nil). Returns(400, "Bad Request", bcode.Bcode{}). Writes(apis.DetailWorkflowRecordResponse{})) - ws.Route(ws.GET("/{appName}/workflows/{workflowName}/records/{record}/rollback").To(c.rollbackWorkflowRecord). + ws.Route(ws.GET("/{appName}/workflows/{workflowName}/records/{record}/rollback").To(c.WorkflowAPI.rollbackWorkflowRecord). Doc("rollback suspend application record"). - Filter(c.rbacUsecase.CheckPerm("application/workflow/record", "rollback")). + Filter(c.RbacService.CheckPerm("application/workflow/record", "rollback")). Param(ws.PathParameter("appName", "identifier of the application.").DataType("string").Required(true)). Param(ws.PathParameter("workflowName", "identifier of the workflow").DataType("string")). Param(ws.PathParameter("record", "identifier of the workflow record").DataType("string")). Param(ws.QueryParameter("rollbackVersion", "identifier of the rollback revision").DataType("string")). Metadata(restfulspec.KeyOpenAPITags, tags). Filter(c.appCheckFilter). - Filter(c.workflowCheckFilter). + Filter(c.WorkflowAPI.workflowCheckFilter). Returns(200, "OK", nil). Returns(400, "Bad Request", bcode.Bcode{}). Writes(apis.DetailWorkflowRecordResponse{})) ws.Route(ws.GET("/{appName}/records").To(c.listApplicationRecords). Doc("list application records"). - Filter(c.rbacUsecase.CheckPerm("application/workflow/record", "list")). + Filter(c.RbacService.CheckPerm("application/workflow/record", "list")). Param(ws.PathParameter("appName", "identifier of the application.").DataType("string").Required(true)). Metadata(restfulspec.KeyOpenAPITags, tags). Filter(c.appCheckFilter). @@ -560,7 +552,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/{appName}/compare").To(c.compareAppWithLatestRevision). Doc("compare application with env latest revision"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("application", "compare")). + Filter(c.RbacService.CheckPerm("application", "compare")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Returns(200, "OK", apis.ApplicationBase{}). @@ -570,7 +562,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/{appName}/reset").To(c.resetAppToLatestRevision). Doc("reset application to latest revision"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("application", "reset")). + Filter(c.RbacService.CheckPerm("application", "reset")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Returns(200, "OK", apis.AppResetResponse{}). @@ -580,7 +572,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/{appName}/dry-run").To(c.dryRunAppOrRevision). Doc("dry-run application to latest revision"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("application", "detail")). + Filter(c.RbacService.CheckPerm("application", "detail")). Filter(c.appCheckFilter). Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")). Returns(200, "OK", apis.AppDryRunResponse{}). @@ -591,7 +583,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService { return ws } -func (c *applicationWebService) createApplication(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) createApplication(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var createReq apis.CreateApplicationRequest if err := req.ReadEntity(&createReq); err != nil { @@ -602,8 +594,8 @@ func (c *applicationWebService) createApplication(req *restful.Request, res *res bcode.ReturnError(req, res, err) return } - // Call the usecase layer code - appBase, err := c.applicationUsecase.CreateApplication(req.Request.Context(), createReq) + // Call the domain layer code + appBase, err := c.ApplicationService.CreateApplication(req.Request.Context(), createReq) if err != nil { log.Logger.Errorf("create application failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -617,12 +609,12 @@ func (c *applicationWebService) createApplication(req *restful.Request, res *res } } -func (c *applicationWebService) listApplications(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) listApplications(req *restful.Request, res *restful.Response) { var projetNames []string if req.QueryParameter("project") != "" { projetNames = append(projetNames, req.QueryParameter("project")) } - apps, err := c.applicationUsecase.ListApplications(req.Request.Context(), apis.ListApplicationOptions{ + apps, err := c.ApplicationService.ListApplications(req.Request.Context(), apis.ListApplicationOptions{ Projects: projetNames, Env: req.QueryParameter("env"), TargetName: req.QueryParameter("targetName"), @@ -638,9 +630,9 @@ func (c *applicationWebService) listApplications(req *restful.Request, res *rest } } -func (c *applicationWebService) detailApplication(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) detailApplication(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - detail, err := c.applicationUsecase.DetailApplication(req.Request.Context(), app) + detail, err := c.ApplicationService.DetailApplication(req.Request.Context(), app) if err != nil { bcode.ReturnError(req, res, err) return @@ -651,14 +643,14 @@ func (c *applicationWebService) detailApplication(req *restful.Request, res *res } } -func (c *applicationWebService) createApplicationTrigger(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) createApplicationTrigger(req *restful.Request, res *restful.Response) { var createReq apis.CreateApplicationTriggerRequest if err := req.ReadEntity(&createReq); err != nil { bcode.ReturnError(req, res, err) return } app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - base, err := c.applicationUsecase.CreateApplicationTrigger(req.Request.Context(), app, createReq) + base, err := c.ApplicationService.CreateApplicationTrigger(req.Request.Context(), app, createReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -669,9 +661,9 @@ func (c *applicationWebService) createApplicationTrigger(req *restful.Request, r } } -func (c *applicationWebService) listApplicationTriggers(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) listApplicationTriggers(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - triggers, err := c.applicationUsecase.ListApplicationTriggers(req.Request.Context(), app) + triggers, err := c.ApplicationService.ListApplicationTriggers(req.Request.Context(), app) if err != nil { bcode.ReturnError(req, res, err) return @@ -682,9 +674,9 @@ func (c *applicationWebService) listApplicationTriggers(req *restful.Request, re } } -func (c *applicationWebService) deleteApplicationTrigger(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) deleteApplicationTrigger(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - if err := c.applicationUsecase.DeleteApplicationTrigger(req.Request.Context(), app, req.PathParameter("token")); err != nil { + if err := c.ApplicationService.DeleteApplicationTrigger(req.Request.Context(), app, req.PathParameter("token")); err != nil { bcode.ReturnError(req, res, err) return } @@ -694,9 +686,9 @@ func (c *applicationWebService) deleteApplicationTrigger(req *restful.Request, r } } -func (c *applicationWebService) publishApplicationTemplate(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) publishApplicationTemplate(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - base, err := c.applicationUsecase.PublishApplicationTemplate(req.Request.Context(), app) + base, err := c.ApplicationService.PublishApplicationTemplate(req.Request.Context(), app) if err != nil { bcode.ReturnError(req, res, err) return @@ -708,7 +700,7 @@ func (c *applicationWebService) publishApplicationTemplate(req *restful.Request, } // deployApplication TODO: return event model -func (c *applicationWebService) deployApplication(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) deployApplication(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) // Verify the validity of parameters var createReq apis.ApplicationDeployRequest @@ -720,7 +712,7 @@ func (c *applicationWebService) deployApplication(req *restful.Request, res *res bcode.ReturnError(req, res, err) return } - deployRes, err := c.applicationUsecase.Deploy(req.Request.Context(), app, createReq) + deployRes, err := c.ApplicationService.Deploy(req.Request.Context(), app, createReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -731,9 +723,9 @@ func (c *applicationWebService) deployApplication(req *restful.Request, res *res } } -func (c *applicationWebService) deleteApplication(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) deleteApplication(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - err := c.applicationUsecase.DeleteApplication(req.Request.Context(), app) + err := c.ApplicationService.DeleteApplication(req.Request.Context(), app) if err != nil { bcode.ReturnError(req, res, err) return @@ -744,9 +736,9 @@ func (c *applicationWebService) deleteApplication(req *restful.Request, res *res } } -func (c *applicationWebService) listApplicationComponents(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) listApplicationComponents(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - components, err := c.applicationUsecase.ListComponents(req.Request.Context(), app, apis.ListApplicationComponentOptions{ + components, err := c.ApplicationService.ListComponents(req.Request.Context(), app, apis.ListApplicationComponentOptions{ EnvName: req.QueryParameter("envName"), }) if err != nil { @@ -759,7 +751,7 @@ func (c *applicationWebService) listApplicationComponents(req *restful.Request, } } -func (c *applicationWebService) createComponent(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) createComponent(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) // Verify the validity of parameters var createReq apis.CreateComponentRequest @@ -771,7 +763,7 @@ func (c *applicationWebService) createComponent(req *restful.Request, res *restf bcode.ReturnError(req, res, err) return } - base, err := c.applicationUsecase.CreateComponent(req.Request.Context(), app, createReq) + base, err := c.ApplicationService.CreateComponent(req.Request.Context(), app, createReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -782,9 +774,9 @@ func (c *applicationWebService) createComponent(req *restful.Request, res *restf } } -func (c *applicationWebService) detailComponent(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) detailComponent(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - detail, err := c.applicationUsecase.DetailComponent(req.Request.Context(), app, req.PathParameter("compName")) + detail, err := c.ApplicationService.DetailComponent(req.Request.Context(), app, req.PathParameter("compName")) if err != nil { bcode.ReturnError(req, res, err) return @@ -795,7 +787,7 @@ func (c *applicationWebService) detailComponent(req *restful.Request, res *restf } } -func (c *applicationWebService) updateComponent(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) updateComponent(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) component := req.Request.Context().Value(&apis.CtxKeyApplicationComponent).(*model.ApplicationComponent) // Verify the validity of parameters @@ -808,7 +800,7 @@ func (c *applicationWebService) updateComponent(req *restful.Request, res *restf bcode.ReturnError(req, res, err) return } - base, err := c.applicationUsecase.UpdateComponent(req.Request.Context(), app, component, updateReq) + base, err := c.ApplicationService.UpdateComponent(req.Request.Context(), app, component, updateReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -819,10 +811,10 @@ func (c *applicationWebService) updateComponent(req *restful.Request, res *restf } } -func (c *applicationWebService) deleteComponent(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) deleteComponent(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) component := req.Request.Context().Value(&apis.CtxKeyApplicationComponent).(*model.ApplicationComponent) - err := c.applicationUsecase.DeleteComponent(req.Request.Context(), app, component) + err := c.ApplicationService.DeleteComponent(req.Request.Context(), app, component) if err != nil { bcode.ReturnError(req, res, err) return @@ -833,7 +825,7 @@ func (c *applicationWebService) deleteComponent(req *restful.Request, res *restf } } -func (c *applicationWebService) createApplicationPolicy(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) createApplicationPolicy(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) // Verify the validity of parameters var createReq apis.CreatePolicyRequest @@ -845,7 +837,7 @@ func (c *applicationWebService) createApplicationPolicy(req *restful.Request, re bcode.ReturnError(req, res, err) return } - base, err := c.applicationUsecase.CreatePolicy(req.Request.Context(), app, createReq) + base, err := c.ApplicationService.CreatePolicy(req.Request.Context(), app, createReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -856,9 +848,9 @@ func (c *applicationWebService) createApplicationPolicy(req *restful.Request, re } } -func (c *applicationWebService) listApplicationPolicies(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) listApplicationPolicies(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - policies, err := c.applicationUsecase.ListPolicies(req.Request.Context(), app) + policies, err := c.ApplicationService.ListPolicies(req.Request.Context(), app) if err != nil { bcode.ReturnError(req, res, err) return @@ -869,9 +861,9 @@ func (c *applicationWebService) listApplicationPolicies(req *restful.Request, re } } -func (c *applicationWebService) detailApplicationPolicy(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) detailApplicationPolicy(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - detail, err := c.applicationUsecase.DetailPolicy(req.Request.Context(), app, req.PathParameter("policyName")) + detail, err := c.ApplicationService.DetailPolicy(req.Request.Context(), app, req.PathParameter("policyName")) if err != nil { bcode.ReturnError(req, res, err) return @@ -882,9 +874,9 @@ func (c *applicationWebService) detailApplicationPolicy(req *restful.Request, re } } -func (c *applicationWebService) deleteApplicationPolicy(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) deleteApplicationPolicy(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - err := c.applicationUsecase.DeletePolicy(req.Request.Context(), app, req.PathParameter("policyName")) + err := c.ApplicationService.DeletePolicy(req.Request.Context(), app, req.PathParameter("policyName")) if err != nil { bcode.ReturnError(req, res, err) return @@ -895,7 +887,7 @@ func (c *applicationWebService) deleteApplicationPolicy(req *restful.Request, re } } -func (c *applicationWebService) updateApplicationPolicy(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) updateApplicationPolicy(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) // Verify the validity of parameters var updateReq apis.UpdatePolicyRequest @@ -907,7 +899,7 @@ func (c *applicationWebService) updateApplicationPolicy(req *restful.Request, re bcode.ReturnError(req, res, err) return } - response, err := c.applicationUsecase.UpdatePolicy(req.Request.Context(), app, req.PathParameter("policyName"), updateReq) + response, err := c.ApplicationService.UpdatePolicy(req.Request.Context(), app, req.PathParameter("policyName"), updateReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -918,7 +910,7 @@ func (c *applicationWebService) updateApplicationPolicy(req *restful.Request, re } } -func (c *applicationWebService) updateApplication(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) updateApplication(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) // Verify the validity of parameters var updateReq apis.UpdateApplicationRequest @@ -930,7 +922,7 @@ func (c *applicationWebService) updateApplication(req *restful.Request, res *res bcode.ReturnError(req, res, err) return } - base, err := c.applicationUsecase.UpdateApplication(req.Request.Context(), app, updateReq) + base, err := c.ApplicationService.UpdateApplication(req.Request.Context(), app, updateReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -941,7 +933,7 @@ func (c *applicationWebService) updateApplication(req *restful.Request, res *res } } -func (c *applicationWebService) addApplicationTrait(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) addApplicationTrait(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) var createReq apis.CreateApplicationTraitRequest if err := req.ReadEntity(&createReq); err != nil { @@ -952,7 +944,7 @@ func (c *applicationWebService) addApplicationTrait(req *restful.Request, res *r bcode.ReturnError(req, res, err) return } - trait, err := c.applicationUsecase.CreateApplicationTrait(req.Request.Context(), app, + trait, err := c.ApplicationService.CreateApplicationTrait(req.Request.Context(), app, &model.ApplicationComponent{Name: req.PathParameter("compName")}, createReq) if err != nil { bcode.ReturnError(req, res, err) @@ -964,7 +956,7 @@ func (c *applicationWebService) addApplicationTrait(req *restful.Request, res *r } } -func (c *applicationWebService) updateApplicationTrait(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) updateApplicationTrait(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) var updateReq apis.UpdateApplicationTraitRequest if err := req.ReadEntity(&updateReq); err != nil { @@ -975,7 +967,7 @@ func (c *applicationWebService) updateApplicationTrait(req *restful.Request, res bcode.ReturnError(req, res, err) return } - trait, err := c.applicationUsecase.UpdateApplicationTrait(req.Request.Context(), app, + trait, err := c.ApplicationService.UpdateApplicationTrait(req.Request.Context(), app, &model.ApplicationComponent{Name: req.PathParameter("compName")}, req.PathParameter("traitType"), updateReq) if err != nil { bcode.ReturnError(req, res, err) @@ -987,9 +979,9 @@ func (c *applicationWebService) updateApplicationTrait(req *restful.Request, res } } -func (c *applicationWebService) deleteApplicationTrait(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) deleteApplicationTrait(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - err := c.applicationUsecase.DeleteApplicationTrait(req.Request.Context(), app, + err := c.ApplicationService.DeleteApplicationTrait(req.Request.Context(), app, &model.ApplicationComponent{Name: req.PathParameter("compName")}, req.PathParameter("traitType")) if err != nil { bcode.ReturnError(req, res, err) @@ -1001,9 +993,9 @@ func (c *applicationWebService) deleteApplicationTrait(req *restful.Request, res } } -func (c *applicationWebService) getApplicationStatus(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) getApplicationStatus(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - status, err := c.applicationUsecase.GetApplicationStatus(req.Request.Context(), app, req.PathParameter("envName")) + status, err := c.ApplicationService.GetApplicationStatus(req.Request.Context(), app, req.PathParameter("envName")) if err != nil { bcode.ReturnError(req, res, err) return @@ -1015,14 +1007,14 @@ func (c *applicationWebService) getApplicationStatus(req *restful.Request, res * } } -func (c *applicationWebService) listApplicationRevisions(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) listApplicationRevisions(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) page, pageSize, err := utils.ExtractPagingParams(req, minPageSize, maxPageSize) if err != nil { bcode.ReturnError(req, res, err) return } - revisions, err := c.applicationUsecase.ListRevisions(req.Request.Context(), app.Name, req.QueryParameter("envName"), req.QueryParameter("status"), page, pageSize) + revisions, err := c.ApplicationService.ListRevisions(req.Request.Context(), app.Name, req.QueryParameter("envName"), req.QueryParameter("status"), page, pageSize) if err != nil { bcode.ReturnError(req, res, err) return @@ -1033,9 +1025,9 @@ func (c *applicationWebService) listApplicationRevisions(req *restful.Request, r } } -func (c *applicationWebService) detailApplicationRevision(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) detailApplicationRevision(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - detail, err := c.applicationUsecase.DetailRevision(req.Request.Context(), app.Name, req.PathParameter("revision")) + detail, err := c.ApplicationService.DetailRevision(req.Request.Context(), app.Name, req.PathParameter("revision")) if err != nil { bcode.ReturnError(req, res, err) return @@ -1046,7 +1038,7 @@ func (c *applicationWebService) detailApplicationRevision(req *restful.Request, } } -func (c *applicationWebService) updateApplicationEnv(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) updateApplicationEnv(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) // Verify the validity of parameters var updateReq apis.PutApplicationEnvBindingRequest @@ -1058,7 +1050,7 @@ func (c *applicationWebService) updateApplicationEnv(req *restful.Request, res * bcode.ReturnError(req, res, err) return } - diff, err := c.envBindingUsecase.UpdateEnvBinding(req.Request.Context(), app, req.PathParameter("envName"), updateReq) + diff, err := c.EnvBindingService.UpdateEnvBinding(req.Request.Context(), app, req.PathParameter("envName"), updateReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -1069,9 +1061,9 @@ func (c *applicationWebService) updateApplicationEnv(req *restful.Request, res * } } -func (c *applicationWebService) listApplicationEnvs(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) listApplicationEnvs(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - envBindings, err := c.envBindingUsecase.GetEnvBindings(req.Request.Context(), app) + envBindings, err := c.EnvBindingService.GetEnvBindings(req.Request.Context(), app) if err != nil { bcode.ReturnError(req, res, err) return @@ -1082,7 +1074,7 @@ func (c *applicationWebService) listApplicationEnvs(req *restful.Request, res *r } } -func (c *applicationWebService) createApplicationEnv(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) createApplicationEnv(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) // Verify the validity of parameters var createReq apis.CreateApplicationEnvbindingRequest @@ -1094,7 +1086,7 @@ func (c *applicationWebService) createApplicationEnv(req *restful.Request, res * bcode.ReturnError(req, res, err) return } - base, err := c.envBindingUsecase.CreateEnvBinding(req.Request.Context(), app, createReq) + base, err := c.EnvBindingService.CreateEnvBinding(req.Request.Context(), app, createReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -1105,9 +1097,9 @@ func (c *applicationWebService) createApplicationEnv(req *restful.Request, res * } } -func (c *applicationWebService) deleteApplicationEnv(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) deleteApplicationEnv(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - err := c.envBindingUsecase.DeleteEnvBinding(req.Request.Context(), app, req.PathParameter("envName")) + err := c.EnvBindingService.DeleteEnvBinding(req.Request.Context(), app, req.PathParameter("envName")) if err != nil { bcode.ReturnError(req, res, err) return @@ -1118,8 +1110,8 @@ func (c *applicationWebService) deleteApplicationEnv(req *restful.Request, res * } } -func (c *applicationWebService) appCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) { - app, err := c.applicationUsecase.GetApplication(req.Request.Context(), req.PathParameter("appName")) +func (c *applicationAPIInterface) appCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) { + app, err := c.ApplicationService.GetApplication(req.Request.Context(), req.PathParameter("appName")) if err != nil { bcode.ReturnError(req, res, err) return @@ -1128,9 +1120,9 @@ func (c *applicationWebService) appCheckFilter(req *restful.Request, res *restfu chain.ProcessFilter(req, res) } -func (c *applicationWebService) componentCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) { +func (c *applicationAPIInterface) componentCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - component, err := c.applicationUsecase.GetApplicationComponent(req.Request.Context(), app, req.PathParameter("compName")) + component, err := c.ApplicationService.GetApplicationComponent(req.Request.Context(), app, req.PathParameter("compName")) if err != nil { bcode.ReturnError(req, res, err) return @@ -1139,9 +1131,9 @@ func (c *applicationWebService) componentCheckFilter(req *restful.Request, res * chain.ProcessFilter(req, res) } -func (c *applicationWebService) envCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) { +func (c *applicationAPIInterface) envCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - envBinding, err := c.envBindingUsecase.GetEnvBinding(req.Request.Context(), app, req.PathParameter("envName")) + envBinding, err := c.EnvBindingService.GetEnvBinding(req.Request.Context(), app, req.PathParameter("envName")) if err != nil { bcode.ReturnError(req, res, err) return @@ -1150,9 +1142,9 @@ func (c *applicationWebService) envCheckFilter(req *restful.Request, res *restfu chain.ProcessFilter(req, res) } -func (c *applicationWebService) applicationStatistics(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) applicationStatistics(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - detail, err := c.applicationUsecase.Statistics(req.Request.Context(), app) + detail, err := c.ApplicationService.Statistics(req.Request.Context(), app) if err != nil { bcode.ReturnError(req, res, err) return @@ -1163,10 +1155,10 @@ func (c *applicationWebService) applicationStatistics(req *restful.Request, res } } -func (c *applicationWebService) recycleApplicationEnv(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) recycleApplicationEnv(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) env := req.Request.Context().Value(&apis.CtxKeyApplicationEnvBinding).(*model.EnvBinding) - err := c.envBindingUsecase.ApplicationEnvRecycle(req.Request.Context(), app, env) + err := c.EnvBindingService.ApplicationEnvRecycle(req.Request.Context(), app, env) if err != nil { bcode.ReturnError(req, res, err) return @@ -1177,9 +1169,9 @@ func (c *applicationWebService) recycleApplicationEnv(req *restful.Request, res } } -func (c *applicationWebService) listApplicationRecords(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) listApplicationRecords(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - records, err := c.applicationUsecase.ListRecords(req.Request.Context(), app.Name) + records, err := c.ApplicationService.ListRecords(req.Request.Context(), app.Name) if err != nil { bcode.ReturnError(req, res, err) return @@ -1190,7 +1182,7 @@ func (c *applicationWebService) listApplicationRecords(req *restful.Request, res } } -func (c *applicationWebService) compareAppWithLatestRevision(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) compareAppWithLatestRevision(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) // Verify the validity of parameters var compareReq apis.AppCompareReq @@ -1203,7 +1195,7 @@ func (c *applicationWebService) compareAppWithLatestRevision(req *restful.Reques return } - base, err := c.applicationUsecase.CompareAppWithLatestRevision(req.Request.Context(), app, compareReq) + base, err := c.ApplicationService.CompareAppWithLatestRevision(req.Request.Context(), app, compareReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -1214,10 +1206,10 @@ func (c *applicationWebService) compareAppWithLatestRevision(req *restful.Reques } } -func (c *applicationWebService) resetAppToLatestRevision(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) resetAppToLatestRevision(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - base, err := c.applicationUsecase.ResetAppToLatestRevision(req.Request.Context(), app.Name) + base, err := c.ApplicationService.ResetAppToLatestRevision(req.Request.Context(), app.Name) if err != nil { bcode.ReturnError(req, res, err) return @@ -1228,7 +1220,7 @@ func (c *applicationWebService) resetAppToLatestRevision(req *restful.Request, r } } -func (c *applicationWebService) dryRunAppOrRevision(req *restful.Request, res *restful.Response) { +func (c *applicationAPIInterface) dryRunAppOrRevision(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) // Verify the validity of parameters var dryRunReq apis.AppDryRunReq @@ -1244,7 +1236,7 @@ func (c *applicationWebService) dryRunAppOrRevision(req *restful.Request, res *r dryRunReq.AppName = app.Name } - base, err := c.applicationUsecase.DryRunAppOrRevision(req.Request.Context(), app, dryRunReq) + base, err := c.ApplicationService.DryRunAppOrRevision(req.Request.Context(), app, dryRunReq) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/interfaces/api/assembler/v1/do2dto.go b/pkg/apiserver/interfaces/api/assembler/v1/do2dto.go new file mode 100644 index 000000000..3093d136e --- /dev/null +++ b/pkg/apiserver/interfaces/api/assembler/v1/do2dto.go @@ -0,0 +1,209 @@ +/* +Copyright 2022 The KubeVela 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 v1 + +import ( + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" +) + +// ConvertEnvBindingModelToBase assemble the DTO from EnvBinding model +func ConvertEnvBindingModelToBase(envBinding *model.EnvBinding, env *model.Env, targets []*model.Target) *apisv1.EnvBindingBase { + var dtMap = make(map[string]*model.Target, len(targets)) + for _, dte := range targets { + dtMap[dte.Name] = dte + } + var envBindingTargets []apisv1.EnvBindingTarget + for _, targetName := range env.Targets { + dt := dtMap[targetName] + if dt != nil { + ebt := apisv1.EnvBindingTarget{ + NameAlias: apisv1.NameAlias{Name: dt.Name, Alias: dt.Alias}, + } + if dt.Cluster != nil { + ebt.Cluster = &apisv1.ClusterTarget{ + ClusterName: dt.Cluster.ClusterName, + Namespace: dt.Cluster.Namespace, + } + } + envBindingTargets = append(envBindingTargets, ebt) + } + } + ebb := &apisv1.EnvBindingBase{ + Name: envBinding.Name, + Alias: env.Alias, + Description: env.Description, + TargetNames: env.Targets, + Targets: envBindingTargets, + CreateTime: envBinding.CreateTime, + UpdateTime: envBinding.UpdateTime, + AppDeployName: envBinding.AppDeployName, + AppDeployNamespace: env.Namespace, + } + return ebb +} + +// ConvertAppModelToBase assemble the Application model to DTO +func ConvertAppModelToBase(app *model.Application, projects []*apisv1.ProjectBase) *apisv1.ApplicationBase { + appBase := &apisv1.ApplicationBase{ + Name: app.Name, + Alias: app.Alias, + CreateTime: app.CreateTime, + UpdateTime: app.UpdateTime, + Description: app.Description, + Icon: app.Icon, + Labels: app.Labels, + Project: &apisv1.ProjectBase{Name: app.Project}, + } + if app.IsSynced() { + appBase.ReadOnly = true + } + for _, project := range projects { + if project.Name == app.Project { + appBase.Project = project + } + } + return appBase +} + +// ConvertComponentModelToBase assemble the ApplicationComponent model to DTO +func ConvertComponentModelToBase(componentModel *model.ApplicationComponent) *apisv1.ComponentBase { + if componentModel == nil { + return nil + } + return &apisv1.ComponentBase{ + Name: componentModel.Name, + Alias: componentModel.Alias, + Description: componentModel.Description, + Labels: componentModel.Labels, + ComponentType: componentModel.Type, + Icon: componentModel.Icon, + DependsOn: componentModel.DependsOn, + Inputs: componentModel.Inputs, + Outputs: componentModel.Outputs, + Creator: componentModel.Creator, + Main: componentModel.Main, + CreateTime: componentModel.CreateTime, + UpdateTime: componentModel.UpdateTime, + Traits: func() (traits []*apisv1.ApplicationTrait) { + for _, trait := range componentModel.Traits { + traits = append(traits, &apisv1.ApplicationTrait{ + Type: trait.Type, + Properties: trait.Properties, + Alias: trait.Alias, + Description: trait.Description, + CreateTime: trait.CreateTime, + UpdateTime: trait.UpdateTime, + }) + } + return + }(), + WorkloadType: componentModel.WorkloadType, + } +} + +// ConvertRevisionModelToBase assemble the ApplicationRevision model to DTO +func ConvertRevisionModelToBase(revision *model.ApplicationRevision, user *model.User) apisv1.ApplicationRevisionBase { + base := apisv1.ApplicationRevisionBase{ + Version: revision.Version, + Status: revision.Status, + Reason: revision.Reason, + Note: revision.Note, + TriggerType: revision.TriggerType, + CreateTime: revision.CreateTime, + EnvName: revision.EnvName, + CodeInfo: revision.CodeInfo, + ImageInfo: revision.ImageInfo, + DeployUser: &apisv1.NameAlias{Name: revision.DeployUser}, + } + if user != nil { + base.DeployUser.Alias = user.Alias + } + return base +} + +// ConvertFromRecordModel assemble the WorkflowRecord model to DTO +func ConvertFromRecordModel(record *model.WorkflowRecord) *apisv1.WorkflowRecord { + return &apisv1.WorkflowRecord{ + Name: record.Name, + Namespace: record.Namespace, + WorkflowName: record.WorkflowName, + WorkflowAlias: record.WorkflowAlias, + ApplicationRevision: record.RevisionPrimaryKey, + StartTime: record.StartTime, + Status: record.Status, + Steps: record.Steps, + } +} + +// ConvertFromWorkflowStepModel assemble the WorkflowStep model to DTO +func ConvertFromWorkflowStepModel(step model.WorkflowStep) apisv1.WorkflowStep { + apiStep := apisv1.WorkflowStep{ + Name: step.Name, + Type: step.Type, + Alias: step.Alias, + Description: step.Description, + Inputs: step.Inputs, + Outputs: step.Outputs, + Properties: step.Properties.JSON(), + DependsOn: step.DependsOn, + } + if step.Properties != nil { + apiStep.Properties = step.Properties.JSON() + } + return apiStep +} + +// ConvertWorkflowBase assemble the Workflow model to DTO +func ConvertWorkflowBase(workflow *model.Workflow) apisv1.WorkflowBase { + var steps []apisv1.WorkflowStep + for _, step := range workflow.Steps { + steps = append(steps, ConvertFromWorkflowStepModel(step)) + } + return apisv1.WorkflowBase{ + Name: workflow.Name, + Alias: workflow.Alias, + Description: workflow.Description, + Default: convertBool(workflow.Default), + EnvName: workflow.EnvName, + CreateTime: workflow.CreateTime, + UpdateTime: workflow.UpdateTime, + Steps: steps, + } +} + +// ConvertPolicyModelToBase assemble the ApplicationPolicy model to DTO +func ConvertPolicyModelToBase(policy *model.ApplicationPolicy) *apisv1.PolicyBase { + pb := &apisv1.PolicyBase{ + Name: policy.Name, + Type: policy.Type, + Properties: policy.Properties, + Description: policy.Description, + Creator: policy.Creator, + CreateTime: policy.CreateTime, + UpdateTime: policy.UpdateTime, + EnvName: policy.EnvName, + } + return pb +} + +func convertBool(b *bool) bool { + if b == nil { + return false + } + return *b +} diff --git a/pkg/apiserver/interfaces/api/assembler/v1/dto2do.go b/pkg/apiserver/interfaces/api/assembler/v1/dto2do.go new file mode 100644 index 000000000..56e4baf67 --- /dev/null +++ b/pkg/apiserver/interfaces/api/assembler/v1/dto2do.go @@ -0,0 +1,67 @@ +/* +Copyright 2022 The KubeVela 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 v1 + +import ( + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" +) + +// CreateEnvBindingModel assemble the EnvBinding model from DTO +func CreateEnvBindingModel(app *model.Application, req apisv1.CreateApplicationEnvbindingRequest) model.EnvBinding { + envBinding := model.EnvBinding{ + AppPrimaryKey: app.Name, + Name: req.Name, + AppDeployName: app.GetAppNameForSynced(), + } + return envBinding +} + +// ConvertToEnvBindingModel assemble the EnvBinding model from DTO +func ConvertToEnvBindingModel(app *model.Application, envBind apisv1.EnvBinding) *model.EnvBinding { + re := model.EnvBinding{ + AppPrimaryKey: app.Name, + Name: envBind.Name, + AppDeployName: app.GetAppNameForSynced(), + } + return &re +} + +// CreateWorkflowStepModel assemble the WorkflowStep model from DTO +func CreateWorkflowStepModel(apiSteps []apisv1.WorkflowStep) ([]model.WorkflowStep, error) { + var steps []model.WorkflowStep + for _, step := range apiSteps { + properties, err := model.NewJSONStructByString(step.Properties) + if err != nil { + log.Logger.Errorf("parse trait properties failure %w", err) + return nil, bcode.ErrInvalidProperties + } + steps = append(steps, model.WorkflowStep{ + Name: step.Name, + Alias: step.Alias, + Description: step.Description, + DependsOn: step.DependsOn, + Type: step.Type, + Inputs: step.Inputs, + Outputs: step.Outputs, + Properties: properties, + }) + } + return steps, nil +} diff --git a/pkg/apiserver/rest/webservice/authentication.go b/pkg/apiserver/interfaces/api/authentication.go similarity index 70% rename from pkg/apiserver/rest/webservice/authentication.go rename to pkg/apiserver/interfaces/api/authentication.go index ace5354cc..bc080f15d 100644 --- a/pkg/apiserver/rest/webservice/authentication.go +++ b/pkg/apiserver/interfaces/api/authentication.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( "context" @@ -23,25 +23,22 @@ import ( restfulspec "github.com/emicklei/go-restful-openapi/v2" "github.com/emicklei/go-restful/v3" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" ) -type authenticationWebService struct { - authenticationUsecase usecase.AuthenticationUsecase - userUsecase usecase.UserUsecase +type authenticationAPIInterface struct { + AuthenticationService service.AuthenticationService `inject:""` + UserService service.UserService `inject:""` } -// NewAuthenticationWebService is the webservice of authentication -func NewAuthenticationWebService(authenticationUsecase usecase.AuthenticationUsecase, userUsecase usecase.UserUsecase) WebService { - return &authenticationWebService{ - authenticationUsecase: authenticationUsecase, - userUsecase: userUsecase, - } +// NewAuthenticationAPIInterface is the APIInterface of authentication +func NewAuthenticationAPIInterface() Interface { + return &authenticationAPIInterface{} } -func (c *authenticationWebService) GetWebService() *restful.WebService { +func (c *authenticationAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/auth"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -101,12 +98,12 @@ func authCheckFilter(req *restful.Request, res *restful.Response, chain *restful return } - token, err := usecase.ParseToken(splitted[1]) + token, err := service.ParseToken(splitted[1]) if err != nil { bcode.ReturnError(req, res, err) return } - if token.GrantType != usecase.GrantTypeAccess { + if token.GrantType != service.GrantTypeAccess { bcode.ReturnError(req, res, bcode.ErrNotAccessToken) return } @@ -115,13 +112,13 @@ func authCheckFilter(req *restful.Request, res *restful.Response, chain *restful chain.ProcessFilter(req, res) } -func (c *authenticationWebService) login(req *restful.Request, res *restful.Response) { +func (c *authenticationAPIInterface) login(req *restful.Request, res *restful.Response) { var loginReq apis.LoginRequest if err := req.ReadEntity(&loginReq); err != nil { bcode.ReturnError(req, res, err) return } - base, err := c.authenticationUsecase.Login(req.Request.Context(), loginReq) + base, err := c.AuthenticationService.Login(req.Request.Context(), loginReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -132,8 +129,8 @@ func (c *authenticationWebService) login(req *restful.Request, res *restful.Resp } } -func (c *authenticationWebService) getDexConfig(req *restful.Request, res *restful.Response) { - base, err := c.authenticationUsecase.GetDexConfig(req.Request.Context()) +func (c *authenticationAPIInterface) getDexConfig(req *restful.Request, res *restful.Response) { + base, err := c.AuthenticationService.GetDexConfig(req.Request.Context()) if err != nil { bcode.ReturnError(req, res, err) return @@ -144,8 +141,8 @@ func (c *authenticationWebService) getDexConfig(req *restful.Request, res *restf } } -func (c *authenticationWebService) refreshToken(req *restful.Request, res *restful.Response) { - base, err := c.authenticationUsecase.RefreshToken(req.Request.Context(), req.HeaderParameter("RefreshToken")) +func (c *authenticationAPIInterface) refreshToken(req *restful.Request, res *restful.Response) { + base, err := c.AuthenticationService.RefreshToken(req.Request.Context(), req.HeaderParameter("RefreshToken")) if err != nil { bcode.ReturnError(req, res, err) return @@ -156,8 +153,8 @@ func (c *authenticationWebService) refreshToken(req *restful.Request, res *restf } } -func (c *authenticationWebService) getLoginType(req *restful.Request, res *restful.Response) { - base, err := c.authenticationUsecase.GetLoginType(req.Request.Context()) +func (c *authenticationAPIInterface) getLoginType(req *restful.Request, res *restful.Response) { + base, err := c.AuthenticationService.GetLoginType(req.Request.Context()) if err != nil { bcode.ReturnError(req, res, err) return @@ -168,8 +165,8 @@ func (c *authenticationWebService) getLoginType(req *restful.Request, res *restf } } -func (c *authenticationWebService) getLoginUserInfo(req *restful.Request, res *restful.Response) { - info, err := c.userUsecase.DetailLoginUserInfo(req.Request.Context()) +func (c *authenticationAPIInterface) getLoginUserInfo(req *restful.Request, res *restful.Response) { + info, err := c.UserService.DetailLoginUserInfo(req.Request.Context()) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/rest/webservice/cluster.go b/pkg/apiserver/interfaces/api/cluster.go similarity index 77% rename from pkg/apiserver/rest/webservice/cluster.go rename to pkg/apiserver/interfaces/api/cluster.go index 1fc59b6b3..1374948fd 100644 --- a/pkg/apiserver/rest/webservice/cluster.go +++ b/pkg/apiserver/interfaces/api/cluster.go @@ -14,31 +14,31 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( restfulspec "github.com/emicklei/go-restful-openapi/v2" restful "github.com/emicklei/go-restful/v3" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" ) -// ClusterWebService cluster manage webservice -type ClusterWebService struct { - clusterUsecase usecase.ClusterUsecase - rbacUsecase usecase.RBACUsecase +// ClusterAPIInterface cluster manage APIInterface +type ClusterAPIInterface struct { + ClusterService service.ClusterService `inject:""` + RbacService service.RBACService `inject:""` } -// NewClusterWebService new cluster webservice -func NewClusterWebService(clusterUsecase usecase.ClusterUsecase, rbacUsecase usecase.RBACUsecase) *ClusterWebService { - return &ClusterWebService{clusterUsecase: clusterUsecase, rbacUsecase: rbacUsecase} +// NewClusterAPIInterface new cluster APIInterface +func NewClusterAPIInterface() *ClusterAPIInterface { + return &ClusterAPIInterface{} } -// GetWebService - -func (c *ClusterWebService) GetWebService() *restful.WebService { +// GetWebServiceRoute - +func (c *ClusterAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/clusters"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -50,7 +50,7 @@ func (c *ClusterWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/").To(c.listKubeClusters). Doc("list all clusters"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("cluster", "list")). + Filter(c.RbacService.CheckPerm("cluster", "list")). Param(ws.QueryParameter("query", "Fuzzy search based on name or description").DataType("string")). Param(ws.QueryParameter("page", "Page for paging").DataType("integer").DefaultValue("0")). Param(ws.QueryParameter("pageSize", "PageSize for paging").DataType("integer").DefaultValue("20")). @@ -62,7 +62,7 @@ func (c *ClusterWebService) GetWebService() *restful.WebService { Doc("create cluster"). Metadata(restfulspec.KeyOpenAPITags, tags). Reads(apis.CreateClusterRequest{}). - Filter(c.rbacUsecase.CheckPerm("cluster", "create")). + Filter(c.RbacService.CheckPerm("cluster", "create")). Returns(200, "OK", apis.ClusterBase{}). Returns(400, "Bad Request", bcode.Bcode{}). Writes(apis.ClusterBase{})) @@ -70,7 +70,7 @@ func (c *ClusterWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{clusterName}").To(c.getKubeCluster). Doc("detail cluster info"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("cluster", "detail")). + Filter(c.RbacService.CheckPerm("cluster", "detail")). Param(ws.PathParameter("clusterName", "identifier of the cluster").DataType("string")). Returns(200, "OK", apis.DetailClusterResponse{}). Returns(400, "Bad Request", bcode.Bcode{}). @@ -79,7 +79,7 @@ func (c *ClusterWebService) GetWebService() *restful.WebService { ws.Route(ws.PUT("/{clusterName}").To(c.modifyKubeCluster). Doc("modify cluster"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("cluster", "update")). + Filter(c.RbacService.CheckPerm("cluster", "update")). Param(ws.PathParameter("clusterName", "identifier of the cluster").DataType("string")). Reads(apis.CreateClusterRequest{}). Returns(200, "OK", apis.ClusterBase{}). @@ -89,7 +89,7 @@ func (c *ClusterWebService) GetWebService() *restful.WebService { ws.Route(ws.DELETE("/{clusterName}").To(c.deleteKubeCluster). Doc("delete cluster"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("cluster", "delete")). + Filter(c.RbacService.CheckPerm("cluster", "delete")). Param(ws.PathParameter("clusterName", "identifier of the cluster").DataType("string")). Returns(200, "OK", apis.ClusterBase{}). Returns(400, "Bad Request", bcode.Bcode{}). @@ -100,7 +100,7 @@ func (c *ClusterWebService) GetWebService() *restful.WebService { Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.PathParameter("clusterName", "name of the target cluster").DataType("string")). Reads(apis.CreateClusterNamespaceRequest{}). - Filter(c.rbacUsecase.CheckPerm("cluster/namespace", "create")). + Filter(c.RbacService.CheckPerm("cluster/namespace", "create")). Returns(200, "OK", apis.CreateClusterNamespaceResponse{}). Returns(400, "Bad Request", bcode.Bcode{}). Writes(apis.CreateClusterNamespaceResponse{})) @@ -108,7 +108,7 @@ func (c *ClusterWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/cloud_clusters/{provider}").To(c.listCloudClusters). Doc("list cloud clusters"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("cluster", "create")). + Filter(c.RbacService.CheckPerm("cluster", "create")). Param(ws.PathParameter("provider", "identifier of the cloud provider").DataType("string")). Param(ws.QueryParameter("page", "Page for paging").DataType("integer").DefaultValue("0")). Param(ws.QueryParameter("pageSize", "PageSize for paging").DataType("integer").DefaultValue("20")). @@ -120,7 +120,7 @@ func (c *ClusterWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/cloud_clusters/{provider}/connect").To(c.connectCloudCluster). Doc("create cluster from cloud cluster"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("cluster", "create")). + Filter(c.RbacService.CheckPerm("cluster", "create")). Param(ws.PathParameter("provider", "identifier of the cloud provider").DataType("string")). Reads(apis.ConnectCloudClusterRequest{}). Returns(200, "OK", apis.ClusterBase{}). @@ -130,7 +130,7 @@ func (c *ClusterWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/cloud_clusters/{provider}/create").To(c.createCloudCluster). Doc("create cloud cluster"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("cluster", "create")). + Filter(c.RbacService.CheckPerm("cluster", "create")). Param(ws.PathParameter("provider", "identifier of the cloud provider").DataType("string").Required(true)). Reads(apis.CreateCloudClusterRequest{}). Returns(200, "OK", apis.CreateCloudClusterResponse{}). @@ -140,7 +140,7 @@ func (c *ClusterWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/cloud_clusters/{provider}/creation/{cloudClusterName}").To(c.getCloudClusterCreationStatus). Doc("check cloud cluster create status"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("cluster", "create")). + Filter(c.RbacService.CheckPerm("cluster", "create")). Param(ws.PathParameter("provider", "identifier of the cloud provider").DataType("string")). Param(ws.PathParameter("cloudClusterName", "identifier for cloud cluster which is creating").DataType("string")). Returns(200, "OK", apis.CreateCloudClusterResponse{}). @@ -149,7 +149,7 @@ func (c *ClusterWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/cloud_clusters/{provider}/creation").To(c.listCloudClusterCreation). Doc("list cloud cluster creation"). - Filter(c.rbacUsecase.CheckPerm("cluster", "create")). + Filter(c.RbacService.CheckPerm("cluster", "create")). Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.PathParameter("provider", "identifier of the cloud provider").DataType("string")). Returns(200, "OK", apis.ListCloudClusterCreationResponse{}). @@ -159,7 +159,7 @@ func (c *ClusterWebService) GetWebService() *restful.WebService { ws.Route(ws.DELETE("/cloud_clusters/{provider}/creation/{cloudClusterName}").To(c.deleteCloudClusterCreation). Doc("delete cloud cluster creation"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("cluster", "create")). + Filter(c.RbacService.CheckPerm("cluster", "create")). Param(ws.PathParameter("provider", "identifier of the cloud provider").DataType("string")). Param(ws.PathParameter("cloudClusterName", "identifier for cloud cluster which is creating").DataType("string")). Returns(200, "OK", apis.CreateCloudClusterResponse{}). @@ -170,7 +170,7 @@ func (c *ClusterWebService) GetWebService() *restful.WebService { return ws } -func (c *ClusterWebService) listKubeClusters(req *restful.Request, res *restful.Response) { +func (c *ClusterAPIInterface) listKubeClusters(req *restful.Request, res *restful.Response) { query := req.QueryParameter("query") page, pageSize, err := utils.ExtractPagingParams(req, minPageSize, maxPageSize) if err != nil { @@ -178,8 +178,8 @@ func (c *ClusterWebService) listKubeClusters(req *restful.Request, res *restful. return } - // Call the usecase layer code - clusters, err := c.clusterUsecase.ListKubeClusters(req.Request.Context(), query, page, pageSize) + // Call the domain layer code + clusters, err := c.ClusterService.ListKubeClusters(req.Request.Context(), query, page, pageSize) if err != nil { bcode.ReturnError(req, res, err) return @@ -192,7 +192,7 @@ func (c *ClusterWebService) listKubeClusters(req *restful.Request, res *restful. } } -func (c *ClusterWebService) createKubeCluster(req *restful.Request, res *restful.Response) { +func (c *ClusterAPIInterface) createKubeCluster(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var createReq apis.CreateClusterRequest if err := req.ReadEntity(&createReq); err != nil { @@ -203,8 +203,8 @@ func (c *ClusterWebService) createKubeCluster(req *restful.Request, res *restful bcode.ReturnError(req, res, err) return } - // Call the usecase layer code - clusterBase, err := c.clusterUsecase.CreateKubeCluster(req.Request.Context(), createReq) + // Call the domain layer code + clusterBase, err := c.ClusterService.CreateKubeCluster(req.Request.Context(), createReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -217,11 +217,11 @@ func (c *ClusterWebService) createKubeCluster(req *restful.Request, res *restful } } -func (c *ClusterWebService) getKubeCluster(req *restful.Request, res *restful.Response) { +func (c *ClusterAPIInterface) getKubeCluster(req *restful.Request, res *restful.Response) { clusterName := req.PathParameter("clusterName") - // Call the usecase layer code - clusterDetail, err := c.clusterUsecase.GetKubeCluster(req.Request.Context(), clusterName) + // Call the domain layer code + clusterDetail, err := c.ClusterService.GetKubeCluster(req.Request.Context(), clusterName) if err != nil { bcode.ReturnError(req, res, err) return @@ -234,7 +234,7 @@ func (c *ClusterWebService) getKubeCluster(req *restful.Request, res *restful.Re } } -func (c *ClusterWebService) modifyKubeCluster(req *restful.Request, res *restful.Response) { +func (c *ClusterAPIInterface) modifyKubeCluster(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var createReq apis.CreateClusterRequest if err := req.ReadEntity(&createReq); err != nil { @@ -247,8 +247,8 @@ func (c *ClusterWebService) modifyKubeCluster(req *restful.Request, res *restful } clusterName := req.PathParameter("clusterName") - // Call the usecase layer code - clusterBase, err := c.clusterUsecase.ModifyKubeCluster(req.Request.Context(), createReq, clusterName) + // Call the domain layer code + clusterBase, err := c.ClusterService.ModifyKubeCluster(req.Request.Context(), createReq, clusterName) if err != nil { bcode.ReturnError(req, res, err) return @@ -261,11 +261,11 @@ func (c *ClusterWebService) modifyKubeCluster(req *restful.Request, res *restful } } -func (c *ClusterWebService) deleteKubeCluster(req *restful.Request, res *restful.Response) { +func (c *ClusterAPIInterface) deleteKubeCluster(req *restful.Request, res *restful.Response) { clusterName := req.PathParameter("clusterName") - // Call the usecase layer code - clusterBase, err := c.clusterUsecase.DeleteKubeCluster(req.Request.Context(), clusterName) + // Call the domain layer code + clusterBase, err := c.ClusterService.DeleteKubeCluster(req.Request.Context(), clusterName) if err != nil { bcode.ReturnError(req, res, err) return @@ -278,7 +278,7 @@ func (c *ClusterWebService) deleteKubeCluster(req *restful.Request, res *restful } } -func (c *ClusterWebService) createNamespace(req *restful.Request, res *restful.Response) { +func (c *ClusterAPIInterface) createNamespace(req *restful.Request, res *restful.Response) { clusterName := req.PathParameter("clusterName") // Verify the validity of parameters @@ -292,8 +292,8 @@ func (c *ClusterWebService) createNamespace(req *restful.Request, res *restful.R return } - // Call the usecase layer code - resp, err := c.clusterUsecase.CreateClusterNamespace(req.Request.Context(), clusterName, createReq) + // Call the domain layer code + resp, err := c.ClusterService.CreateClusterNamespace(req.Request.Context(), clusterName, createReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -306,7 +306,7 @@ func (c *ClusterWebService) createNamespace(req *restful.Request, res *restful.R } } -func (c *ClusterWebService) listCloudClusters(req *restful.Request, res *restful.Response) { +func (c *ClusterAPIInterface) listCloudClusters(req *restful.Request, res *restful.Response) { provider := req.PathParameter("provider") page, pageSize, err := utils.ExtractPagingParams(req, minPageSize, maxPageSize) if err != nil { @@ -325,8 +325,8 @@ func (c *ClusterWebService) listCloudClusters(req *restful.Request, res *restful return } - // Call the usecase layer code - clustersResp, err := c.clusterUsecase.ListCloudClusters(req.Request.Context(), provider, accessKeyRequest, page, pageSize) + // Call the domain layer code + clustersResp, err := c.ClusterService.ListCloudClusters(req.Request.Context(), provider, accessKeyRequest, page, pageSize) if err != nil { bcode.ReturnError(req, res, err) return @@ -339,7 +339,7 @@ func (c *ClusterWebService) listCloudClusters(req *restful.Request, res *restful } } -func (c *ClusterWebService) connectCloudCluster(req *restful.Request, res *restful.Response) { +func (c *ClusterAPIInterface) connectCloudCluster(req *restful.Request, res *restful.Response) { provider := req.PathParameter("provider") // Verify the validity of parameters @@ -353,8 +353,8 @@ func (c *ClusterWebService) connectCloudCluster(req *restful.Request, res *restf return } - // Call the usecase layer code - cluster, err := c.clusterUsecase.ConnectCloudCluster(req.Request.Context(), provider, connectReq) + // Call the domain layer code + cluster, err := c.ClusterService.ConnectCloudCluster(req.Request.Context(), provider, connectReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -367,7 +367,7 @@ func (c *ClusterWebService) connectCloudCluster(req *restful.Request, res *restf } } -func (c *ClusterWebService) createCloudCluster(req *restful.Request, res *restful.Response) { +func (c *ClusterAPIInterface) createCloudCluster(req *restful.Request, res *restful.Response) { provider := req.PathParameter("provider") // Verify the validity of parameters @@ -381,8 +381,8 @@ func (c *ClusterWebService) createCloudCluster(req *restful.Request, res *restfu return } - // Call the usecase layer code - resp, err := c.clusterUsecase.CreateCloudCluster(req.Request.Context(), provider, createReq) + // Call the domain layer code + resp, err := c.ClusterService.CreateCloudCluster(req.Request.Context(), provider, createReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -395,12 +395,12 @@ func (c *ClusterWebService) createCloudCluster(req *restful.Request, res *restfu } } -func (c *ClusterWebService) getCloudClusterCreationStatus(req *restful.Request, res *restful.Response) { +func (c *ClusterAPIInterface) getCloudClusterCreationStatus(req *restful.Request, res *restful.Response) { provider := req.PathParameter("provider") cloudClusterName := req.PathParameter("cloudClusterName") - // Call the usecase layer code - resp, err := c.clusterUsecase.GetCloudClusterCreationStatus(req.Request.Context(), provider, cloudClusterName) + // Call the domain layer code + resp, err := c.ClusterService.GetCloudClusterCreationStatus(req.Request.Context(), provider, cloudClusterName) if err != nil { bcode.ReturnError(req, res, err) return @@ -413,11 +413,11 @@ func (c *ClusterWebService) getCloudClusterCreationStatus(req *restful.Request, } } -func (c *ClusterWebService) listCloudClusterCreation(req *restful.Request, res *restful.Response) { +func (c *ClusterAPIInterface) listCloudClusterCreation(req *restful.Request, res *restful.Response) { provider := req.PathParameter("provider") - // Call the usecase layer code - resp, err := c.clusterUsecase.ListCloudClusterCreation(req.Request.Context(), provider) + // Call the domain layer code + resp, err := c.ClusterService.ListCloudClusterCreation(req.Request.Context(), provider) if err != nil { bcode.ReturnError(req, res, err) return @@ -430,12 +430,12 @@ func (c *ClusterWebService) listCloudClusterCreation(req *restful.Request, res * } } -func (c *ClusterWebService) deleteCloudClusterCreation(req *restful.Request, res *restful.Response) { +func (c *ClusterAPIInterface) deleteCloudClusterCreation(req *restful.Request, res *restful.Response) { provider := req.PathParameter("provider") cloudClusterName := req.PathParameter("cloudClusterName") - // Call the usecase layer code - resp, err := c.clusterUsecase.DeleteCloudClusterCreation(req.Request.Context(), provider, cloudClusterName) + // Call the domain layer code + resp, err := c.ClusterService.DeleteCloudClusterCreation(req.Request.Context(), provider, cloudClusterName) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/rest/webservice/config.go b/pkg/apiserver/interfaces/api/config.go similarity index 70% rename from pkg/apiserver/rest/webservice/config.go rename to pkg/apiserver/interfaces/api/config.go index 2deb48738..b9db648e5 100644 --- a/pkg/apiserver/rest/webservice/config.go +++ b/pkg/apiserver/interfaces/api/config.go @@ -14,31 +14,28 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( restfulspec "github.com/emicklei/go-restful-openapi/v2" "github.com/emicklei/go-restful/v3" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" ) -// ConfigWebService returns config web service -func ConfigWebService(u usecase.ConfigHandler, rbacUseCase usecase.RBACUsecase) WebService { - return &configWebService{ - handler: u, - rbacUseCase: rbacUseCase, - } +// ConfigAPIInterface returns config web service +func ConfigAPIInterface() Interface { + return &configAPIInterface{} } -type configWebService struct { - handler usecase.ConfigHandler - rbacUseCase usecase.RBACUsecase +type configAPIInterface struct { + ConfigService service.ConfigService `inject:""` + RbacService service.RBACService `inject:""` } -func (s *configWebService) GetWebService() *restful.WebService { +func (s *configAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/config_types"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -50,7 +47,7 @@ func (s *configWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/").To(s.listConfigTypes). Doc("list all config types"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(s.rbacUseCase.CheckPerm("configType", "list")). + Filter(s.RbacService.CheckPerm("configType", "list")). Param(ws.QueryParameter("query", "Fuzzy search based on name and description.").DataType("string")). Returns(200, "OK", []apis.ConfigType{}). Returns(400, "Bad Request", bcode.Bcode{}). @@ -59,7 +56,7 @@ func (s *configWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{configType}").To(s.getConfigType). Doc("get a config type"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(s.rbacUseCase.CheckPerm("configType", "get")). + Filter(s.RbacService.CheckPerm("configType", "get")). Param(ws.PathParameter("configType", "identifier of the config type").DataType("string")). Returns(200, "OK", apis.ConfigType{}). Returns(400, "Bad Request", bcode.Bcode{}). @@ -68,7 +65,7 @@ func (s *configWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/{configType}").To(s.createConfig). Doc("create or update a config"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(s.rbacUseCase.CheckPerm("configType", "create")). + Filter(s.RbacService.CheckPerm("configType", "create")). Param(ws.PathParameter("configType", "identifier of the config type").DataType("string")). Reads(apis.CreateConfigRequest{}). Returns(200, "OK", apis.EmptyResponse{}). @@ -79,7 +76,7 @@ func (s *configWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{configType}/configs").To(s.getConfigs). Doc("get configs from a config type"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(s.rbacUseCase.CheckPerm("config", "list")). + Filter(s.RbacService.CheckPerm("config", "list")). Param(ws.PathParameter("configType", "identifier of the config").DataType("string")). Returns(200, "OK", []*apis.Config{}). Returns(400, "Bad Request", bcode.Bcode{}). @@ -88,7 +85,7 @@ func (s *configWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{configType}/configs/{name}").To(s.getConfig). Doc("get a config from a config type"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(s.rbacUseCase.CheckPerm("config", "get")). + Filter(s.RbacService.CheckPerm("config", "get")). Param(ws.PathParameter("configType", "identifier of the config type").DataType("string")). Param(ws.PathParameter("name", "identifier of the config").DataType("string")). Returns(200, "OK", []*apis.Config{}). @@ -98,7 +95,7 @@ func (s *configWebService) GetWebService() *restful.WebService { ws.Route(ws.DELETE("/{configType}/configs/{name}").To(s.deleteConfig). Doc("delete a config"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(s.rbacUseCase.CheckPerm("config", "delete")). + Filter(s.RbacService.CheckPerm("config", "delete")). Param(ws.PathParameter("configType", "identifier of the config type").DataType("string")). Param(ws.PathParameter("name", "identifier of the config").DataType("string")). Returns(200, "OK", apis.EmptyResponse{}). @@ -110,8 +107,8 @@ func (s *configWebService) GetWebService() *restful.WebService { return ws } -func (s *configWebService) listConfigTypes(req *restful.Request, res *restful.Response) { - types, err := s.handler.ListConfigTypes(req.Request.Context(), req.QueryParameter("query")) +func (s *configAPIInterface) listConfigTypes(req *restful.Request, res *restful.Response) { + types, err := s.ConfigService.ListConfigTypes(req.Request.Context(), req.QueryParameter("query")) if len(types) == 0 && err != nil { bcode.ReturnError(req, res, err) return @@ -123,8 +120,8 @@ func (s *configWebService) listConfigTypes(req *restful.Request, res *restful.Re } } -func (s *configWebService) getConfigType(req *restful.Request, res *restful.Response) { - t, err := s.handler.GetConfigType(req.Request.Context(), req.PathParameter("configType")) +func (s *configAPIInterface) getConfigType(req *restful.Request, res *restful.Response) { + t, err := s.ConfigService.GetConfigType(req.Request.Context(), req.PathParameter("configType")) if err != nil { bcode.ReturnError(req, res, err) return @@ -136,7 +133,7 @@ func (s *configWebService) getConfigType(req *restful.Request, res *restful.Resp } } -func (s *configWebService) createConfig(req *restful.Request, res *restful.Response) { +func (s *configAPIInterface) createConfig(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var createReq apis.CreateConfigRequest if err := req.ReadEntity(&createReq); err != nil { @@ -148,7 +145,7 @@ func (s *configWebService) createConfig(req *restful.Request, res *restful.Respo return } - err := s.handler.CreateConfig(req.Request.Context(), createReq) + err := s.ConfigService.CreateConfig(req.Request.Context(), createReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -159,8 +156,8 @@ func (s *configWebService) createConfig(req *restful.Request, res *restful.Respo } } -func (s *configWebService) getConfigs(req *restful.Request, res *restful.Response) { - configs, err := s.handler.GetConfigs(req.Request.Context(), req.PathParameter("configType")) +func (s *configAPIInterface) getConfigs(req *restful.Request, res *restful.Response) { + configs, err := s.ConfigService.GetConfigs(req.Request.Context(), req.PathParameter("configType")) if err != nil { bcode.ReturnError(req, res, err) return @@ -172,8 +169,8 @@ func (s *configWebService) getConfigs(req *restful.Request, res *restful.Respons } } -func (s *configWebService) getConfig(req *restful.Request, res *restful.Response) { - t, err := s.handler.GetConfig(req.Request.Context(), req.PathParameter("configType"), req.PathParameter("name")) +func (s *configAPIInterface) getConfig(req *restful.Request, res *restful.Response) { + t, err := s.ConfigService.GetConfig(req.Request.Context(), req.PathParameter("configType"), req.PathParameter("name")) if err != nil { bcode.ReturnError(req, res, err) return @@ -185,8 +182,8 @@ func (s *configWebService) getConfig(req *restful.Request, res *restful.Response } } -func (s *configWebService) deleteConfig(req *restful.Request, res *restful.Response) { - err := s.handler.DeleteConfig(req.Request.Context(), req.PathParameter("configType"), req.PathParameter("name")) +func (s *configAPIInterface) deleteConfig(req *restful.Request, res *restful.Response) { + err := s.ConfigService.DeleteConfig(req.Request.Context(), req.PathParameter("configType"), req.PathParameter("name")) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/rest/webservice/definition.go b/pkg/apiserver/interfaces/api/definition.go similarity index 75% rename from pkg/apiserver/rest/webservice/definition.go rename to pkg/apiserver/interfaces/api/definition.go index fc07bb55c..a95181fef 100644 --- a/pkg/apiserver/rest/webservice/definition.go +++ b/pkg/apiserver/interfaces/api/definition.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( "strconv" @@ -22,18 +22,18 @@ import ( restfulspec "github.com/emicklei/go-restful-openapi/v2" restful "github.com/emicklei/go-restful/v3" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" ) -type definitionWebservice struct { - definitionUsecase usecase.DefinitionUsecase - rbacUsecase usecase.RBACUsecase +type definitionAPIInterface struct { + DefinitionService service.DefinitionService `inject:""` + RbacService service.RBACService `inject:""` } -func (d *definitionWebservice) GetWebService() *restful.WebService { +func (d *definitionAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/definitions"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -46,7 +46,7 @@ func (d *definitionWebservice) GetWebService() *restful.WebService { Doc("list all definitions"). Metadata(restfulspec.KeyOpenAPITags, tags). // TODO: provide project scope api for query definition list - // Filter(d.rbacUsecase.CheckPerm("definition", "list")). + // Filter(d.RbacService.CheckPerm("definition", "list")). Param(ws.QueryParameter("type", "query the definition type").DataType("string").Required(true).AllowableValues(map[string]string{"component": "", "trait": "", "workflowstep": ""})). Param(ws.QueryParameter("queryAll", "query all definitions include hidden in UI").DataType("boolean").DefaultValue("false")). Param(ws.QueryParameter("appliedWorkload", "if specified, query the trait definition applied to the workload").DataType("string")). @@ -55,7 +55,7 @@ func (d *definitionWebservice) GetWebService() *restful.WebService { ws.Route(ws.GET("/{definitionName}").To(d.detailDefinition). Doc("Detail a definition"). - // Filter(d.rbacUsecase.CheckPerm("definition", "detail")). + // Filter(d.RbacService.CheckPerm("definition", "detail")). Param(ws.PathParameter("definitionName", "identifier of the definition").DataType("string")). Param(ws.QueryParameter("type", "query the definition type").DataType("string")). Metadata(restfulspec.KeyOpenAPITags, tags). @@ -64,7 +64,7 @@ func (d *definitionWebservice) GetWebService() *restful.WebService { ws.Route(ws.PUT("/{definitionName}/uischema").To(d.updateUISchema). Doc("Update the UI schema for a definition"). - Filter(d.rbacUsecase.CheckPerm("definition", "update")). + Filter(d.RbacService.CheckPerm("definition", "update")). Metadata(restfulspec.KeyOpenAPITags, tags). Reads(apis.UpdateUISchemaRequest{}). Returns(200, "update successfully", utils.UISchema{}). @@ -72,7 +72,7 @@ func (d *definitionWebservice) GetWebService() *restful.WebService { ws.Route(ws.PUT("/{definitionName}/status").To(d.updateDefinitionStatus). Doc("Update the status for a definition"). - Filter(d.rbacUsecase.CheckPerm("definition", "update")). + Filter(d.RbacService.CheckPerm("definition", "update")). Metadata(restfulspec.KeyOpenAPITags, tags). Reads(apis.UpdateDefinitionStatusRequest{}). Returns(200, "update successfully", utils.UISchema{}). @@ -82,20 +82,17 @@ func (d *definitionWebservice) GetWebService() *restful.WebService { return ws } -// NewDefinitionWebservice new definition webservice -func NewDefinitionWebservice(du usecase.DefinitionUsecase, rbacUsecase usecase.RBACUsecase) WebService { - return &definitionWebservice{ - definitionUsecase: du, - rbacUsecase: rbacUsecase, - } +// NewDefinitionAPIInterface new definition APIInterface +func NewDefinitionAPIInterface() Interface { + return &definitionAPIInterface{} } -func (d *definitionWebservice) listDefinitions(req *restful.Request, res *restful.Response) { +func (d *definitionAPIInterface) listDefinitions(req *restful.Request, res *restful.Response) { queryAll, err := strconv.ParseBool(req.QueryParameter("queryAll")) if err != nil { queryAll = false } - definitions, err := d.definitionUsecase.ListDefinitions(req.Request.Context(), usecase.DefinitionQueryOption{ + definitions, err := d.DefinitionService.ListDefinitions(req.Request.Context(), service.DefinitionQueryOption{ Type: req.QueryParameter("type"), AppliedWorkloads: req.QueryParameter("appliedWorkload"), QueryAll: queryAll, @@ -110,8 +107,8 @@ func (d *definitionWebservice) listDefinitions(req *restful.Request, res *restfu } } -func (d *definitionWebservice) detailDefinition(req *restful.Request, res *restful.Response) { - definition, err := d.definitionUsecase.DetailDefinition(req.Request.Context(), req.PathParameter("definitionName"), req.QueryParameter("type")) +func (d *definitionAPIInterface) detailDefinition(req *restful.Request, res *restful.Response) { + definition, err := d.DefinitionService.DetailDefinition(req.Request.Context(), req.PathParameter("definitionName"), req.QueryParameter("type")) if err != nil { bcode.ReturnError(req, res, err) return @@ -122,7 +119,7 @@ func (d *definitionWebservice) detailDefinition(req *restful.Request, res *restf } } -func (d *definitionWebservice) updateUISchema(req *restful.Request, res *restful.Response) { +func (d *definitionAPIInterface) updateUISchema(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var updateReq apis.UpdateUISchemaRequest if err := req.ReadEntity(&updateReq); err != nil { @@ -137,7 +134,7 @@ func (d *definitionWebservice) updateUISchema(req *restful.Request, res *restful bcode.ReturnError(req, res, bcode.ErrInvalidDefinitionUISchema.SetMessage(err.Error())) return } - schema, err := d.definitionUsecase.AddDefinitionUISchema(req.Request.Context(), req.PathParameter("definitionName"), updateReq.DefinitionType, updateReq.UISchema) + schema, err := d.DefinitionService.AddDefinitionUISchema(req.Request.Context(), req.PathParameter("definitionName"), updateReq.DefinitionType, updateReq.UISchema) if err != nil { bcode.ReturnError(req, res, err) return @@ -148,7 +145,7 @@ func (d *definitionWebservice) updateUISchema(req *restful.Request, res *restful } } -func (d *definitionWebservice) updateDefinitionStatus(req *restful.Request, res *restful.Response) { +func (d *definitionAPIInterface) updateDefinitionStatus(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var updateReq apis.UpdateDefinitionStatusRequest if err := req.ReadEntity(&updateReq); err != nil { @@ -159,7 +156,7 @@ func (d *definitionWebservice) updateDefinitionStatus(req *restful.Request, res bcode.ReturnError(req, res, err) return } - schema, err := d.definitionUsecase.UpdateDefinitionStatus(req.Request.Context(), req.PathParameter("definitionName"), updateReq) + schema, err := d.DefinitionService.UpdateDefinitionStatus(req.Request.Context(), req.PathParameter("definitionName"), updateReq) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/rest/apis/v1/oam_application.go b/pkg/apiserver/interfaces/api/dto/v1/oam_application.go similarity index 100% rename from pkg/apiserver/rest/apis/v1/oam_application.go rename to pkg/apiserver/interfaces/api/dto/v1/oam_application.go diff --git a/pkg/apiserver/rest/apis/v1/types.go b/pkg/apiserver/interfaces/api/dto/v1/types.go similarity index 99% rename from pkg/apiserver/rest/apis/v1/types.go rename to pkg/apiserver/interfaces/api/dto/v1/types.go index a6f4c7c85..b0a2924b1 100644 --- a/pkg/apiserver/rest/apis/v1/types.go +++ b/pkg/apiserver/interfaces/api/dto/v1/types.go @@ -27,8 +27,8 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/addon" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" "github.com/oam-dev/kubevela/pkg/cloudprovider" ) diff --git a/pkg/apiserver/rest/webservice/env.go b/pkg/apiserver/interfaces/api/env.go similarity index 71% rename from pkg/apiserver/rest/webservice/env.go rename to pkg/apiserver/interfaces/api/env.go index 10285acbe..7b24b9619 100644 --- a/pkg/apiserver/rest/webservice/env.go +++ b/pkg/apiserver/interfaces/api/env.go @@ -14,31 +14,31 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( restfulspec "github.com/emicklei/go-restful-openapi/v2" "github.com/emicklei/go-restful/v3" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" ) -type envWebService struct { - envUsecase usecase.EnvUsecase - appUsecase usecase.ApplicationUsecase - rbacUsecase usecase.RBACUsecase +type envAPIInterface struct { + EnvService service.EnvService `inject:""` + ApplicationService service.ApplicationService `inject:""` + RBACService service.RBACService `inject:""` } -// NewEnvWebService new env webservice -func NewEnvWebService(envUsecase usecase.EnvUsecase, appUseCase usecase.ApplicationUsecase, rbacUsecase usecase.RBACUsecase) WebService { - return &envWebService{envUsecase: envUsecase, appUsecase: appUseCase, rbacUsecase: rbacUsecase} +// NewEnvAPIInterface new env APIInterface +func NewEnvAPIInterface() Interface { + return &envAPIInterface{} } -func (n *envWebService) GetWebService() *restful.WebService { +func (n *envAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/envs"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -51,7 +51,7 @@ func (n *envWebService) GetWebService() *restful.WebService { Operation("envlist"). Doc("list all envs"). // This api will filter the environments by user's permissions - // Filter(n.rbacUsecase.CheckPerm("environment", "list")). + // Filter(n.RbacService.CheckPerm("environment", "list")). Metadata(restfulspec.KeyOpenAPITags, tags). Returns(200, "OK", apis.ListEnvResponse{}). Writes(apis.ListEnvResponse{})) @@ -59,7 +59,7 @@ func (n *envWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/").To(n.create). Operation("envcreate"). Doc("create an env"). - Filter(n.rbacUsecase.CheckPerm("environment", "create")). + Filter(n.RBACService.CheckPerm("environment", "create")). Metadata(restfulspec.KeyOpenAPITags, tags). Reads(apis.CreateEnvRequest{}). Returns(200, "OK", apis.Env{}). @@ -69,7 +69,7 @@ func (n *envWebService) GetWebService() *restful.WebService { Operation("envupdate"). Doc("update an env"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(n.rbacUsecase.CheckPerm("environment", "update")). + Filter(n.RBACService.CheckPerm("environment", "update")). Param(ws.PathParameter("envName", "identifier of the application ").DataType("string")). Reads(apis.CreateEnvRequest{}). Returns(200, "OK", apis.Env{}). @@ -79,7 +79,7 @@ func (n *envWebService) GetWebService() *restful.WebService { Operation("envdelete"). Doc("delete one env"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(n.rbacUsecase.CheckPerm("environment", "delete")). + Filter(n.RBACService.CheckPerm("environment", "delete")). Param(ws.PathParameter("envName", "identifier of the application ").DataType("string")). Returns(200, "OK", apis.EmptyResponse{}). Returns(400, "Bad Request", bcode.Bcode{}). @@ -89,14 +89,14 @@ func (n *envWebService) GetWebService() *restful.WebService { return ws } -func (n *envWebService) list(req *restful.Request, res *restful.Response) { +func (n *envAPIInterface) list(req *restful.Request, res *restful.Response) { page, pageSize, err := utils.ExtractPagingParams(req, minPageSize, maxPageSize) if err != nil { bcode.ReturnError(req, res, err) return } project := req.QueryParameter("project") - envs, err := n.envUsecase.ListEnvs(req.Request.Context(), page, pageSize, apis.ListEnvOptions{Project: project}) + envs, err := n.EnvService.ListEnvs(req.Request.Context(), page, pageSize, apis.ListEnvOptions{Project: project}) if err != nil { bcode.ReturnError(req, res, err) return @@ -108,11 +108,11 @@ func (n *envWebService) list(req *restful.Request, res *restful.Response) { } // it will prevent the deletion if there's still application in it. -func (n *envWebService) delete(req *restful.Request, res *restful.Response) { +func (n *envAPIInterface) delete(req *restful.Request, res *restful.Response) { envname := req.PathParameter("envName") ctx := req.Request.Context() - lists, err := n.appUsecase.ListApplications(ctx, apis.ListApplicationOptions{Env: envname}) + lists, err := n.ApplicationService.ListApplications(ctx, apis.ListApplicationOptions{Env: envname}) if err != nil { bcode.ReturnError(req, res, err) return @@ -123,7 +123,7 @@ func (n *envWebService) delete(req *restful.Request, res *restful.Response) { return } - err = n.envUsecase.DeleteEnv(ctx, envname) + err = n.EnvService.DeleteEnv(ctx, envname) if err != nil { bcode.ReturnError(req, res, err) return @@ -134,7 +134,7 @@ func (n *envWebService) delete(req *restful.Request, res *restful.Response) { } } -func (n *envWebService) create(req *restful.Request, res *restful.Response) { +func (n *envAPIInterface) create(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var createReq apis.CreateEnvRequest if err := req.ReadEntity(&createReq); err != nil { @@ -145,8 +145,8 @@ func (n *envWebService) create(req *restful.Request, res *restful.Response) { bcode.ReturnError(req, res, err) return } - // Call the usecase layer code - env, err := n.envUsecase.CreateEnv(req.Request.Context(), createReq) + // Call the Domain layer code + env, err := n.EnvService.CreateEnv(req.Request.Context(), createReq) if err != nil { log.Logger.Errorf("create application failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -160,7 +160,7 @@ func (n *envWebService) create(req *restful.Request, res *restful.Response) { } } -func (n *envWebService) update(req *restful.Request, res *restful.Response) { +func (n *envAPIInterface) update(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var updateReq apis.UpdateEnvRequest if err := req.ReadEntity(&updateReq); err != nil { @@ -172,7 +172,7 @@ func (n *envWebService) update(req *restful.Request, res *restful.Response) { return } - env, err := n.envUsecase.UpdateEnv(req.Request.Context(), req.PathParameter("envName"), updateReq) + env, err := n.EnvService.UpdateEnv(req.Request.Context(), req.PathParameter("envName"), updateReq) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/rest/webservice/helm.go b/pkg/apiserver/interfaces/api/helm.go similarity index 76% rename from pkg/apiserver/rest/webservice/helm.go rename to pkg/apiserver/interfaces/api/helm.go index 49d3c1efe..f2d7844d3 100644 --- a/pkg/apiserver/rest/webservice/helm.go +++ b/pkg/apiserver/interfaces/api/helm.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( "context" @@ -23,21 +23,22 @@ import ( restfulspec "github.com/emicklei/go-restful-openapi/v2" "github.com/emicklei/go-restful/v3" - v1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + v1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/utils" ) -type helmWebService struct { - usecase usecase.HelmHandler +type helmAPIInterface struct { + HelmService service.HelmService `inject:""` } -// NewHelmWebService will return helm webService -func NewHelmWebService(u usecase.HelmHandler) WebService { - return helmWebService{usecase: u} +// NewHelmAPIInterface will return helm APIInterface +func NewHelmAPIInterface() Interface { + return &helmAPIInterface{} } -func (h helmWebService) GetWebService() *restful.WebService { +func (h helmAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/repository"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -89,15 +90,15 @@ func (h helmWebService) GetWebService() *restful.WebService { return ws } -func (h helmWebService) listCharts(req *restful.Request, res *restful.Response) { - url := req.QueryParameter("repoUrl") - secName := req.QueryParameter("secretName") +func (h helmAPIInterface) listCharts(req *restful.Request, res *restful.Response) { + url := utils.Sanitize(req.QueryParameter("repoUrl")) + secName := utils.Sanitize(req.QueryParameter("secretName")) skipCache, err := isSkipCache(req) if err != nil { bcode.ReturnError(req, res, bcode.ErrSkipCacheParameter) return } - charts, err := h.usecase.ListChartNames(context.Background(), url, secName, skipCache) + charts, err := h.HelmService.ListChartNames(context.Background(), url, secName, skipCache) if err != nil { bcode.ReturnError(req, res, err) return @@ -109,7 +110,7 @@ func (h helmWebService) listCharts(req *restful.Request, res *restful.Response) } } -func (h helmWebService) listVersions(req *restful.Request, res *restful.Response) { +func (h helmAPIInterface) listVersions(req *restful.Request, res *restful.Response) { url := req.QueryParameter("repoUrl") chartName := req.PathParameter("chart") secName := req.QueryParameter("secretName") @@ -119,7 +120,7 @@ func (h helmWebService) listVersions(req *restful.Request, res *restful.Response return } - versions, err := h.usecase.ListChartVersions(context.Background(), url, chartName, secName, skipCache) + versions, err := h.HelmService.ListChartVersions(context.Background(), url, chartName, secName, skipCache) if err != nil { bcode.ReturnError(req, res, err) return @@ -131,7 +132,7 @@ func (h helmWebService) listVersions(req *restful.Request, res *restful.Response } } -func (h helmWebService) chartValues(req *restful.Request, res *restful.Response) { +func (h helmAPIInterface) chartValues(req *restful.Request, res *restful.Response) { url := req.QueryParameter("repoUrl") secName := req.QueryParameter("secretName") chartName := req.PathParameter("chart") @@ -142,7 +143,7 @@ func (h helmWebService) chartValues(req *restful.Request, res *restful.Response) return } - versions, err := h.usecase.GetChartValues(context.Background(), url, chartName, version, secName, skipCache) + versions, err := h.HelmService.GetChartValues(context.Background(), url, chartName, version, secName, skipCache) if err != nil { bcode.ReturnError(req, res, err) return @@ -154,9 +155,9 @@ func (h helmWebService) chartValues(req *restful.Request, res *restful.Response) } } -func (h helmWebService) listRepo(req *restful.Request, res *restful.Response) { +func (h helmAPIInterface) listRepo(req *restful.Request, res *restful.Response) { project := req.QueryParameter("project") - repos, err := h.usecase.ListChartRepo(context.Background(), project) + repos, err := h.HelmService.ListChartRepo(context.Background(), project) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/interfaces/api/interfaces.go b/pkg/apiserver/interfaces/api/interfaces.go new file mode 100644 index 000000000..ef1d2de33 --- /dev/null +++ b/pkg/apiserver/interfaces/api/interfaces.go @@ -0,0 +1,94 @@ +/* +Copyright 2021 The KubeVela 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 api + +import ( + "net/http" + + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + + "github.com/emicklei/go-restful/v3" +) + +// versionPrefix API version prefix. +var versionPrefix = "/api/v1" + +// Interface the API should define the http route +type Interface interface { + GetWebServiceRoute() *restful.WebService +} + +var registeredAPIInterface []Interface + +// RegisterAPIInterface register APIInterface +func RegisterAPIInterface(ws Interface) { + registeredAPIInterface = append(registeredAPIInterface, ws) +} + +// GetRegisteredAPIInterface return registeredAPIInterface +func GetRegisteredAPIInterface() []Interface { + return registeredAPIInterface +} + +func returns200(b *restful.RouteBuilder) { + b.Returns(http.StatusOK, "OK", apisv1.SimpleResponse{Status: "ok"}) +} + +func returns500(b *restful.RouteBuilder) { + b.Returns(http.StatusInternalServerError, "Bummer, something went wrong", nil) +} + +// InitAPIBean inits all APIInterface, pass in the required parameter object. +// It can be implemented using the idea of dependency injection. +func InitAPIBean() []interface{} { + // Application + RegisterAPIInterface(NewApplicationAPIInterface()) + RegisterAPIInterface(NewProjectAPIInterface()) + RegisterAPIInterface(NewEnvAPIInterface()) + + // Extension + RegisterAPIInterface(NewDefinitionAPIInterface()) + RegisterAPIInterface(NewAddonAPIInterface()) + RegisterAPIInterface(NewEnabledAddonAPIInterface()) + RegisterAPIInterface(NewAddonRegistryAPIInterface()) + + // Config management + RegisterAPIInterface(ConfigAPIInterface()) + + // Resources + RegisterAPIInterface(NewClusterAPIInterface()) + RegisterAPIInterface(NewOAMApplication()) + RegisterAPIInterface(NewPayloadTypesAPIInterface()) + RegisterAPIInterface(NewTargetAPIInterface()) + RegisterAPIInterface(NewVelaQLAPIInterface()) + RegisterAPIInterface(NewWebhookAPIInterface()) + RegisterAPIInterface(NewHelmAPIInterface()) + + // Authentication + RegisterAPIInterface(NewAuthenticationAPIInterface()) + RegisterAPIInterface(NewUserAPIInterface()) + RegisterAPIInterface(NewSystemInfoAPIInterface()) + + // RBAC + RegisterAPIInterface(NewRBACAPIInterface()) + var beans []interface{} + for i := range registeredAPIInterface { + beans = append(beans, registeredAPIInterface[i]) + } + beans = append(beans, NewWorkflowAPIInterface()) + return beans +} diff --git a/pkg/apiserver/datastore/kubeapi/kubeapi_suite_test.go b/pkg/apiserver/interfaces/api/interfaces_test.go similarity index 73% rename from pkg/apiserver/datastore/kubeapi/kubeapi_suite_test.go rename to pkg/apiserver/interfaces/api/interfaces_test.go index 0f2956c96..92e9c7d0c 100644 --- a/pkg/apiserver/datastore/kubeapi/kubeapi_suite_test.go +++ b/pkg/apiserver/interfaces/api/interfaces_test.go @@ -1,5 +1,5 @@ /* -Copyright 2021 The KubeVela Authors. +Copyright 2022 The KubeVela Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,16 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubeapi +package api import ( "testing" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" + "gotest.tools/assert" ) -func TestKubeapi(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Kubeapi Suite") +func TestInitAPIBean(t *testing.T) { + assert.Equal(t, len(InitAPIBean()), 20) } diff --git a/pkg/apiserver/rest/webservice/oam_application.go b/pkg/apiserver/interfaces/api/oam_application.go similarity index 72% rename from pkg/apiserver/rest/webservice/oam_application.go rename to pkg/apiserver/interfaces/api/oam_application.go index 5b57ea6f5..9bc672a01 100644 --- a/pkg/apiserver/rest/webservice/oam_application.go +++ b/pkg/apiserver/interfaces/api/oam_application.go @@ -14,32 +14,29 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( restfulspec "github.com/emicklei/go-restful-openapi/v2" "github.com/emicklei/go-restful/v3" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" ) -type oamApplicationWebService struct { - oamApplicationUsecase usecase.OAMApplicationUsecase - rbacUsecase usecase.RBACUsecase +type oamApplicationAPIInterface struct { + OamApplicationService service.OAMApplicationService `inject:""` + RbacService service.RBACService `inject:""` } // NewOAMApplication new oam application -func NewOAMApplication(oamApplicationUsecase usecase.OAMApplicationUsecase, rbacUsecase usecase.RBACUsecase) WebService { - return &oamApplicationWebService{ - oamApplicationUsecase: oamApplicationUsecase, - rbacUsecase: rbacUsecase, - } +func NewOAMApplication() Interface { + return &oamApplicationAPIInterface{} } -func (c *oamApplicationWebService) GetWebService() *restful.WebService { +func (c *oamApplicationAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path("/v1"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -51,7 +48,7 @@ func (c *oamApplicationWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/namespaces/{namespace}/applications/{appname}").To(c.getApplication). Doc("get the specified oam application in the specified namespace"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("application", "detail")). + Filter(c.RbacService.CheckPerm("application", "detail")). Param(ws.PathParameter("namespace", "identifier of the namespace").DataType("string")). Param(ws.PathParameter("appname", "identifier of the oam application").DataType("string")). Returns(200, "OK", apis.ApplicationResponse{}). @@ -60,7 +57,7 @@ func (c *oamApplicationWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/namespaces/{namespace}/applications/{appname}").To(c.createOrUpdateApplication). Doc("create or update oam application in the specified namespace"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("application", "deploy")). + Filter(c.RbacService.CheckPerm("application", "deploy")). Param(ws.PathParameter("namespace", "identifier of the namespace").DataType("string")). Param(ws.PathParameter("appname", "identifier of the oam application").DataType("string")). Reads(apis.ApplicationRequest{})) @@ -69,7 +66,7 @@ func (c *oamApplicationWebService) GetWebService() *restful.WebService { Operation("deleteOAMApplication"). Doc("create or update oam application in the specified namespace"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("application", "delete")). + Filter(c.RbacService.CheckPerm("application", "delete")). Param(ws.PathParameter("namespace", "identifier of the namespace").DataType("string")). Param(ws.PathParameter("appname", "identifier of the oam application").DataType("string"))) @@ -77,10 +74,10 @@ func (c *oamApplicationWebService) GetWebService() *restful.WebService { return ws } -func (c *oamApplicationWebService) getApplication(req *restful.Request, res *restful.Response) { +func (c *oamApplicationAPIInterface) getApplication(req *restful.Request, res *restful.Response) { namespace := req.PathParameter("namespace") appName := req.PathParameter("appname") - appRes, err := c.oamApplicationUsecase.GetOAMApplication(req.Request.Context(), appName, namespace) + appRes, err := c.OamApplicationService.GetOAMApplication(req.Request.Context(), appName, namespace) if err != nil { log.Logger.Errorf("get application failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -94,7 +91,7 @@ func (c *oamApplicationWebService) getApplication(req *restful.Request, res *res } } -func (c *oamApplicationWebService) createOrUpdateApplication(req *restful.Request, res *restful.Response) { +func (c *oamApplicationAPIInterface) createOrUpdateApplication(req *restful.Request, res *restful.Response) { namespace := req.PathParameter("namespace") appName := req.PathParameter("appname") @@ -104,7 +101,7 @@ func (c *oamApplicationWebService) createOrUpdateApplication(req *restful.Reques return } - err := c.oamApplicationUsecase.CreateOrUpdateOAMApplication(req.Request.Context(), createReq, appName, namespace) + err := c.OamApplicationService.CreateOrUpdateOAMApplication(req.Request.Context(), createReq, appName, namespace) if err != nil { log.Logger.Errorf("create application failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -117,11 +114,11 @@ func (c *oamApplicationWebService) createOrUpdateApplication(req *restful.Reques } } -func (c *oamApplicationWebService) deleteApplication(req *restful.Request, res *restful.Response) { +func (c *oamApplicationAPIInterface) deleteApplication(req *restful.Request, res *restful.Response) { namespace := req.PathParameter("namespace") appName := req.PathParameter("appname") - err := c.oamApplicationUsecase.DeleteOAMApplication(req.Request.Context(), appName, namespace) + err := c.OamApplicationService.DeleteOAMApplication(req.Request.Context(), appName, namespace) if err != nil { log.Logger.Errorf("delete application failure %s", err.Error()) bcode.ReturnError(req, res, err) diff --git a/pkg/apiserver/rest/webservice/payload_types.go b/pkg/apiserver/interfaces/api/payload_types.go similarity index 70% rename from pkg/apiserver/rest/webservice/payload_types.go rename to pkg/apiserver/interfaces/api/payload_types.go index 9d5142ead..290e82d53 100644 --- a/pkg/apiserver/rest/webservice/payload_types.go +++ b/pkg/apiserver/interfaces/api/payload_types.go @@ -14,20 +14,25 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( restfulspec "github.com/emicklei/go-restful-openapi/v2" restful "github.com/emicklei/go-restful/v3" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" ) -type payloadTypesWebservice struct { +type payloadTypesAPIInterface struct { } -func (c *payloadTypesWebservice) GetWebService() *restful.WebService { +// NewPayloadTypesAPIInterface new - +func NewPayloadTypesAPIInterface() Interface { + return &payloadTypesAPIInterface{} +} + +func (c *payloadTypesAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/payload_types"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -47,8 +52,8 @@ func (c *payloadTypesWebservice) GetWebService() *restful.WebService { return ws } -func (c *payloadTypesWebservice) ListPayloadTypes(req *restful.Request, res *restful.Response) { - if err := res.WriteEntity(usecase.WebhookHandlers); err != nil { +func (c *payloadTypesAPIInterface) ListPayloadTypes(req *restful.Request, res *restful.Response) { + if err := res.WriteEntity(service.WebhookHandlers); err != nil { bcode.ReturnError(req, res, err) return } diff --git a/pkg/apiserver/rest/webservice/project.go b/pkg/apiserver/interfaces/api/project.go similarity index 76% rename from pkg/apiserver/rest/webservice/project.go rename to pkg/apiserver/interfaces/api/project.go index fdb254f0a..e15c032f8 100644 --- a/pkg/apiserver/rest/webservice/project.go +++ b/pkg/apiserver/interfaces/api/project.go @@ -14,31 +14,31 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( restfulspec "github.com/emicklei/go-restful-openapi/v2" "github.com/emicklei/go-restful/v3" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" ) -type projectWebService struct { - rbacUsecase usecase.RBACUsecase - projectUsecase usecase.ProjectUsecase - targetUsecase usecase.TargetUsecase +type projectAPIInterface struct { + RbacService service.RBACService `inject:""` + ProjectService service.ProjectService `inject:""` + TargetService service.TargetService `inject:""` } -// NewProjectWebService new project webservice -func NewProjectWebService(projectUsecase usecase.ProjectUsecase, rbacUsecase usecase.RBACUsecase, targetUsecase usecase.TargetUsecase) WebService { - return &projectWebService{projectUsecase: projectUsecase, rbacUsecase: rbacUsecase, targetUsecase: targetUsecase} +// NewProjectAPIInterface new project APIInterface +func NewProjectAPIInterface() Interface { + return &projectAPIInterface{} } -func (n *projectWebService) GetWebService() *restful.WebService { +func (n *projectAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/projects"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -50,14 +50,14 @@ func (n *projectWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/").To(n.listprojects). Doc("list all projects"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(n.rbacUsecase.CheckPerm("project", "list")). + Filter(n.RbacService.CheckPerm("project", "list")). Returns(200, "OK", apis.ListProjectResponse{}). Writes(apis.ListProjectResponse{})) ws.Route(ws.POST("/").To(n.createproject). Doc("create a project"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(n.rbacUsecase.CheckPerm("project", "create")). + Filter(n.RbacService.CheckPerm("project", "create")). Reads(apis.CreateProjectRequest{}). Returns(200, "OK", apis.ProjectBase{}). Writes(apis.ProjectBase{})) @@ -66,7 +66,7 @@ func (n *projectWebService) GetWebService() *restful.WebService { Doc("detail a project"). Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.PathParameter("projectName", "identifier of the project").DataType("string")). - Filter(n.rbacUsecase.CheckPerm("project", "detail")). + Filter(n.RbacService.CheckPerm("project", "detail")). Returns(200, "OK", apis.ProjectBase{}). Writes(apis.ProjectBase{})) @@ -74,7 +74,7 @@ func (n *projectWebService) GetWebService() *restful.WebService { Doc("update a project"). Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.PathParameter("projectName", "identifier of the project").DataType("string")). - Filter(n.rbacUsecase.CheckPerm("project", "update")). + Filter(n.RbacService.CheckPerm("project", "update")). Reads(apis.UpdateProjectRequest{}). Returns(200, "OK", apis.ProjectBase{}). Writes(apis.ProjectBase{})) @@ -83,7 +83,7 @@ func (n *projectWebService) GetWebService() *restful.WebService { Doc("delete a project"). Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.PathParameter("projectName", "identifier of the project").DataType("string")). - Filter(n.rbacUsecase.CheckPerm("project", "delete")). + Filter(n.RbacService.CheckPerm("project", "delete")). Returns(200, "OK", apis.EmptyResponse{}). Writes(apis.EmptyResponse{})) @@ -91,7 +91,7 @@ func (n *projectWebService) GetWebService() *restful.WebService { Doc("get targets list belong to a project"). Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.PathParameter("projectName", "identifier of the project").DataType("string")). - Filter(n.rbacUsecase.CheckPerm("project", "detail")). + Filter(n.RbacService.CheckPerm("project", "detail")). Returns(200, "OK", apis.EmptyResponse{}). Writes(apis.EmptyResponse{})) @@ -99,7 +99,7 @@ func (n *projectWebService) GetWebService() *restful.WebService { Doc("add a user to a project"). Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.PathParameter("projectName", "identifier of the project").DataType("string")). - Filter(n.rbacUsecase.CheckPerm("project/projectUser", "create")). + Filter(n.RbacService.CheckPerm("project/projectUser", "create")). Reads(apis.AddProjectUserRequest{}). Returns(200, "OK", apis.ProjectUserBase{}). Writes(apis.ProjectUserBase{})) @@ -108,7 +108,7 @@ func (n *projectWebService) GetWebService() *restful.WebService { Doc("list all users belong to a project"). Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.PathParameter("projectName", "identifier of the project").DataType("string")). - Filter(n.rbacUsecase.CheckPerm("project/projectUser", "list")). + Filter(n.RbacService.CheckPerm("project/projectUser", "list")). Returns(200, "OK", apis.ListProjectUsersResponse{}). Writes(apis.ListProjectUsersResponse{})) @@ -118,7 +118,7 @@ func (n *projectWebService) GetWebService() *restful.WebService { Reads(apis.UpdateProjectUserRequest{}). Param(ws.PathParameter("projectName", "identifier of the project").DataType("string")). Param(ws.PathParameter("userName", "identifier of the project user").DataType("string")). - Filter(n.rbacUsecase.CheckPerm("project/projectUser", "create")). + Filter(n.RbacService.CheckPerm("project/projectUser", "create")). Returns(200, "OK", apis.ProjectUserBase{}). Writes(apis.ProjectUserBase{})) @@ -128,7 +128,7 @@ func (n *projectWebService) GetWebService() *restful.WebService { Reads(apis.UpdateProjectUserRequest{}). Param(ws.PathParameter("projectName", "identifier of the project").DataType("string")). Param(ws.PathParameter("userName", "identifier of the project user").DataType("string")). - Filter(n.rbacUsecase.CheckPerm("project/projectUser", "delete")). + Filter(n.RbacService.CheckPerm("project/projectUser", "delete")). Returns(200, "OK", apis.EmptyResponse{}). Writes(apis.EmptyResponse{})) @@ -136,7 +136,7 @@ func (n *projectWebService) GetWebService() *restful.WebService { Doc("list all project level roles"). Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.PathParameter("projectName", "identifier of the project").DataType("string")). - Filter(n.rbacUsecase.CheckPerm("project/role", "list")). + Filter(n.RbacService.CheckPerm("project/role", "list")). Returns(200, "OK", apis.ListRolesResponse{}). Writes(apis.ListRolesResponse{})) @@ -144,7 +144,7 @@ func (n *projectWebService) GetWebService() *restful.WebService { Doc("create project level role"). Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.PathParameter("projectName", "identifier of the project").DataType("string")). - Filter(n.rbacUsecase.CheckPerm("project/role", "create")). + Filter(n.RbacService.CheckPerm("project/role", "create")). Returns(200, "OK", apis.RoleBase{}). Reads(apis.CreateRoleRequest{}). Writes(apis.RoleBase{})) @@ -154,7 +154,7 @@ func (n *projectWebService) GetWebService() *restful.WebService { Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.PathParameter("projectName", "identifier of the project").DataType("string")). Param(ws.PathParameter("roleName", "identifier of the project role").DataType("string")). - Filter(n.rbacUsecase.CheckPerm("project/role", "update")). + Filter(n.RbacService.CheckPerm("project/role", "update")). Reads(apis.UpdateRoleRequest{}). Returns(200, "OK", apis.RoleBase{}). Writes(apis.RoleBase{})) @@ -164,7 +164,7 @@ func (n *projectWebService) GetWebService() *restful.WebService { Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.PathParameter("projectName", "identifier of the project").DataType("string")). Param(ws.PathParameter("roleName", "identifier of the project role").DataType("string")). - Filter(n.rbacUsecase.CheckPerm("project/role", "delete")). + Filter(n.RbacService.CheckPerm("project/role", "delete")). Returns(200, "OK", apis.EmptyResponse{}). Writes(apis.EmptyResponse{})) @@ -172,14 +172,14 @@ func (n *projectWebService) GetWebService() *restful.WebService { Doc("list all project level perm policies"). Metadata(restfulspec.KeyOpenAPITags, tags). Param(ws.PathParameter("projectName", "identifier of the project").DataType("string")). - Filter(n.rbacUsecase.CheckPerm("project/permission", "list")). + Filter(n.RbacService.CheckPerm("project/permission", "list")). Returns(200, "OK", []apis.PermissionBase{}). Writes([]apis.PermissionBase{})) ws.Route(ws.GET("/{projectName}/configs").To(n.getConfigs). Doc("get configs which are in a project"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(n.rbacUsecase.CheckPerm("project/configs", "list")). + Filter(n.RbacService.CheckPerm("project/configs", "list")). Param(ws.QueryParameter("configType", "config type").DataType("string")). Param(ws.PathParameter("projectName", "identifier of the project").DataType("string")). Returns(200, "OK", []*apis.Config{}). @@ -189,7 +189,7 @@ func (n *projectWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{projectName}/validate_image").To(n.validateImage). Doc("validate an image in a project"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(n.rbacUsecase.CheckPerm("project/image", "get")). + Filter(n.RbacService.CheckPerm("project/image", "get")). Param(ws.QueryParameter("image", "image name").DataType("string")). Param(ws.PathParameter("projectName", "identifier of the project").DataType("string")). Returns(200, "OK", []*apis.ImageResponse{}). @@ -200,13 +200,13 @@ func (n *projectWebService) GetWebService() *restful.WebService { return ws } -func (n *projectWebService) listprojects(req *restful.Request, res *restful.Response) { +func (n *projectAPIInterface) listprojects(req *restful.Request, res *restful.Response) { page, pageSize, err := utils.ExtractPagingParams(req, minPageSize, maxPageSize) if err != nil { bcode.ReturnError(req, res, err) return } - projects, err := n.projectUsecase.ListProjects(req.Request.Context(), page, pageSize) + projects, err := n.ProjectService.ListProjects(req.Request.Context(), page, pageSize) if err != nil { bcode.ReturnError(req, res, err) return @@ -217,7 +217,7 @@ func (n *projectWebService) listprojects(req *restful.Request, res *restful.Resp } } -func (n *projectWebService) createproject(req *restful.Request, res *restful.Response) { +func (n *projectAPIInterface) createproject(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var createReq apis.CreateProjectRequest if err := req.ReadEntity(&createReq); err != nil { @@ -228,8 +228,8 @@ func (n *projectWebService) createproject(req *restful.Request, res *restful.Res bcode.ReturnError(req, res, err) return } - // Call the usecase layer code - projectBase, err := n.projectUsecase.CreateProject(req.Request.Context(), createReq) + // Call the domain layer code + projectBase, err := n.ProjectService.CreateProject(req.Request.Context(), createReq) if err != nil { log.Logger.Errorf("create project failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -243,7 +243,7 @@ func (n *projectWebService) createproject(req *restful.Request, res *restful.Res } } -func (n *projectWebService) updateProject(req *restful.Request, res *restful.Response) { +func (n *projectAPIInterface) updateProject(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var updateReq apis.UpdateProjectRequest if err := req.ReadEntity(&updateReq); err != nil { @@ -254,8 +254,8 @@ func (n *projectWebService) updateProject(req *restful.Request, res *restful.Res bcode.ReturnError(req, res, err) return } - // Call the usecase layer code - projectBase, err := n.projectUsecase.UpdateProject(req.Request.Context(), req.PathParameter("projectName"), updateReq) + // Call the domain layer code + projectBase, err := n.ProjectService.UpdateProject(req.Request.Context(), req.PathParameter("projectName"), updateReq) if err != nil { log.Logger.Errorf("update project failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -269,8 +269,8 @@ func (n *projectWebService) updateProject(req *restful.Request, res *restful.Res } } -func (n *projectWebService) detailProject(req *restful.Request, res *restful.Response) { - project, err := n.projectUsecase.DetailProject(req.Request.Context(), req.PathParameter("projectName")) +func (n *projectAPIInterface) detailProject(req *restful.Request, res *restful.Response) { + project, err := n.ProjectService.DetailProject(req.Request.Context(), req.PathParameter("projectName")) if err != nil { bcode.ReturnError(req, res, err) return @@ -282,8 +282,8 @@ func (n *projectWebService) detailProject(req *restful.Request, res *restful.Res } } -func (n *projectWebService) deleteProject(req *restful.Request, res *restful.Response) { - err := n.projectUsecase.DeleteProject(req.Request.Context(), req.PathParameter("projectName")) +func (n *projectAPIInterface) deleteProject(req *restful.Request, res *restful.Response) { + err := n.ProjectService.DeleteProject(req.Request.Context(), req.PathParameter("projectName")) if err != nil { bcode.ReturnError(req, res, err) return @@ -295,13 +295,13 @@ func (n *projectWebService) deleteProject(req *restful.Request, res *restful.Res } } -func (n *projectWebService) listProjectTargets(req *restful.Request, res *restful.Response) { - project, err := n.projectUsecase.GetProject(req.Request.Context(), req.PathParameter("projectName")) +func (n *projectAPIInterface) listProjectTargets(req *restful.Request, res *restful.Response) { + project, err := n.ProjectService.GetProject(req.Request.Context(), req.PathParameter("projectName")) if err != nil { bcode.ReturnError(req, res, err) return } - projects, err := n.targetUsecase.ListTargets(req.Request.Context(), 0, 0, project.Name) + projects, err := n.TargetService.ListTargets(req.Request.Context(), 0, 0, project.Name) if err != nil { bcode.ReturnError(req, res, err) return @@ -313,7 +313,7 @@ func (n *projectWebService) listProjectTargets(req *restful.Request, res *restfu } } -func (n *projectWebService) createProjectUser(req *restful.Request, res *restful.Response) { +func (n *projectAPIInterface) createProjectUser(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var createReq apis.AddProjectUserRequest if err := req.ReadEntity(&createReq); err != nil { @@ -328,8 +328,8 @@ func (n *projectWebService) createProjectUser(req *restful.Request, res *restful bcode.ReturnError(req, res, bcode.ErrProjectRoleCheckFailure) return } - // Call the usecase layer code - userBase, err := n.projectUsecase.AddProjectUser(req.Request.Context(), req.PathParameter("projectName"), createReq) + // Call the domain layer code + userBase, err := n.ProjectService.AddProjectUser(req.Request.Context(), req.PathParameter("projectName"), createReq) if err != nil { log.Logger.Errorf("create project user failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -343,14 +343,14 @@ func (n *projectWebService) createProjectUser(req *restful.Request, res *restful } } -func (n *projectWebService) listProjectUser(req *restful.Request, res *restful.Response) { +func (n *projectAPIInterface) listProjectUser(req *restful.Request, res *restful.Response) { page, pageSize, err := utils.ExtractPagingParams(req, minPageSize, maxPageSize) if err != nil { bcode.ReturnError(req, res, err) return } - // Call the usecase layer code - users, err := n.projectUsecase.ListProjectUser(req.Request.Context(), req.PathParameter("projectName"), page, pageSize) + // Call the domain layer code + users, err := n.ProjectService.ListProjectUser(req.Request.Context(), req.PathParameter("projectName"), page, pageSize) if err != nil { log.Logger.Errorf("list project users failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -364,7 +364,7 @@ func (n *projectWebService) listProjectUser(req *restful.Request, res *restful.R } } -func (n *projectWebService) updateProjectUser(req *restful.Request, res *restful.Response) { +func (n *projectAPIInterface) updateProjectUser(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var updateReq apis.UpdateProjectUserRequest if err := req.ReadEntity(&updateReq); err != nil { @@ -379,8 +379,8 @@ func (n *projectWebService) updateProjectUser(req *restful.Request, res *restful bcode.ReturnError(req, res, bcode.ErrProjectRoleCheckFailure) return } - // Call the usecase layer code - userBase, err := n.projectUsecase.UpdateProjectUser(req.Request.Context(), req.PathParameter("projectName"), req.PathParameter("userName"), updateReq) + // Call the domain layer code + userBase, err := n.ProjectService.UpdateProjectUser(req.Request.Context(), req.PathParameter("projectName"), req.PathParameter("userName"), updateReq) if err != nil { log.Logger.Errorf("update project user failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -394,9 +394,9 @@ func (n *projectWebService) updateProjectUser(req *restful.Request, res *restful } } -func (n *projectWebService) deleteProjectUser(req *restful.Request, res *restful.Response) { - // Call the usecase layer code - err := n.projectUsecase.DeleteProjectUser(req.Request.Context(), req.PathParameter("projectName"), req.PathParameter("userName")) +func (n *projectAPIInterface) deleteProjectUser(req *restful.Request, res *restful.Response) { + // Call the domain layer code + err := n.ProjectService.DeleteProjectUser(req.Request.Context(), req.PathParameter("projectName"), req.PathParameter("userName")) if err != nil { log.Logger.Errorf("delete project user failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -410,7 +410,7 @@ func (n *projectWebService) deleteProjectUser(req *restful.Request, res *restful } } -func (n *projectWebService) listProjectRoles(req *restful.Request, res *restful.Response) { +func (n *projectAPIInterface) listProjectRoles(req *restful.Request, res *restful.Response) { if req.PathParameter("projectName") == "" { bcode.ReturnError(req, res, bcode.ErrProjectIsNotExist) return @@ -420,7 +420,7 @@ func (n *projectWebService) listProjectRoles(req *restful.Request, res *restful. bcode.ReturnError(req, res, err) return } - roles, err := n.rbacUsecase.ListRole(req.Request.Context(), req.PathParameter("projectName"), page, pageSize) + roles, err := n.RbacService.ListRole(req.Request.Context(), req.PathParameter("projectName"), page, pageSize) if err != nil { bcode.ReturnError(req, res, err) return @@ -431,7 +431,7 @@ func (n *projectWebService) listProjectRoles(req *restful.Request, res *restful. } } -func (n *projectWebService) createProjectRole(req *restful.Request, res *restful.Response) { +func (n *projectAPIInterface) createProjectRole(req *restful.Request, res *restful.Response) { if req.PathParameter("projectName") == "" { bcode.ReturnError(req, res, bcode.ErrProjectIsNotExist) return @@ -446,8 +446,8 @@ func (n *projectWebService) createProjectRole(req *restful.Request, res *restful bcode.ReturnError(req, res, err) return } - // Call the usecase layer code - projectBase, err := n.rbacUsecase.CreateRole(req.Request.Context(), req.PathParameter("projectName"), createReq) + // Call the domain layer code + projectBase, err := n.RbacService.CreateRole(req.Request.Context(), req.PathParameter("projectName"), createReq) if err != nil { log.Logger.Errorf("create role failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -461,7 +461,7 @@ func (n *projectWebService) createProjectRole(req *restful.Request, res *restful } } -func (n *projectWebService) updateProjectRole(req *restful.Request, res *restful.Response) { +func (n *projectAPIInterface) updateProjectRole(req *restful.Request, res *restful.Response) { if req.PathParameter("projectName") == "" { bcode.ReturnError(req, res, bcode.ErrProjectIsNotExist) return @@ -476,8 +476,8 @@ func (n *projectWebService) updateProjectRole(req *restful.Request, res *restful bcode.ReturnError(req, res, err) return } - // Call the usecase layer code - roleBase, err := n.rbacUsecase.UpdateRole(req.Request.Context(), req.PathParameter("projectName"), req.PathParameter("roleName"), updateReq) + // Call the domain layer code + roleBase, err := n.RbacService.UpdateRole(req.Request.Context(), req.PathParameter("projectName"), req.PathParameter("roleName"), updateReq) if err != nil { log.Logger.Errorf("update role failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -491,12 +491,12 @@ func (n *projectWebService) updateProjectRole(req *restful.Request, res *restful } } -func (n *projectWebService) deleteProjectRole(req *restful.Request, res *restful.Response) { +func (n *projectAPIInterface) deleteProjectRole(req *restful.Request, res *restful.Response) { if req.PathParameter("projectName") == "" { bcode.ReturnError(req, res, bcode.ErrProjectIsNotExist) return } - err := n.rbacUsecase.DeleteRole(req.Request.Context(), req.PathParameter("projectName"), req.PathParameter("roleName")) + err := n.RbacService.DeleteRole(req.Request.Context(), req.PathParameter("projectName"), req.PathParameter("roleName")) if err != nil { bcode.ReturnError(req, res, err) return @@ -508,12 +508,12 @@ func (n *projectWebService) deleteProjectRole(req *restful.Request, res *restful } } -func (n *projectWebService) listProjectPermissions(req *restful.Request, res *restful.Response) { +func (n *projectAPIInterface) listProjectPermissions(req *restful.Request, res *restful.Response) { if req.PathParameter("projectName") == "" { bcode.ReturnError(req, res, bcode.ErrProjectIsNotExist) return } - policies, err := n.rbacUsecase.ListPermissions(req.Request.Context(), req.PathParameter("projectName")) + policies, err := n.RbacService.ListPermissions(req.Request.Context(), req.PathParameter("projectName")) if err != nil { bcode.ReturnError(req, res, err) return @@ -524,8 +524,8 @@ func (n *projectWebService) listProjectPermissions(req *restful.Request, res *re } } -func (n *projectWebService) getConfigs(req *restful.Request, res *restful.Response) { - configs, err := n.projectUsecase.GetConfigs(req.Request.Context(), req.PathParameter("projectName"), req.QueryParameter("configType")) +func (n *projectAPIInterface) getConfigs(req *restful.Request, res *restful.Response) { + configs, err := n.ProjectService.GetConfigs(req.Request.Context(), req.PathParameter("projectName"), req.QueryParameter("configType")) if err != nil { bcode.ReturnError(req, res, err) return @@ -544,8 +544,8 @@ func (n *projectWebService) getConfigs(req *restful.Request, res *restful.Respon } } -func (n *projectWebService) validateImage(req *restful.Request, res *restful.Response) { - resp, err := n.projectUsecase.ValidateImage(req.Request.Context(), req.PathParameter("projectName"), req.QueryParameter("image")) +func (n *projectAPIInterface) validateImage(req *restful.Request, res *restful.Response) { + resp, err := n.ProjectService.ValidateImage(req.Request.Context(), req.PathParameter("projectName"), req.QueryParameter("image")) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/rest/webservice/rbac.go b/pkg/apiserver/interfaces/api/rbac.go similarity index 69% rename from pkg/apiserver/rest/webservice/rbac.go rename to pkg/apiserver/interfaces/api/rbac.go index a89b517ac..fa7961b1f 100644 --- a/pkg/apiserver/rest/webservice/rbac.go +++ b/pkg/apiserver/interfaces/api/rbac.go @@ -14,29 +14,29 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( restfulspec "github.com/emicklei/go-restful-openapi/v2" "github.com/emicklei/go-restful/v3" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" ) -type rbacWebService struct { - rbacUsecase usecase.RBACUsecase +type rbacAPIInterface struct { + RbacService service.RBACService `inject:""` } -// NewRBACWebService new rbac webservice -func NewRBACWebService(rbacUsecase usecase.RBACUsecase) WebService { - return &rbacWebService{rbacUsecase: rbacUsecase} +// NewRBACAPIInterface new rbac APIInterface +func NewRBACAPIInterface() Interface { + return &rbacAPIInterface{} } -func (r *rbacWebService) GetWebService() *restful.WebService { +func (r *rbacAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -48,14 +48,14 @@ func (r *rbacWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/roles").To(r.listPlatformRoles). Doc("list all platform level roles"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(r.rbacUsecase.CheckPerm("role", "list")). + Filter(r.RbacService.CheckPerm("role", "list")). Returns(200, "OK", apis.ListRolesResponse{}). Writes(apis.ListRolesResponse{})) ws.Route(ws.POST("/roles").To(r.createPlatformRole). Doc("create platform level role"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(r.rbacUsecase.CheckPerm("role", "create")). + Filter(r.RbacService.CheckPerm("role", "create")). Returns(200, "OK", apis.RoleBase{}). Reads(apis.CreateRoleRequest{}). Writes(apis.RoleBase{})) @@ -63,7 +63,7 @@ func (r *rbacWebService) GetWebService() *restful.WebService { ws.Route(ws.PUT("/roles/{roleName}").To(r.updatePlatformRole). Doc("update platform level role"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(r.rbacUsecase.CheckPerm("role", "update")). + Filter(r.RbacService.CheckPerm("role", "update")). Reads(apis.UpdateRoleRequest{}). Returns(200, "OK", apis.RoleBase{}). Writes(apis.RoleBase{})) @@ -71,14 +71,14 @@ func (r *rbacWebService) GetWebService() *restful.WebService { ws.Route(ws.DELETE("/roles/{roleName}").To(r.deletePlatformRole). Doc("update platform level role"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(r.rbacUsecase.CheckPerm("role", "delete")). + Filter(r.RbacService.CheckPerm("role", "delete")). Returns(200, "OK", apis.EmptyResponse{}). Writes(apis.EmptyResponse{})) ws.Route(ws.GET("/permissions").To(r.listPlatformPermissions). Doc("list all project level perm policies"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(r.rbacUsecase.CheckPerm("permission", "list")). + Filter(r.RbacService.CheckPerm("permission", "list")). Returns(200, "OK", []apis.PermissionBase{}). Writes([]apis.PermissionBase{})) @@ -86,13 +86,13 @@ func (r *rbacWebService) GetWebService() *restful.WebService { return ws } -func (r *rbacWebService) listPlatformRoles(req *restful.Request, res *restful.Response) { +func (r *rbacAPIInterface) listPlatformRoles(req *restful.Request, res *restful.Response) { page, pageSize, err := utils.ExtractPagingParams(req, minPageSize, maxPageSize) if err != nil { bcode.ReturnError(req, res, err) return } - roles, err := r.rbacUsecase.ListRole(req.Request.Context(), "", page, pageSize) + roles, err := r.RbacService.ListRole(req.Request.Context(), "", page, pageSize) if err != nil { bcode.ReturnError(req, res, err) return @@ -103,7 +103,7 @@ func (r *rbacWebService) listPlatformRoles(req *restful.Request, res *restful.Re } } -func (r *rbacWebService) createPlatformRole(req *restful.Request, res *restful.Response) { +func (r *rbacAPIInterface) createPlatformRole(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var createReq apis.CreateRoleRequest if err := req.ReadEntity(&createReq); err != nil { @@ -114,8 +114,8 @@ func (r *rbacWebService) createPlatformRole(req *restful.Request, res *restful.R bcode.ReturnError(req, res, err) return } - // Call the usecase layer code - projectBase, err := r.rbacUsecase.CreateRole(req.Request.Context(), "", createReq) + // Call the domain layer code + projectBase, err := r.RbacService.CreateRole(req.Request.Context(), "", createReq) if err != nil { log.Logger.Errorf("create role failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -129,7 +129,7 @@ func (r *rbacWebService) createPlatformRole(req *restful.Request, res *restful.R } } -func (r *rbacWebService) updatePlatformRole(req *restful.Request, res *restful.Response) { +func (r *rbacAPIInterface) updatePlatformRole(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var updateReq apis.UpdateRoleRequest if err := req.ReadEntity(&updateReq); err != nil { @@ -140,8 +140,8 @@ func (r *rbacWebService) updatePlatformRole(req *restful.Request, res *restful.R bcode.ReturnError(req, res, err) return } - // Call the usecase layer code - roleBase, err := r.rbacUsecase.UpdateRole(req.Request.Context(), "", req.PathParameter("roleName"), updateReq) + // Call the domain layer code + roleBase, err := r.RbacService.UpdateRole(req.Request.Context(), "", req.PathParameter("roleName"), updateReq) if err != nil { log.Logger.Errorf("update role failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -155,8 +155,8 @@ func (r *rbacWebService) updatePlatformRole(req *restful.Request, res *restful.R } } -func (r *rbacWebService) deletePlatformRole(req *restful.Request, res *restful.Response) { - err := r.rbacUsecase.DeleteRole(req.Request.Context(), "", req.PathParameter("roleName")) +func (r *rbacAPIInterface) deletePlatformRole(req *restful.Request, res *restful.Response) { + err := r.RbacService.DeleteRole(req.Request.Context(), "", req.PathParameter("roleName")) if err != nil { bcode.ReturnError(req, res, err) return @@ -168,8 +168,8 @@ func (r *rbacWebService) deletePlatformRole(req *restful.Request, res *restful.R } } -func (r *rbacWebService) listPlatformPermissions(req *restful.Request, res *restful.Response) { - policies, err := r.rbacUsecase.ListPermissions(req.Request.Context(), "") +func (r *rbacAPIInterface) listPlatformPermissions(req *restful.Request, res *restful.Response) { + policies, err := r.RbacService.ListPermissions(req.Request.Context(), "") if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/rest/webservice/system_info.go b/pkg/apiserver/interfaces/api/system_info.go similarity index 66% rename from pkg/apiserver/rest/webservice/system_info.go rename to pkg/apiserver/interfaces/api/system_info.go index 958ffeba5..92dce9d4a 100644 --- a/pkg/apiserver/rest/webservice/system_info.go +++ b/pkg/apiserver/interfaces/api/system_info.go @@ -14,29 +14,29 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( restfulspec "github.com/emicklei/go-restful-openapi/v2" "github.com/emicklei/go-restful/v3" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" ) -type systemInfoWebService struct { - useCase usecase.SystemInfoUsecase - rbacUsecase usecase.RBACUsecase +type systemInfoAPIInterface struct { + SystemInfoService service.SystemInfoService `inject:""` + RbacService service.RBACService `inject:""` } -// NewSystemInfoWebService return systemInfo webservice -func NewSystemInfoWebService(systemInfoUseCase usecase.SystemInfoUsecase, rbacUsecase usecase.RBACUsecase) WebService { - return &systemInfoWebService{useCase: systemInfoUseCase, rbacUsecase: rbacUsecase} +// NewSystemInfoAPIInterface return systemInfo APIInterface +func NewSystemInfoAPIInterface() Interface { + return &systemInfoAPIInterface{} } -// GetWebService return systemInfo webservice -func (u systemInfoWebService) GetWebService() *restful.WebService { +// GetAPIInterface return systemInfo APIInterface +func (u systemInfoAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/system_info").Consumes(restful.MIME_XML, restful.MIME_JSON). Produces(restful.MIME_JSON, restful.MIME_XML). @@ -55,7 +55,7 @@ func (u systemInfoWebService) GetWebService() *restful.WebService { ws.Route(ws.PUT("/").To(u.updateSystemInfo). Metadata(restfulspec.KeyOpenAPITags, tags). Reads(apis.SystemInfoRequest{}). - Filter(u.rbacUsecase.CheckPerm("systemSetting", "update")). + Filter(u.RbacService.CheckPerm("systemSetting", "update")). Returns(200, "OK", apis.SystemInfoResponse{}). Returns(400, "Bad Request", bcode.Bcode{}). Writes(apis.SystemInfoResponse{})) @@ -64,8 +64,8 @@ func (u systemInfoWebService) GetWebService() *restful.WebService { return ws } -func (u systemInfoWebService) getSystemInfo(req *restful.Request, res *restful.Response) { - info, err := u.useCase.GetSystemInfo(req.Request.Context()) +func (u systemInfoAPIInterface) getSystemInfo(req *restful.Request, res *restful.Response) { + info, err := u.SystemInfoService.GetSystemInfo(req.Request.Context()) if err != nil { bcode.ReturnError(req, res, err) return @@ -76,7 +76,7 @@ func (u systemInfoWebService) getSystemInfo(req *restful.Request, res *restful.R } } -func (u systemInfoWebService) updateSystemInfo(req *restful.Request, res *restful.Response) { +func (u systemInfoAPIInterface) updateSystemInfo(req *restful.Request, res *restful.Response) { var systemInfoReq apis.SystemInfoRequest var args []byte _, err := req.Request.Body.Read(args) @@ -92,7 +92,7 @@ func (u systemInfoWebService) updateSystemInfo(req *restful.Request, res *restfu } } - info, err := u.useCase.UpdateSystemInfo(req.Request.Context(), systemInfoReq) + info, err := u.SystemInfoService.UpdateSystemInfo(req.Request.Context(), systemInfoReq) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/rest/webservice/target.go b/pkg/apiserver/interfaces/api/target.go similarity index 69% rename from pkg/apiserver/rest/webservice/target.go rename to pkg/apiserver/interfaces/api/target.go index bd9c2a816..86e267cce 100644 --- a/pkg/apiserver/rest/webservice/target.go +++ b/pkg/apiserver/interfaces/api/target.go @@ -14,44 +14,40 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( "context" "github.com/pkg/errors" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" restfulspec "github.com/emicklei/go-restful-openapi/v2" "github.com/emicklei/go-restful/v3" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" ) -// NewTargetWebService new Target webservice -func NewTargetWebService(targetUsecase usecase.TargetUsecase, applicationUsecase usecase.ApplicationUsecase, rbacUsecase usecase.RBACUsecase) WebService { - return &TargetWebService{ - TargetUsecase: targetUsecase, - applicationUsecase: applicationUsecase, - rbacUsecase: rbacUsecase, - } +// NewTargetAPIInterface new Target Interface +func NewTargetAPIInterface() Interface { + return &TargetAPIInterface{} } -// TargetWebService target web service -type TargetWebService struct { - TargetUsecase usecase.TargetUsecase - applicationUsecase usecase.ApplicationUsecase - rbacUsecase usecase.RBACUsecase +// TargetAPIInterface target web service +type TargetAPIInterface struct { + TargetService service.TargetService `inject:""` + ApplicationService service.ApplicationService `inject:""` + RbacService service.RBACService `inject:""` } -// GetWebService get web service -func (dt *TargetWebService) GetWebService() *restful.WebService { +// GetWebServiceRoute get web service +func (dt *TargetAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/targets"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -63,7 +59,7 @@ func (dt *TargetWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/").To(dt.listTargets). Doc("list Target"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(dt.rbacUsecase.CheckPerm("target", "list")). + Filter(dt.RbacService.CheckPerm("target", "list")). Param(ws.QueryParameter("page", "Page for paging").DataType("integer")). Param(ws.QueryParameter("pageSize", "PageSize for paging").DataType("integer")). Param(ws.QueryParameter("project", "list targets by project name").DataType("string")). @@ -74,7 +70,7 @@ func (dt *TargetWebService) GetWebService() *restful.WebService { Doc("create Target"). Metadata(restfulspec.KeyOpenAPITags, tags). Reads(apis.CreateTargetRequest{}). - Filter(dt.rbacUsecase.CheckPerm("target", "create")). + Filter(dt.RbacService.CheckPerm("target", "create")). Returns(200, "create success", apis.DetailTargetResponse{}). Returns(400, "create failure", bcode.Bcode{}). Writes(apis.DetailTargetResponse{}).Do(returns200, returns500)) @@ -84,7 +80,7 @@ func (dt *TargetWebService) GetWebService() *restful.WebService { Param(ws.PathParameter("targetName", "identifier of the Target.").DataType("string")). Metadata(restfulspec.KeyOpenAPITags, tags). Filter(dt.targetCheckFilter). - Filter(dt.rbacUsecase.CheckPerm("target", "detail")). + Filter(dt.RbacService.CheckPerm("target", "detail")). Returns(200, "create success", apis.DetailTargetResponse{}). Writes(apis.DetailTargetResponse{}).Do(returns200, returns500)) @@ -94,7 +90,7 @@ func (dt *TargetWebService) GetWebService() *restful.WebService { Filter(dt.targetCheckFilter). Param(ws.PathParameter("targetName", "identifier of the Target").DataType("string")). Reads(apis.UpdateTargetRequest{}). - Filter(dt.rbacUsecase.CheckPerm("target", "update")). + Filter(dt.RbacService.CheckPerm("target", "update")). Returns(200, "OK", apis.DetailTargetResponse{}). Writes(apis.DetailTargetResponse{}).Do(returns200, returns500)) @@ -102,7 +98,7 @@ func (dt *TargetWebService) GetWebService() *restful.WebService { Doc("deletet Target"). Metadata(restfulspec.KeyOpenAPITags, tags). Filter(dt.targetCheckFilter). - Filter(dt.rbacUsecase.CheckPerm("target", "delete")). + Filter(dt.RbacService.CheckPerm("target", "delete")). Param(ws.PathParameter("targetName", "identifier of the Target").DataType("string")). Returns(200, "OK", apis.EmptyResponse{}). Writes(apis.EmptyResponse{}).Do(returns200, returns500)) @@ -111,7 +107,7 @@ func (dt *TargetWebService) GetWebService() *restful.WebService { return ws } -func (dt *TargetWebService) createTarget(req *restful.Request, res *restful.Response) { +func (dt *TargetAPIInterface) createTarget(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var createReq apis.CreateTargetRequest if err := req.ReadEntity(&createReq); err != nil { @@ -122,8 +118,8 @@ func (dt *TargetWebService) createTarget(req *restful.Request, res *restful.Resp bcode.ReturnError(req, res, err) return } - // Call the usecase layer code - TargetDetail, err := dt.TargetUsecase.CreateTarget(req.Request.Context(), createReq) + // Call the domain layer code + TargetDetail, err := dt.TargetService.CreateTarget(req.Request.Context(), createReq) if err != nil { log.Logger.Errorf("create -target failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -136,8 +132,8 @@ func (dt *TargetWebService) createTarget(req *restful.Request, res *restful.Resp } } -func (dt *TargetWebService) targetCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) { - Target, err := dt.TargetUsecase.GetTarget(req.Request.Context(), req.PathParameter("targetName")) +func (dt *TargetAPIInterface) targetCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) { + Target, err := dt.TargetService.GetTarget(req.Request.Context(), req.PathParameter("targetName")) if err != nil { bcode.ReturnError(req, res, err) return @@ -146,9 +142,9 @@ func (dt *TargetWebService) targetCheckFilter(req *restful.Request, res *restful chain.ProcessFilter(req, res) } -func (dt *TargetWebService) detailTarget(req *restful.Request, res *restful.Response) { +func (dt *TargetAPIInterface) detailTarget(req *restful.Request, res *restful.Response) { Target := req.Request.Context().Value(&apis.CtxKeyTarget).(*model.Target) - detail, err := dt.TargetUsecase.DetailTarget(req.Request.Context(), Target) + detail, err := dt.TargetService.DetailTarget(req.Request.Context(), Target) if err != nil { bcode.ReturnError(req, res, err) return @@ -159,7 +155,7 @@ func (dt *TargetWebService) detailTarget(req *restful.Request, res *restful.Resp } } -func (dt *TargetWebService) updateTarget(req *restful.Request, res *restful.Response) { +func (dt *TargetAPIInterface) updateTarget(req *restful.Request, res *restful.Response) { Target := req.Request.Context().Value(&apis.CtxKeyTarget).(*model.Target) // Verify the validity of parameters var updateReq apis.UpdateTargetRequest @@ -171,7 +167,7 @@ func (dt *TargetWebService) updateTarget(req *restful.Request, res *restful.Resp bcode.ReturnError(req, res, err) return } - detail, err := dt.TargetUsecase.UpdateTarget(req.Request.Context(), Target, updateReq) + detail, err := dt.TargetService.UpdateTarget(req.Request.Context(), Target, updateReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -182,10 +178,10 @@ func (dt *TargetWebService) updateTarget(req *restful.Request, res *restful.Resp } } -func (dt *TargetWebService) deleteTarget(req *restful.Request, res *restful.Response) { +func (dt *TargetAPIInterface) deleteTarget(req *restful.Request, res *restful.Response) { TargetName := req.PathParameter("targetName") // Target in use, can't be deleted - applications, err := dt.applicationUsecase.ListApplications(req.Request.Context(), apis.ListApplicationOptions{TargetName: TargetName}) + applications, err := dt.ApplicationService.ListApplications(req.Request.Context(), apis.ListApplicationOptions{TargetName: TargetName}) if err != nil { if !errors.Is(err, datastore.ErrRecordNotExist) { bcode.ReturnError(req, res, err) @@ -196,7 +192,7 @@ func (dt *TargetWebService) deleteTarget(req *restful.Request, res *restful.Resp bcode.ReturnError(req, res, bcode.ErrTargetInUseCantDeleted) return } - if err := dt.TargetUsecase.DeleteTarget(req.Request.Context(), TargetName); err != nil { + if err := dt.TargetService.DeleteTarget(req.Request.Context(), TargetName); err != nil { bcode.ReturnError(req, res, err) return } @@ -206,13 +202,13 @@ func (dt *TargetWebService) deleteTarget(req *restful.Request, res *restful.Resp } } -func (dt *TargetWebService) listTargets(req *restful.Request, res *restful.Response) { +func (dt *TargetAPIInterface) listTargets(req *restful.Request, res *restful.Response) { page, pageSize, err := utils.ExtractPagingParams(req, minPageSize, maxPageSize) if err != nil { bcode.ReturnError(req, res, err) return } - Targets, err := dt.TargetUsecase.ListTargets(req.Request.Context(), page, pageSize, req.QueryParameter("project")) + Targets, err := dt.TargetService.ListTargets(req.Request.Context(), page, pageSize, req.QueryParameter("project")) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/rest/webservice/user.go b/pkg/apiserver/interfaces/api/user.go similarity index 71% rename from pkg/apiserver/rest/webservice/user.go rename to pkg/apiserver/interfaces/api/user.go index 0687f6586..eb830ad3d 100644 --- a/pkg/apiserver/rest/webservice/user.go +++ b/pkg/apiserver/interfaces/api/user.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( "context" @@ -22,27 +22,24 @@ import ( restfulspec "github.com/emicklei/go-restful-openapi/v2" "github.com/emicklei/go-restful/v3" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" ) -type userWebService struct { - userUsecase usecase.UserUsecase - rbacUsecase usecase.RBACUsecase +type userAPIInterface struct { + UserService service.UserService `inject:""` + RbacService service.RBACService `inject:""` } -// NewUserWebService is the webservice of user -func NewUserWebService(userUsecase usecase.UserUsecase, rbacUsecase usecase.RBACUsecase) WebService { - return &userWebService{ - userUsecase: userUsecase, - rbacUsecase: rbacUsecase, - } +// NewUserAPIInterface is the APIInterface of user +func NewUserAPIInterface() Interface { + return &userAPIInterface{} } -func (c *userWebService) GetWebService() *restful.WebService { +func (c *userAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/users"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -54,7 +51,7 @@ func (c *userWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/").To(c.listUser). Doc("list users"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("user", "list")). + Filter(c.RbacService.CheckPerm("user", "list")). Param(ws.QueryParameter("page", "query the page number").DataType("integer")). Param(ws.QueryParameter("pageSize", "query the page size number").DataType("integer")). Param(ws.QueryParameter("name", "fuzzy search based on name").DataType("string")). @@ -66,7 +63,7 @@ func (c *userWebService) GetWebService() *restful.WebService { ws.Route(ws.POST("/").To(c.createUser). Doc("create a user"). - Filter(c.rbacUsecase.CheckPerm("user", "create")). + Filter(c.RbacService.CheckPerm("user", "create")). Metadata(restfulspec.KeyOpenAPITags, tags). Reads(apis.CreateUserRequest{}). Returns(200, "OK", apis.UserBase{}). @@ -76,7 +73,7 @@ func (c *userWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{username}").To(c.detailUser). Doc("get user detail"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("user", "detail")). + Filter(c.RbacService.CheckPerm("user", "detail")). Filter(c.userCheckFilter). Returns(200, "OK", apis.DetailUserResponse{}). Returns(400, "Bad Request", bcode.Bcode{}). @@ -85,7 +82,7 @@ func (c *userWebService) GetWebService() *restful.WebService { ws.Route(ws.PUT("/{username}").To(c.updateUser). Doc("update a user's alias or password"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("user", "update")). + Filter(c.RbacService.CheckPerm("user", "update")). Filter(c.userCheckFilter). Returns(200, "OK", apis.UserBase{}). Returns(400, "Bad Request", bcode.Bcode{}). @@ -94,7 +91,7 @@ func (c *userWebService) GetWebService() *restful.WebService { ws.Route(ws.DELETE("/{username}").To(c.deleteUser). Doc("delete a user"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("user", "delete")). + Filter(c.RbacService.CheckPerm("user", "delete")). Returns(200, "OK", apis.EmptyResponse{}). Returns(400, "Bad Request", bcode.Bcode{}). Writes(apis.EmptyResponse{})) @@ -102,7 +99,7 @@ func (c *userWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{username}/disable").To(c.disableUser). Doc("disable a user"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("user", "disable")). + Filter(c.RbacService.CheckPerm("user", "disable")). Filter(c.userCheckFilter). Returns(200, "OK", apis.EmptyResponse{}). Returns(400, "Bad Request", bcode.Bcode{}). @@ -111,7 +108,7 @@ func (c *userWebService) GetWebService() *restful.WebService { ws.Route(ws.GET("/{username}/enable").To(c.enableUser). Doc("enable a user"). Metadata(restfulspec.KeyOpenAPITags, tags). - Filter(c.rbacUsecase.CheckPerm("user", "enable")). + Filter(c.RbacService.CheckPerm("user", "enable")). Filter(c.userCheckFilter). Returns(200, "OK", apis.EmptyResponse{}). Returns(400, "Bad Request", bcode.Bcode{}). @@ -121,8 +118,8 @@ func (c *userWebService) GetWebService() *restful.WebService { return ws } -func (c *userWebService) userCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) { - user, err := c.userUsecase.GetUser(req.Request.Context(), req.PathParameter("username")) +func (c *userAPIInterface) userCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) { + user, err := c.UserService.GetUser(req.Request.Context(), req.PathParameter("username")) if err != nil { bcode.ReturnError(req, res, err) return @@ -131,7 +128,7 @@ func (c *userWebService) userCheckFilter(req *restful.Request, res *restful.Resp chain.ProcessFilter(req, res) } -func (c *userWebService) createUser(req *restful.Request, res *restful.Response) { +func (c *userAPIInterface) createUser(req *restful.Request, res *restful.Response) { var createReq apis.CreateUserRequest if err := req.ReadEntity(&createReq); err != nil { bcode.ReturnError(req, res, err) @@ -141,7 +138,7 @@ func (c *userWebService) createUser(req *restful.Request, res *restful.Response) bcode.ReturnError(req, res, err) return } - resp, err := c.userUsecase.CreateUser(req.Request.Context(), createReq) + resp, err := c.UserService.CreateUser(req.Request.Context(), createReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -152,9 +149,9 @@ func (c *userWebService) createUser(req *restful.Request, res *restful.Response) } } -func (c *userWebService) detailUser(req *restful.Request, res *restful.Response) { +func (c *userAPIInterface) detailUser(req *restful.Request, res *restful.Response) { user := req.Request.Context().Value(&apis.CtxKeyUser).(*model.User) - resp, err := c.userUsecase.DetailUser(req.Request.Context(), user) + resp, err := c.UserService.DetailUser(req.Request.Context(), user) if err != nil { bcode.ReturnError(req, res, err) return @@ -165,8 +162,8 @@ func (c *userWebService) detailUser(req *restful.Request, res *restful.Response) } } -func (c *userWebService) deleteUser(req *restful.Request, res *restful.Response) { - err := c.userUsecase.DeleteUser(req.Request.Context(), req.PathParameter("username")) +func (c *userAPIInterface) deleteUser(req *restful.Request, res *restful.Response) { + err := c.UserService.DeleteUser(req.Request.Context(), req.PathParameter("username")) if err != nil { bcode.ReturnError(req, res, err) return @@ -177,13 +174,13 @@ func (c *userWebService) deleteUser(req *restful.Request, res *restful.Response) } } -func (c *userWebService) listUser(req *restful.Request, res *restful.Response) { +func (c *userAPIInterface) listUser(req *restful.Request, res *restful.Response) { page, pageSize, err := utils.ExtractPagingParams(req, minPageSize, maxPageSize) if err != nil { bcode.ReturnError(req, res, err) return } - resp, err := c.userUsecase.ListUsers(req.Request.Context(), page, pageSize, apis.ListUserOptions{ + resp, err := c.UserService.ListUsers(req.Request.Context(), page, pageSize, apis.ListUserOptions{ Name: req.QueryParameter("name"), Alias: req.QueryParameter("alias"), Email: req.QueryParameter("email"), @@ -198,7 +195,7 @@ func (c *userWebService) listUser(req *restful.Request, res *restful.Response) { } } -func (c *userWebService) updateUser(req *restful.Request, res *restful.Response) { +func (c *userAPIInterface) updateUser(req *restful.Request, res *restful.Response) { user := req.Request.Context().Value(&apis.CtxKeyUser).(*model.User) var updateReq apis.UpdateUserRequest if err := req.ReadEntity(&updateReq); err != nil { @@ -209,7 +206,7 @@ func (c *userWebService) updateUser(req *restful.Request, res *restful.Response) bcode.ReturnError(req, res, err) return } - resp, err := c.userUsecase.UpdateUser(req.Request.Context(), user, updateReq) + resp, err := c.UserService.UpdateUser(req.Request.Context(), user, updateReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -220,9 +217,9 @@ func (c *userWebService) updateUser(req *restful.Request, res *restful.Response) } } -func (c *userWebService) disableUser(req *restful.Request, res *restful.Response) { +func (c *userAPIInterface) disableUser(req *restful.Request, res *restful.Response) { user := req.Request.Context().Value(&apis.CtxKeyUser).(*model.User) - err := c.userUsecase.DisableUser(req.Request.Context(), user) + err := c.UserService.DisableUser(req.Request.Context(), user) if err != nil { bcode.ReturnError(req, res, err) return @@ -233,9 +230,9 @@ func (c *userWebService) disableUser(req *restful.Request, res *restful.Response } } -func (c *userWebService) enableUser(req *restful.Request, res *restful.Response) { +func (c *userAPIInterface) enableUser(req *restful.Request, res *restful.Response) { user := req.Request.Context().Value(&apis.CtxKeyUser).(*model.User) - err := c.userUsecase.EnableUser(req.Request.Context(), user) + err := c.UserService.EnableUser(req.Request.Context(), user) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/rest/webservice/validate.go b/pkg/apiserver/interfaces/api/validate.go similarity index 95% rename from pkg/apiserver/rest/webservice/validate.go rename to pkg/apiserver/interfaces/api/validate.go index ec7012474..4c38f9624 100644 --- a/pkg/apiserver/rest/webservice/validate.go +++ b/pkg/apiserver/interfaces/api/validate.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( "regexp" @@ -22,7 +22,7 @@ import ( "github.com/go-playground/validator/v10" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" ) var validate = validator.New() @@ -58,7 +58,7 @@ func init() { // ValidatePayloadType check PayloadType func ValidatePayloadType(fl validator.FieldLevel) bool { value := fl.Field().String() - for _, v := range usecase.WebhookHandlers { + for _, v := range service.WebhookHandlers { if v == value { return true } diff --git a/pkg/apiserver/rest/webservice/validate_test.go b/pkg/apiserver/interfaces/api/validate_test.go similarity index 97% rename from pkg/apiserver/rest/webservice/validate_test.go rename to pkg/apiserver/interfaces/api/validate_test.go index 05566e915..a95074b9b 100644 --- a/pkg/apiserver/rest/webservice/validate_test.go +++ b/pkg/apiserver/interfaces/api/validate_test.go @@ -14,14 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( "github.com/google/go-cmp/cmp" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" ) var _ = Describe("Test validate function", func() { diff --git a/pkg/apiserver/rest/webservice/velaql.go b/pkg/apiserver/interfaces/api/velaql.go similarity index 66% rename from pkg/apiserver/rest/webservice/velaql.go rename to pkg/apiserver/interfaces/api/velaql.go index 77d01a1a4..56905a569 100644 --- a/pkg/apiserver/rest/webservice/velaql.go +++ b/pkg/apiserver/interfaces/api/velaql.go @@ -14,31 +14,28 @@ limitations under the License. */ -package webservice +package api import ( restfulspec "github.com/emicklei/go-restful-openapi/v2" "github.com/emicklei/go-restful/v3" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" ) -type velaQLWebService struct { - velaQLUsecase usecase.VelaQLUsecase - rbacUsecase usecase.RBACUsecase +type velaQLAPIInterface struct { + VelaQLService service.VelaQLService `inject:""` + RbacService service.RBACService `inject:""` } -// NewVelaQLWebService new velaQL webservice -func NewVelaQLWebService(velaQLUsecase usecase.VelaQLUsecase, rbacUsecase usecase.RBACUsecase) WebService { - return &velaQLWebService{ - velaQLUsecase: velaQLUsecase, - rbacUsecase: rbacUsecase, - } +// NewVelaQLAPIInterface new velaQL APIInterface +func NewVelaQLAPIInterface() Interface { + return &velaQLAPIInterface{} } -func (v *velaQLWebService) GetWebService() *restful.WebService { +func (v *velaQLAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/query"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -51,7 +48,7 @@ func (v *velaQLWebService) GetWebService() *restful.WebService { Doc("use velaQL to query resource status"). Metadata(restfulspec.KeyOpenAPITags, tags). // TODO: VelaQL is an open data query API that is currently not compatible with RBAC. - // Filter(v.rbacUsecase.CheckPerm("application", "detail")). + // Filter(v.RbacService.CheckPerm("application", "detail")). Param(ws.QueryParameter("velaql", "velaql query statement").DataType("string")). Returns(200, "OK", apis.VelaQLViewResponse{}). Returns(400, "Bad Request", bcode.Bcode{}). @@ -61,10 +58,10 @@ func (v *velaQLWebService) GetWebService() *restful.WebService { return ws } -func (v *velaQLWebService) queryView(req *restful.Request, res *restful.Response) { +func (v *velaQLAPIInterface) queryView(req *restful.Request, res *restful.Response) { velaQL := req.QueryParameter("velaql") - qlResp, err := v.velaQLUsecase.QueryView(req.Request.Context(), velaQL) + qlResp, err := v.VelaQLService.QueryView(req.Request.Context(), velaQL) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/rest/webservice/webhook.go b/pkg/apiserver/interfaces/api/webhook.go similarity index 64% rename from pkg/apiserver/rest/webservice/webhook.go rename to pkg/apiserver/interfaces/api/webhook.go index e7b96ef93..8e83c2f49 100644 --- a/pkg/apiserver/rest/webservice/webhook.go +++ b/pkg/apiserver/interfaces/api/webhook.go @@ -14,31 +14,28 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( restfulspec "github.com/emicklei/go-restful-openapi/v2" "github.com/emicklei/go-restful/v3" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" ) -type webhookWebService struct { - webhookUsecase usecase.WebhookUsecase - applicationUsecase usecase.ApplicationUsecase +type webhookAPIInterface struct { + WebhookService service.WebhookService `inject:""` + ApplicationService service.ApplicationService `inject:""` } -// NewWebhookWebService new application manage webservice -func NewWebhookWebService(webhookUsecase usecase.WebhookUsecase, applicationUsecase usecase.ApplicationUsecase) WebService { - return &webhookWebService{ - webhookUsecase: webhookUsecase, - applicationUsecase: applicationUsecase, - } +// NewWebhookAPIInterface new application manage APIInterface +func NewWebhookAPIInterface() Interface { + return &webhookAPIInterface{} } -func (c *webhookWebService) GetWebService() *restful.WebService { +func (c *webhookAPIInterface) GetWebServiceRoute() *restful.WebService { ws := new(restful.WebService) ws.Path(versionPrefix+"/webhook"). Consumes(restful.MIME_XML, restful.MIME_JSON). @@ -58,8 +55,8 @@ func (c *webhookWebService) GetWebService() *restful.WebService { return ws } -func (c *webhookWebService) handleApplicationWebhook(req *restful.Request, res *restful.Response) { - base, err := c.webhookUsecase.HandleApplicationWebhook(req.Request.Context(), req.PathParameter("token"), req) +func (c *webhookAPIInterface) handleApplicationWebhook(req *restful.Request, res *restful.Response) { + base, err := c.WebhookService.HandleApplicationWebhook(req.Request.Context(), req.PathParameter("token"), req) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/rest/webservice/workflow.go b/pkg/apiserver/interfaces/api/workflow.go similarity index 67% rename from pkg/apiserver/rest/webservice/workflow.go rename to pkg/apiserver/interfaces/api/workflow.go index 60f48b56a..84124d0dd 100644 --- a/pkg/apiserver/rest/webservice/workflow.go +++ b/pkg/apiserver/interfaces/api/workflow.go @@ -14,29 +14,35 @@ See the License for the specific language governing permissions and limitations under the License. */ -package webservice +package api import ( "context" restful "github.com/emicklei/go-restful/v3" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" ) -type workflowWebService struct { - workflowUsecase usecase.WorkflowUsecase - applicationUsecase usecase.ApplicationUsecase +// WorkflowAPIInterface workflow api +type WorkflowAPIInterface struct { + WorkflowService service.WorkflowService `inject:""` + ApplicationService service.ApplicationService `inject:""` } -func (w *workflowWebService) workflowCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) { +// NewWorkflowAPIInterface new workflow api interface +func NewWorkflowAPIInterface() interface{} { + return &WorkflowAPIInterface{} +} + +func (w *WorkflowAPIInterface) workflowCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - workflow, err := w.workflowUsecase.GetWorkflow(req.Request.Context(), app, req.PathParameter("workflowName")) + workflow, err := w.WorkflowService.GetWorkflow(req.Request.Context(), app, req.PathParameter("workflowName")) if err != nil { bcode.ReturnError(req, res, err) return @@ -45,9 +51,9 @@ func (w *workflowWebService) workflowCheckFilter(req *restful.Request, res *rest chain.ProcessFilter(req, res) } -func (w *workflowWebService) listApplicationWorkflows(req *restful.Request, res *restful.Response) { +func (w *WorkflowAPIInterface) listApplicationWorkflows(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - workflows, err := w.workflowUsecase.ListApplicationWorkflow(req.Request.Context(), app) + workflows, err := w.WorkflowService.ListApplicationWorkflow(req.Request.Context(), app) if err != nil { bcode.ReturnError(req, res, err) return @@ -58,7 +64,7 @@ func (w *workflowWebService) listApplicationWorkflows(req *restful.Request, res } } -func (w *workflowWebService) createOrUpdateApplicationWorkflow(req *restful.Request, res *restful.Response) { +func (w *WorkflowAPIInterface) createOrUpdateApplicationWorkflow(req *restful.Request, res *restful.Response) { // Verify the validity of parameters var createReq apis.CreateWorkflowRequest if err := req.ReadEntity(&createReq); err != nil { @@ -70,8 +76,8 @@ func (w *workflowWebService) createOrUpdateApplicationWorkflow(req *restful.Requ return } app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - // Call the usecase layer code - workflowDetail, err := w.workflowUsecase.CreateOrUpdateWorkflow(req.Request.Context(), app, createReq) + // Call the domain service layer code + workflowDetail, err := w.WorkflowService.CreateOrUpdateWorkflow(req.Request.Context(), app, createReq) if err != nil { log.Logger.Errorf("create application failure %s", err.Error()) bcode.ReturnError(req, res, err) @@ -85,9 +91,9 @@ func (w *workflowWebService) createOrUpdateApplicationWorkflow(req *restful.Requ } } -func (w *workflowWebService) detailWorkflow(req *restful.Request, res *restful.Response) { +func (w *WorkflowAPIInterface) detailWorkflow(req *restful.Request, res *restful.Response) { workflow := req.Request.Context().Value(&apis.CtxKeyWorkflow).(*model.Workflow) - detail, err := w.workflowUsecase.DetailWorkflow(req.Request.Context(), workflow) + detail, err := w.WorkflowService.DetailWorkflow(req.Request.Context(), workflow) if err != nil { bcode.ReturnError(req, res, err) return @@ -98,7 +104,7 @@ func (w *workflowWebService) detailWorkflow(req *restful.Request, res *restful.R } } -func (w *workflowWebService) updateWorkflow(req *restful.Request, res *restful.Response) { +func (w *WorkflowAPIInterface) updateWorkflow(req *restful.Request, res *restful.Response) { workflow := req.Request.Context().Value(&apis.CtxKeyWorkflow).(*model.Workflow) // Verify the validity of parameters var updateReq apis.UpdateWorkflowRequest @@ -110,7 +116,7 @@ func (w *workflowWebService) updateWorkflow(req *restful.Request, res *restful.R bcode.ReturnError(req, res, err) return } - detail, err := w.workflowUsecase.UpdateWorkflow(req.Request.Context(), workflow, updateReq) + detail, err := w.WorkflowService.UpdateWorkflow(req.Request.Context(), workflow, updateReq) if err != nil { bcode.ReturnError(req, res, err) return @@ -121,9 +127,9 @@ func (w *workflowWebService) updateWorkflow(req *restful.Request, res *restful.R } } -func (w *workflowWebService) deleteWorkflow(req *restful.Request, res *restful.Response) { +func (w *WorkflowAPIInterface) deleteWorkflow(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) - if err := w.workflowUsecase.DeleteWorkflow(req.Request.Context(), app, req.PathParameter("workflowName")); err != nil { + if err := w.WorkflowService.DeleteWorkflow(req.Request.Context(), app, req.PathParameter("workflowName")); err != nil { bcode.ReturnError(req, res, err) return } @@ -133,14 +139,14 @@ func (w *workflowWebService) deleteWorkflow(req *restful.Request, res *restful.R } } -func (w *workflowWebService) listWorkflowRecords(req *restful.Request, res *restful.Response) { +func (w *WorkflowAPIInterface) listWorkflowRecords(req *restful.Request, res *restful.Response) { page, pageSize, err := utils.ExtractPagingParams(req, minPageSize, maxPageSize) if err != nil { bcode.ReturnError(req, res, err) return } workflow := req.Request.Context().Value(&apis.CtxKeyWorkflow).(*model.Workflow) - records, err := w.workflowUsecase.ListWorkflowRecords(req.Request.Context(), workflow, page, pageSize) + records, err := w.WorkflowService.ListWorkflowRecords(req.Request.Context(), workflow, page, pageSize) if err != nil { bcode.ReturnError(req, res, err) return @@ -152,9 +158,9 @@ func (w *workflowWebService) listWorkflowRecords(req *restful.Request, res *rest } } -func (w *workflowWebService) detailWorkflowRecord(req *restful.Request, res *restful.Response) { +func (w *WorkflowAPIInterface) detailWorkflowRecord(req *restful.Request, res *restful.Response) { workflow := req.Request.Context().Value(&apis.CtxKeyWorkflow).(*model.Workflow) - record, err := w.workflowUsecase.DetailWorkflowRecord(req.Request.Context(), workflow, req.PathParameter("record")) + record, err := w.WorkflowService.DetailWorkflowRecord(req.Request.Context(), workflow, req.PathParameter("record")) if err != nil { bcode.ReturnError(req, res, err) return @@ -166,10 +172,10 @@ func (w *workflowWebService) detailWorkflowRecord(req *restful.Request, res *res } } -func (w *workflowWebService) resumeWorkflowRecord(req *restful.Request, res *restful.Response) { +func (w *WorkflowAPIInterface) resumeWorkflowRecord(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) workflow := req.Request.Context().Value(&apis.CtxKeyWorkflow).(*model.Workflow) - err := w.workflowUsecase.ResumeRecord(req.Request.Context(), app, workflow, req.PathParameter("record")) + err := w.WorkflowService.ResumeRecord(req.Request.Context(), app, workflow, req.PathParameter("record")) if err != nil { bcode.ReturnError(req, res, err) return @@ -180,10 +186,10 @@ func (w *workflowWebService) resumeWorkflowRecord(req *restful.Request, res *res } } -func (w *workflowWebService) terminateWorkflowRecord(req *restful.Request, res *restful.Response) { +func (w *WorkflowAPIInterface) terminateWorkflowRecord(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) workflow := req.Request.Context().Value(&apis.CtxKeyWorkflow).(*model.Workflow) - err := w.workflowUsecase.TerminateRecord(req.Request.Context(), app, workflow, req.PathParameter("record")) + err := w.WorkflowService.TerminateRecord(req.Request.Context(), app, workflow, req.PathParameter("record")) if err != nil { bcode.ReturnError(req, res, err) return @@ -194,10 +200,10 @@ func (w *workflowWebService) terminateWorkflowRecord(req *restful.Request, res * } } -func (w *workflowWebService) rollbackWorkflowRecord(req *restful.Request, res *restful.Response) { +func (w *WorkflowAPIInterface) rollbackWorkflowRecord(req *restful.Request, res *restful.Response) { app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application) workflow := req.Request.Context().Value(&apis.CtxKeyWorkflow).(*model.Workflow) - err := w.workflowUsecase.RollbackRecord(req.Request.Context(), app, workflow, req.PathParameter("record"), req.QueryParameter("rollbackVersion")) + err := w.WorkflowService.RollbackRecord(req.Request.Context(), app, workflow, req.PathParameter("record"), req.QueryParameter("rollbackVersion")) if err != nil { bcode.ReturnError(req, res, err) return diff --git a/pkg/apiserver/rest/usecase/converter.go b/pkg/apiserver/rest/usecase/converter.go deleted file mode 100644 index 72c29fcd7..000000000 --- a/pkg/apiserver/rest/usecase/converter.go +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright 2021 The KubeVela 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 usecase - -import ( - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" -) - -func convertPolicyModelToBase(policy *model.ApplicationPolicy) *apisv1.PolicyBase { - pb := &apisv1.PolicyBase{ - Name: policy.Name, - Type: policy.Type, - Properties: policy.Properties, - Description: policy.Description, - Creator: policy.Creator, - CreateTime: policy.CreateTime, - UpdateTime: policy.UpdateTime, - EnvName: policy.EnvName, - } - return pb -} - -func convertWorkflowBase(workflow *model.Workflow) apisv1.WorkflowBase { - var steps []apisv1.WorkflowStep - for _, step := range workflow.Steps { - steps = append(steps, convertFromWorkflowStepModel(step)) - } - return apisv1.WorkflowBase{ - Name: workflow.Name, - Alias: workflow.Alias, - Description: workflow.Description, - Default: convertBool(workflow.Default), - EnvName: workflow.EnvName, - CreateTime: workflow.CreateTime, - UpdateTime: workflow.UpdateTime, - Steps: steps, - } -} - -// convertAPIStep2ModelStep will convert api types of workflow step to model type -func convertAPIStep2ModelStep(apiSteps []apisv1.WorkflowStep) ([]model.WorkflowStep, error) { - var steps []model.WorkflowStep - for _, step := range apiSteps { - properties, err := model.NewJSONStructByString(step.Properties) - if err != nil { - log.Logger.Errorf("parse trait properties failire %w", err) - return nil, bcode.ErrInvalidProperties - } - steps = append(steps, model.WorkflowStep{ - Name: step.Name, - Alias: step.Alias, - Description: step.Description, - DependsOn: step.DependsOn, - Type: step.Type, - Inputs: step.Inputs, - Outputs: step.Outputs, - Properties: properties, - }) - } - return steps, nil -} diff --git a/pkg/apiserver/rest/usecase/envbinding.go b/pkg/apiserver/rest/usecase/envbinding.go deleted file mode 100644 index 1120c8645..000000000 --- a/pkg/apiserver/rest/usecase/envbinding.go +++ /dev/null @@ -1,425 +0,0 @@ -/* -Copyright 2021 The KubeVela 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 usecase - -import ( - "context" - "errors" - "fmt" - - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" - utils2 "github.com/oam-dev/kubevela/pkg/utils" -) - -const ( - // Deploy2Env deploy app to target cluster, suitable for common applications - Deploy2Env string = "deploy2env" - // DeployCloudResource deploy app to local and copy secret to target cluster, suitable for cloud application. - DeployCloudResource string = "deploy-cloud-resource" - // TerraformWorkloadType cloud application - TerraformWorkloadType string = "configurations.terraform.core.oam.dev" - // TerraformWorkloadKind terraform workload kind - TerraformWorkloadKind string = "Configuration" -) - -// EnvBindingUsecase envbinding usecase -type EnvBindingUsecase interface { - GetEnvBindings(ctx context.Context, app *model.Application) ([]*apisv1.EnvBindingBase, error) - GetEnvBinding(ctx context.Context, app *model.Application, envName string) (*model.EnvBinding, error) - CreateEnvBinding(ctx context.Context, app *model.Application, env apisv1.CreateApplicationEnvbindingRequest) (*apisv1.EnvBinding, error) - BatchCreateEnvBinding(ctx context.Context, app *model.Application, env apisv1.EnvBindingList) error - UpdateEnvBinding(ctx context.Context, app *model.Application, envName string, diff apisv1.PutApplicationEnvBindingRequest) (*apisv1.DetailEnvBindingResponse, error) - DeleteEnvBinding(ctx context.Context, app *model.Application, envName string) error - BatchDeleteEnvBinding(ctx context.Context, app *model.Application) error - DetailEnvBinding(ctx context.Context, app *model.Application, envBinding *model.EnvBinding) (*apisv1.DetailEnvBindingResponse, error) - ApplicationEnvRecycle(ctx context.Context, appModel *model.Application, envBinding *model.EnvBinding) error -} - -type envBindingUsecaseImpl struct { - ds datastore.DataStore - workflowUsecase WorkflowUsecase - envUsecase EnvUsecase - definitionUsecase DefinitionUsecase - kubeClient client.Client -} - -// NewEnvBindingUsecase new envBinding usecase -func NewEnvBindingUsecase(ds datastore.DataStore, workflowUsecase WorkflowUsecase, definitionUsecase DefinitionUsecase, envUsecase EnvUsecase) EnvBindingUsecase { - kubecli, err := clients.GetKubeClient() - if err != nil { - log.Logger.Fatalf("get kubeclient failure %s", err.Error()) - } - return &envBindingUsecaseImpl{ - ds: ds, - workflowUsecase: workflowUsecase, - definitionUsecase: definitionUsecase, - kubeClient: kubecli, - envUsecase: envUsecase, - } -} - -func pickEnv(envs []*model.Env, name string) (*model.Env, error) { - for _, e := range envs { - if e.Name == name { - return e, nil - } - } - return nil, bcode.ErrEnvNotExisted -} - -func listFullEnvBinding(ctx context.Context, ds datastore.DataStore, option envListOption) ([]*apisv1.EnvBindingBase, error) { - envBindings, err := listEnvBindings(ctx, ds, option) - if err != nil { - return nil, bcode.ErrEnvBindingsNotExist - } - targets, err := listTarget(ctx, ds, option.projectName, nil) - if err != nil { - return nil, err - } - var listOption *datastore.ListOptions - if option.projectName != "" { - listOption = &datastore.ListOptions{ - FilterOptions: datastore.FilterOptions{ - In: []datastore.InQueryOption{ - { - Key: "project", - Values: []string{option.projectName}, - }, - }, - }, - } - } - envs, err := listEnvs(ctx, ds, listOption) - if err != nil { - return nil, err - } - var list []*apisv1.EnvBindingBase - for _, eb := range envBindings { - env, err := pickEnv(envs, eb.Name) - if err != nil { - log.Logger.Errorf("envbinding invalid %s", err.Error()) - continue - } - list = append(list, convertEnvBindingModelToBase(eb, env, targets)) - } - return list, nil -} - -func (e *envBindingUsecaseImpl) GetEnvBindings(ctx context.Context, app *model.Application) ([]*apisv1.EnvBindingBase, error) { - full, err := listFullEnvBinding(ctx, e.ds, envListOption{appPrimaryKey: app.PrimaryKey(), projectName: app.Project}) - if err != nil { - log.Logger.Errorf("list envbinding for app %s err: %v\n", app.Name, err) - return nil, err - } - return full, nil -} - -func (e *envBindingUsecaseImpl) GetEnvBinding(ctx context.Context, app *model.Application, envName string) (*model.EnvBinding, error) { - envBinding, err := e.getBindingByEnv(ctx, app, envName) - if err != nil { - if errors.Is(err, datastore.ErrRecordNotExist) { - return nil, bcode.ErrEnvBindingsNotExist - } - return nil, err - } - return envBinding, nil -} - -// CheckAppEnvBindingsContainTarget check envbinding contain target -func CheckAppEnvBindingsContainTarget(envBindings []*apisv1.EnvBindingBase, targetName string) (bool, error) { - var filteredList []*apisv1.EnvBindingBase - for _, envBinding := range envBindings { - if utils.StringsContain(envBinding.TargetNames, targetName) { - filteredList = append(filteredList, envBinding) - } - } - return len(filteredList) > 0, nil -} - -func (e *envBindingUsecaseImpl) CreateEnvBinding(ctx context.Context, app *model.Application, envReq apisv1.CreateApplicationEnvbindingRequest) (*apisv1.EnvBinding, error) { - envBinding, err := e.getBindingByEnv(ctx, app, envReq.Name) - if err != nil { - if !errors.Is(err, datastore.ErrRecordNotExist) { - return nil, err - } - } - if envBinding != nil { - return nil, bcode.ErrEnvBindingExist - } - env, err := getEnv(ctx, e.ds, envReq.Name) - if err != nil { - return nil, err - } - envBindingModel := convertCreateReqToEnvBindingModel(app, envReq) - err = e.createEnvWorkflow(ctx, app, env, false) - if err != nil { - return nil, err - } - if err := e.ds.Add(ctx, &envBindingModel); err != nil { - return nil, err - } - - return &envReq.EnvBinding, nil -} - -func (e *envBindingUsecaseImpl) BatchCreateEnvBinding(ctx context.Context, app *model.Application, envbindings apisv1.EnvBindingList) error { - for i := range envbindings { - envBindingModel := convertToEnvBindingModel(app, *envbindings[i]) - env, err := getEnv(ctx, e.ds, envBindingModel.Name) - if err != nil { - log.Logger.Errorf("get env failure %s", err.Error()) - continue - } - if err := e.ds.Add(ctx, envBindingModel); err != nil { - log.Logger.Errorf("add envbinding %s failure %s", utils2.Sanitize(envBindingModel.Name), err.Error()) - continue - } - err = e.createEnvWorkflow(ctx, app, env, i == 0) - if err != nil { - log.Logger.Errorf("create env workflow failure %s", err.Error()) - continue - } - } - return nil -} - -func (e *envBindingUsecaseImpl) getBindingByEnv(ctx context.Context, app *model.Application, envName string) (*model.EnvBinding, error) { - var envBinding = model.EnvBinding{ - AppPrimaryKey: app.PrimaryKey(), - Name: envName, - } - err := e.ds.Get(ctx, &envBinding) - if err != nil { - return nil, err - } - return &envBinding, nil -} - -func (e *envBindingUsecaseImpl) UpdateEnvBinding(ctx context.Context, app *model.Application, envName string, _ apisv1.PutApplicationEnvBindingRequest) (*apisv1.DetailEnvBindingResponse, error) { - envBinding, err := e.getBindingByEnv(ctx, app, envName) - if err != nil { - if errors.Is(err, datastore.ErrRecordNotExist) { - return nil, bcode.ErrEnvBindingNotExist - } - return nil, err - } - env, err := getEnv(ctx, e.ds, envName) - if err != nil { - return nil, err - } - // update env - if err := e.ds.Put(ctx, envBinding); err != nil { - return nil, err - } - // update env workflow - if err := UpdateEnvWorkflow(ctx, e.kubeClient, e.ds, app, env); err != nil { - return nil, bcode.ErrEnvBindingUpdateWorkflow - } - return e.DetailEnvBinding(ctx, app, envBinding) -} - -func (e *envBindingUsecaseImpl) DeleteEnvBinding(ctx context.Context, appModel *model.Application, envName string) error { - envBinding, err := e.getBindingByEnv(ctx, appModel, envName) - if err != nil { - if errors.Is(err, datastore.ErrRecordNotExist) { - return bcode.ErrEnvBindingNotExist - } - return err - } - env, err := getEnv(ctx, e.ds, envName) - if err != nil && errors.Is(err, datastore.ErrRecordNotExist) { - return err - } - if env != nil { - var app v1beta1.Application - err = e.kubeClient.Get(ctx, types.NamespacedName{Namespace: env.Namespace, Name: appModel.Name}, &app) - if err == nil || !apierrors.IsNotFound(err) { - return bcode.ErrApplicationEnvRefusedDelete - } - if err := e.ds.Delete(ctx, &model.EnvBinding{AppPrimaryKey: appModel.PrimaryKey(), Name: envBinding.Name}); err != nil { - return err - } - } - // delete env workflow - if err := e.deleteEnvWorkflow(ctx, appModel, convertWorkflowName(envBinding.Name)); err != nil { - return fmt.Errorf("fail to clear the workflow belong to the env %w", err) - } - - // delete the topology and env-bindings policies - if err := e.ds.Delete(ctx, &model.ApplicationPolicy{AppPrimaryKey: appModel.PrimaryKey(), EnvName: envName}); err != nil && !errors.Is(err, datastore.ErrRecordNotExist) { - return fmt.Errorf("fail to clear the policies belong to the env %w", err) - } - return nil -} - -func (e *envBindingUsecaseImpl) BatchDeleteEnvBinding(ctx context.Context, app *model.Application) error { - envBindings, err := e.GetEnvBindings(ctx, app) - if err != nil { - return err - } - for _, envBinding := range envBindings { - // delete env - if err := e.ds.Delete(ctx, &model.EnvBinding{AppPrimaryKey: app.PrimaryKey(), Name: envBinding.Name}); err != nil { - return err - } - // delete env workflow - err := e.deleteEnvWorkflow(ctx, app, convertWorkflowName(envBinding.Name)) - if err != nil { - return err - } - } - return nil -} - -func (e *envBindingUsecaseImpl) createEnvWorkflow(ctx context.Context, app *model.Application, env *model.Env, isDefault bool) error { - steps, policies := GenEnvWorkflowStepsAndPolicies(ctx, e.kubeClient, e.ds, env, app) - workflow := &model.Workflow{ - Steps: steps, - Name: convertWorkflowName(env.Name), - Alias: fmt.Sprintf("%s Workflow", env.Alias), - Description: "Created automatically by envbinding.", - Default: &isDefault, - EnvName: env.Name, - AppPrimaryKey: app.PrimaryKey(), - } - log.Logger.Infof("create workflow %s for app %s", utils2.Sanitize(workflow.Name), utils2.Sanitize(app.PrimaryKey())) - if err := e.ds.Add(ctx, workflow); err != nil { - return err - } - err := e.ds.BatchAdd(ctx, policies) - if err != nil { - if err := e.workflowUsecase.DeleteWorkflow(ctx, app, convertWorkflowName(env.Name)); err != nil { - log.Logger.Errorf("fail to rollback the workflow after fail to create policies, %s", err.Error()) - } - return fmt.Errorf("fail to create policies %w", err) - } - return nil -} - -func (e *envBindingUsecaseImpl) deleteEnvWorkflow(ctx context.Context, app *model.Application, workflowName string) error { - if err := e.workflowUsecase.DeleteWorkflow(ctx, app, workflowName); err != nil { - if !errors.Is(err, bcode.ErrWorkflowNotExist) { - return err - } - } - return nil -} - -func (e *envBindingUsecaseImpl) DetailEnvBinding(ctx context.Context, app *model.Application, envBinding *model.EnvBinding) (*apisv1.DetailEnvBindingResponse, error) { - targets, err := listTarget(ctx, e.ds, "", nil) - if err != nil { - return nil, err - } - env, err := getEnv(ctx, e.ds, envBinding.Name) - if err != nil { - return nil, err - } - return &apisv1.DetailEnvBindingResponse{ - EnvBindingBase: *convertEnvBindingModelToBase(envBinding, env, targets), - }, nil -} - -func (e *envBindingUsecaseImpl) ApplicationEnvRecycle(ctx context.Context, appModel *model.Application, envBinding *model.EnvBinding) error { - env, err := getEnv(ctx, e.ds, envBinding.Name) - if err != nil { - return err - } - var app v1beta1.Application - err = e.kubeClient.Get(ctx, types.NamespacedName{Namespace: env.Namespace, Name: appModel.Name}, &app) - if err != nil { - if apierrors.IsNotFound(err) { - return nil - } - return err - } - if err := e.kubeClient.Delete(ctx, &app); err != nil { - return err - } - - if err := resetRevisionsAndRecords(ctx, e.ds, appModel.Name, "", "", ""); err != nil { - return err - } - return nil -} - -func convertCreateReqToEnvBindingModel(app *model.Application, req apisv1.CreateApplicationEnvbindingRequest) model.EnvBinding { - envBinding := model.EnvBinding{ - AppPrimaryKey: app.Name, - Name: req.Name, - AppDeployName: app.GetAppNameForSynced(), - } - return envBinding -} - -func convertEnvBindingModelToBase(envBinding *model.EnvBinding, env *model.Env, targets []*model.Target) *apisv1.EnvBindingBase { - var dtMap = make(map[string]*model.Target, len(targets)) - for _, dte := range targets { - dtMap[dte.Name] = dte - } - var envBindingTargets []apisv1.EnvBindingTarget - for _, targetName := range env.Targets { - dt := dtMap[targetName] - if dt != nil { - ebt := apisv1.EnvBindingTarget{ - NameAlias: apisv1.NameAlias{Name: dt.Name, Alias: dt.Alias}, - } - if dt.Cluster != nil { - ebt.Cluster = &apisv1.ClusterTarget{ - ClusterName: dt.Cluster.ClusterName, - Namespace: dt.Cluster.Namespace, - } - } - envBindingTargets = append(envBindingTargets, ebt) - } - } - ebb := &apisv1.EnvBindingBase{ - Name: envBinding.Name, - Alias: env.Alias, - Description: env.Description, - TargetNames: env.Targets, - Targets: envBindingTargets, - CreateTime: envBinding.CreateTime, - UpdateTime: envBinding.UpdateTime, - AppDeployName: envBinding.AppDeployName, - AppDeployNamespace: env.Namespace, - } - return ebb -} - -func convertToEnvBindingModel(app *model.Application, envBind apisv1.EnvBinding) *model.EnvBinding { - re := model.EnvBinding{ - AppPrimaryKey: app.Name, - Name: envBind.Name, - AppDeployName: app.GetAppNameForSynced(), - } - return &re -} - -func convertWorkflowName(envName string) string { - return fmt.Sprintf("workflow-%s", envName) -} diff --git a/pkg/apiserver/rest/usecase/envbinding_model.go b/pkg/apiserver/rest/usecase/envbinding_model.go deleted file mode 100644 index 6d6008871..000000000 --- a/pkg/apiserver/rest/usecase/envbinding_model.go +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright 2021 The KubeVela 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 usecase - -import ( - "context" - - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/model" -) - -type envListOption struct { - appPrimaryKey string - envName string - projectName string -} - -func listEnvBindings(ctx context.Context, ds datastore.DataStore, listOption envListOption) ([]*model.EnvBinding, error) { - var envBinding = model.EnvBinding{} - if listOption.appPrimaryKey != "" { - envBinding.AppPrimaryKey = listOption.appPrimaryKey - } - if listOption.envName != "" { - envBinding.Name = listOption.envName - } - envBindings, err := ds.List(ctx, &envBinding, &datastore.ListOptions{}) - if err != nil { - return nil, err - } - var ret []*model.EnvBinding - for _, et := range envBindings { - eb, ok := et.(*model.EnvBinding) - if !ok { - continue - } - ret = append(ret, eb) - } - return ret, nil -} diff --git a/pkg/apiserver/rest/webservice/webservice.go b/pkg/apiserver/rest/webservice/webservice.go deleted file mode 100644 index 66c3270cf..000000000 --- a/pkg/apiserver/rest/webservice/webservice.go +++ /dev/null @@ -1,132 +0,0 @@ -/* -Copyright 2021 The KubeVela 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 webservice - -import ( - "context" - "log" - "net/http" - "time" - - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - - "github.com/emicklei/go-restful/v3" -) - -// versionPrefix API version prefix. -var versionPrefix = "/api/v1" - -// WebService webservice interface -type WebService interface { - GetWebService() *restful.WebService -} - -var registeredWebService []WebService - -// RegisterWebService register webservice -func RegisterWebService(ws WebService) { - registeredWebService = append(registeredWebService, ws) -} - -// GetRegisteredWebService return registeredWebService -func GetRegisteredWebService() []WebService { - return registeredWebService -} - -func returns200(b *restful.RouteBuilder) { - b.Returns(http.StatusOK, "OK", apisv1.SimpleResponse{Status: "ok"}) -} - -func returns500(b *restful.RouteBuilder) { - b.Returns(http.StatusInternalServerError, "Bummer, something went wrong", nil) -} - -// Init inits all webservice, pass in the required parameter object. -// It can be implemented using the idea of dependency injection. -func Init(ctx context.Context, ds datastore.DataStore, addonCacheTime time.Duration, initDatabase bool) map[string]interface{} { - clusterUsecase := usecase.NewClusterUsecase(ds) - rbacUsecase := usecase.NewRBACUsecase(ds) - projectUsecase := usecase.NewProjectUsecase(ds, rbacUsecase) - envUsecase := usecase.NewEnvUsecase(ds, projectUsecase) - targetUsecase := usecase.NewTargetUsecase(ds) - workflowUsecase := usecase.NewWorkflowUsecase(ds, envUsecase) - oamApplicationUsecase := usecase.NewOAMApplicationUsecase() - velaQLUsecase := usecase.NewVelaQLUsecase() - definitionUsecase := usecase.NewDefinitionUsecase() - addonUsecase := usecase.NewAddonUsecase(addonCacheTime) - envBindingUsecase := usecase.NewEnvBindingUsecase(ds, workflowUsecase, definitionUsecase, envUsecase) - systemInfoUsecase := usecase.NewSystemInfoUsecase(ds) - helmUsecase := usecase.NewHelmUsecase() - userUsecase := usecase.NewUserUsecase(ds, projectUsecase, systemInfoUsecase, rbacUsecase) - authenticationUsecase := usecase.NewAuthenticationUsecase(ds, systemInfoUsecase, userUsecase) - configUseCase := usecase.NewConfigUseCase(authenticationUsecase) - applicationUsecase := usecase.NewApplicationUsecase(ds, workflowUsecase, envBindingUsecase, envUsecase, targetUsecase, definitionUsecase, projectUsecase, userUsecase) - webhookUsecase := usecase.NewWebhookUsecase(ds, applicationUsecase) - // Modules that require default data initialization, Call it here in order - if initDatabase { - initData(ctx, userUsecase, rbacUsecase, projectUsecase, targetUsecase, systemInfoUsecase) - } - - // Application - RegisterWebService(NewApplicationWebService(applicationUsecase, envBindingUsecase, workflowUsecase, rbacUsecase)) - RegisterWebService(NewProjectWebService(projectUsecase, rbacUsecase, targetUsecase)) - RegisterWebService(NewEnvWebService(envUsecase, applicationUsecase, rbacUsecase)) - - // Extension - RegisterWebService(NewDefinitionWebservice(definitionUsecase, rbacUsecase)) - RegisterWebService(NewAddonWebService(addonUsecase, rbacUsecase, clusterUsecase)) - RegisterWebService(NewEnabledAddonWebService(addonUsecase, rbacUsecase)) - RegisterWebService(NewAddonRegistryWebService(addonUsecase, rbacUsecase)) - - // Config management - RegisterWebService(ConfigWebService(configUseCase, rbacUsecase)) - - // Resources - RegisterWebService(NewClusterWebService(clusterUsecase, rbacUsecase)) - RegisterWebService(NewOAMApplication(oamApplicationUsecase, rbacUsecase)) - RegisterWebService(&payloadTypesWebservice{}) - RegisterWebService(NewTargetWebService(targetUsecase, applicationUsecase, rbacUsecase)) - RegisterWebService(NewVelaQLWebService(velaQLUsecase, rbacUsecase)) - RegisterWebService(NewWebhookWebService(webhookUsecase, applicationUsecase)) - RegisterWebService(NewHelmWebService(helmUsecase)) - - // Authentication - RegisterWebService(NewAuthenticationWebService(authenticationUsecase, userUsecase)) - RegisterWebService(NewUserWebService(userUsecase, rbacUsecase)) - RegisterWebService(NewSystemInfoWebService(systemInfoUsecase, rbacUsecase)) - - // RBAC - RegisterWebService(NewRBACWebService(rbacUsecase)) - - // return some usecase instance - return map[string]interface{}{"workflow": workflowUsecase, "project": projectUsecase} -} - -// InitUsecase the usecase set that needs init data -type InitUsecase interface { - Init(ctx context.Context) error -} - -func initData(ctx context.Context, inits ...InitUsecase) { - for _, init := range inits { - if err := init.Init(ctx); err != nil { - log.Fatalf("database init failure %s", err.Error()) - } - } -} diff --git a/pkg/apiserver/rest/rest_server.go b/pkg/apiserver/server.go similarity index 53% rename from pkg/apiserver/rest/rest_server.go rename to pkg/apiserver/server.go index a5c4f36ad..8b363770e 100644 --- a/pkg/apiserver/rest/rest_server.go +++ b/pkg/apiserver/server.go @@ -14,18 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package rest +package apiserver import ( "context" "fmt" "net/http" - "os" "time" - "github.com/oam-dev/kubevela/pkg/apiserver/collect" - - restfulspec "github.com/emicklei/go-restful-openapi/v2" + restfulSpec "github.com/emicklei/go-restful-openapi/v2" "github.com/emicklei/go-restful/v3" "github.com/go-openapi/spec" "k8s.io/client-go/tools/leaderelection" @@ -34,61 +31,37 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore/kubeapi" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore/mongodb" - "github.com/oam-dev/kubevela/pkg/apiserver/log" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/webservice" - velasync "github.com/oam-dev/kubevela/pkg/apiserver/sync" - utils2 "github.com/oam-dev/kubevela/pkg/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/config" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/service" + "github.com/oam-dev/kubevela/pkg/apiserver/event" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore/kubeapi" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore/mongodb" + "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/container" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" + pkgUtils "github.com/oam-dev/kubevela/pkg/utils" + "github.com/oam-dev/kubevela/pkg/utils/apply" ) -var _ APIServer = &restServer{} - -// Config config for server -type Config struct { - // api server bind address - BindAddr string - // monitor metric path - MetricPath string - - // Datastore config - Datastore datastore.Config - - // LeaderConfig for leader election - LeaderConfig leaderConfig - - // AddonCacheTime is how long between two cache operations - AddonCacheTime time.Duration - - // DisableStatisticCronJob close the calculate system info cronJob - DisableStatisticCronJob bool -} - -type leaderConfig struct { - ID string - LockName string - Duration time.Duration -} - // APIServer interface for call api server type APIServer interface { - Run(context.Context) error - RegisterServices(ctx context.Context, initDatabase bool) restfulspec.Config + Run(context.Context, chan error) error + BuildRestfulConfig() (*restfulSpec.Config, error) } +// restServer rest server type restServer struct { - webContainer *restful.Container - cfg Config - dataStore datastore.DataStore - // usecases, we register part of the usecase instances - usecases map[string]interface{} + webContainer *restful.Container + beanContainer *container.Container + cfg config.Config + dataStore datastore.DataStore } -// New create restserver with config data -func New(cfg Config) (a APIServer, err error) { +// New create api server with config data +func New(cfg config.Config) (a APIServer, err error) { var ds datastore.DataStore switch cfg.Datastore.Type { case "mongodb": @@ -106,17 +79,73 @@ func New(cfg Config) (a APIServer, err error) { } s := &restServer{ - webContainer: restful.NewContainer(), - cfg: cfg, - dataStore: ds, + webContainer: restful.NewContainer(), + beanContainer: container.NewContainer(), + cfg: cfg, + dataStore: ds, } return s, nil } -func (s *restServer) Run(ctx context.Context) error { - s.RegisterServices(ctx, true) +func (s *restServer) buildIoCContainer() error { + // infrastructure + if err := s.beanContainer.ProvideWithName("datastore", s.dataStore); err != nil { + return fmt.Errorf("fail to provides the datastore bean to the container: %w", err) + } + kubeConfig, err := clients.GetKubeConfig() + if err != nil { + return err + } + kubeClient, err := clients.GetKubeClient() + if err != nil { + return err + } + if err := s.beanContainer.ProvideWithName("kubeClient", kubeClient); err != nil { + return fmt.Errorf("fail to provides the kubeClient bean to the container: %w", err) + } + if err := s.beanContainer.ProvideWithName("kubeConfig", kubeConfig); err != nil { + return fmt.Errorf("fail to provides the kubeConfig bean to the container: %w", err) + } + if err := s.beanContainer.ProvideWithName("apply", apply.NewAPIApplicator(kubeClient)); err != nil { + return fmt.Errorf("fail to provides the apply bean to the container: %w", err) + } - l, err := s.setupLeaderElection() + // domain + if err := s.beanContainer.Provides(service.InitServiceBean(s.cfg)...); err != nil { + return fmt.Errorf("fail to provides the service bean to the container: %w", err) + } + + // interfaces + if err := s.beanContainer.Provides(api.InitAPIBean()...); err != nil { + return fmt.Errorf("fail to provides the api bean to the container: %w", err) + } + + // event + if err := s.beanContainer.Provides(event.InitEvent(s.cfg)...); err != nil { + return fmt.Errorf("fail to provides the event bean to the container: %w", err) + } + + if err := s.beanContainer.Populate(); err != nil { + return fmt.Errorf("fail to populate the bean container: %w", err) + } + return nil +} + +func (s *restServer) Run(ctx context.Context, errChan chan error) error { + + // build the Ioc Container + if err := s.buildIoCContainer(); err != nil { + return err + } + + // init database + if err := service.InitData(ctx); err != nil { + return fmt.Errorf("fail to init database %w", err) + } + + s.RegisterAPIRoute() + + l, err := s.setupLeaderElection(errChan) if err != nil { return err } @@ -127,7 +156,7 @@ func (s *restServer) Run(ctx context.Context) error { return s.startHTTP(ctx) } -func (s *restServer) setupLeaderElection() (*leaderelection.LeaderElectionConfig, error) { +func (s *restServer) setupLeaderElection(errChan chan error) (*leaderelection.LeaderElectionConfig, error) { restCfg := ctrl.GetConfigOrDie() rl, err := resourcelock.NewFromKubeconfig(resourcelock.LeasesResourceLock, types.DefaultKubeVelaNS, s.cfg.LeaderConfig.LockName, resourcelock.ResourceLockConfig{ @@ -145,18 +174,10 @@ func (s *restServer) setupLeaderElection() (*leaderelection.LeaderElectionConfig RetryPeriod: time.Second * 2, Callbacks: leaderelection.LeaderCallbacks{ OnStartedLeading: func(ctx context.Context) { - go velasync.Start(ctx, s.dataStore, restCfg, s.usecases) - if !s.cfg.DisableStatisticCronJob { - collect.StartCalculatingInfoCronJob(s.dataStore) - } - // this process would block the whole process, any other handler should start before this func - s.runWorkflowRecordSync(ctx, s.cfg.LeaderConfig.Duration) + go event.StartEventWorker(ctx, errChan) }, OnStoppedLeading: func() { - klog.Infof("leader lost: %s", s.cfg.LeaderConfig.ID) - // Currently, the started goroutine will all closed by the context, so there seems no need to call os.Exit here. - // But it can be safe to stop the process as leader lost. - os.Exit(0) + errChan <- fmt.Errorf("leader lost %s", s.cfg.LeaderConfig.ID) }, OnNewLeader: func(identity string) { if identity == s.cfg.LeaderConfig.ID { @@ -169,32 +190,21 @@ func (s *restServer) setupLeaderElection() (*leaderelection.LeaderElectionConfig }, nil } -func (s *restServer) runWorkflowRecordSync(ctx context.Context, duration time.Duration) { - klog.Infof("start to syncing workflow record") - w := s.usecases["workflow"].(usecase.WorkflowUsecase) - t := time.NewTicker(duration) - defer t.Stop() - - for { - select { - case <-t.C: - if err := w.SyncWorkflowRecord(ctx); err != nil { - klog.ErrorS(err, "syncWorkflowRecordError") - } - case <-ctx.Done(): - return - } +// BuildRestfulConfig build the restful config +// This function will build the smallest set of beans +func (s *restServer) BuildRestfulConfig() (*restfulSpec.Config, error) { + if err := s.buildIoCContainer(); err != nil { + return nil, err } + config := s.RegisterAPIRoute() + return &config, nil } -// RegisterServices register web service -func (s *restServer) RegisterServices(ctx context.Context, initDatabase bool) restfulspec.Config { - s.usecases = webservice.Init(ctx, s.dataStore, s.cfg.AddonCacheTime, initDatabase) - +// RegisterAPIRoute register the API route +func (s *restServer) RegisterAPIRoute() restfulSpec.Config { /* ************************************************************** */ /* ************* Open API Route Group ***************** */ /* ************************************************************** */ - // Add container filter to enable CORS cors := restful.CrossOriginResourceSharing{ ExposeHeaders: []string{}, @@ -210,16 +220,16 @@ func (s *restServer) RegisterServices(ctx context.Context, initDatabase bool) re // Add request log s.webContainer.Filter(s.requestLog) - // Register all custom webservice - for _, handler := range webservice.GetRegisteredWebService() { - s.webContainer.Add(handler.GetWebService()) + // Register all custom api + for _, handler := range api.GetRegisteredAPIInterface() { + s.webContainer.Add(handler.GetWebServiceRoute()) } - config := restfulspec.Config{ + config := restfulSpec.Config{ WebServices: s.webContainer.RegisteredWebServices(), // you control what services are visible APIPath: "/apidocs.json", PostBuildSwaggerObjectHandler: enrichSwaggerObject} - s.webContainer.Add(restfulspec.NewOpenAPIService(config)) + s.webContainer.Add(restfulSpec.NewOpenAPIService(config)) return config } @@ -230,8 +240,8 @@ func (s *restServer) requestLog(req *restful.Request, resp *restful.Response, ch chain.ProcessFilter(req, resp) takeTime := time.Since(start) log.Logger.With( - "clientIP", utils2.Sanitize(utils.ClientIP(req.Request)), - "path", utils2.Sanitize(req.Request.URL.Path), + "clientIP", pkgUtils.Sanitize(utils.ClientIP(req.Request)), + "path", pkgUtils.Sanitize(req.Request.URL.Path), "method", req.Request.Method, "status", c.StatusCode(), "time", takeTime.String(), diff --git a/pkg/apiserver/server_test.go b/pkg/apiserver/server_test.go new file mode 100644 index 000000000..ac9aa43dd --- /dev/null +++ b/pkg/apiserver/server_test.go @@ -0,0 +1,17 @@ +/* +Copyright 2022 The KubeVela 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 apiserver diff --git a/pkg/apiserver/rest/utils/bcode/001_application.go b/pkg/apiserver/utils/bcode/001_application.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/001_application.go rename to pkg/apiserver/utils/bcode/001_application.go diff --git a/pkg/apiserver/rest/utils/bcode/002_workflow.go b/pkg/apiserver/utils/bcode/002_workflow.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/002_workflow.go rename to pkg/apiserver/utils/bcode/002_workflow.go diff --git a/pkg/apiserver/rest/utils/bcode/003_project.go b/pkg/apiserver/utils/bcode/003_project.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/003_project.go rename to pkg/apiserver/utils/bcode/003_project.go diff --git a/pkg/apiserver/rest/utils/bcode/004_cluster.go b/pkg/apiserver/utils/bcode/004_cluster.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/004_cluster.go rename to pkg/apiserver/utils/bcode/004_cluster.go diff --git a/pkg/apiserver/rest/utils/bcode/005_addon.go b/pkg/apiserver/utils/bcode/005_addon.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/005_addon.go rename to pkg/apiserver/utils/bcode/005_addon.go diff --git a/pkg/apiserver/rest/utils/bcode/006_velaql.go b/pkg/apiserver/utils/bcode/006_velaql.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/006_velaql.go rename to pkg/apiserver/utils/bcode/006_velaql.go diff --git a/pkg/apiserver/rest/utils/bcode/007_definition.go b/pkg/apiserver/utils/bcode/007_definition.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/007_definition.go rename to pkg/apiserver/utils/bcode/007_definition.go diff --git a/pkg/apiserver/rest/utils/bcode/008_target.go b/pkg/apiserver/utils/bcode/008_target.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/008_target.go rename to pkg/apiserver/utils/bcode/008_target.go diff --git a/pkg/apiserver/rest/utils/bcode/009_envbinding.go b/pkg/apiserver/utils/bcode/009_envbinding.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/009_envbinding.go rename to pkg/apiserver/utils/bcode/009_envbinding.go diff --git a/pkg/apiserver/rest/utils/bcode/011_env.go b/pkg/apiserver/utils/bcode/011_env.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/011_env.go rename to pkg/apiserver/utils/bcode/011_env.go diff --git a/pkg/apiserver/rest/utils/bcode/012_authentication.go b/pkg/apiserver/utils/bcode/012_authentication.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/012_authentication.go rename to pkg/apiserver/utils/bcode/012_authentication.go diff --git a/pkg/apiserver/rest/utils/bcode/013_repository.go b/pkg/apiserver/utils/bcode/013_repository.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/013_repository.go rename to pkg/apiserver/utils/bcode/013_repository.go diff --git a/pkg/apiserver/rest/utils/bcode/014_user.go b/pkg/apiserver/utils/bcode/014_user.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/014_user.go rename to pkg/apiserver/utils/bcode/014_user.go diff --git a/pkg/apiserver/rest/utils/bcode/015_rbac.go b/pkg/apiserver/utils/bcode/015_rbac.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/015_rbac.go rename to pkg/apiserver/utils/bcode/015_rbac.go diff --git a/pkg/apiserver/rest/utils/bcode/bcode.go b/pkg/apiserver/utils/bcode/bcode.go similarity index 96% rename from pkg/apiserver/rest/utils/bcode/bcode.go rename to pkg/apiserver/utils/bcode/bcode.go index 0b652c635..6f53f3e31 100644 --- a/pkg/apiserver/rest/utils/bcode/bcode.go +++ b/pkg/apiserver/utils/bcode/bcode.go @@ -23,8 +23,8 @@ import ( "github.com/emicklei/go-restful/v3" "github.com/go-playground/validator/v10" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - "github.com/oam-dev/kubevela/pkg/apiserver/log" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" "github.com/oam-dev/kubevela/pkg/utils" ) diff --git a/pkg/apiserver/rest/utils/bcode/bcode_suite_test.go b/pkg/apiserver/utils/bcode/bcode_suite_test.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/bcode_suite_test.go rename to pkg/apiserver/utils/bcode/bcode_suite_test.go diff --git a/pkg/apiserver/rest/utils/bcode/bcode_test.go b/pkg/apiserver/utils/bcode/bcode_test.go similarity index 100% rename from pkg/apiserver/rest/utils/bcode/bcode_test.go rename to pkg/apiserver/utils/bcode/bcode_test.go diff --git a/pkg/apiserver/rest/utils/cache.go b/pkg/apiserver/utils/cache.go similarity index 100% rename from pkg/apiserver/rest/utils/cache.go rename to pkg/apiserver/utils/cache.go diff --git a/pkg/apiserver/rest/utils/cache_test.go b/pkg/apiserver/utils/cache_test.go similarity index 100% rename from pkg/apiserver/rest/utils/cache_test.go rename to pkg/apiserver/utils/cache_test.go diff --git a/pkg/apiserver/utils/container/container.go b/pkg/apiserver/utils/container/container.go new file mode 100644 index 000000000..aff45f330 --- /dev/null +++ b/pkg/apiserver/utils/container/container.go @@ -0,0 +1,61 @@ +/* +Copyright 2022 The KubeVela 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 container + +import ( + "github.com/barnettZQG/inject" + "helm.sh/helm/v3/pkg/time" + + "github.com/oam-dev/kubevela/pkg/apiserver/utils/log" +) + +// NewContainer new a IoC container +func NewContainer() *Container { + return &Container{ + graph: inject.Graph{}, + } +} + +// Container the IoC container +type Container struct { + graph inject.Graph +} + +// Provides provide some beans with default name +func (c *Container) Provides(beans ...interface{}) error { + for _, bean := range beans { + if err := c.graph.Provide(&inject.Object{Value: bean}); err != nil { + return err + } + } + return nil +} + +// ProvideWithName provide the bean with name +func (c *Container) ProvideWithName(name string, bean interface{}) error { + return c.graph.Provide(&inject.Object{Name: name, Value: bean}) +} + +// Populate populate dependency fields for all beans. +// this function must be called after providing all beans +func (c *Container) Populate() error { + start := time.Now() + defer func() { + log.Logger.Infof("populate the bean container take time %s", time.Now().Sub(start)) + }() + return c.graph.Populate() +} diff --git a/pkg/apiserver/rest/utils/dex.go b/pkg/apiserver/utils/dex.go similarity index 100% rename from pkg/apiserver/rest/utils/dex.go rename to pkg/apiserver/utils/dex.go diff --git a/pkg/apiserver/rest/utils/dex_test.go b/pkg/apiserver/utils/dex_test.go similarity index 100% rename from pkg/apiserver/rest/utils/dex_test.go rename to pkg/apiserver/utils/dex_test.go diff --git a/pkg/apiserver/rest/utils/http.go b/pkg/apiserver/utils/http.go similarity index 100% rename from pkg/apiserver/rest/utils/http.go rename to pkg/apiserver/utils/http.go diff --git a/pkg/apiserver/rest/utils/http_test.go b/pkg/apiserver/utils/http_test.go similarity index 100% rename from pkg/apiserver/rest/utils/http_test.go rename to pkg/apiserver/utils/http_test.go diff --git a/pkg/apiserver/log/logger.go b/pkg/apiserver/utils/log/logger.go similarity index 100% rename from pkg/apiserver/log/logger.go rename to pkg/apiserver/utils/log/logger.go diff --git a/pkg/apiserver/rest/utils/params.go b/pkg/apiserver/utils/params.go similarity index 100% rename from pkg/apiserver/rest/utils/params.go rename to pkg/apiserver/utils/params.go diff --git a/pkg/apiserver/rest/utils/params_test.go b/pkg/apiserver/utils/params_test.go similarity index 100% rename from pkg/apiserver/rest/utils/params_test.go rename to pkg/apiserver/utils/params_test.go diff --git a/pkg/apiserver/rest/utils/ui_schema.go b/pkg/apiserver/utils/ui_schema.go similarity index 100% rename from pkg/apiserver/rest/utils/ui_schema.go rename to pkg/apiserver/utils/ui_schema.go diff --git a/pkg/apiserver/rest/utils/ui_schema_test.go b/pkg/apiserver/utils/ui_schema_test.go similarity index 100% rename from pkg/apiserver/rest/utils/ui_schema_test.go rename to pkg/apiserver/utils/ui_schema_test.go diff --git a/pkg/apiserver/rest/utils/utils_suite_test.go b/pkg/apiserver/utils/utils_suite_test.go similarity index 100% rename from pkg/apiserver/rest/utils/utils_suite_test.go rename to pkg/apiserver/utils/utils_suite_test.go diff --git a/pkg/apiserver/rest/utils/version.go b/pkg/apiserver/utils/version.go similarity index 100% rename from pkg/apiserver/rest/utils/version.go rename to pkg/apiserver/utils/version.go diff --git a/pkg/apiserver/rest/utils/version_test.go b/pkg/apiserver/utils/version_test.go similarity index 100% rename from pkg/apiserver/rest/utils/version_test.go rename to pkg/apiserver/utils/version_test.go diff --git a/pkg/utils/config/application.go b/pkg/utils/config/application.go index 76df9ca81..535e873e6 100644 --- a/pkg/utils/config/application.go +++ b/pkg/utils/config/application.go @@ -31,7 +31,7 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/model" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" ) const ( diff --git a/pkg/utils/helm/helm_helper.go b/pkg/utils/helm/helm_helper.go index a6f1f9bc4..d47899c09 100644 --- a/pkg/utils/helm/helm_helper.go +++ b/pkg/utils/helm/helm_helper.go @@ -45,7 +45,7 @@ import ( k8scmdutil "k8s.io/kubectl/pkg/cmd/util" "sigs.k8s.io/yaml" - utils2 "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" + utils2 "github.com/oam-dev/kubevela/pkg/apiserver/utils" "github.com/oam-dev/kubevela/pkg/utils" "github.com/oam-dev/kubevela/pkg/utils/common" cmdutil "github.com/oam-dev/kubevela/pkg/utils/util" @@ -203,6 +203,7 @@ func (h *Helper) ListVersions(repoURL string, chartName string, skipCache bool, // GetIndexInfo get index.yaml form given repo url func (h *Helper) GetIndexInfo(repoURL string, skipCache bool, opts *common.HTTPOption) (*repo.IndexFile, error) { + repoURL = utils.Sanitize(repoURL) if h.cache != nil && !skipCache { if i := h.cache.Get(fmt.Sprintf(repoPatten, repoURL)); i != nil { return i.(*repo.IndexFile), nil diff --git a/pkg/velaql/suite_test.go b/pkg/velaql/suite_test.go index ac92454b4..3d7eae575 100644 --- a/pkg/velaql/suite_test.go +++ b/pkg/velaql/suite_test.go @@ -31,7 +31,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" "github.com/oam-dev/kubevela/pkg/cue/packages" "github.com/oam-dev/kubevela/pkg/oam/discoverymapper" "github.com/oam-dev/kubevela/pkg/utils/common" diff --git a/references/cli/uischema.go b/references/cli/uischema.go index 09f3dda43..35373fc06 100644 --- a/references/cli/uischema.go +++ b/references/cli/uischema.go @@ -36,7 +36,7 @@ import ( "sigs.k8s.io/yaml" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" "github.com/oam-dev/kubevela/pkg/utils/common" "github.com/oam-dev/kubevela/pkg/utils/util" ) diff --git a/test/e2e-apiserver-test/addon_test.go b/test/e2e-apiserver-test/addon_test.go index 2146e7dd6..2ef04beff 100644 --- a/test/e2e-apiserver-test/addon_test.go +++ b/test/e2e-apiserver-test/addon_test.go @@ -24,7 +24,7 @@ import ( . "github.com/onsi/gomega" "github.com/oam-dev/kubevela/pkg/addon" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" ) var _ = Describe("Test addon rest api", func() { diff --git a/test/e2e-apiserver-test/application_test.go b/test/e2e-apiserver-test/application_test.go index 4fcd736df..7ab734535 100644 --- a/test/e2e-apiserver-test/application_test.go +++ b/test/e2e-apiserver-test/application_test.go @@ -27,8 +27,8 @@ import ( "k8s.io/apimachinery/pkg/types" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/apiserver/model" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/domain/model" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" ) var appName = "app-e2e" diff --git a/test/e2e-apiserver-test/cluster_test.go b/test/e2e-apiserver-test/cluster_test.go index 91fab73a3..63c7e1f80 100644 --- a/test/e2e-apiserver-test/cluster_test.go +++ b/test/e2e-apiserver-test/cluster_test.go @@ -25,7 +25,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - v1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + v1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" "github.com/oam-dev/kubevela/pkg/multicluster" util "github.com/oam-dev/kubevela/pkg/utils" ) diff --git a/test/e2e-apiserver-test/definition_test.go b/test/e2e-apiserver-test/definition_test.go index 890ec3b3f..3077eba11 100644 --- a/test/e2e-apiserver-test/definition_test.go +++ b/test/e2e-apiserver-test/definition_test.go @@ -24,8 +24,8 @@ import ( . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils" "github.com/oam-dev/kubevela/pkg/oam/util" "github.com/oam-dev/kubevela/pkg/utils/common" ) diff --git a/test/e2e-apiserver-test/env_test.go b/test/e2e-apiserver-test/env_test.go index 6e75242c4..6d97370c7 100644 --- a/test/e2e-apiserver-test/env_test.go +++ b/test/e2e-apiserver-test/env_test.go @@ -24,7 +24,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" "github.com/oam-dev/kubevela/pkg/multicluster" ) diff --git a/test/e2e-apiserver-test/oam_application_test.go b/test/e2e-apiserver-test/oam_application_test.go index 5420946a0..e08b2a002 100644 --- a/test/e2e-apiserver-test/oam_application_test.go +++ b/test/e2e-apiserver-test/oam_application_test.go @@ -28,7 +28,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - apiv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + apiv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" "github.com/oam-dev/kubevela/pkg/utils/common" ) diff --git a/test/e2e-apiserver-test/project_test.go b/test/e2e-apiserver-test/project_test.go index 2a2ce7da6..a8d32e6f2 100644 --- a/test/e2e-apiserver-test/project_test.go +++ b/test/e2e-apiserver-test/project_test.go @@ -24,7 +24,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" ) var _ = Describe("Test project rest api", func() { diff --git a/test/e2e-apiserver-test/suite_test.go b/test/e2e-apiserver-test/suite_test.go index cde4ea3a2..242719d01 100644 --- a/test/e2e-apiserver-test/suite_test.go +++ b/test/e2e-apiserver-test/suite_test.go @@ -32,11 +32,12 @@ import ( v1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/oam-dev/kubevela/pkg/apiserver/clients" - "github.com/oam-dev/kubevela/pkg/apiserver/datastore" - arest "github.com/oam-dev/kubevela/pkg/apiserver/rest" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" - "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" + "github.com/oam-dev/kubevela/pkg/apiserver" + "github.com/oam-dev/kubevela/pkg/apiserver/config" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients" + "github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode" ) var k8sClient client.Client @@ -64,7 +65,7 @@ var _ = BeforeSuite(func() { ctx := context.Background() - cfg := arest.Config{ + cfg := config.Config{ BindAddr: "127.0.0.1:8000", Datastore: datastore.Config{ Type: "kubeapi", @@ -76,11 +77,11 @@ var _ = BeforeSuite(func() { cfg.LeaderConfig.LockName = "apiserver-lock" cfg.LeaderConfig.Duration = time.Second * 10 - server, err := arest.New(cfg) + server, err := apiserver.New(cfg) Expect(err).ShouldNot(HaveOccurred()) Expect(server).ShouldNot(BeNil()) go func() { - err = server.Run(ctx) + err = server.Run(ctx, make(chan error)) Expect(err).ShouldNot(HaveOccurred()) }() By("wait for api server to start") diff --git a/test/e2e-apiserver-test/system_info_test.go b/test/e2e-apiserver-test/system_info_test.go index defd69cb6..13d6773de 100644 --- a/test/e2e-apiserver-test/system_info_test.go +++ b/test/e2e-apiserver-test/system_info_test.go @@ -20,7 +20,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" ) var _ = Describe("Test system info rest api", func() { diff --git a/test/e2e-apiserver-test/user_test.go b/test/e2e-apiserver-test/user_test.go index cd8ef95fb..8d92340c3 100644 --- a/test/e2e-apiserver-test/user_test.go +++ b/test/e2e-apiserver-test/user_test.go @@ -22,7 +22,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" ) const ( diff --git a/test/e2e-apiserver-test/velaql_test.go b/test/e2e-apiserver-test/velaql_test.go index fd191afeb..d6c5ecdef 100644 --- a/test/e2e-apiserver-test/velaql_test.go +++ b/test/e2e-apiserver-test/velaql_test.go @@ -34,7 +34,7 @@ import ( common2 "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - apiv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + apiv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1" "github.com/oam-dev/kubevela/pkg/oam/util" "github.com/oam-dev/kubevela/pkg/utils/common" )