feat: [CDE-192]: show user info for gitspace listing. (#2531)

* feat: [CDE-192]: added TODO to move to user int as key
* feat: [CDE-192]: added created by col for gitspace config
* feat: [CDE-192]: added created by col for gitspace config
* feat: [CDE-192]: added created by col for gitspace config
* feat: [CDE-192]: added created by col for gitspace config
* feat: [CDE-192]: wire principal info cache
* feat: [CDE-192]: show user info for gitspace listing.
* feat: [CDE-192]: show user info for gitspace listing.
This commit is contained in:
Ansuman Satapathy 2024-08-20 09:34:10 +00:00 committed by Harness
parent 8d487921a6
commit 93af2c724e
20 changed files with 354 additions and 250 deletions

View File

@ -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,

View File

@ -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 {

View File

@ -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,
}

View File

@ -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 {

View File

@ -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)

View File

@ -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{

View File

@ -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

View File

@ -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)
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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.

View File

@ -0,0 +1 @@
ALTER TABLE gitspace_configs DROP COLUMN gconf_created_by;

View File

@ -0,0 +1 @@
ALTER TABLE gitspace_configs ADD COLUMN gconf_created_by INTEGER;

View File

@ -0,0 +1 @@
ALTER TABLE gitspace_configs DROP COLUMN gconf_created_by;

View File

@ -0,0 +1 @@
ALTER TABLE gitspace_configs ADD COLUMN gconf_created_by INTEGER;

View File

@ -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.

View File

@ -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)

View File

@ -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 {