From 947a3fdb7c46c53fc39b6b95cd8c8ca0aa977ac5 Mon Sep 17 00:00:00 2001 From: yiling Date: Fri, 27 Dec 2024 17:07:36 +0800 Subject: [PATCH] Sync Space/SpaceResource component with enterprise --- .../component/mock_SpaceComponent.go | 21 +- api/handler/space.go | 2 +- api/handler/space_resource.go | 2 +- common/types/space.go | 21 +- component/space.go | 106 ++++------ component/space_ce.go | 94 +++++++++ component/space_ce_test.go | 168 +++++++++++++++ component/space_resource.go | 51 ++--- component/space_resource_ce.go | 58 +++++ component/space_resource_ce_test.go | 38 ++++ component/space_resource_test.go | 141 ++++++------- component/space_test.go | 199 +++--------------- component/wireset.go | 34 --- component/wireset_ce.go | 48 +++++ 14 files changed, 588 insertions(+), 395 deletions(-) create mode 100644 component/space_ce.go create mode 100644 component/space_ce_test.go create mode 100644 component/space_resource_ce.go create mode 100644 component/space_resource_ce_test.go create mode 100644 component/wireset_ce.go diff --git a/_mocks/opencsg.com/csghub-server/component/mock_SpaceComponent.go b/_mocks/opencsg.com/csghub-server/component/mock_SpaceComponent.go index 026277cb..99d6cde9 100644 --- a/_mocks/opencsg.com/csghub-server/component/mock_SpaceComponent.go +++ b/_mocks/opencsg.com/csghub-server/component/mock_SpaceComponent.go @@ -726,17 +726,17 @@ func (_c *MockSpaceComponent_Status_Call) RunAndReturn(run func(context.Context, return _c } -// Stop provides a mock function with given fields: ctx, namespace, name -func (_m *MockSpaceComponent) Stop(ctx context.Context, namespace string, name string) error { - ret := _m.Called(ctx, namespace, name) +// Stop provides a mock function with given fields: ctx, namespace, name, deleteSpace +func (_m *MockSpaceComponent) Stop(ctx context.Context, namespace string, name string, deleteSpace bool) error { + ret := _m.Called(ctx, namespace, name, deleteSpace) if len(ret) == 0 { panic("no return value specified for Stop") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok { - r0 = rf(ctx, namespace, name) + if rf, ok := ret.Get(0).(func(context.Context, string, string, bool) error); ok { + r0 = rf(ctx, namespace, name, deleteSpace) } else { r0 = ret.Error(0) } @@ -753,13 +753,14 @@ type MockSpaceComponent_Stop_Call struct { // - ctx context.Context // - namespace string // - name string -func (_e *MockSpaceComponent_Expecter) Stop(ctx interface{}, namespace interface{}, name interface{}) *MockSpaceComponent_Stop_Call { - return &MockSpaceComponent_Stop_Call{Call: _e.mock.On("Stop", ctx, namespace, name)} +// - deleteSpace bool +func (_e *MockSpaceComponent_Expecter) Stop(ctx interface{}, namespace interface{}, name interface{}, deleteSpace interface{}) *MockSpaceComponent_Stop_Call { + return &MockSpaceComponent_Stop_Call{Call: _e.mock.On("Stop", ctx, namespace, name, deleteSpace)} } -func (_c *MockSpaceComponent_Stop_Call) Run(run func(ctx context.Context, namespace string, name string)) *MockSpaceComponent_Stop_Call { +func (_c *MockSpaceComponent_Stop_Call) Run(run func(ctx context.Context, namespace string, name string, deleteSpace bool)) *MockSpaceComponent_Stop_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(string)) + run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(bool)) }) return _c } @@ -769,7 +770,7 @@ func (_c *MockSpaceComponent_Stop_Call) Return(_a0 error) *MockSpaceComponent_St return _c } -func (_c *MockSpaceComponent_Stop_Call) RunAndReturn(run func(context.Context, string, string) error) *MockSpaceComponent_Stop_Call { +func (_c *MockSpaceComponent_Stop_Call) RunAndReturn(run func(context.Context, string, string, bool) error) *MockSpaceComponent_Stop_Call { _c.Call.Return(run) return _c } diff --git a/api/handler/space.go b/api/handler/space.go index 04d7c290..da4ddd05 100644 --- a/api/handler/space.go +++ b/api/handler/space.go @@ -387,7 +387,7 @@ func (h *SpaceHandler) Stop(ctx *gin.Context) { return } - err = h.c.Stop(ctx, namespace, name) + err = h.c.Stop(ctx, namespace, name, false) if err != nil { slog.Error("failed to stop space", slog.String("namespace", namespace), slog.String("name", name), slog.Any("error", err)) diff --git a/api/handler/space_resource.go b/api/handler/space_resource.go index 86ad56db..91f7563e 100644 --- a/api/handler/space_resource.go +++ b/api/handler/space_resource.go @@ -51,7 +51,7 @@ func (h *SpaceResourceHandler) Index(ctx *gin.Context) { httpbase.BadRequest(ctx, err.Error()) return } - spaceResources, err := h.c.Index(ctx, clusterId, deployType) + spaceResources, err := h.c.Index(ctx, clusterId, deployType, "") if err != nil { slog.Error("Failed to get space resources", slog.String("cluster_id", clusterId), slog.String("deploy_type", deployTypeStr), slog.Any("error", err)) httpbase.ServerError(ctx, err) diff --git a/common/types/space.go b/common/types/space.go index 2584d626..9b6dc9d0 100644 --- a/common/types/space.go +++ b/common/types/space.go @@ -43,16 +43,17 @@ type Space struct { // the serving endpoint url Endpoint string `json:"endpoint,omitempty" example:"https://localhost/spaces/myname/myspace"` // deploying, running, failed - Status string `json:"status"` - RepositoryID int64 `json:"repository_id,omitempty"` - UserLikes bool `json:"user_likes"` - Source RepositorySource `json:"source"` - SyncStatus RepositorySyncStatus `json:"sync_status"` - SKU string `json:"sku,omitempty"` - SvcName string `json:"svc_name,omitempty"` - CanWrite bool `json:"can_write"` - CanManage bool `json:"can_manage"` - Namespace *Namespace `json:"namespace"` + Status string `json:"status"` + RepositoryID int64 `json:"repository_id,omitempty"` + UserLikes bool `json:"user_likes"` + Source RepositorySource `json:"source"` + SyncStatus RepositorySyncStatus `json:"sync_status"` + SKU string `json:"sku,omitempty"` + SvcName string `json:"svc_name,omitempty"` + CanWrite bool `json:"can_write"` + CanManage bool `json:"can_manage"` + Namespace *Namespace `json:"namespace"` + SensitiveCheckStatus string `json:"sensitive_check_status"` } type UpdateSpaceReq struct { diff --git a/component/space.go b/component/space.go index 422d41b8..1850810e 100644 --- a/component/space.go +++ b/component/space.go @@ -11,12 +11,9 @@ import ( "opencsg.com/csghub-server/builder/deploy" "opencsg.com/csghub-server/builder/deploy/scheduler" - "opencsg.com/csghub-server/builder/git" "opencsg.com/csghub-server/builder/git/gitserver" "opencsg.com/csghub-server/builder/git/membership" - "opencsg.com/csghub-server/builder/rpc" "opencsg.com/csghub-server/builder/store/database" - "opencsg.com/csghub-server/common/config" "opencsg.com/csghub-server/common/types" "opencsg.com/csghub-server/common/utils/common" ) @@ -45,7 +42,7 @@ type SpaceComponent interface { Delete(ctx context.Context, namespace, name, currentUser string) error Deploy(ctx context.Context, namespace, name, currentUser string) (int64, error) Wakeup(ctx context.Context, namespace, name string) error - Stop(ctx context.Context, namespace, name string) error + Stop(ctx context.Context, namespace, name string, deleteSpace bool) error // FixHasEntryFile checks whether git repo has entry point file and update space's HasAppFile property in db FixHasEntryFile(ctx context.Context, s *database.Space) *database.Space Status(ctx context.Context, namespace, name string) (string, string, error) @@ -54,55 +51,6 @@ type SpaceComponent interface { HasEntryFile(ctx context.Context, space *database.Space) bool } -func NewSpaceComponent(config *config.Config) (SpaceComponent, error) { - c := &spaceComponentImpl{} - c.spaceStore = database.NewSpaceStore() - var err error - c.spaceSdkStore = database.NewSpaceSdkStore() - c.spaceResourceStore = database.NewSpaceResourceStore() - c.repoStore = database.NewRepoStore() - c.repoComponent, err = NewRepoComponentImpl(config) - if err != nil { - return nil, err - } - c.deployer = deploy.NewDeployer() - c.publicRootDomain = config.Space.PublicRootDomain - c.userStore = database.NewUserStore() - c.accountingComponent, err = NewAccountingComponent(config) - if err != nil { - return nil, err - } - c.git, err = git.NewGitServer(config) - if err != nil { - return nil, err - } - c.serverBaseUrl = config.APIServer.PublicDomain - c.deployTaskStore = database.NewDeployTaskStore() - c.userSvcClient = rpc.NewUserSvcHttpClient(fmt.Sprintf("%s:%d", config.User.Host, config.User.Port), - rpc.AuthWithApiKey(config.APIToken)) - c.userLikesStore = database.NewUserLikesStore() - c.config = config - return c, nil -} - -type spaceComponentImpl struct { - config *config.Config - repoComponent RepoComponent - git gitserver.GitServer - spaceStore database.SpaceStore - spaceSdkStore database.SpaceSdkStore - spaceResourceStore database.SpaceResourceStore - repoStore database.RepoStore - userStore database.UserStore - deployer deploy.Deployer - publicRootDomain string - accountingComponent AccountingComponent - serverBaseUrl string - deployTaskStore database.DeployTaskStore - userSvcClient rpc.UserSvcClient - userLikesStore database.UserLikesStore -} - func (c *spaceComponentImpl) Create(ctx context.Context, req types.CreateSpaceReq) (*types.Space, error) { var nickname string if req.Nickname != "" { @@ -110,13 +58,19 @@ func (c *spaceComponentImpl) Create(ctx context.Context, req types.CreateSpaceRe } else { nickname = req.Name } + if req.DefaultBranch == "" { req.DefaultBranch = types.MainBranch } + req.Nickname = nickname req.RepoType = types.SpaceRepo req.Readme = generateReadmeData(req.License) resource, err := c.spaceResourceStore.FindByID(ctx, req.ResourceID) + if err != nil { + return nil, fmt.Errorf("fail to find resource by id, %w", err) + } + err = c.checkResourcePurchasableForCreate(ctx, req, resource) if err != nil { return nil, err } @@ -125,7 +79,7 @@ func (c *spaceComponentImpl) Create(ctx context.Context, req types.CreateSpaceRe if err != nil { return nil, fmt.Errorf("invalid hardware setting, %w", err) } - _, err = c.deployer.CheckResourceAvailable(ctx, req.ClusterID, 0, &hardware) + _, err = c.checkResourceAvailable(ctx, req, hardware) if err != nil { return nil, fmt.Errorf("fail to check resource, %w", err) } @@ -145,6 +99,7 @@ func (c *spaceComponentImpl) Create(ctx context.Context, req types.CreateSpaceRe Secrets: req.Secrets, SKU: strconv.FormatInt(resource.ID, 10), } + dbSpace = c.updateSpaceByReq(dbSpace, req) resSpace, err := c.spaceStore.Create(ctx, dbSpace) if err != nil { @@ -302,12 +257,26 @@ func (c *spaceComponentImpl) Show(ctx context.Context, namespace, name, currentU CanManage: permission.CanAdmin, Namespace: ns, } + if permission.CanAdmin { + resModel.SensitiveCheckStatus = space.Repository.SensitiveCheckStatus.String() + } return resModel, nil } func (c *spaceComponentImpl) Update(ctx context.Context, req *types.UpdateSpaceReq) (*types.Space, error) { req.RepoType = types.SpaceRepo + if req.ResourceID != nil { + resource, err := c.spaceResourceStore.FindByID(ctx, *req.ResourceID) + if err != nil { + return nil, fmt.Errorf("fail to find resource by id, %w", err) + } + + err = c.checkResourcePurchasableForUpdate(ctx, *req, resource) + if err != nil { + return nil, err + } + } dbRepo, err := c.repoComponent.UpdateRepo(ctx, req.UpdateRepoReq) if err != nil { return nil, err @@ -317,6 +286,10 @@ func (c *spaceComponentImpl) Update(ctx context.Context, req *types.UpdateSpaceR if err != nil { return nil, fmt.Errorf("failed to find space, error: %w", err) } + // don't support switch reserved resource + if c.resourceReserved(space, req) { + return nil, fmt.Errorf("don't support switch reserved resource so far") + } err = c.mergeUpdateSpaceRequest(ctx, space, req) if err != nil { return nil, fmt.Errorf("failed to merge update space request, error: %w", err) @@ -602,7 +575,12 @@ func (c *spaceComponentImpl) Delete(ctx context.Context, namespace, name, curren } // stop any running space instance - go func() { _ = c.Stop(ctx, namespace, name) }() + go func() { + err := c.Stop(ctx, namespace, name, true) + if err != nil { + slog.Error("stop space failed", slog.Any("error", err)) + } + }() return nil } @@ -641,7 +619,7 @@ func (c *spaceComponentImpl) Deploy(ctx context.Context, namespace, name, curren slog.Info("run space with container image", slog.Any("namespace", namespace), slog.Any("name", name), slog.Any("containerImg", containerImg)) // create deploy for space - return c.deployer.Deploy(ctx, types.DeployRepo{ + dr := types.DeployRepo{ SpaceID: s.ID, Path: s.Repository.Path, GitPath: s.Repository.GitPath, @@ -660,7 +638,9 @@ func (c *spaceComponentImpl) Deploy(ctx context.Context, namespace, name, curren Type: types.SpaceType, UserUUID: user.UUID, SKU: s.SKU, - }) + } + dr = c.updateDeployRepoBySpace(dr, s) + return c.deployer.Deploy(ctx, dr) } func (c *spaceComponentImpl) Wakeup(ctx context.Context, namespace, name string) error { @@ -682,7 +662,7 @@ func (c *spaceComponentImpl) Wakeup(ctx context.Context, namespace, name string) }) } -func (c *spaceComponentImpl) Stop(ctx context.Context, namespace, name string) error { +func (c *spaceComponentImpl) Stop(ctx context.Context, namespace, name string, deleteSpace bool) error { s, err := c.spaceStore.FindByPath(ctx, namespace, name) if err != nil { slog.Error("can't stop space", slog.Any("error", err), slog.String("namespace", namespace), slog.String("name", name)) @@ -698,12 +678,14 @@ func (c *spaceComponentImpl) Stop(ctx context.Context, namespace, name string) e return fmt.Errorf("can't get space deployment") } - err = c.deployer.Stop(ctx, types.DeployRepo{ + dr := types.DeployRepo{ SpaceID: s.ID, Namespace: namespace, Name: name, SvcName: deploy.SvcName, - }) + } + dr = c.updateDeployRepoByDeploy(dr, deploy) + err = c.deployer.Stop(ctx, dr) if err != nil { return fmt.Errorf("can't stop space service deploy for service '%s', %w", deploy.SvcName, err) } @@ -720,9 +702,7 @@ func (c *spaceComponentImpl) FixHasEntryFile(ctx context.Context, s *database.Sp hasAppFile := c.HasEntryFile(ctx, s) if s.HasAppFile != hasAppFile { s.HasAppFile = hasAppFile - if er := c.spaceStore.Update(ctx, *s); er != nil { - slog.Error("update space failed", "error", er) - } + _ = c.spaceStore.Update(ctx, *s) } return s diff --git a/component/space_ce.go b/component/space_ce.go new file mode 100644 index 00000000..c9e93a69 --- /dev/null +++ b/component/space_ce.go @@ -0,0 +1,94 @@ +//go:build !saas + +package component + +import ( + "context" + "fmt" + + "opencsg.com/csghub-server/builder/deploy" + "opencsg.com/csghub-server/builder/git" + "opencsg.com/csghub-server/builder/git/gitserver" + "opencsg.com/csghub-server/builder/rpc" + "opencsg.com/csghub-server/builder/store/database" + "opencsg.com/csghub-server/common/config" + "opencsg.com/csghub-server/common/types" +) + +func NewSpaceComponent(config *config.Config) (SpaceComponent, error) { + c := &spaceComponentImpl{} + c.spaceStore = database.NewSpaceStore() + var err error + c.spaceSdkStore = database.NewSpaceSdkStore() + c.spaceResourceStore = database.NewSpaceResourceStore() + c.repoStore = database.NewRepoStore() + c.repoComponent, err = NewRepoComponentImpl(config) + if err != nil { + return nil, err + } + c.deployer = deploy.NewDeployer() + c.publicRootDomain = config.Space.PublicRootDomain + c.userStore = database.NewUserStore() + c.accountingComponent, err = NewAccountingComponent(config) + if err != nil { + return nil, err + } + c.serverBaseUrl = config.APIServer.PublicDomain + c.userLikesStore = database.NewUserLikesStore() + c.config = config + c.userSvcClient = rpc.NewUserSvcHttpClient(fmt.Sprintf("%s:%d", config.User.Host, config.User.Port), + rpc.AuthWithApiKey(config.APIToken)) + + c.deployTaskStore = database.NewDeployTaskStore() + c.git, err = git.NewGitServer(config) + if err != nil { + return nil, err + } + return c, nil +} + +type spaceComponentImpl struct { + repoComponent RepoComponent + git gitserver.GitServer + spaceStore database.SpaceStore + spaceSdkStore database.SpaceSdkStore + spaceResourceStore database.SpaceResourceStore + repoStore database.RepoStore + userStore database.UserStore + deployer deploy.Deployer + publicRootDomain string + accountingComponent AccountingComponent + serverBaseUrl string + userLikesStore database.UserLikesStore + config *config.Config + userSvcClient rpc.UserSvcClient + deployTaskStore database.DeployTaskStore +} + +func (c *spaceComponentImpl) checkResourcePurchasableForCreate(ctx context.Context, req types.CreateSpaceReq, resource *database.SpaceResource) error { + return nil +} + +func (c *spaceComponentImpl) checkResourcePurchasableForUpdate(ctx context.Context, req types.UpdateSpaceReq, resource *database.SpaceResource) error { + return nil +} + +func (c *spaceComponentImpl) checkResourceAvailable(ctx context.Context, req types.CreateSpaceReq, hardware types.HardWare) (bool, error) { + return c.deployer.CheckResourceAvailable(ctx, req.ClusterID, 0, &hardware) +} + +func (c *spaceComponentImpl) updateSpaceByReq(space database.Space, req types.CreateSpaceReq) database.Space { + return space +} + +func (c *spaceComponentImpl) resourceReserved(space *database.Space, req *types.UpdateSpaceReq) bool { + return false +} + +func (c *spaceComponentImpl) updateDeployRepoBySpace(repo types.DeployRepo, space *database.Space) types.DeployRepo { + return repo +} + +func (c *spaceComponentImpl) updateDeployRepoByDeploy(repo types.DeployRepo, deploy *database.Deploy) types.DeployRepo { + return repo +} diff --git a/component/space_ce_test.go b/component/space_ce_test.go new file mode 100644 index 00000000..c9175045 --- /dev/null +++ b/component/space_ce_test.go @@ -0,0 +1,168 @@ +//go:build !saas + +package component + +import ( + "context" + "testing" + + "github.com/alibabacloud-go/tea/tea" + "github.com/stretchr/testify/require" + "opencsg.com/csghub-server/builder/deploy/scheduler" + "opencsg.com/csghub-server/builder/store/database" + "opencsg.com/csghub-server/common/types" +) + +func TestSpaceComponent_Create(t *testing.T) { + ctx := context.TODO() + sc := initializeTestSpaceComponent(ctx, t) + + sc.mocks.stores.SpaceResourceMock().EXPECT().FindByID(ctx, int64(1)).Return(&database.SpaceResource{ + ID: 1, + Name: "sp", + Resources: `{"memory": "foo"}`, + }, nil) + + sc.mocks.deployer.EXPECT().CheckResourceAvailable(ctx, "cluster", int64(0), &types.HardWare{ + Memory: "foo", + }).Return(true, nil) + + sc.mocks.components.repo.EXPECT().CreateRepo(ctx, types.CreateRepoReq{ + DefaultBranch: "main", + Readme: generateReadmeData("MIT"), + License: "MIT", + Namespace: "ns", + Name: "n", + Nickname: "n", + RepoType: types.SpaceRepo, + Username: "user", + }).Return(nil, &database.Repository{ + ID: 321, + User: database.User{ + Username: "user", + Email: "foo@bar.com", + }, + }, nil) + + sc.mocks.stores.SpaceMock().EXPECT().Create(ctx, database.Space{ + RepositoryID: 321, + Sdk: scheduler.STREAMLIT.Name, + SdkVersion: "v1", + Env: "env", + Hardware: `{"memory": "foo"}`, + Secrets: "sss", + SKU: "1", + }).Return(&database.Space{}, nil) + sc.mocks.gitServer.EXPECT().CreateRepoFile(buildCreateFileReq(&types.CreateFileParams{ + Username: "user", + Email: "foo@bar.com", + Message: initCommitMessage, + Branch: "main", + Content: generateReadmeData("MIT"), + NewBranch: "main", + Namespace: "ns", + Name: "n", + FilePath: readmeFileName, + }, types.SpaceRepo)).Return(nil) + sc.mocks.gitServer.EXPECT().CreateRepoFile(buildCreateFileReq(&types.CreateFileParams{ + Username: "user", + Email: "foo@bar.com", + Message: initCommitMessage, + Branch: "main", + Content: spaceGitattributesContent, + NewBranch: "main", + Namespace: "ns", + Name: "n", + FilePath: gitattributesFileName, + }, types.SpaceRepo)).Return(nil) + sc.mocks.gitServer.EXPECT().CreateRepoFile(buildCreateFileReq(&types.CreateFileParams{ + Username: "user", + Email: "foo@bar.com", + Message: initCommitMessage, + Branch: "main", + Content: streamlitConfigContent, + NewBranch: "main", + Namespace: "ns", + Name: "n", + FilePath: streamlitConfig, + }, types.SpaceRepo)).Return(nil) + + space, err := sc.Create(ctx, types.CreateSpaceReq{ + Sdk: scheduler.STREAMLIT.Name, + SdkVersion: "v1", + Env: "env", + Secrets: "sss", + ResourceID: 1, + ClusterID: "cluster", + CreateRepoReq: types.CreateRepoReq{ + DefaultBranch: "main", + Readme: "readme", + Namespace: "ns", + Name: "n", + License: "MIT", + Username: "user", + }, + }) + require.Nil(t, err) + + require.Equal(t, &types.Space{ + License: "MIT", + Name: "n", + Sdk: "streamlit", + SdkVersion: "v1", + Env: "env", + Secrets: "sss", + Hardware: `{"memory": "foo"}`, + Creator: "user", + }, space) + +} + +func TestSpaceComponent_Update(t *testing.T) { + ctx := context.TODO() + sc := initializeTestSpaceComponent(ctx, t) + + sc.mocks.stores.SpaceResourceMock().EXPECT().FindByID(ctx, int64(12)).Return(&database.SpaceResource{ + ID: 12, + Name: "sp", + Resources: `{"memory": "foo"}`, + }, nil) + + sc.mocks.components.repo.EXPECT().UpdateRepo(ctx, types.UpdateRepoReq{ + Username: "user", + Namespace: "ns", + Name: "n", + RepoType: types.SpaceRepo, + }).Return( + &database.Repository{ + ID: 123, + Name: "repo", + }, nil, + ) + sc.mocks.stores.SpaceMock().EXPECT().ByRepoID(ctx, int64(123)).Return(&database.Space{ + ID: 321, + }, nil) + sc.mocks.stores.SpaceMock().EXPECT().Update(ctx, database.Space{ + ID: 321, + Hardware: `{"memory": "foo"}`, + SKU: "12", + }).Return(nil) + + space, err := sc.Update(ctx, &types.UpdateSpaceReq{ + ResourceID: tea.Int64(12), + UpdateRepoReq: types.UpdateRepoReq{ + Username: "user", + Namespace: "ns", + Name: "n", + }, + }) + require.Nil(t, err) + + require.Equal(t, &types.Space{ + ID: 321, + Name: "repo", + Hardware: `{"memory": "foo"}`, + SKU: "12", + }, space) + +} diff --git a/component/space_resource.go b/component/space_resource.go index b40939e0..28430d88 100644 --- a/component/space_resource.go +++ b/component/space_resource.go @@ -8,30 +8,17 @@ import ( "opencsg.com/csghub-server/builder/deploy" "opencsg.com/csghub-server/builder/store/database" - "opencsg.com/csghub-server/common/config" "opencsg.com/csghub-server/common/types" ) type SpaceResourceComponent interface { - Index(ctx context.Context, clusterId string, deployType int) ([]types.SpaceResource, error) + Index(ctx context.Context, clusterId string, deployType int, currentUser string) ([]types.SpaceResource, error) Update(ctx context.Context, req *types.UpdateSpaceResourceReq) (*types.SpaceResource, error) Create(ctx context.Context, req *types.CreateSpaceResourceReq) (*types.SpaceResource, error) Delete(ctx context.Context, id int64) error } -func NewSpaceResourceComponent(config *config.Config) (SpaceResourceComponent, error) { - c := &spaceResourceComponentImpl{} - c.srs = database.NewSpaceResourceStore() - c.deployer = deploy.NewDeployer() - return c, nil -} - -type spaceResourceComponentImpl struct { - srs database.SpaceResourceStore - deployer deploy.Deployer -} - -func (c *spaceResourceComponentImpl) Index(ctx context.Context, clusterId string, deployType int) ([]types.SpaceResource, error) { +func (c *spaceResourceComponentImpl) Index(ctx context.Context, clusterId string, deployType int, currentUser string) ([]types.SpaceResource, error) { // backward compatibility for old api if clusterId == "" { clusters, err := c.deployer.ListCluster(ctx) @@ -44,7 +31,7 @@ func (c *spaceResourceComponentImpl) Index(ctx context.Context, clusterId string clusterId = clusters[0].ClusterID } var result []types.SpaceResource - databaseSpaceResources, err := c.srs.Index(ctx, clusterId) + databaseSpaceResources, err := c.spaceResourceStore.Index(ctx, clusterId) if err != nil { return nil, err } @@ -52,6 +39,7 @@ func (c *spaceResourceComponentImpl) Index(ctx context.Context, clusterId string if err != nil { return nil, err } + for _, r := range databaseSpaceResources { var isAvailable bool var hardware types.HardWare @@ -61,16 +49,10 @@ func (c *spaceResourceComponentImpl) Index(ctx context.Context, clusterId string } else { isAvailable = deploy.CheckResource(clusterResources, &hardware) } - if deployType == types.FinetuneType { - if hardware.Gpu.Num == "" { - continue - } - } - resourceType := types.ResourceTypeCPU - if hardware.Gpu.Num != "" { - resourceType = types.ResourceTypeGPU + if !c.deployAvailable(deployType, hardware) { + continue } - + resourceType := c.resourceType(hardware) result = append(result, types.SpaceResource{ ID: r.ID, Name: r.Name, @@ -79,12 +61,21 @@ func (c *spaceResourceComponentImpl) Index(ctx context.Context, clusterId string Type: resourceType, }) } + err = c.updatePriceInfo(currentUser, result) + if err != nil { + return nil, err + } + + result, err = c.appendUserResources(ctx, currentUser, clusterId, result) + if err != nil { + return nil, err + } return result, nil } func (c *spaceResourceComponentImpl) Update(ctx context.Context, req *types.UpdateSpaceResourceReq) (*types.SpaceResource, error) { - sr, err := c.srs.FindByID(ctx, req.ID) + sr, err := c.spaceResourceStore.FindByID(ctx, req.ID) if err != nil { slog.Error("error getting space resource", slog.Any("error", err)) return nil, err @@ -92,7 +83,7 @@ func (c *spaceResourceComponentImpl) Update(ctx context.Context, req *types.Upda sr.Name = req.Name sr.Resources = req.Resources - sr, err = c.srs.Update(ctx, *sr) + sr, err = c.spaceResourceStore.Update(ctx, *sr) if err != nil { slog.Error("error updating space resource", slog.Any("error", err)) return nil, err @@ -113,7 +104,7 @@ func (c *spaceResourceComponentImpl) Create(ctx context.Context, req *types.Crea Resources: req.Resources, ClusterID: req.ClusterID, } - res, err := c.srs.Create(ctx, sr) + res, err := c.spaceResourceStore.Create(ctx, sr) if err != nil { slog.Error("error creating space resource", slog.Any("error", err)) return nil, err @@ -129,13 +120,13 @@ func (c *spaceResourceComponentImpl) Create(ctx context.Context, req *types.Crea } func (c *spaceResourceComponentImpl) Delete(ctx context.Context, id int64) error { - sr, err := c.srs.FindByID(ctx, id) + sr, err := c.spaceResourceStore.FindByID(ctx, id) if err != nil { slog.Error("error finding space resource", slog.Any("error", err)) return err } - err = c.srs.Delete(ctx, *sr) + err = c.spaceResourceStore.Delete(ctx, *sr) if err != nil { slog.Error("error deleting space resource", slog.Any("error", err)) return err diff --git a/component/space_resource_ce.go b/component/space_resource_ce.go new file mode 100644 index 00000000..fe43d8fe --- /dev/null +++ b/component/space_resource_ce.go @@ -0,0 +1,58 @@ +//go:build !ee && !saas + +package component + +import ( + "context" + + "opencsg.com/csghub-server/builder/deploy" + "opencsg.com/csghub-server/builder/store/database" + "opencsg.com/csghub-server/common/config" + "opencsg.com/csghub-server/common/types" +) + +func NewSpaceResourceComponent(config *config.Config) (SpaceResourceComponent, error) { + c := &spaceResourceComponentImpl{} + c.spaceResourceStore = database.NewSpaceResourceStore() + c.deployer = deploy.NewDeployer() + c.userStore = database.NewUserStore() + ac, err := NewAccountingComponent(config) + if err != nil { + return nil, err + } + c.accountComponent = ac + return c, nil +} + +type spaceResourceComponentImpl struct { + spaceResourceStore database.SpaceResourceStore + deployer deploy.Deployer + userStore database.UserStore + accountComponent AccountingComponent +} + +func (c *spaceResourceComponentImpl) updatePriceInfo(currentUser string, resources []types.SpaceResource) error { + return nil + +} + +func (c *spaceResourceComponentImpl) appendUserResources(ctx context.Context, currentUser string, clusterID string, resources []types.SpaceResource) ([]types.SpaceResource, error) { + return resources, nil +} + +func (c *spaceResourceComponentImpl) deployAvailable(deployType int, hardware types.HardWare) bool { + if deployType == types.FinetuneType { + if hardware.Gpu.Num == "" { + return false + } + } + return true +} + +func (c *spaceResourceComponentImpl) resourceType(hardware types.HardWare) types.ResourceType { + resourceType := types.ResourceTypeCPU + if hardware.Gpu.Num != "" { + resourceType = types.ResourceTypeGPU + } + return resourceType +} diff --git a/component/space_resource_ce_test.go b/component/space_resource_ce_test.go new file mode 100644 index 00000000..931427dd --- /dev/null +++ b/component/space_resource_ce_test.go @@ -0,0 +1,38 @@ +//go:build !ee && !saas + +package component + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "opencsg.com/csghub-server/builder/store/database" + "opencsg.com/csghub-server/common/types" +) + +func TestSpaceResourceComponent_Index(t *testing.T) { + ctx := context.TODO() + sc := initializeTestSpaceResourceComponent(ctx, t) + + sc.mocks.deployer.EXPECT().ListCluster(ctx).Return([]types.ClusterRes{ + {ClusterID: "c1"}, + }, nil) + sc.mocks.stores.SpaceResourceMock().EXPECT().Index(ctx, "c1").Return( + []database.SpaceResource{ + {ID: 1, Name: "sr", Resources: `{"memory": "1000", "gpu": {"num": "5"}}`}, + {ID: 2, Name: "sr2", Resources: `{"memory": "1000"}`}, + }, nil, + ) + sc.mocks.deployer.EXPECT().GetClusterById(ctx, "c1").Return(&types.ClusterRes{}, nil) + + data, err := sc.Index(ctx, "", types.FinetuneType, "user") + require.Nil(t, err) + require.Equal(t, []types.SpaceResource{ + { + ID: 1, Name: "sr", Resources: `{"memory": "1000", "gpu": {"num": "5"}}`, + IsAvailable: false, Type: "gpu", + }, + }, data) + +} diff --git a/component/space_resource_test.go b/component/space_resource_test.go index 024cc1e9..28a93fe3 100644 --- a/component/space_resource_test.go +++ b/component/space_resource_test.go @@ -1,94 +1,71 @@ package component -// func TestSpaceResourceComponent_Index(t *testing.T) { -// ctx := context.TODO() -// sc := initializeTestSpaceResourceComponent(ctx, t) +import ( + "context" + "testing" -// sc.mocks.deployer.EXPECT().ListCluster(ctx).Return([]types.ClusterRes{ -// {ClusterID: "c1"}, -// }, nil) -// sc.mocks.stores.SpaceResourceMock().EXPECT().Index(ctx, "c1").Return( -// []database.SpaceResource{ -// {ID: 1, Name: "sr", Resources: `{"memory": "1000"}`}, -// }, nil, -// ) -// sc.mocks.deployer.EXPECT().GetClusterById(ctx, "c1").Return(&types.ClusterRes{}, nil) -// sc.mocks.stores.UserMock().EXPECT().FindByUsername(ctx, "user").Return(database.User{ -// UUID: "uid", -// }, nil) + "github.com/stretchr/testify/require" + "opencsg.com/csghub-server/builder/store/database" + "opencsg.com/csghub-server/common/types" +) -// data, err := sc.Index(ctx, "", 1) -// require.Nil(t, err) -// require.Equal(t, []types.SpaceResource{ -// { -// ID: 1, Name: "sr", Resources: "{\"memory\": \"1000\"}", -// IsAvailable: false, Type: "cpu", -// }, -// { -// ID: 0, Name: "", Resources: "{\"memory\": \"2000\"}", IsAvailable: true, -// Type: "cpu", -// }, -// }, data) +func TestSpaceResourceComponent_Update(t *testing.T) { + ctx := context.TODO() + sc := initializeTestSpaceResourceComponent(ctx, t) -// } + sc.mocks.stores.SpaceResourceMock().EXPECT().FindByID(ctx, int64(1)).Return( + &database.SpaceResource{}, nil, + ) + sc.mocks.stores.SpaceResourceMock().EXPECT().Update(ctx, database.SpaceResource{ + Name: "n", + Resources: "r", + }).Return(&database.SpaceResource{ID: 1, Name: "n", Resources: "r"}, nil) -// func TestSpaceResourceComponent_Update(t *testing.T) { -// ctx := context.TODO() -// sc := initializeTestSpaceResourceComponent(ctx, t) + data, err := sc.Update(ctx, &types.UpdateSpaceResourceReq{ + ID: 1, + Name: "n", + Resources: "r", + }) + require.Nil(t, err) + require.Equal(t, &types.SpaceResource{ + ID: 1, + Name: "n", + Resources: "r", + }, data) +} -// sc.mocks.stores.SpaceResourceMock().EXPECT().FindByID(ctx, int64(1)).Return( -// &database.SpaceResource{}, nil, -// ) -// sc.mocks.stores.SpaceResourceMock().EXPECT().Update(ctx, database.SpaceResource{ -// Name: "n", -// Resources: "r", -// }).Return(&database.SpaceResource{ID: 1, Name: "n", Resources: "r"}, nil) +func TestSpaceResourceComponent_Create(t *testing.T) { + ctx := context.TODO() + sc := initializeTestSpaceResourceComponent(ctx, t) -// data, err := sc.Update(ctx, &types.UpdateSpaceResourceReq{ -// ID: 1, -// Name: "n", -// Resources: "r", -// }) -// require.Nil(t, err) -// require.Equal(t, &types.SpaceResource{ -// ID: 1, -// Name: "n", -// Resources: "r", -// }, data) -// } + sc.mocks.stores.SpaceResourceMock().EXPECT().Create(ctx, database.SpaceResource{ + Name: "n", + Resources: "r", + ClusterID: "c", + }).Return(&database.SpaceResource{ID: 1, Name: "n", Resources: "r"}, nil) -// func TestSpaceResourceComponent_Create(t *testing.T) { -// ctx := context.TODO() -// sc := initializeTestSpaceResourceComponent(ctx, t) + data, err := sc.Create(ctx, &types.CreateSpaceResourceReq{ + Name: "n", + Resources: "r", + ClusterID: "c", + }) + require.Nil(t, err) + require.Equal(t, &types.SpaceResource{ + ID: 1, + Name: "n", + Resources: "r", + }, data) +} -// sc.mocks.stores.SpaceResourceMock().EXPECT().Create(ctx, database.SpaceResource{ -// Name: "n", -// Resources: "r", -// ClusterID: "c", -// }).Return(&database.SpaceResource{ID: 1, Name: "n", Resources: "r"}, nil) +func TestSpaceResourceComponent_Delete(t *testing.T) { + ctx := context.TODO() + sc := initializeTestSpaceResourceComponent(ctx, t) -// data, err := sc.Create(ctx, &types.CreateSpaceResourceReq{ -// Name: "n", -// Resources: "r", -// ClusterID: "c", -// }) -// require.Nil(t, err) -// require.Equal(t, &types.SpaceResource{ -// ID: 1, -// Name: "n", -// Resources: "r", -// }, data) -// } + sc.mocks.stores.SpaceResourceMock().EXPECT().FindByID(ctx, int64(1)).Return( + &database.SpaceResource{}, nil, + ) + sc.mocks.stores.SpaceResourceMock().EXPECT().Delete(ctx, database.SpaceResource{}).Return(nil) -// func TestSpaceResourceComponent_Delete(t *testing.T) { -// ctx := context.TODO() -// sc := initializeTestSpaceResourceComponent(ctx, t) - -// sc.mocks.stores.SpaceResourceMock().EXPECT().FindByID(ctx, int64(1)).Return( -// &database.SpaceResource{}, nil, -// ) -// sc.mocks.stores.SpaceResourceMock().EXPECT().Delete(ctx, database.SpaceResource{}).Return(nil) - -// err := sc.Delete(ctx, 1) -// require.Nil(t, err) -// } + err := sc.Delete(ctx, 1) + require.Nil(t, err) +} diff --git a/component/space_test.go b/component/space_test.go index 57d894de..72486077 100644 --- a/component/space_test.go +++ b/component/space_test.go @@ -6,7 +6,6 @@ import ( "testing" "time" - "github.com/alibabacloud-go/tea/tea" "github.com/stretchr/testify/require" "opencsg.com/csghub-server/builder/deploy" "opencsg.com/csghub-server/builder/deploy/scheduler" @@ -16,111 +15,6 @@ import ( "opencsg.com/csghub-server/common/types" ) -// func TestSpaceComponent_Create(t *testing.T) { -// ctx := context.TODO() -// sc := initializeTestSpaceComponent(ctx, t) - -// sc.mocks.stores.SpaceResourceMock().EXPECT().FindByID(ctx, int64(1)).Return(&database.SpaceResource{ -// ID: 1, -// Name: "sp", -// Resources: `{"memory": "foo"}`, -// }, nil) - -// sc.mocks.deployer.EXPECT().CheckResourceAvailable(ctx, int64(0), &types.HardWare{ -// Memory: "foo", -// }).Return(true, nil) - -// sc.mocks.components.repo.EXPECT().CreateRepo(ctx, types.CreateRepoReq{ -// DefaultBranch: "main", -// Readme: generateReadmeData("MIT"), -// License: "MIT", -// Namespace: "ns", -// Name: "n", -// Nickname: "n", -// RepoType: types.SpaceRepo, -// Username: "user", -// }).Return(nil, &database.Repository{ -// ID: 321, -// User: database.User{ -// Username: "user", -// Email: "foo@bar.com", -// }, -// }, nil) - -// sc.mocks.stores.SpaceMock().EXPECT().Create(ctx, database.Space{ -// RepositoryID: 321, -// Sdk: scheduler.STREAMLIT.Name, -// SdkVersion: "v1", -// Env: "env", -// Hardware: `{"memory": "foo"}`, -// Secrets: "sss", -// SKU: "1", -// }).Return(&database.Space{}, nil) -// sc.mocks.gitServer.EXPECT().CreateRepoFile(buildCreateFileReq(&types.CreateFileParams{ -// Username: "user", -// Email: "foo@bar.com", -// Message: initCommitMessage, -// Branch: "main", -// Content: generateReadmeData("MIT"), -// NewBranch: "main", -// Namespace: "ns", -// Name: "n", -// FilePath: readmeFileName, -// }, types.SpaceRepo)).Return(nil) -// sc.mocks.gitServer.EXPECT().CreateRepoFile(buildCreateFileReq(&types.CreateFileParams{ -// Username: "user", -// Email: "foo@bar.com", -// Message: initCommitMessage, -// Branch: "main", -// Content: spaceGitattributesContent, -// NewBranch: "main", -// Namespace: "ns", -// Name: "n", -// FilePath: gitattributesFileName, -// }, types.SpaceRepo)).Return(nil) -// sc.mocks.gitServer.EXPECT().CreateRepoFile(buildCreateFileReq(&types.CreateFileParams{ -// Username: "user", -// Email: "foo@bar.com", -// Message: initCommitMessage, -// Branch: "main", -// Content: streamlitConfigContent, -// NewBranch: "main", -// Namespace: "ns", -// Name: "n", -// FilePath: streamlitConfig, -// }, types.SpaceRepo)).Return(nil) - -// space, err := sc.Create(ctx, types.CreateSpaceReq{ -// Sdk: scheduler.STREAMLIT.Name, -// SdkVersion: "v1", -// Env: "env", -// Secrets: "sss", -// ResourceID: 1, -// ClusterID: "cluster", -// CreateRepoReq: types.CreateRepoReq{ -// DefaultBranch: "main", -// Readme: "readme", -// Namespace: "ns", -// Name: "n", -// License: "MIT", -// Username: "user", -// }, -// }) -// require.Nil(t, err) - -// require.Equal(t, &types.Space{ -// License: "MIT", -// Name: "n", -// Sdk: "streamlit", -// SdkVersion: "v1", -// Env: "env", -// Secrets: "sss", -// Hardware: `{"memory": "foo"}`, -// Creator: "user", -// }, space) - -// } - func TestSpaceComponent_Show(t *testing.T) { ctx := context.TODO() sc := initializeTestSpaceComponent(ctx, t) @@ -152,15 +46,16 @@ func TestSpaceComponent_Show(t *testing.T) { space, err := sc.Show(ctx, "ns", "n", "user") require.Nil(t, err) require.Equal(t, &types.Space{ - ID: 1, - Name: "n", - Namespace: &types.Namespace{Path: "ns"}, - UserLikes: true, - RepositoryID: 123, - Status: "Stopped", - CanManage: true, - User: &types.User{}, - Path: "foo/bar", + ID: 1, + Name: "n", + Namespace: &types.Namespace{Path: "ns"}, + UserLikes: true, + RepositoryID: 123, + Status: "Stopped", + CanManage: true, + User: &types.User{}, + Path: "foo/bar", + SensitiveCheckStatus: "Pending", Repository: &types.Repository{ HTTPCloneURL: "/s/foo/bar.git", SSHCloneURL: ":s/foo/bar.git", @@ -170,55 +65,6 @@ func TestSpaceComponent_Show(t *testing.T) { }, space) } -func TestSpaceComponent_Update(t *testing.T) { - ctx := context.TODO() - sc := initializeTestSpaceComponent(ctx, t) - - sc.mocks.stores.SpaceResourceMock().EXPECT().FindByID(ctx, int64(12)).Return(&database.SpaceResource{ - ID: 12, - Name: "sp", - Resources: `{"memory": "foo"}`, - }, nil) - - sc.mocks.components.repo.EXPECT().UpdateRepo(ctx, types.UpdateRepoReq{ - Username: "user", - Namespace: "ns", - Name: "n", - RepoType: types.SpaceRepo, - }).Return( - &database.Repository{ - ID: 123, - Name: "repo", - }, nil, - ) - sc.mocks.stores.SpaceMock().EXPECT().ByRepoID(ctx, int64(123)).Return(&database.Space{ - ID: 321, - }, nil) - sc.mocks.stores.SpaceMock().EXPECT().Update(ctx, database.Space{ - ID: 321, - Hardware: `{"memory": "foo"}`, - SKU: "12", - }).Return(nil) - - space, err := sc.Update(ctx, &types.UpdateSpaceReq{ - ResourceID: tea.Int64(12), - UpdateRepoReq: types.UpdateRepoReq{ - Username: "user", - Namespace: "ns", - Name: "n", - }, - }) - require.Nil(t, err) - - require.Equal(t, &types.Space{ - ID: 321, - Name: "repo", - Hardware: `{"memory": "foo"}`, - SKU: "12", - }, space) - -} - func TestSpaceComponent_Index(t *testing.T) { ctx := context.TODO() sc := initializeTestSpaceComponent(ctx, t) @@ -457,6 +303,31 @@ func TestSpaceComponent_Wakeup(t *testing.T) { } +func TestSpaceComponent_Stop(t *testing.T) { + ctx := context.TODO() + sc := initializeTestSpaceComponent(ctx, t) + sc.mocks.stores.SpaceMock().EXPECT().FindByPath(ctx, "ns", "n").Return(&database.Space{ + ID: 1, + }, nil) + + sc.mocks.stores.DeployTaskMock().EXPECT().GetLatestDeployBySpaceID(ctx, int64(1)).Return( + &database.Deploy{SvcName: "svc", RepoID: 1, UserID: 2, ID: 3}, nil, + ) + + sc.mocks.deployer.EXPECT().Stop(ctx, types.DeployRepo{ + SpaceID: 1, + Namespace: "ns", + Name: "n", + SvcName: "svc", + }).Return(nil) + sc.mocks.stores.DeployTaskMock().EXPECT().StopDeploy( + ctx, types.SpaceRepo, int64(1), int64(2), int64(3), + ).Return(nil) + + err := sc.Stop(ctx, "ns", "n", false) + require.Nil(t, err) +} + func TestSpaceComponent_FixHasEntryFile(t *testing.T) { cases := []struct { diff --git a/component/wireset.go b/component/wireset.go index e9394a66..a63d2ab5 100644 --- a/component/wireset.go +++ b/component/wireset.go @@ -207,34 +207,6 @@ func NewTestUserComponent( var UserComponentSet = wire.NewSet(NewTestUserComponent) -func NewTestSpaceComponent( - stores *tests.MockStores, - repoComponent RepoComponent, - git gitserver.GitServer, - deployer deploy.Deployer, - accountingComponent AccountingComponent, - config *config.Config, - userSvcClient rpc.UserSvcClient, -) *spaceComponentImpl { - return &spaceComponentImpl{ - repoComponent: repoComponent, - git: git, - spaceStore: stores.Space, - spaceSdkStore: stores.SpaceSdk, - spaceResourceStore: stores.SpaceResource, - repoStore: stores.Repo, - userStore: stores.User, - deployer: deployer, - publicRootDomain: config.Space.PublicRootDomain, - accountingComponent: accountingComponent, - serverBaseUrl: config.APIServer.PublicDomain, - userLikesStore: stores.UserLikes, - config: config, - userSvcClient: userSvcClient, - deployTaskStore: stores.DeployTask, - } -} - var SpaceComponentSet = wire.NewSet(NewTestSpaceComponent) func NewTestModelComponent( @@ -452,12 +424,6 @@ func NewTestMirrorSourceComponent(config *config.Config, stores *tests.MockStore var MirrorSourceComponentSet = wire.NewSet(NewTestMirrorSourceComponent) -func NewTestSpaceResourceComponent(config *config.Config, stores *tests.MockStores, deployer deploy.Deployer, accountComponent AccountingComponent) *spaceResourceComponentImpl { - return &spaceResourceComponentImpl{ - deployer: deployer, - } -} - var SpaceResourceComponentSet = wire.NewSet(NewTestSpaceResourceComponent) func NewTestTagComponent(config *config.Config, stores *tests.MockStores, sensitiveChecker rpc.ModerationSvcClient) *tagComponentImpl { diff --git a/component/wireset_ce.go b/component/wireset_ce.go new file mode 100644 index 00000000..ce845e06 --- /dev/null +++ b/component/wireset_ce.go @@ -0,0 +1,48 @@ +//go:build !saas + +package component + +import ( + "opencsg.com/csghub-server/builder/deploy" + "opencsg.com/csghub-server/builder/git/gitserver" + "opencsg.com/csghub-server/builder/rpc" + "opencsg.com/csghub-server/common/config" + "opencsg.com/csghub-server/common/tests" +) + +func NewTestSpaceComponent( + stores *tests.MockStores, + repoComponent RepoComponent, + git gitserver.GitServer, + deployer deploy.Deployer, + accountingComponent AccountingComponent, + config *config.Config, + userSvcClient rpc.UserSvcClient, +) *spaceComponentImpl { + return &spaceComponentImpl{ + repoComponent: repoComponent, + git: git, + spaceStore: stores.Space, + spaceSdkStore: stores.SpaceSdk, + spaceResourceStore: stores.SpaceResource, + repoStore: stores.Repo, + userStore: stores.User, + deployer: deployer, + publicRootDomain: config.Space.PublicRootDomain, + accountingComponent: accountingComponent, + serverBaseUrl: config.APIServer.PublicDomain, + userLikesStore: stores.UserLikes, + config: config, + userSvcClient: userSvcClient, + deployTaskStore: stores.DeployTask, + } +} + +func NewTestSpaceResourceComponent(config *config.Config, stores *tests.MockStores, deployer deploy.Deployer, accountComponent AccountingComponent) *spaceResourceComponentImpl { + return &spaceResourceComponentImpl{ + spaceResourceStore: stores.SpaceResource, + deployer: deployer, + userStore: stores.User, + accountComponent: accountComponent, + } +}