diff --git a/app/api/controller/gitspace/action.go b/app/api/controller/gitspace/action.go index f9a5e0d4c..a7ebb5637 100644 --- a/app/api/controller/gitspace/action.go +++ b/app/api/controller/gitspace/action.go @@ -69,11 +69,11 @@ func (c *Controller) Action( } // check if it's an internal repo - if gitspaceConfig.CodeRepoType == enum.CodeRepoTypeGitness { - if gitspaceConfig.CodeRepoRef == nil { + if gitspaceConfig.CodeRepo.Type == enum.CodeRepoTypeGitness { + if gitspaceConfig.CodeRepo.Ref == nil { return nil, fmt.Errorf("couldn't fetch repo for the user, no ref found: %w", err) } - repo, err := c.repoStore.FindByRef(ctx, *gitspaceConfig.CodeRepoRef) + repo, err := c.repoStore.FindByRef(ctx, *gitspaceConfig.CodeRepo.Ref) if err != nil { return nil, fmt.Errorf("couldn't fetch repo for the user: %w", err) } @@ -221,7 +221,7 @@ func (c *Controller) buildGitspaceInstance(config *types.GitspaceConfig) (*types GitSpaceConfigID: config.ID, Identifier: identifier, State: enum.GitspaceInstanceStateStarting, - UserID: config.UserID, + UserID: config.GitspaceUser.Identifier, SpaceID: config.SpaceID, SpacePath: config.SpacePath, Created: now, diff --git a/app/api/controller/gitspace/create.go b/app/api/controller/gitspace/create.go index ba66a114d..ef00884fd 100644 --- a/app/api/controller/gitspace/create.go +++ b/app/api/controller/gitspace/create.go @@ -133,24 +133,35 @@ func (c *Controller) Create( if err != nil { return fmt.Errorf("could not find infra provider resource : %q %w", resourceIdentifier, err) } + codeRepo := types.CodeRepo{ + URL: in.CodeRepoURL, + Ref: in.CodeRepoRef, + Type: in.CodeRepoType, + Branch: in.Branch, + DevcontainerPath: in.DevcontainerPath, + } + + principal := session.Principal + principalID := principal.ID + user := types.GitspaceUser{ + Identifier: principal.UID, + Email: principal.Email, + DisplayName: principal.DisplayName, + ID: &principalID} gitspaceConfig = &types.GitspaceConfig{ Identifier: identifier, Name: in.Name, IDE: in.IDE, InfraProviderResourceID: infraProviderResource.ID, InfraProviderResourceIdentifier: infraProviderResource.Identifier, - CodeRepoType: in.CodeRepoType, State: enum.GitspaceStateUninitialized, - CodeRepoURL: in.CodeRepoURL, - CodeRepoRef: in.CodeRepoRef, - Branch: in.Branch, - DevcontainerPath: in.DevcontainerPath, - UserID: session.Principal.UID, SpaceID: space.ID, SpacePath: space.Path, Created: now, Updated: now, SSHTokenIdentifier: in.SSHTokenIdentifier, + CodeRepo: codeRepo, + GitspaceUser: user, } err = c.gitspaceConfigStore.Create(ctx, gitspaceConfig) if err != nil { diff --git a/app/gitspace/orchestrator/container/embedded_docker.go b/app/gitspace/orchestrator/container/embedded_docker.go index 7751018ad..b491b5098 100644 --- a/app/gitspace/orchestrator/container/embedded_docker.go +++ b/app/gitspace/orchestrator/container/embedded_docker.go @@ -111,7 +111,7 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace( return nil, err } - homeDir := GetUserHomeDir(gitspaceConfig.UserID) + homeDir := GetUserHomeDir(gitspaceConfig.GitspaceUser.Identifier) codeRepoDir := filepath.Join(homeDir, resolvedRepoDetails.RepoName) switch state { @@ -142,7 +142,7 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace( ContainerName: containerName, DockerClient: dockerClient, HomeDir: homeDir, - UserIdentifier: gitspaceConfig.UserID, + UserIdentifier: gitspaceConfig.GitspaceUser.Identifier, AccessKey: accessKey, AccessType: gitspaceConfig.GitspaceInstance.AccessType, } @@ -265,7 +265,7 @@ func (e *EmbeddedDockerOrchestrator) startGitspace( ContainerName: containerName, DockerClient: dockerClient, HomeDir: homeDir, - UserIdentifier: gitspaceConfig.UserID, + UserIdentifier: gitspaceConfig.GitspaceUser.Identifier, AccessKey: accessKey, AccessType: gitspaceConfig.GitspaceInstance.AccessType, } diff --git a/app/gitspace/orchestrator/container/util.go b/app/gitspace/orchestrator/container/util.go index 1879c6fe4..ce9cb16be 100644 --- a/app/gitspace/orchestrator/container/util.go +++ b/app/gitspace/orchestrator/container/util.go @@ -25,7 +25,7 @@ const ( ) func GetGitspaceContainerName(config types.GitspaceConfig) string { - return "gitspace-" + config.UserID + "-" + config.Identifier + return "gitspace-" + config.GitspaceUser.Identifier + "-" + config.Identifier } func GetUserHomeDir(userIdentifier string) string { diff --git a/app/gitspace/orchestrator/orchestrator_impl.go b/app/gitspace/orchestrator/orchestrator_impl.go index 4e638e52d..6dd4d1540 100644 --- a/app/gitspace/orchestrator/orchestrator_impl.go +++ b/app/gitspace/orchestrator/orchestrator_impl.go @@ -170,7 +170,7 @@ func (o orchestrator) stopGitspaceContainer( o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceStopStart) // NOTE: Currently we use a static identifier as the Gitspace user. - gitspaceConfig.UserID = harnessUser + gitspaceConfig.GitspaceUser.Identifier = harnessUser err = o.containerOrchestrator.StopGitspace(ctx, gitspaceConfig, infra) if err != nil { @@ -202,7 +202,7 @@ func (o orchestrator) stopAndRemoveGitspaceContainer( o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceDeletionStart) // NOTE: Currently we use a static identifier as the Gitspace user. - gitspaceConfig.UserID = harnessUser + gitspaceConfig.GitspaceUser.Identifier = harnessUser err = o.containerOrchestrator.StopAndRemoveGitspace(ctx, gitspaceConfig, infra) if err != nil { @@ -304,7 +304,7 @@ func (o orchestrator) ResumeStartGitspace( return *gitspaceInstance, err } resolvedSecret, err := secretResolver.Resolve(ctx, secret.ResolutionContext{ - UserIdentifier: gitspaceConfig.UserID, + UserIdentifier: gitspaceConfig.GitspaceUser.Identifier, GitspaceIdentifier: gitspaceConfig.Identifier, SecretRef: *gitspaceInstance.AccessKeyRef, SpaceIdentifier: rootSpaceID, @@ -375,7 +375,7 @@ func (o orchestrator) ResumeStartGitspace( o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationStart) // NOTE: Currently we use a static identifier as the Gitspace user. - gitspaceConfig.UserID = harnessUser + gitspaceConfig.GitspaceUser.Identifier = harnessUser startResponse, err := o.containerOrchestrator.CreateAndStartGitspace( ctx, gitspaceConfig, provisionedInfra, *scmResolvedDetails, o.config.DefaultBaseImage, ideSvc) @@ -418,7 +418,7 @@ func (o orchestrator) ResumeStartGitspace( Host: "", // Empty since we include the host and port in the path Path: fmt.Sprintf( "ssh-remote+%s@%s:%s", - gitspaceConfig.UserID, + gitspaceConfig.GitspaceUser.Identifier, host, filepath.Join(forwardedPort, relativeRepoPath), ), @@ -547,7 +547,7 @@ func (o orchestrator) GetGitspaceLogs(ctx context.Context, gitspaceConfig types. return "", fmt.Errorf("cannot find the provisioned infra: %w", err) } // NOTE: Currently we use a static identifier as the Gitspace user. - gitspaceConfig.UserID = harnessUser + gitspaceConfig.GitspaceUser.Identifier = harnessUser logs, err := o.containerOrchestrator.StreamLogs(ctx, gitspaceConfig, *infra) if err != nil { return "", fmt.Errorf("error while fetching logs from container orchestrator: %w", err) diff --git a/app/gitspace/scm/gitness_scm.go b/app/gitspace/scm/gitness_scm.go index 9e1e1761b..6249017fe 100644 --- a/app/gitspace/scm/gitness_scm.go +++ b/app/gitspace/scm/gitness_scm.go @@ -64,12 +64,12 @@ func (s GitnessSCM) ResolveCredentials( ctx context.Context, gitspaceConfig types.GitspaceConfig, ) (*ResolvedCredentials, error) { - repoURL, err := url.Parse(gitspaceConfig.CodeRepoURL) + repoURL, err := url.Parse(gitspaceConfig.CodeRepo.URL) if err != nil { - return nil, fmt.Errorf("failed to parse repository URL %s: %w", gitspaceConfig.CodeRepoURL, err) + return nil, fmt.Errorf("failed to parse repository URL %s: %w", gitspaceConfig.CodeRepo.URL, err) } repoName := strings.TrimSuffix(path.Base(repoURL.Path), ".git") - repo, err := s.repoStore.FindByRef(ctx, *gitspaceConfig.CodeRepoRef) + repo, err := s.repoStore.FindByRef(ctx, *gitspaceConfig.CodeRepo.Ref) if err != nil { return nil, fmt.Errorf("failed to find repository: %w", err) } @@ -79,10 +79,10 @@ func (s GitnessSCM) ResolveCredentials( } // Backfill clone URL gitURL := s.urlProvider.GenerateContainerGITCloneURL(ctx, repo.Path) - resolvedCredentails := &ResolvedCredentials{Branch: gitspaceConfig.Branch, CloneURL: gitURL} + resolvedCredentails := &ResolvedCredentials{Branch: gitspaceConfig.CodeRepo.Branch, CloneURL: gitURL} resolvedCredentails.RepoName = repoName gitspacePrincipal := bootstrap.NewGitspaceServiceSession().Principal - user, err := findUserFromUID(ctx, s.principalStore, gitspaceConfig.UserID) + user, err := findUserFromUID(ctx, s.principalStore, gitspaceConfig.GitspaceUser.Identifier) if err != nil { return nil, err } @@ -119,7 +119,7 @@ func (s GitnessSCM) GetFileContent(ctx context.Context, gitspaceConfig types.GitspaceConfig, filePath string, ) ([]byte, error) { - repo, err := s.repoStore.FindByRef(ctx, *gitspaceConfig.CodeRepoRef) + repo, err := s.repoStore.FindByRef(ctx, *gitspaceConfig.CodeRepo.Ref) if err != nil { return nil, fmt.Errorf("failed to find repository: %w", err) } @@ -127,7 +127,7 @@ func (s GitnessSCM) GetFileContent(ctx context.Context, readParams := git.CreateReadParams(repo) treeNodeOutput, err := s.git.GetTreeNode(ctx, &git.GetTreeNodeParams{ ReadParams: readParams, - GitREF: gitspaceConfig.Branch, + GitREF: gitspaceConfig.CodeRepo.Branch, Path: filePath, IncludeLatestCommit: false, }) @@ -139,7 +139,7 @@ func (s GitnessSCM) GetFileContent(ctx context.Context, if treeNodeOutput.Node.Type != git.TreeNodeTypeBlob { return nil, usererror.BadRequestf( "Object in '%s' at '/%s' is of type '%s'. Only objects of type %s support raw viewing.", - gitspaceConfig.Branch, filePath, treeNodeOutput.Node.Type, git.TreeNodeTypeBlob) + gitspaceConfig.CodeRepo.Branch, filePath, treeNodeOutput.Node.Type, git.TreeNodeTypeBlob) } blobReader, err := s.git.GetBlob(ctx, &git.GetBlobParams{ diff --git a/app/gitspace/scm/public_scm.go b/app/gitspace/scm/public_scm.go index 73156a9ca..643c34fcd 100644 --- a/app/gitspace/scm/public_scm.go +++ b/app/gitspace/scm/public_scm.go @@ -58,14 +58,14 @@ func (s GenericSCM) GetFileContent(ctx context.Context, log.Info().Msg("Cloning the repository...") cmd := command.New("clone", - command.WithFlag("--branch", gitspaceConfig.Branch), + command.WithFlag("--branch", gitspaceConfig.CodeRepo.Branch), command.WithFlag("--no-checkout"), command.WithFlag("--depth", "1"), - command.WithArg(gitspaceConfig.CodeRepoURL), + command.WithArg(gitspaceConfig.CodeRepo.URL), command.WithArg(cloneDir), ) if err := cmd.Run(ctx, command.WithDir(cloneDir)); err != nil { - return nil, fmt.Errorf("failed to clone repository %s: %w", gitspaceConfig.CodeRepoURL, err) + return nil, fmt.Errorf("failed to clone repository %s: %w", gitspaceConfig.CodeRepo.URL, err) } var lsTreeOutput bytes.Buffer @@ -106,11 +106,11 @@ func (s GenericSCM) ResolveCredentials( ) (*ResolvedCredentials, error) { var resolvedCredentials = &ResolvedCredentials{ Branch: gitspaceConfig.Branch, - CloneURL: gitspaceConfig.CodeRepoURL, + CloneURL: gitspaceConfig.CodeRepo.URL, } - repoURL, err := url.Parse(gitspaceConfig.CodeRepoURL) + repoURL, err := url.Parse(gitspaceConfig.CodeRepo.URL) if err != nil { - return nil, fmt.Errorf("failed to parse repository URL %s: %w", gitspaceConfig.CodeRepoURL, err) + return nil, fmt.Errorf("failed to parse repository URL %s: %w", gitspaceConfig.CodeRepo.URL, err) } repoName := strings.TrimSuffix(path.Base(repoURL.Path), ".git") resolvedCredentials.RepoName = repoName diff --git a/app/gitspace/scm/scm.go b/app/gitspace/scm/scm.go index f85ed0428..5a5a3cc1e 100644 --- a/app/gitspace/scm/scm.go +++ b/app/gitspace/scm/scm.go @@ -81,10 +81,10 @@ func (s scm) GetSCMRepoDetails( gitspaceConfig types.GitspaceConfig, ) (*ResolvedDetails, error) { filePath := devcontainerDefaultPath - if gitspaceConfig.CodeRepoType == "" { - gitspaceConfig.CodeRepoType = enum.CodeRepoTypeUnknown + if gitspaceConfig.CodeRepo.Type == "" { + gitspaceConfig.CodeRepo.Type = enum.CodeRepoTypeUnknown } - scmProvider, err := s.scmProviderFactory.GetSCMProvider(gitspaceConfig.CodeRepoType) + scmProvider, err := s.scmProviderFactory.GetSCMProvider(gitspaceConfig.CodeRepo.Type) if err != nil { return nil, fmt.Errorf("failed to resolve scm provider: %w", err) } diff --git a/app/services/infraprovider/create.go b/app/services/infraprovider/create.go new file mode 100644 index 000000000..eedde0eae --- /dev/null +++ b/app/services/infraprovider/create.go @@ -0,0 +1,114 @@ +// Copyright 2023 Harness, Inc. +// +// 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 infraprovider + +import ( + "context" + "fmt" + + "github.com/harness/gitness/infraprovider" + "github.com/harness/gitness/types" + + "github.com/rs/zerolog/log" +) + +func (c *Service) CreateTemplate( + ctx context.Context, + template *types.InfraProviderTemplate, +) error { + return c.infraProviderTemplateStore.Create(ctx, template) +} + +func (c *Service) CreateInfraProvider( + ctx context.Context, + infraProviderConfig *types.InfraProviderConfig, +) error { + err := c.tx.WithTx(ctx, func(ctx context.Context) error { + err := c.createConfig(ctx, infraProviderConfig) + if err != nil { + return fmt.Errorf("could not autocreate the config: %q %w", infraProviderConfig.Identifier, err) + } + err = c.createResources(ctx, infraProviderConfig.Resources, infraProviderConfig.ID) + if err != nil { + return fmt.Errorf("could not autocreate the resources: %v %w", infraProviderConfig.Resources, err) + } + return nil + }) + if err != nil { + return fmt.Errorf("failed to complete txn for the infraprovider %w", err) + } + return nil +} + +func (c *Service) createConfig(ctx context.Context, infraProviderConfig *types.InfraProviderConfig) error { + err := c.infraProviderConfigStore.Create(ctx, infraProviderConfig) + if err != nil { + return fmt.Errorf("failed to create infraprovider config for : %q %w", infraProviderConfig.Identifier, err) + } + return nil +} + +func (c *Service) CreateResources(ctx context.Context, resources []types.InfraProviderResource, configID int64) error { + err := c.tx.WithTx(ctx, func(ctx context.Context) error { + return c.createResources(ctx, resources, configID) + }) + if err != nil { + return fmt.Errorf("failed to complete create txn for the infraprovider resource %w", err) + } + return nil +} + +func (c *Service) createResources(ctx context.Context, resources []types.InfraProviderResource, configID int64) error { + for idx := range resources { + resource := &resources[idx] + resource.InfraProviderConfigID = configID + infraProvider, err := c.infraProviderFactory.GetInfraProvider(resource.InfraProviderType) + if err != nil { + return fmt.Errorf("failed to fetch infrastructure impl for type : %q %w", resource.InfraProviderType, err) + } + if len(infraProvider.TemplateParams()) > 0 { + err = c.validateTemplates(ctx, infraProvider, *resource) + if err != nil { + return err + } + } + err = c.infraProviderResourceStore.Create(ctx, resource) + if err != nil { + return fmt.Errorf("failed to create infraprovider resource for : %q %w", resource.Identifier, err) + } + } + return nil +} + +func (c *Service) validateTemplates( + ctx context.Context, + infraProvider infraprovider.InfraProvider, + res types.InfraProviderResource, +) error { + templateParams := infraProvider.TemplateParams() + for _, param := range templateParams { + key := param.Name + if res.Metadata[key] != "" { + templateIdentifier := res.Metadata[key] + _, err := c.infraProviderTemplateStore.FindByIdentifier( + ctx, res.SpaceID, templateIdentifier) + if err != nil { + log.Warn().Msgf("unable to get template params for ID : %s", + res.Metadata[key]) + } + } + } + return nil +} diff --git a/app/services/infraprovider/infraprovider.go b/app/services/infraprovider/infraprovider.go index d1c116034..0fab1cbe6 100644 --- a/app/services/infraprovider/infraprovider.go +++ b/app/services/infraprovider/infraprovider.go @@ -22,8 +22,6 @@ import ( "github.com/harness/gitness/infraprovider" "github.com/harness/gitness/store/database/dbtx" "github.com/harness/gitness/types" - - "github.com/rs/zerolog/log" ) func NewService( @@ -73,6 +71,7 @@ func (c *Service) Find( for i, resource := range resources { if resource != nil { providerResources[i] = *resource + providerResources[i].SpacePath = space.Path } } infraProviderConfig.Resources = providerResources @@ -80,6 +79,18 @@ func (c *Service) Find( return infraProviderConfig, nil } +func (c *Service) FindTemplate( + ctx context.Context, + space *types.Space, + identifier string, +) (*types.InfraProviderTemplate, error) { + infraProviderTemplate, err := c.infraProviderTemplateStore.FindByIdentifier(ctx, space.ID, identifier) + if err != nil { + return nil, fmt.Errorf("failed to find infraprovider template: %q %w", identifier, err) + } + return infraProviderTemplate, nil +} + func (c *Service) FindResourceByIdentifier( ctx context.Context, spaceID int64, @@ -90,137 +101,3 @@ func (c *Service) FindResourceByIdentifier( func (c *Service) FindResource(ctx context.Context, id int64) (*types.InfraProviderResource, error) { return c.infraProviderResourceStore.Find(ctx, id) } - -func (c *Service) CreateInfraProvider( - ctx context.Context, - infraProviderConfig *types.InfraProviderConfig, -) error { - err := c.tx.WithTx(ctx, func(ctx context.Context) error { - err := c.createConfig(ctx, infraProviderConfig) - if err != nil { - return fmt.Errorf("could not autocreate the config: %q %w", infraProviderConfig.Identifier, err) - } - err = c.createResources(ctx, infraProviderConfig.Resources, infraProviderConfig.ID) - if err != nil { - return fmt.Errorf("could not autocreate the resources: %v %w", infraProviderConfig.Resources, err) - } - return nil - }) - if err != nil { - return fmt.Errorf("failed to complete txn for the infraprovider %w", err) - } - return nil -} - -func (c *Service) createConfig(ctx context.Context, infraProviderConfig *types.InfraProviderConfig) error { - err := c.infraProviderConfigStore.Create(ctx, infraProviderConfig) - if err != nil { - return fmt.Errorf("failed to create infraprovider config for : %q %w", infraProviderConfig.Identifier, err) - } - return nil -} - -func (c *Service) CreateResources(ctx context.Context, resources []types.InfraProviderResource, configID int64) error { - err := c.tx.WithTx(ctx, func(ctx context.Context) error { - return c.createResources(ctx, resources, configID) - }) - if err != nil { - return fmt.Errorf("failed to complete create txn for the infraprovider resource %w", err) - } - return nil -} - -func (c *Service) UpdateResource(ctx context.Context, resource types.InfraProviderResource) error { - err := c.tx.WithTx(ctx, func(ctx context.Context) error { - space, err := c.spaceStore.FindByRef(ctx, resource.SpacePath) - if err != nil { - return err - } - infraProviderResource, err := c.FindResourceByIdentifier(ctx, space.ID, resource.Identifier) - if err != nil { - return err - } - resource.ID = infraProviderResource.ID - if err = c.infraProviderResourceStore.Update(ctx, &resource); err != nil { - return err - } - return nil - }) - if err != nil { - return fmt.Errorf("failed to complete update txn for the infraprovider resource %w", err) - } - return nil -} - -func (c *Service) UpdateTemplate(ctx context.Context, template types.InfraProviderTemplate) error { - err := c.tx.WithTx(ctx, func(ctx context.Context) error { - space, err := c.spaceStore.FindByRef(ctx, template.SpacePath) - if err != nil { - return err - } - templateInDB, err := c.infraProviderTemplateStore.FindByIdentifier(ctx, space.ID, template.Identifier) - if err != nil { - return err - } - template.ID = templateInDB.ID - template.SpaceID = space.ID - if err = c.infraProviderTemplateStore.Update(ctx, &template); err != nil { - return err - } - return nil - }) - if err != nil { - return fmt.Errorf("failed to complete update txn for the infraprovider template %w", err) - } - return nil -} - -func (c *Service) createResources(ctx context.Context, resources []types.InfraProviderResource, configID int64) error { - for idx := range resources { - resource := &resources[idx] - resource.InfraProviderConfigID = configID - infraProvider, err := c.infraProviderFactory.GetInfraProvider(resource.InfraProviderType) - if err != nil { - return fmt.Errorf("failed to fetch infrastructure impl for type : %q %w", resource.InfraProviderType, err) - } - if len(infraProvider.TemplateParams()) > 0 { - err = c.validateTemplates(ctx, infraProvider, *resource) - if err != nil { - return err - } - } - err = c.infraProviderResourceStore.Create(ctx, resource) - if err != nil { - return fmt.Errorf("failed to create infraprovider resource for : %q %w", resource.Identifier, err) - } - } - return nil -} - -func (c *Service) validateTemplates( - ctx context.Context, - infraProvider infraprovider.InfraProvider, - res types.InfraProviderResource, -) error { - templateParams := infraProvider.TemplateParams() - for _, param := range templateParams { - key := param.Name - if res.Metadata[key] != "" { - templateIdentifier := res.Metadata[key] - _, err := c.infraProviderTemplateStore.FindByIdentifier( - ctx, res.SpaceID, templateIdentifier) - if err != nil { - log.Warn().Msgf("unable to get template params for ID : %s", - res.Metadata[key]) - } - } - } - return nil -} - -func (c *Service) CreateTemplate( - ctx context.Context, - template *types.InfraProviderTemplate, -) error { - return c.infraProviderTemplateStore.Create(ctx, template) -} diff --git a/app/services/infraprovider/update.go b/app/services/infraprovider/update.go new file mode 100644 index 000000000..5fcf15083 --- /dev/null +++ b/app/services/infraprovider/update.go @@ -0,0 +1,67 @@ +// Copyright 2023 Harness, Inc. +// +// 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 infraprovider + +import ( + "context" + "fmt" + + "github.com/harness/gitness/types" +) + +func (c *Service) UpdateResource(ctx context.Context, resource types.InfraProviderResource) error { + err := c.tx.WithTx(ctx, func(ctx context.Context) error { + space, err := c.spaceStore.FindByRef(ctx, resource.SpacePath) + if err != nil { + return err + } + infraProviderResource, err := c.FindResourceByIdentifier(ctx, space.ID, resource.Identifier) + if err != nil { + return err + } + resource.ID = infraProviderResource.ID + if err = c.infraProviderResourceStore.Update(ctx, &resource); err != nil { + return err + } + return nil + }) + if err != nil { + return fmt.Errorf("failed to complete update txn for the infraprovider resource %w", err) + } + return nil +} + +func (c *Service) UpdateTemplate(ctx context.Context, template types.InfraProviderTemplate) error { + err := c.tx.WithTx(ctx, func(ctx context.Context) error { + space, err := c.spaceStore.FindByRef(ctx, template.SpacePath) + if err != nil { + return err + } + templateInDB, err := c.infraProviderTemplateStore.FindByIdentifier(ctx, space.ID, template.Identifier) + if err != nil { + return err + } + template.ID = templateInDB.ID + template.SpaceID = space.ID + if err = c.infraProviderTemplateStore.Update(ctx, &template); err != nil { + return err + } + return nil + }) + if err != nil { + return fmt.Errorf("failed to complete update txn for the infraprovider template %w", err) + } + return nil +} diff --git a/app/store/database/gitspace_config.go b/app/store/database/gitspace_config.go index bc325a494..74b5ac86e 100644 --- a/app/store/database/gitspace_config.go +++ b/app/store/database/gitspace_config.go @@ -49,7 +49,8 @@ const ( gconf_updated, gconf_is_deleted, gconf_code_repo_ref, - gconf_ssh_token_identifier + gconf_ssh_token_identifier, + gconf_created_by ` gitspaceConfigsTable = `gitspace_configs` ReturningClause = "RETURNING " @@ -70,25 +71,29 @@ type gitspaceConfig struct { CodeRepoURL string `db:"gconf_code_repo_url"` DevcontainerPath null.String `db:"gconf_devcontainer_path"` Branch string `db:"gconf_branch"` - UserUID string `db:"gconf_user_uid"` - SpaceID int64 `db:"gconf_space_id"` - Created int64 `db:"gconf_created"` - Updated int64 `db:"gconf_updated"` - IsDeleted bool `db:"gconf_is_deleted"` - SSHTokenIdentifier string `db:"gconf_ssh_token_identifier"` + // TODO: migrate to principal int64 id to use principal cache and consistent with gitness code. + UserUID string `db:"gconf_user_uid"` + SpaceID int64 `db:"gconf_space_id"` + Created int64 `db:"gconf_created"` + Updated int64 `db:"gconf_updated"` + IsDeleted bool `db:"gconf_is_deleted"` + SSHTokenIdentifier string `db:"gconf_ssh_token_identifier"` + CreatedBy null.Int `db:"gconf_created_by"` } var _ store.GitspaceConfigStore = (*gitspaceConfigStore)(nil) // NewGitspaceConfigStore returns a new GitspaceConfigStore. -func NewGitspaceConfigStore(db *sqlx.DB) store.GitspaceConfigStore { +func NewGitspaceConfigStore(db *sqlx.DB, pCache store.PrincipalInfoCache) store.GitspaceConfigStore { return &gitspaceConfigStore{ - db: db, + db: db, + pCache: pCache, } } type gitspaceConfigStore struct { - db *sqlx.DB + db *sqlx.DB + pCache store.PrincipalInfoCache } func (s gitspaceConfigStore) Count(ctx context.Context, filter *types.GitspaceFilter) (int64, error) { @@ -115,8 +120,8 @@ func (s gitspaceConfigStore) Find(ctx context.Context, id int64) (*types.Gitspac stmt := database.Builder. Select(gitspaceConfigSelectColumns). From(gitspaceConfigsTable). - Where("gconf_id = $1", id). //nolint:goconst - Where("gconf_is_deleted = $2", false) + Where("gconf_id = ?", id). //nolint:goconst + Where("gconf_is_deleted = ?", false) dst := new(gitspaceConfig) sql, args, err := stmt.ToSql() if err != nil { @@ -162,20 +167,21 @@ func (s gitspaceConfigStore) Create(ctx context.Context, gitspaceConfig *types.G gitspaceConfig.Name, gitspaceConfig.IDE, gitspaceConfig.InfraProviderResourceID, - gitspaceConfig.CodeAuthType, - gitspaceConfig.CodeAuthID, - gitspaceConfig.CodeRepoType, - gitspaceConfig.CodeRepoIsPrivate, - gitspaceConfig.CodeRepoURL, + gitspaceConfig.CodeRepo.AuthType, + gitspaceConfig.CodeRepo.AuthID, + gitspaceConfig.CodeRepo.Type, + gitspaceConfig.CodeRepo.IsPrivate, + gitspaceConfig.CodeRepo.URL, gitspaceConfig.DevcontainerPath, gitspaceConfig.Branch, - gitspaceConfig.UserID, + gitspaceConfig.GitspaceUser.Identifier, gitspaceConfig.SpaceID, gitspaceConfig.Created, gitspaceConfig.Updated, gitspaceConfig.IsDeleted, - gitspaceConfig.CodeRepoRef, + gitspaceConfig.CodeRepo.Ref, gitspaceConfig.SSHTokenIdentifier, + gitspaceConfig.GitspaceUser.ID, ). Suffix(ReturningClause + "gconf_id") sql, args, err := stmt.ToSql() @@ -200,7 +206,7 @@ func (s gitspaceConfigStore) Update(ctx context.Context, Set("gconf_updated", dbGitspaceConfig.Updated). Set("gconf_infra_provider_resource_id", dbGitspaceConfig.InfraProviderResourceID). Set("gconf_is_deleted", dbGitspaceConfig.IsDeleted). - Where("gconf_id = $6", gitspaceConfig.ID) + Where("gconf_id = ?", gitspaceConfig.ID) sql, args, err := stmt.ToSql() if err != nil { return errors.Wrap(err, "Failed to convert squirrel builder to sql") @@ -220,20 +226,21 @@ func mapToInternalGitspaceConfig(config *types.GitspaceConfig) *gitspaceConfig { Name: config.Name, IDE: config.IDE, InfraProviderResourceID: config.InfraProviderResourceID, - CodeAuthType: config.CodeAuthType, - CodeAuthID: config.CodeAuthID, - CodeRepoIsPrivate: config.CodeRepoIsPrivate, - CodeRepoType: config.CodeRepoType, - CodeRepoRef: null.StringFromPtr(config.CodeRepoRef), - CodeRepoURL: config.CodeRepoURL, + CodeAuthType: config.CodeRepo.AuthType, + CodeAuthID: config.CodeRepo.AuthID, + CodeRepoIsPrivate: config.CodeRepo.IsPrivate, + CodeRepoType: config.CodeRepo.Type, + CodeRepoRef: null.StringFromPtr(config.CodeRepo.Ref), + CodeRepoURL: config.CodeRepo.URL, DevcontainerPath: null.StringFromPtr(config.DevcontainerPath), Branch: config.Branch, - UserUID: config.UserID, + UserUID: config.GitspaceUser.Identifier, SpaceID: config.SpaceID, IsDeleted: config.IsDeleted, Created: config.Created, Updated: config.Updated, SSHTokenIdentifier: config.SSHTokenIdentifier, + CreatedBy: null.IntFromPtr(config.GitspaceUser.ID), } } @@ -256,7 +263,7 @@ func (s gitspaceConfigStore) List(ctx context.Context, filter *types.GitspaceFil db := dbtx.GetAccessor(ctx, s.db) var dst []*gitspaceConfig if err = db.SelectContext(ctx, &dst, sql, args...); err != nil { - return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing gitspace config list query") + return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing gitspace config list space query") } return s.mapToGitspaceConfigs(ctx, dst) } @@ -278,34 +285,46 @@ func (s gitspaceConfigStore) ListAll( db := dbtx.GetAccessor(ctx, s.db) var dst []*gitspaceConfig if err = db.SelectContext(ctx, &dst, sql, args...); err != nil { - return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing gitspace config list query") + return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing gitspace config list all query") } return s.mapToGitspaceConfigs(ctx, dst) } func (s *gitspaceConfigStore) mapToGitspaceConfig( - _ context.Context, + ctx context.Context, in *gitspaceConfig, ) (*types.GitspaceConfig, error) { + codeRepo := types.CodeRepo{ + URL: in.CodeRepoURL, + Ref: in.CodeRepoRef.Ptr(), + Type: in.CodeRepoType, + Branch: in.Branch, + DevcontainerPath: in.DevcontainerPath.Ptr(), + IsPrivate: in.CodeRepoIsPrivate, + AuthType: in.CodeAuthType, + AuthID: in.CodeAuthID, + } var res = &types.GitspaceConfig{ ID: in.ID, Identifier: in.Identifier, Name: in.Name, InfraProviderResourceID: in.InfraProviderResourceID, IDE: in.IDE, - CodeRepoType: in.CodeRepoType, - CodeRepoRef: in.CodeRepoRef.Ptr(), - CodeRepoURL: in.CodeRepoURL, - Branch: in.Branch, - DevcontainerPath: in.DevcontainerPath.Ptr(), - UserID: in.UserUID, SpaceID: in.SpaceID, - CodeAuthType: in.CodeAuthType, - CodeAuthID: in.CodeAuthID, - CodeRepoIsPrivate: in.CodeRepoIsPrivate, Created: in.Created, Updated: in.Updated, SSHTokenIdentifier: in.SSHTokenIdentifier, + CodeRepo: codeRepo, + GitspaceUser: types.GitspaceUser{ + ID: in.CreatedBy.Ptr(), + Identifier: in.UserUID}, + } + if res.GitspaceUser.ID != nil { + author, _ := s.pCache.Get(ctx, *res.GitspaceUser.ID) + if author != nil { + res.GitspaceUser.DisplayName = author.DisplayName + res.GitspaceUser.Email = author.Email + } } return res, nil } diff --git a/app/store/database/gitspace_instance.go b/app/store/database/gitspace_instance.go index a092fc3d5..32b55cfc8 100644 --- a/app/store/database/gitspace_instance.go +++ b/app/store/database/gitspace_instance.go @@ -59,18 +59,19 @@ type gitspaceInstance struct { GitSpaceConfigID int64 `db:"gits_gitspace_config_id"` URL null.String `db:"gits_url"` State enum.GitspaceInstanceStateType `db:"gits_state"` - UserUID string `db:"gits_user_uid"` - ResourceUsage null.String `db:"gits_resource_usage"` - SpaceID int64 `db:"gits_space_id"` - LastUsed int64 `db:"gits_last_used"` - TotalTimeUsed int64 `db:"gits_total_time_used"` - TrackedChanges null.String `db:"gits_tracked_changes"` - AccessType enum.GitspaceAccessType `db:"gits_access_type"` - AccessKeyRef null.String `db:"gits_access_key_ref"` - MachineUser null.String `db:"gits_machine_user"` - Identifier string `db:"gits_uid"` - Created int64 `db:"gits_created"` - Updated int64 `db:"gits_updated"` + // TODO: migrate to principal int64 id to use principal cache and consistent with gitness code. + UserUID string `db:"gits_user_uid"` + ResourceUsage null.String `db:"gits_resource_usage"` + SpaceID int64 `db:"gits_space_id"` + LastUsed int64 `db:"gits_last_used"` + TotalTimeUsed int64 `db:"gits_total_time_used"` + TrackedChanges null.String `db:"gits_tracked_changes"` + AccessType enum.GitspaceAccessType `db:"gits_access_type"` + AccessKeyRef null.String `db:"gits_access_key_ref"` + MachineUser null.String `db:"gits_machine_user"` + Identifier string `db:"gits_uid"` + Created int64 `db:"gits_created"` + Updated int64 `db:"gits_updated"` } // NewGitspaceInstanceStore returns a new GitspaceInstanceStore. diff --git a/app/store/database/migrate/postgres/0066_alter_gitspace_config_add_created_by.down.sql b/app/store/database/migrate/postgres/0066_alter_gitspace_config_add_created_by.down.sql new file mode 100644 index 000000000..fd8e3e2ff --- /dev/null +++ b/app/store/database/migrate/postgres/0066_alter_gitspace_config_add_created_by.down.sql @@ -0,0 +1 @@ +ALTER TABLE gitspace_configs DROP COLUMN gconf_created_by; \ No newline at end of file diff --git a/app/store/database/migrate/postgres/0066_alter_gitspace_config_add_created_by.up.sql b/app/store/database/migrate/postgres/0066_alter_gitspace_config_add_created_by.up.sql new file mode 100644 index 000000000..aa203bce3 --- /dev/null +++ b/app/store/database/migrate/postgres/0066_alter_gitspace_config_add_created_by.up.sql @@ -0,0 +1 @@ +ALTER TABLE gitspace_configs ADD COLUMN gconf_created_by INTEGER; \ No newline at end of file diff --git a/app/store/database/migrate/sqlite/0066_alter_gitspace_config_add_created_by.down.sql b/app/store/database/migrate/sqlite/0066_alter_gitspace_config_add_created_by.down.sql new file mode 100644 index 000000000..9b05765b3 --- /dev/null +++ b/app/store/database/migrate/sqlite/0066_alter_gitspace_config_add_created_by.down.sql @@ -0,0 +1 @@ +ALTER TABLE gitspace_configs DROP COLUMN gconf_created_by; diff --git a/app/store/database/migrate/sqlite/0066_alter_gitspace_config_add_created_by.up.sql b/app/store/database/migrate/sqlite/0066_alter_gitspace_config_add_created_by.up.sql new file mode 100644 index 000000000..aa203bce3 --- /dev/null +++ b/app/store/database/migrate/sqlite/0066_alter_gitspace_config_add_created_by.up.sql @@ -0,0 +1 @@ +ALTER TABLE gitspace_configs ADD COLUMN gconf_created_by INTEGER; \ No newline at end of file diff --git a/app/store/database/wire.go b/app/store/database/wire.go index 429776277..b02b4248e 100644 --- a/app/store/database/wire.go +++ b/app/store/database/wire.go @@ -154,8 +154,8 @@ func ProvideInfraProviderResourceStore(db *sqlx.DB) store.InfraProviderResourceS } // ProvideGitspaceConfigStore provides a gitspace config store. -func ProvideGitspaceConfigStore(db *sqlx.DB) store.GitspaceConfigStore { - return NewGitspaceConfigStore(db) +func ProvideGitspaceConfigStore(db *sqlx.DB, pCache store.PrincipalInfoCache) store.GitspaceConfigStore { + return NewGitspaceConfigStore(db, pCache) } // ProvideGitspaceInstanceStore provides a gitspace instance store. diff --git a/cmd/gitness/wire_gen.go b/cmd/gitness/wire_gen.go index 1c9c9a072..0c21cbaf0 100644 --- a/cmd/gitness/wire_gen.go +++ b/cmd/gitness/wire_gen.go @@ -256,7 +256,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro if err != nil { return nil, err } - gitspaceConfigStore := database.ProvideGitspaceConfigStore(db) + gitspaceConfigStore := database.ProvideGitspaceConfigStore(db, principalInfoCache) gitspaceInstanceStore := database.ProvideGitspaceInstanceStore(db) infraProviderResourceStore := database.ProvideInfraProviderResourceStore(db) infraProviderConfigStore := database.ProvideInfraProviderConfigStore(db) diff --git a/types/gitspace.go b/types/gitspace.go index a4f714118..c7853608b 100644 --- a/types/gitspace.go +++ b/types/gitspace.go @@ -19,29 +19,40 @@ import ( ) type GitspaceConfig struct { - ID int64 `json:"-"` - Identifier string `json:"identifier"` - Name string `json:"name"` - IDE enum.IDEType `json:"ide"` - State enum.GitspaceStateType `json:"state"` - InfraProviderResourceID int64 `json:"-"` - InfraProviderResourceIdentifier string `json:"resource_identifier"` - CodeRepoURL string `json:"code_repo_url"` - CodeRepoRef *string `json:"code_repo_ref"` - CodeRepoType enum.GitspaceCodeRepoType `json:"code_repo_type"` - Branch string `json:"branch"` - DevcontainerPath *string `json:"devcontainer_path,omitempty"` - UserID string `json:"user_id"` - SpaceID int64 `json:"-"` - CodeAuthType string `json:"-"` - CodeAuthID string `json:"-"` - IsDeleted bool `json:"-"` - CodeRepoIsPrivate bool `json:"-"` - GitspaceInstance *GitspaceInstance `json:"instance"` - SpacePath string `json:"space_path"` - Created int64 `json:"created"` - Updated int64 `json:"updated"` - SSHTokenIdentifier string `json:"ssh_token_identifier"` + ID int64 `json:"-"` + Identifier string `json:"identifier"` + Name string `json:"name"` + IDE enum.IDEType `json:"ide"` + State enum.GitspaceStateType `json:"state"` + InfraProviderResourceID int64 `json:"-"` + InfraProviderResourceIdentifier string `json:"resource_identifier"` + SpaceID int64 `json:"-"` + IsDeleted bool `json:"-"` + GitspaceInstance *GitspaceInstance `json:"instance"` + SpacePath string `json:"space_path"` + Created int64 `json:"created"` + Updated int64 `json:"updated"` + SSHTokenIdentifier string `json:"ssh_token_identifier"` + CodeRepo + GitspaceUser +} + +type CodeRepo struct { + URL string `json:"code_repo_url"` + Ref *string `json:"code_repo_ref"` + Type enum.GitspaceCodeRepoType `json:"code_repo_type"` + Branch string `json:"branch"` + DevcontainerPath *string `json:"devcontainer_path,omitempty"` + IsPrivate bool `json:"code_repo_is_private"` + AuthType string `json:"-"` + AuthID string `json:"-"` +} + +type GitspaceUser struct { + ID *int64 `json:"-"` + Identifier string `json:"user_id"` + Email string `json:"user_email"` + DisplayName string `json:"user_display_name"` } type GitspaceInstance struct {