gitspaces API Implementation (#2136)

* feat: [CDE-83]: fixed linting issues.
* feat: [CDE-83]: fixed linting issues.
* feat: [CDE-83]: fixed linting issues.
* feat: [CDE-83]: fixed types
* feat: [CDE-83]: fixed types
* feat: [CDE-83]: fixed types
* feat: [CDE-83]: fixed types
* feat: [CDE-83]: fixed types
* feat: [CDE-83]: fixed DB comments.
* feat: [CDE-83]: fixed DB comments.
* feat: [CDE-83]: Implemented the action API
* gitspaces API Implementation
unified-ui
Ansuman Satapathy 2024-07-09 05:23:02 +00:00 committed by Harness
parent 34df7cf137
commit f78439593c
39 changed files with 1868 additions and 251 deletions

View File

@ -0,0 +1,45 @@
// 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 auth
import (
"context"
"github.com/harness/gitness/app/auth"
"github.com/harness/gitness/app/auth/authz"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
// CheckInfraProvider checks if a gitspace specific permission is granted for the current auth session
// in the scope of its parent.
// Returns nil if the permission is granted, otherwise returns an error.
// NotAuthenticated, NotAuthorized, or any underlying error.
func CheckInfraProvider(
ctx context.Context,
authorizer authz.Authorizer,
session *auth.Session,
parentPath,
identifier string,
permission enum.Permission,
) error {
scope := &types.Scope{SpacePath: parentPath}
resource := &types.Resource{
Type: enum.ResourceTypeInfraProvider,
Identifier: identifier,
}
return Check(ctx, authorizer, session, scope, resource, permission)
}

View File

@ -16,23 +16,172 @@ package gitspace
import (
"context"
"errors"
"fmt"
"strconv"
"strings"
"time"
apiauth "github.com/harness/gitness/app/api/auth"
"github.com/harness/gitness/app/auth"
events "github.com/harness/gitness/app/events/gitspace"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/check"
"github.com/harness/gitness/types/enum"
gonanoid "github.com/matoous/go-nanoid"
)
const defaultAccessKey = "Harness@123"
const defaultMachineUser = "harness"
type ActionInput struct {
Action enum.GitspaceActionType `json:"action"`
Action enum.GitspaceActionType `json:"action"`
Identifier string `json:"-"`
SpaceRef string `json:"-"` // Ref of the parent space
}
func (c *Controller) Action(
_ context.Context,
_ *auth.Session,
_ string,
_ string,
_ *ActionInput,
ctx context.Context,
session *auth.Session,
in *ActionInput,
) (*types.GitspaceConfig, error) {
return nil, errors.New("unimplemented")
if err := c.sanitizeActionInput(in); err != nil {
return nil, fmt.Errorf("failed to sanitize input: %w", err)
}
space, err := c.spaceStore.FindByRef(ctx, in.SpaceRef)
if err != nil {
return nil, fmt.Errorf("failed to find space: %w", err)
}
err = apiauth.CheckGitspace(ctx, c.authorizer, session, space.Path, in.Identifier, enum.PermissionGitspaceAccess)
if err != nil {
return nil, fmt.Errorf("failed to authorize: %w", err)
}
gitspaceConfig, err := c.gitspaceConfigStore.FindByIdentifier(ctx, space.ID, in.Identifier)
gitspaceConfig.SpacePath = space.Path
gitspaceConfig.SpaceID = space.ID
if err != nil {
return nil, fmt.Errorf("failed to find gitspace config: %w", err)
}
// All the actions should be idempotent.
switch in.Action {
case enum.GitspaceActionTypeStart:
c.emitGitspaceConfigEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStart)
gitspace, err := c.startGitspace(ctx, gitspaceConfig)
if err != nil {
c.emitGitspaceConfigEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStartFailed)
}
return gitspace, err
case enum.GitspaceActionTypeStop:
c.emitGitspaceConfigEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStop)
gitspace, err := c.stopGitspace(ctx, gitspaceConfig)
if err != nil {
c.emitGitspaceConfigEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStopFailed)
}
return gitspace, err
default:
return nil, fmt.Errorf("unknown action %s on gitspace : %s", string(in.Action), gitspaceConfig.Identifier)
}
}
func (c *Controller) startGitspace(ctx context.Context, config *types.GitspaceConfig) (*types.GitspaceConfig, error) {
savedGitspaceInstance, err := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, config.ID, config.SpaceID)
const resourceNotFoundErr = "Failed to find gitspace: resource not found"
if err != nil && err.Error() != resourceNotFoundErr { // TODO fix this
return nil, fmt.Errorf("failed to find gitspace with config ID : %s %w", config.Identifier, err)
}
config.GitspaceInstance = savedGitspaceInstance
if savedGitspaceInstance == nil || savedGitspaceInstance.State.IsFinalStatus() {
codeServerPassword := defaultAccessKey
gitspaceMachineUser := defaultMachineUser
now := time.Now().UnixMilli()
suffixUID, err := gonanoid.Generate(allowedUIDAlphabet, 6)
if err != nil {
return nil, fmt.Errorf("could not generate UID for gitspace config : %q %w", config.Identifier, err)
}
identifier := strings.ToLower(config.Identifier + "-" + suffixUID)
var gitspaceInstance = &types.GitspaceInstance{
GitSpaceConfigID: config.ID,
Identifier: identifier,
State: enum.GitspaceInstanceStateUninitialized,
UserID: config.UserID,
SpaceID: config.SpaceID,
SpacePath: config.SpacePath,
Created: now,
Updated: now,
TotalTimeUsed: 0,
}
if config.IDE == enum.IDETypeVSCodeWeb || config.IDE == enum.IDETypeVSCode {
gitspaceInstance.AccessKey = &codeServerPassword
gitspaceInstance.AccessType = enum.GitspaceAccessTypeUserCredentials
gitspaceInstance.MachineUser = &gitspaceMachineUser
}
if err = c.gitspaceInstanceStore.Create(ctx, gitspaceInstance); err != nil {
return nil, fmt.Errorf("failed to create gitspace instance for %s %w", config.Identifier, err)
}
newGitspaceInstance, err := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, config.ID, config.SpaceID)
newGitspaceInstance.SpacePath = config.SpacePath
if err != nil {
return nil, fmt.Errorf("failed to find gitspace with config ID : %s %w", config.Identifier, err)
}
config.GitspaceInstance = newGitspaceInstance
}
updatedGitspace, err := c.orchestrator.StartGitspace(ctx, config)
if err != nil {
return nil, fmt.Errorf("failed to find start gitspace : %s %w", config.Identifier, err)
}
if err = c.gitspaceInstanceStore.Update(ctx, updatedGitspace); err != nil {
return nil, fmt.Errorf("failed to update gitspace %w", err)
}
config.GitspaceInstance = updatedGitspace
config.State, _ = enum.GetGitspaceStateFromInstance(updatedGitspace.State)
return config, nil
}
func (c *Controller) stopGitspace(ctx context.Context, config *types.GitspaceConfig) (*types.GitspaceConfig, error) {
savedGitspace, err := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, config.ID, config.SpaceID)
if err != nil {
return nil, fmt.Errorf("failed to find gitspace with config ID : %s %w", config.Identifier, err)
}
if savedGitspace.State.IsFinalStatus() {
return nil, fmt.Errorf(
"gitspace Instance cannot be stopped with ID %s %w", savedGitspace.Identifier, err)
}
config.GitspaceInstance = savedGitspace
if updatedGitspace, stopErr := c.orchestrator.StopGitspace(ctx, config); stopErr != nil {
return nil, fmt.Errorf(
"failed to stop gitspace instance with ID %s %w", savedGitspace.Identifier, stopErr)
} else if updatedGitspace != nil {
if stopErr = c.gitspaceInstanceStore.Update(ctx, updatedGitspace); stopErr != nil {
return nil, fmt.Errorf(
"unable to update the gitspace with config id %s %w", savedGitspace.Identifier, stopErr)
}
config.GitspaceInstance = updatedGitspace
config.State, _ = enum.GetGitspaceStateFromInstance(updatedGitspace.State)
}
return config, nil
}
func (c *Controller) sanitizeActionInput(in *ActionInput) error {
if err := check.Identifier(in.Identifier); err != nil {
return err
}
parentRefAsID, err := strconv.ParseInt(in.SpaceRef, 10, 64)
if (err == nil && parentRefAsID <= 0) || (len(strings.TrimSpace(in.SpaceRef)) == 0) {
return ErrGitspaceRequiresParent
}
return nil
}
func (c *Controller) emitGitspaceConfigEvent(
ctx context.Context,
config *types.GitspaceConfig,
eventType enum.GitspaceEventType) {
c.eventReporter.EmitGitspaceEvent(ctx, events.GitspaceEvent, &events.GitspaceEventPayload{
QueryKey: config.Identifier,
EntityID: config.ID,
EntityType: enum.GitspaceEntityTypeGitspaceConfig,
EventType: eventType,
Created: time.Now().UnixMilli(),
})
}

View File

@ -16,6 +16,8 @@ package gitspace
import (
"github.com/harness/gitness/app/auth/authz"
gitspaceevents "github.com/harness/gitness/app/events/gitspace"
"github.com/harness/gitness/app/gitspace/orchestrator"
"github.com/harness/gitness/app/store"
)
@ -25,16 +27,19 @@ type Controller struct {
gitspaceConfigStore store.GitspaceConfigStore
gitspaceInstanceStore store.GitspaceInstanceStore
spaceStore store.SpaceStore
eventReporter *gitspaceevents.Reporter
orchestrator orchestrator.Orchestrator
gitspaceEventStore store.GitspaceEventStore
}
// TODO Stubbed Impl
func NewController(
authorizer authz.Authorizer,
infraProviderResourceStore store.InfraProviderResourceStore,
gitspaceConfigStore store.GitspaceConfigStore,
gitspaceInstanceStore store.GitspaceInstanceStore,
spaceStore store.SpaceStore,
eventReporter *gitspaceevents.Reporter,
orchestrator orchestrator.Orchestrator,
gitspaceEventStore store.GitspaceEventStore,
) *Controller {
return &Controller{
@ -43,6 +48,8 @@ func NewController(
gitspaceConfigStore: gitspaceConfigStore,
gitspaceInstanceStore: gitspaceInstanceStore,
spaceStore: spaceStore,
eventReporter: eventReporter,
orchestrator: orchestrator,
gitspaceEventStore: gitspaceEventStore,
}
}

View File

@ -16,32 +16,108 @@ package gitspace
import (
"context"
"errors"
"fmt"
"strconv"
"strings"
"time"
apiauth "github.com/harness/gitness/app/api/auth"
"github.com/harness/gitness/app/api/usererror"
"github.com/harness/gitness/app/auth"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/check"
"github.com/harness/gitness/types/enum"
gonanoid "github.com/matoous/go-nanoid"
)
const allowedUIDAlphabet = "abcdefghijklmnopqrstuvwxyz0123456789"
var (
// errSecretRequiresParent if the user tries to create a secret without a parent space.
ErrGitspaceRequiresParent = usererror.BadRequest(
"Parent space required - standalone gitspace are not supported.")
)
// TODO Stubbed Impl
// CreateInput is the input used for create operations.
type CreateInput struct {
Identifier string `json:"identifier"`
Name string `json:"name"`
SpaceRef string `json:"space_ref"` // Ref of the parent space
IDE enum.IDEType `json:"ide"`
InfraProviderResourceID string `json:"resource_identifier"`
CodeRepoURL string `json:"code_repo_url"`
Branch string `json:"branch"`
DevcontainerPath string `json:"devcontainer_path"`
Metadata map[string]string `json:"metadata"`
Identifier string `json:"identifier"`
Name string `json:"name"`
SpaceRef string `json:"space_ref"` // Ref of the parent space
IDE enum.IDEType `json:"ide"`
ResourceIdentifier string `json:"resource_identifier"`
CodeRepoURL string `json:"code_repo_url"`
Branch string `json:"branch"`
DevcontainerPath *string `json:"devcontainer_path"`
Metadata map[string]string `json:"metadata"`
}
// Create creates a new gitspace.
func (c *Controller) Create(
_ context.Context,
_ *auth.Session,
_ *CreateInput,
ctx context.Context,
session *auth.Session,
in *CreateInput,
) (*types.GitspaceConfig, error) {
return nil, errors.New("unimplemented")
parentSpace, err := c.spaceStore.FindByRef(ctx, in.SpaceRef)
if err != nil {
return nil, fmt.Errorf("failed to find parent by ref: %w", err)
}
if err = apiauth.CheckGitspace(
ctx,
c.authorizer,
session,
parentSpace.Path,
"",
enum.PermissionGitspaceEdit); err != nil {
return nil, err
}
suffixUID, err := gonanoid.Generate(allowedUIDAlphabet, 6)
if err != nil {
return nil, fmt.Errorf("could not generate UID for gitspace config : %q %w", in.Identifier, err)
}
identifier := strings.ToLower(in.Identifier + "-" + suffixUID)
if err = c.sanitizeCreateInput(in); err != nil {
return nil, fmt.Errorf("invalid input: %w", err)
}
now := time.Now().UnixMilli()
infraProviderResource, err := c.infraProviderResourceStore.FindByIdentifier(
ctx,
parentSpace.ID,
in.ResourceIdentifier)
if err != nil {
return nil, fmt.Errorf("could not find infra provider resource : %q %w", in.ResourceIdentifier, err)
}
gitspaceConfig := &types.GitspaceConfig{
Identifier: identifier,
Name: in.Name,
IDE: in.IDE,
InfraProviderResourceID: infraProviderResource.ID,
InfraProviderResourceIdentifier: infraProviderResource.Identifier,
CodeRepoType: enum.CodeRepoTypeUnknown, // TODO fix this
State: enum.GitspaceStateUninitialized,
CodeRepoURL: in.CodeRepoURL,
Branch: in.Branch,
DevcontainerPath: in.DevcontainerPath,
UserID: session.Principal.UID,
SpaceID: parentSpace.ID,
SpacePath: parentSpace.Path,
Created: now,
Updated: now,
}
err = c.gitspaceConfigStore.Create(ctx, gitspaceConfig)
if err != nil {
return nil, fmt.Errorf("failed to create gitspace config for : %q %w", identifier, err)
}
return gitspaceConfig, nil
}
func (c *Controller) sanitizeCreateInput(in *CreateInput) error {
if err := check.Identifier(in.Identifier); err != nil {
return err
}
parentRefAsID, err := strconv.ParseInt(in.SpaceRef, 10, 64)
if (err == nil && parentRefAsID <= 0) || (len(strings.TrimSpace(in.SpaceRef)) == 0) {
return ErrGitspaceRequiresParent
}
return nil
}

View File

@ -16,16 +16,68 @@ package gitspace
import (
"context"
"fmt"
"strconv"
apiauth "github.com/harness/gitness/app/api/auth"
"github.com/harness/gitness/app/auth"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/rs/zerolog/log"
)
// TODO Stubbed Impl
const gitspaceConfigNotFound = "Failed to find gitspace config with identifier "
func (c *Controller) Delete(
_ context.Context,
_ *auth.Session,
_ string,
_ string,
ctx context.Context,
session *auth.Session,
spaceRef string,
identifier string,
) error {
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
if err != nil {
return fmt.Errorf("failed to find space: %w", err)
}
err = apiauth.CheckGitspace(ctx, c.authorizer, session, space.Path, identifier, enum.PermissionGitspaceDelete)
if err != nil {
return fmt.Errorf("failed to authorize: %w", err)
}
gitspaceConfig, err := c.gitspaceConfigStore.FindByIdentifier(ctx, space.ID, identifier)
if err != nil || gitspaceConfig == nil {
log.Err(err).Msg(gitspaceConfigNotFound + identifier)
return err
}
instance, err := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, gitspaceConfig.ID, gitspaceConfig.SpaceID)
gitspaceConfig.GitspaceInstance = instance
if err != nil {
return fmt.Errorf("failed to find gitspace with config : %q %w", gitspaceConfig.Identifier, err)
}
stopErr := c.stopRunningGitspace(ctx, instance, gitspaceConfig)
if stopErr != nil {
return stopErr
}
gitspaceConfig.IsDeleted = true
if err = c.gitspaceConfigStore.Update(ctx, gitspaceConfig); err != nil {
log.Err(err).Msg("Failed to delete gitspace config with ID " + strconv.FormatInt(gitspaceConfig.ID, 10))
return err
}
return nil
}
func (c *Controller) stopRunningGitspace(
ctx context.Context,
instance *types.GitspaceInstance,
config *types.GitspaceConfig) error {
if instance != nil &&
(instance.State == enum.GitspaceInstanceStateRunning ||
instance.State == enum.GitspaceInstanceStateUnknown) {
if instanceUpdated, err := c.orchestrator.DeleteGitspace(ctx, config); err != nil {
return err
} else if err = c.gitspaceInstanceStore.Update(ctx, instanceUpdated); err != nil {
return err
}
}
return nil
}

View File

@ -16,18 +16,53 @@ package gitspace
import (
"context"
"errors"
"fmt"
apiauth "github.com/harness/gitness/app/api/auth"
"github.com/harness/gitness/app/auth"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
// TODO Stubbed Impl
func (c *Controller) Find(
_ context.Context,
_ *auth.Session,
_ string,
_ string,
ctx context.Context,
session *auth.Session,
spaceRef string,
identifier string,
) (*types.GitspaceConfig, error) {
return nil, errors.New("unimplemented")
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
if err != nil {
return nil, fmt.Errorf("failed to find space: %w", err)
}
err = apiauth.CheckGitspace(ctx, c.authorizer, session, space.Path, identifier, enum.PermissionGitspaceView)
if err != nil {
return nil, fmt.Errorf("failed to authorize: %w", err)
}
gitspaceConfig, err := c.gitspaceConfigStore.FindByIdentifier(ctx, space.ID, identifier)
if err != nil {
return nil, fmt.Errorf("failed to find gitspace config: %w", err)
}
infraProviderResource, err := c.infraProviderResourceStore.Find(
ctx,
gitspaceConfig.InfraProviderResourceID)
if err != nil {
return nil, fmt.Errorf("failed to find infra provider resource for gitspace config: %w", err)
}
gitspaceConfig.SpacePath = space.Path
gitspaceConfig.InfraProviderResourceIdentifier = infraProviderResource.Identifier
instance, err := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, gitspaceConfig.ID, gitspaceConfig.SpaceID)
if err != nil {
return nil, err
}
if instance != nil {
gitspaceConfig.GitspaceInstance = instance
gitspaceStateType, err := enum.GetGitspaceStateFromInstance(instance.State)
if err != nil {
return nil, err
}
gitspaceConfig.State = gitspaceStateType
} else {
gitspaceConfig.State = enum.GitspaceStateUninitialized
}
return gitspaceConfig, nil
}

View File

@ -16,29 +16,62 @@ package gitspace
import (
"context"
"errors"
"fmt"
"strconv"
"strings"
apiauth "github.com/harness/gitness/app/api/auth"
"github.com/harness/gitness/app/auth"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/check"
"github.com/harness/gitness/types/enum"
)
// TODO Stubbed Impl
// UpdateInput is used for updating a gitspace.
type UpdateInput struct {
IDE enum.IDEType `json:"ide"`
InfraProviderResourceID string `json:"infra_provider_resource_id"`
Name string `json:"name"`
Identifier string `json:"-"`
SpaceRef string `json:"-"`
IDE enum.IDEType `json:"ide"`
ResourceIdentifier string `json:"resource_identifier"`
Name string `json:"name"`
Identifier string `json:"-"`
SpaceRef string `json:"-"`
}
func (c *Controller) Update(
_ context.Context,
_ *auth.Session,
_ string,
_ string,
_ *UpdateInput,
) (*types.GitspaceConfig, error) {
return nil, errors.New("unimplemented")
ctx context.Context,
session *auth.Session,
spaceRef string,
identifier string,
in *UpdateInput,
) error {
in.SpaceRef = spaceRef
in.Identifier = identifier
if err := c.sanitizeUpdateInput(in); err != nil {
return fmt.Errorf("failed to sanitize input: %w", err)
}
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
if err != nil {
return fmt.Errorf("failed to find space: %w", err)
}
err = apiauth.CheckGitspace(ctx, c.authorizer, session, space.Path, identifier, enum.PermissionGitspaceEdit)
if err != nil {
return fmt.Errorf("failed to authorize: %w", err)
}
gitspaceConfig, err := c.gitspaceConfigStore.FindByIdentifier(ctx, space.ID, identifier)
if err != nil {
return fmt.Errorf("failed to find gitspace config: %w", err)
}
// TODO Update with proper locks
return c.gitspaceConfigStore.Update(ctx, gitspaceConfig)
}
func (c *Controller) sanitizeUpdateInput(in *UpdateInput) error {
parentRefAsID, err := strconv.ParseInt(in.SpaceRef, 10, 64)
if (err == nil && parentRefAsID <= 0) || (len(strings.TrimSpace(in.SpaceRef)) == 0) {
return ErrGitspaceRequiresParent
}
if err := check.Identifier(in.Identifier); err != nil {
return err
}
return nil
}

View File

@ -16,6 +16,8 @@ package gitspace
import (
"github.com/harness/gitness/app/auth/authz"
gitspaceevents "github.com/harness/gitness/app/events/gitspace"
"github.com/harness/gitness/app/gitspace/orchestrator"
"github.com/harness/gitness/app/store"
"github.com/google/wire"
@ -32,7 +34,17 @@ func ProvideController(
configStore store.GitspaceConfigStore,
instanceStore store.GitspaceInstanceStore,
spaceStore store.SpaceStore,
reporter *gitspaceevents.Reporter,
orchestrator orchestrator.Orchestrator,
eventStore store.GitspaceEventStore,
) *Controller {
return NewController(authorizer, resourceStore, configStore, instanceStore, spaceStore, eventStore)
return NewController(
authorizer,
resourceStore,
configStore,
instanceStore,
spaceStore,
reporter,
orchestrator,
eventStore)
}

View File

@ -0,0 +1,148 @@
// 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"
"strings"
"time"
apiauth "github.com/harness/gitness/app/api/auth"
"github.com/harness/gitness/app/auth"
"github.com/harness/gitness/infraprovider"
infraproviderenum "github.com/harness/gitness/infraprovider/enum"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/check"
"github.com/harness/gitness/types/enum"
)
type CreateInput struct {
Identifier string `json:"identifier"`
SpaceRef string `json:"space_ref"` // Ref of the parent space
Name string `json:"name"`
Type infraproviderenum.InfraProviderType `json:"type"`
Metadata map[string]string `json:"metadata"`
Resources []ResourceInput `json:"resources"`
}
type ResourceInput struct {
Identifier string `json:"identifier"`
Name string `json:"name"`
InfraProviderType infraproviderenum.InfraProviderType `json:"infra_provider_type"`
CPU *string `json:"cpu"`
Memory *string `json:"memory"`
Disk *string `json:"disk"`
Network *string `json:"network"`
Region []string `json:"region"`
Metadata map[string]string `json:"metadata"`
GatewayHost *string `json:"gateway_host"`
GatewayPort *string `json:"gateway_port"`
TemplateIdentifier *string `json:"template_identifier"`
}
// Create creates a new infraprovider config.
func (c *Controller) Create(
ctx context.Context,
session *auth.Session,
in *CreateInput,
) (*types.InfraProviderConfig, error) {
if err := c.sanitizeCreateInput(in); err != nil {
return nil, fmt.Errorf("invalid input: %w", err)
}
now := time.Now().UnixMilli()
parentSpace, err := c.spaceStore.FindByRef(ctx, in.SpaceRef)
if err != nil {
return nil, fmt.Errorf("failed to find parent by ref: %w", err)
}
if err = apiauth.CheckInfraProvider(
ctx,
c.authorizer,
session,
parentSpace.Path,
"",
enum.PermissionInfraProviderEdit); err != nil {
return nil, err
}
infraProviderConfig := &types.InfraProviderConfig{
Identifier: in.Identifier,
Name: in.Name,
SpaceID: parentSpace.ID,
Type: in.Type,
Created: now,
Updated: now,
}
err = c.infraProviderConfigStore.Create(ctx, infraProviderConfig)
if err != nil {
return nil, fmt.Errorf("failed to create infraprovider config for : %q %w", infraProviderConfig.Identifier, err)
}
infraProviderConfiginDB, err := c.infraProviderConfigStore.FindByIdentifier(
ctx,
parentSpace.ID,
infraProviderConfig.Identifier)
if err != nil {
return nil, err
}
infraProvider, err := c.infraProviderFactory.GetInfraProvider(infraProviderConfiginDB.Type)
if err != nil {
return nil, err
}
if len(infraProvider.TemplateParams()) > 0 {
return nil, fmt.Errorf("failed to fetch templates") // TODO Implement
}
parameters := []infraprovider.Parameter{}
// TODO logic to populate paramteters as per the provider type
err = infraProvider.ValidateParams(parameters)
if err != nil {
return nil, err
}
for _, res := range in.Resources {
entity := &types.InfraProviderResource{
Identifier: res.Identifier,
InfraProviderConfigID: infraProviderConfiginDB.ID,
InfraProviderType: res.InfraProviderType,
Name: res.Name,
SpaceID: parentSpace.ID,
CPU: res.CPU,
Memory: res.Memory,
Disk: res.Disk,
Network: res.Network,
Region: strings.Join(res.Region, " "), // TODO fix
Metadata: res.Metadata,
GatewayHost: res.GatewayHost,
GatewayPort: res.GatewayPort, // No template as of now
Created: now,
Updated: now,
}
err = c.infraProviderResourceStore.Create(ctx, infraProviderConfiginDB.ID, entity)
if err != nil {
return nil, fmt.Errorf("failed to create infraprovider resource for : %q %w", entity.Identifier, err)
}
}
resources, err := c.infraProviderResourceStore.List(ctx, infraProviderConfiginDB.ID, types.ListQueryFilter{})
infraProviderConfig.Resources = resources
if err != nil {
return nil, fmt.Errorf(
"error creating infra provider resource for config : %q %w", infraProviderConfiginDB.Identifier, err)
}
return infraProviderConfig, nil
}
func (c *Controller) sanitizeCreateInput(in *CreateInput) error {
if err := check.Identifier(in.Identifier); err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,51 @@
// 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"
apiauth "github.com/harness/gitness/app/api/auth"
"github.com/harness/gitness/app/auth"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
func (c *Controller) Find(
ctx context.Context,
session *auth.Session,
spaceRef string,
identifier string,
) (*types.InfraProviderConfig, error) {
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
if err != nil {
return nil, fmt.Errorf("failed to find space: %w", err)
}
err = apiauth.CheckGitspace(ctx, c.authorizer, session, space.Path, identifier, enum.PermissionInfraProviderView)
if err != nil {
return nil, fmt.Errorf("failed to authorize: %w", err)
}
infraProviderConfig, err := c.infraProviderConfigStore.FindByIdentifier(ctx, space.ID, identifier)
if err != nil {
return nil, fmt.Errorf("failed to find infraprovider config: %w", err)
}
resources, err := c.infraProviderResourceStore.List(ctx, infraProviderConfig.ID, types.ListQueryFilter{})
if err != nil {
return nil, fmt.Errorf("failed to find infraprovider resources: %w", err)
}
infraProviderConfig.Resources = resources
return infraProviderConfig, nil
}

View File

@ -61,27 +61,28 @@ func (s SpaceOutput) MarshalJSON() ([]byte, error) {
type Controller struct {
nestedSpacesEnabled bool
tx dbtx.Transactor
urlProvider url.Provider
sseStreamer sse.Streamer
identifierCheck check.SpaceIdentifier
authorizer authz.Authorizer
spacePathStore store.SpacePathStore
pipelineStore store.PipelineStore
secretStore store.SecretStore
connectorStore store.ConnectorStore
templateStore store.TemplateStore
spaceStore store.SpaceStore
repoStore store.RepoStore
principalStore store.PrincipalStore
repoCtrl *repo.Controller
membershipStore store.MembershipStore
importer *importer.Repository
exporter *exporter.Repository
resourceLimiter limiter.ResourceLimiter
publicAccess publicaccess.Service
auditService audit.Service
gitspaceStore store.GitspaceConfigStore
tx dbtx.Transactor
urlProvider url.Provider
sseStreamer sse.Streamer
identifierCheck check.SpaceIdentifier
authorizer authz.Authorizer
spacePathStore store.SpacePathStore
pipelineStore store.PipelineStore
secretStore store.SecretStore
connectorStore store.ConnectorStore
templateStore store.TemplateStore
spaceStore store.SpaceStore
repoStore store.RepoStore
principalStore store.PrincipalStore
repoCtrl *repo.Controller
membershipStore store.MembershipStore
importer *importer.Repository
exporter *exporter.Repository
resourceLimiter limiter.ResourceLimiter
publicAccess publicaccess.Service
auditService audit.Service
gitspaceConfigStore store.GitspaceConfigStore
gitspaceInstanceStore store.GitspaceInstanceStore
}
func NewController(config *types.Config, tx dbtx.Transactor, urlProvider url.Provider,
@ -92,29 +93,31 @@ func NewController(config *types.Config, tx dbtx.Transactor, urlProvider url.Pro
membershipStore store.MembershipStore, importer *importer.Repository, exporter *exporter.Repository,
limiter limiter.ResourceLimiter, publicAccess publicaccess.Service, auditService audit.Service,
gitspaceStore store.GitspaceConfigStore,
gitspaceInstanceStore store.GitspaceInstanceStore,
) *Controller {
return &Controller{
nestedSpacesEnabled: config.NestedSpacesEnabled,
tx: tx,
urlProvider: urlProvider,
sseStreamer: sseStreamer,
identifierCheck: identifierCheck,
authorizer: authorizer,
spacePathStore: spacePathStore,
pipelineStore: pipelineStore,
secretStore: secretStore,
connectorStore: connectorStore,
templateStore: templateStore,
spaceStore: spaceStore,
repoStore: repoStore,
principalStore: principalStore,
repoCtrl: repoCtrl,
membershipStore: membershipStore,
importer: importer,
exporter: exporter,
resourceLimiter: limiter,
publicAccess: publicAccess,
auditService: auditService,
gitspaceStore: gitspaceStore,
nestedSpacesEnabled: config.NestedSpacesEnabled,
tx: tx,
urlProvider: urlProvider,
sseStreamer: sseStreamer,
identifierCheck: identifierCheck,
authorizer: authorizer,
spacePathStore: spacePathStore,
pipelineStore: pipelineStore,
secretStore: secretStore,
connectorStore: connectorStore,
templateStore: templateStore,
spaceStore: spaceStore,
repoStore: repoStore,
principalStore: principalStore,
repoCtrl: repoCtrl,
membershipStore: membershipStore,
importer: importer,
exporter: exporter,
resourceLimiter: limiter,
publicAccess: publicAccess,
auditService: auditService,
gitspaceConfigStore: gitspaceStore,
gitspaceInstanceStore: gitspaceInstanceStore,
}
}

View File

@ -16,16 +16,76 @@ package space
import (
"context"
"fmt"
apiauth "github.com/harness/gitness/app/api/auth"
"github.com/harness/gitness/app/auth"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
func (c *Controller) ListGitspaces(
_ context.Context,
_ *auth.Session,
_ string,
_ types.ListQueryFilter,
ctx context.Context,
session *auth.Session,
spaceRef string,
filter types.ListQueryFilter,
) ([]*types.GitspaceConfig, int64, error) {
return nil, 0, nil
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
if err != nil {
return nil, 0, fmt.Errorf("failed to find space: %w", err)
}
err = apiauth.CheckGitspace(ctx, c.authorizer, session, space.Path, "", enum.PermissionGitspaceView)
if err != nil {
return nil, 0, fmt.Errorf("failed to authorize gitspace: %w", err)
}
gitspaceFilter := &types.GitspaceFilter{
QueryFilter: filter,
UserID: session.Principal.UID,
SpaceIDs: []int64{space.ID},
}
gitspaceConfigs, err := c.gitspaceConfigStore.List(ctx, gitspaceFilter)
if err != nil {
return nil, 0, fmt.Errorf("failed to list gitspace configs: %w", err)
}
count, err := c.gitspaceConfigStore.Count(ctx, gitspaceFilter)
if err != nil {
return nil, 0, fmt.Errorf("failed to count gitspaces in space: %w", err)
}
var gitspaceConfigIDs = make([]int64, 0)
for idx := 0; idx < len(gitspaceConfigs); idx++ {
if gitspaceConfigs[idx].IsDeleted {
continue
}
gitspaceConfigs[idx].SpacePath = space.Path // As the API is for a space, this will remain same
gitspaceConfigIDs = append(gitspaceConfigIDs, gitspaceConfigs[idx].ID)
}
gitspaceInstancesMap, err := c.getLatestInstanceMap(ctx, gitspaceConfigIDs)
if err != nil {
return nil, 0, err
}
for _, gitspaceConfig := range gitspaceConfigs {
gitspaceConfig.GitspaceInstance = gitspaceInstancesMap[gitspaceConfig.ID]
if gitspaceConfig.GitspaceInstance != nil {
gitspaceConfig.State, _ = enum.GetGitspaceStateFromInstance(gitspaceConfig.GitspaceInstance.State)
gitspaceConfig.GitspaceInstance.SpacePath = gitspaceConfig.SpacePath
} else {
gitspaceConfig.State = enum.GitspaceStateUninitialized
}
}
return gitspaceConfigs, count, nil
}
func (c *Controller) getLatestInstanceMap(
ctx context.Context,
gitspaceConfigIDs []int64,
) (map[int64]*types.GitspaceInstance, error) {
var gitspaceInstances, err = c.gitspaceInstanceStore.FindAllLatestByGitspaceConfigID(ctx, gitspaceConfigIDs)
if err != nil {
return nil, err
}
var gitspaceInstancesMap = make(map[int64]*types.GitspaceInstance)
for _, gitspaceEntry := range gitspaceInstances {
gitspaceInstancesMap[gitspaceEntry.GitSpaceConfigID] = gitspaceEntry
}
return gitspaceInstancesMap, nil
}

View File

@ -44,11 +44,13 @@ func ProvideController(config *types.Config, tx dbtx.Transactor, urlProvider url
spaceStore store.SpaceStore, repoStore store.RepoStore, principalStore store.PrincipalStore,
repoCtrl *repo.Controller, membershipStore store.MembershipStore, importer *importer.Repository,
exporter *exporter.Repository, limiter limiter.ResourceLimiter, publicAccess publicaccess.Service,
auditService audit.Service, gitspaceStore store.GitspaceConfigStore,
auditService audit.Service, gitspaceConfigStore store.GitspaceConfigStore, instanceStore store.GitspaceInstanceStore,
) *Controller {
return NewController(config, tx, urlProvider, sseStreamer, identifierCheck, authorizer,
spacePathStore, pipelineStore, secretStore,
connectorStore, templateStore,
spaceStore, repoStore, principalStore,
repoCtrl, membershipStore, importer, exporter, limiter, publicAccess, auditService, gitspaceStore)
repoCtrl, membershipStore, importer,
exporter, limiter, publicAccess,
auditService, gitspaceConfigStore, instanceStore)
}

View File

@ -35,19 +35,19 @@ func HandleAction(gitspaceCtrl *gitspace.Controller) http.HandlerFunc {
render.BadRequestf(ctx, w, "Invalid Request Body: %s.", err)
return
}
gitspaceConfigRef, err := request.GetGitspaceRefFromPath(r)
if err != nil {
render.TranslatedUserError(ctx, w, err)
return
}
spaceRef, gitspaceConfigIdentifier, err := paths.DisectLeaf(gitspaceConfigRef)
in.SpaceRef = spaceRef
in.Identifier = gitspaceConfigIdentifier
if err != nil {
render.TranslatedUserError(ctx, w, err)
return
}
gitspaceConfig, err := gitspaceCtrl.Action(ctx, session, spaceRef, gitspaceConfigIdentifier, in)
gitspaceConfig, err := gitspaceCtrl.Action(ctx, session, in)
if err != nil {
render.TranslatedUserError(ctx, w, err)
return

View File

@ -47,12 +47,12 @@ func HandleUpdateConfig(gitspaceCtrl *gitspace.Controller) http.HandlerFunc {
return
}
gitspaceConfig, err := gitspaceCtrl.Update(ctx, session, spaceRef, gitspaceConfigIdentifier, in)
err = gitspaceCtrl.Update(ctx, session, spaceRef, gitspaceConfigIdentifier, in)
if err != nil {
render.TranslatedUserError(ctx, w, err)
return
}
render.JSON(w, http.StatusOK, gitspaceConfig)
render.JSON(w, http.StatusOK, nil)
}
}

View File

@ -0,0 +1,47 @@
// 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 (
"encoding/json"
"net/http"
"github.com/harness/gitness/app/api/controller/infraprovider"
"github.com/harness/gitness/app/api/render"
"github.com/harness/gitness/app/api/request"
)
// HandleCreateConfig returns a http.HandlerFunc that creates a new InfraProviderConfig with its resources.
func HandleCreateConfig(infraProviderCtrl *infraprovider.Controller) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
session, _ := request.AuthSessionFrom(ctx)
in := new(infraprovider.CreateInput)
err := json.NewDecoder(r.Body).Decode(in)
if err != nil {
render.BadRequestf(ctx, w, "Invalid Request Body: %s.", err)
return
}
infraProviderConfig, err := infraProviderCtrl.Create(ctx, session, in)
if err != nil {
render.TranslatedUserError(ctx, w, err)
return
}
render.JSON(w, http.StatusCreated, infraProviderConfig)
}
}

View File

@ -0,0 +1,49 @@
// 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 (
"net/http"
"github.com/harness/gitness/app/api/controller/infraprovider"
"github.com/harness/gitness/app/api/render"
"github.com/harness/gitness/app/api/request"
"github.com/harness/gitness/app/paths"
)
func HandleFind(infraProviderCtrl *infraprovider.Controller) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
session, _ := request.AuthSessionFrom(ctx)
infraProviderRefFromPath, err := request.GetInfraProviderRefFromPath(r)
if err != nil {
render.TranslatedUserError(ctx, w, err)
return
}
spaceRef, infraProviderIdentifier, err := paths.DisectLeaf(infraProviderRefFromPath)
if err != nil {
render.TranslatedUserError(ctx, w, err)
return
}
infraProviderConfig, err := infraProviderCtrl.Find(ctx, session, spaceRef, infraProviderIdentifier)
if err != nil {
render.TranslatedUserError(ctx, w, err)
return
}
render.JSON(w, http.StatusOK, infraProviderConfig)
}
}

View File

@ -0,0 +1,59 @@
// 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 openapi
import (
"net/http"
"github.com/harness/gitness/app/api/controller/infraprovider"
"github.com/harness/gitness/app/api/usererror"
"github.com/harness/gitness/types"
"github.com/swaggest/openapi-go/openapi3"
)
type createInfraProviderConfigRequest struct {
infraprovider.CreateInput
}
type getInfraProviderRequest struct {
Ref string `path:"infraprovider_identifier"`
}
func infraProviderOperations(reflector *openapi3.Reflector) {
opFind := openapi3.Operation{}
opFind.WithTags("infraproviders")
opFind.WithSummary("Get infraProviderConfig")
opFind.WithMapOfAnything(map[string]interface{}{"operationId": "getInfraProvider"})
_ = reflector.SetRequest(&opFind, new(getInfraProviderRequest), http.MethodGet)
_ = reflector.SetJSONResponse(&opFind, new(types.InfraProviderConfig), http.StatusOK)
_ = reflector.SetJSONResponse(&opFind, new(usererror.Error), http.StatusBadRequest)
_ = reflector.SetJSONResponse(&opFind, new(usererror.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&opFind, new(usererror.Error), http.StatusNotFound)
_ = reflector.Spec.AddOperation(
http.MethodGet, "/infraproviders/{infraprovider_identifier}", opFind)
opCreate := openapi3.Operation{}
opCreate.WithTags("infraproviders")
opCreate.WithSummary("Create infraProvider config")
opCreate.WithMapOfAnything(map[string]interface{}{"operationId": "createInfraProvider"})
_ = reflector.SetRequest(&opCreate, new(createInfraProviderConfigRequest), http.MethodPost)
_ = reflector.SetJSONResponse(&opCreate, new(types.InfraProviderConfig), http.StatusCreated)
_ = reflector.SetJSONResponse(&opCreate, new(usererror.Error), http.StatusBadRequest)
_ = reflector.SetJSONResponse(&opCreate, new(usererror.Error), http.StatusInternalServerError)
_ = reflector.SetJSONResponse(&opCreate, new(usererror.Error), http.StatusUnauthorized)
_ = reflector.SetJSONResponse(&opCreate, new(usererror.Error), http.StatusForbidden)
_ = reflector.Spec.AddOperation(http.MethodPost, "/infraproviders", opCreate)
}

View File

@ -71,6 +71,7 @@ func (*OpenAPI) Generate() *openapi3.Spec {
checkOperations(&reflector)
uploadOperations(&reflector)
gitspaceOperations(&reflector)
infraProviderOperations(&reflector)
//
// define security scheme

View File

@ -0,0 +1,34 @@
// 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 request
import (
"net/http"
"net/url"
)
const (
PathParamInfraProviderConfigIdentifier = "infraprovider_identifier"
)
func GetInfraProviderRefFromPath(r *http.Request) (string, error) {
rawRef, err := PathParamOrError(r, PathParamInfraProviderConfigIdentifier)
if err != nil {
return "", err
}
// paths are unescaped
return url.PathUnescape(rawRef)
}

View File

@ -107,6 +107,9 @@ func (a *MembershipAuthorizer) Check(
case enum.ResourceTypeGitspace:
spacePath = scope.SpacePath
case enum.ResourceTypeInfraProvider:
spacePath = scope.SpacePath
case enum.ResourceTypeUser:
// a user is allowed to edit themselves
if resource.Identifier == session.Principal.UID &&

View File

@ -266,7 +266,7 @@ func (e *EmbeddedDockerOrchestrator) setupSSHServer(
sshServerScript, err := GenerateScriptFromTemplate(
templateSetupSSHServer, &SetupSSHServerPayload{
Username: "harness",
Password: gitspaceInstance.AccessKey.String,
Password: *gitspaceInstance.AccessKey,
WorkingDirectory: devcontainer.WorkingDir,
})
if err != nil {

View File

@ -47,7 +47,7 @@ func (v *VSCodeWeb) Setup(
) error {
installScript, err := GenerateScriptFromTemplate(
templateInstallVSCodeWeb, &InstallVSCodeWebPayload{
Password: gitspaceInstance.AccessKey.String,
Password: *gitspaceInstance.AccessKey,
Port: v.config.Port,
})
if err != nil {

View File

@ -27,7 +27,6 @@ import (
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/guregu/null"
"github.com/rs/zerolog/log"
)
@ -116,7 +115,8 @@ func (o orchestrator) StartGitspace(
Path: fmt.Sprintf("ssh-remote+%s@%s:%s/gitspace/%s", "harness", infra.Host, port, repoName),
}
}
gitspaceInstance.URL = null.NewString(ideURL.String(), true)
ideURLString := ideURL.String()
gitspaceInstance.URL = &ideURLString
gitspaceInstance.LastUsed = time.Now().UnixMilli()
gitspaceInstance.State = enum.GitspaceInstanceStateRunning
@ -152,8 +152,6 @@ func (o orchestrator) StopGitspace(
gitspaceInstance := gitspaceConfig.GitspaceInstance
gitspaceInstance.State = enum.GitspaceInstanceStateDeleted
gitspaceInstance.URL = null.NewString("", false)
return gitspaceInstance, err
}

View File

@ -71,7 +71,6 @@ func NewExecutionRunner(
if err != nil {
return nil, err
}
exec := runtime.NewExecer(tracer, remote, upload,
engine, int64(config.CI.ParallelWorkers))

View File

@ -24,6 +24,7 @@ import (
"github.com/harness/gitness/app/api/controller/execution"
controllergithook "github.com/harness/gitness/app/api/controller/githook"
"github.com/harness/gitness/app/api/controller/gitspace"
"github.com/harness/gitness/app/api/controller/infraprovider"
"github.com/harness/gitness/app/api/controller/keywordsearch"
"github.com/harness/gitness/app/api/controller/logs"
"github.com/harness/gitness/app/api/controller/migrate"
@ -48,6 +49,7 @@ import (
handlerexecution "github.com/harness/gitness/app/api/handler/execution"
handlergithook "github.com/harness/gitness/app/api/handler/githook"
handlergitspace "github.com/harness/gitness/app/api/handler/gitspace"
handlerinfraProvider "github.com/harness/gitness/app/api/handler/infraprovider"
handlerkeywordsearch "github.com/harness/gitness/app/api/handler/keywordsearch"
handlerlogs "github.com/harness/gitness/app/api/handler/logs"
handlerpipeline "github.com/harness/gitness/app/api/handler/pipeline"
@ -125,6 +127,7 @@ func NewAPIHandler(
sysCtrl *system.Controller,
uploadCtrl *upload.Controller,
searchCtrl *keywordsearch.Controller,
infraProviderCtrl *infraprovider.Controller,
migrateCtrl *migrate.Controller,
gitspaceCtrl *gitspace.Controller,
) APIHandler {
@ -159,7 +162,7 @@ func NewAPIHandler(
setupRoutesV1WithAuth(r, appCtx, config, repoCtrl, repoSettingsCtrl, executionCtrl, triggerCtrl, logCtrl,
pipelineCtrl, connectorCtrl, templateCtrl, pluginCtrl, secretCtrl, spaceCtrl, pullreqCtrl,
webhookCtrl, githookCtrl, git, saCtrl, userCtrl, principalCtrl, checkCtrl, uploadCtrl,
searchCtrl, gitspaceCtrl, migrateCtrl)
searchCtrl, gitspaceCtrl, infraProviderCtrl, migrateCtrl)
})
})
@ -206,6 +209,7 @@ func setupRoutesV1WithAuth(r chi.Router,
uploadCtrl *upload.Controller,
searchCtrl *keywordsearch.Controller,
gitspaceCtrl *gitspace.Controller,
infraProviderCtrl *infraprovider.Controller,
migrateCtrl *migrate.Controller,
) {
setupAccountWithAuth(r, userCtrl, config)
@ -222,6 +226,7 @@ func setupRoutesV1WithAuth(r chi.Router,
setupAdmin(r, userCtrl)
setupPlugins(r, pluginCtrl)
setupKeywordSearch(r, searchCtrl)
setupInfraProviders(r, infraProviderCtrl)
setupGitspaces(r, gitspaceCtrl)
setupMigrate(r, migrateCtrl)
}
@ -707,7 +712,7 @@ func setupGitspaces(r chi.Router, gitspacesCtrl *gitspace.Controller) {
r.Post("/", handlergitspace.HandleCreateConfig(gitspacesCtrl))
r.Route(fmt.Sprintf("/{%s}", request.PathParamGitspaceIdentifier), func(r chi.Router) {
r.Get("/", handlergitspace.HandleFind(gitspacesCtrl))
r.Post("/action", handlergitspace.HandleAction(gitspacesCtrl))
r.Post("/actions", handlergitspace.HandleAction(gitspacesCtrl))
r.Delete("/", handlergitspace.HandleDeleteConfig(gitspacesCtrl))
r.Patch("/", handlergitspace.HandleUpdateConfig(gitspacesCtrl))
r.Get("/events", handlergitspace.HandleGetEvents(gitspacesCtrl))
@ -715,6 +720,15 @@ func setupGitspaces(r chi.Router, gitspacesCtrl *gitspace.Controller) {
})
}
func setupInfraProviders(r chi.Router, infraProviderCtrl *infraprovider.Controller) {
r.Route("/infraproviders", func(r chi.Router) {
r.Post("/", handlerinfraProvider.HandleCreateConfig(infraProviderCtrl))
r.Route(fmt.Sprintf("/{%s}", request.PathParamInfraProviderConfigIdentifier), func(r chi.Router) {
r.Get("/", handlerinfraProvider.HandleFind(infraProviderCtrl))
})
})
}
func setupAdmin(r chi.Router, userCtrl *user.Controller) {
r.Route("/admin", func(r chi.Router) {
r.Use(middlewareprincipal.RestrictToAdmin())

View File

@ -23,6 +23,7 @@ import (
"github.com/harness/gitness/app/api/controller/execution"
"github.com/harness/gitness/app/api/controller/githook"
"github.com/harness/gitness/app/api/controller/gitspace"
"github.com/harness/gitness/app/api/controller/infraprovider"
"github.com/harness/gitness/app/api/controller/keywordsearch"
"github.com/harness/gitness/app/api/controller/logs"
"github.com/harness/gitness/app/api/controller/migrate"
@ -116,6 +117,7 @@ func ProvideAPIHandler(
sysCtrl *system.Controller,
blobCtrl *upload.Controller,
searchCtrl *keywordsearch.Controller,
infraProviderCtrl *infraprovider.Controller,
gitspaceCtrl *gitspace.Controller,
migrateCtrl *migrate.Controller,
) APIHandler {
@ -123,7 +125,7 @@ func ProvideAPIHandler(
authenticator, repoCtrl, repoSettingsCtrl, executionCtrl, logCtrl, spaceCtrl, pipelineCtrl,
secretCtrl, triggerCtrl, connectorCtrl, templateCtrl, pluginCtrl, pullreqCtrl, webhookCtrl,
githookCtrl, git, saCtrl, userCtrl, principalCtrl, checkCtrl, sysCtrl, blobCtrl, searchCtrl,
migrateCtrl, gitspaceCtrl)
infraProviderCtrl, migrateCtrl, gitspaceCtrl)
}
func ProvideWebHandler(config *types.Config, openapi openapi.Service) WebHandler {

View File

@ -572,19 +572,13 @@ type (
Create(ctx context.Context, gitspaceConfig *types.GitspaceConfig) error
// Update tries to update a gitspace config in the datastore with optimistic locking.
Update(ctx context.Context, gitspaceConfig *types.GitspaceConfig) (*types.GitspaceConfig, error)
Update(ctx context.Context, gitspaceConfig *types.GitspaceConfig) error
// List lists the gitspace configs present in a parent space ID in the datastore.
List(ctx context.Context, filter *types.GitspaceFilter) ([]*types.GitspaceConfig, error)
// Count the number of gitspace configs in a space matching the given filter.
Count(ctx context.Context, filter *types.GitspaceFilter) (int64, error)
// Delete deletes a pipeline ID from the datastore.
Delete(ctx context.Context, id int64) error
// DeleteByIdentifier deletes the gitspaceConfig with the given identifier for the given space.
DeleteByIdentifier(ctx context.Context, spaceID int64, identifier string) error
}
GitspaceInstanceStore interface {
@ -602,13 +596,13 @@ type (
Create(ctx context.Context, gitspaceInstance *types.GitspaceInstance) error
// Update tries to update a gitspace instance in the datastore with optimistic locking.
Update(ctx context.Context, gitspaceInstance *types.GitspaceInstance) (*types.GitspaceInstance, error)
Update(ctx context.Context, gitspaceInstance *types.GitspaceInstance) error
// List lists the gitspace instance present in a parent space ID in the datastore.
List(ctx context.Context, filter *types.GitspaceFilter) ([]*types.GitspaceInstance, error)
// Delete deletes a gitspace instance ID from the datastore.
Delete(ctx context.Context, id int64) error
// List lists the latest gitspace instance present for the gitspace configs in the datastore.
FindAllLatestByGitspaceConfigID(ctx context.Context, gitspaceConfigIDs []int64) ([]*types.GitspaceInstance, error)
}
InfraProviderConfigStore interface {
@ -620,9 +614,6 @@ type (
// Create creates a new infra provider config in the datastore.
Create(ctx context.Context, infraProviderConfig *types.InfraProviderConfig) error
// DeleteByIdentifier deletes the infra provider config with the given identifier for the given space.
DeleteByIdentifier(ctx context.Context, spaceID int64, identifier string) error
}
InfraProviderResourceStore interface {
@ -641,9 +632,6 @@ type (
filter types.ListQueryFilter,
) ([]*types.InfraProviderResource, error)
// ListAll lists all the infra provider resource in a given space.
ListAll(ctx context.Context, parentID int64, filter types.ListQueryFilter) ([]*types.InfraProviderResource, error)
// DeleteByIdentifier deletes the Infra provider resource with the given identifier for the given space.
DeleteByIdentifier(ctx context.Context, spaceID int64, identifier string) error
}

View File

@ -16,16 +16,66 @@ package database
import (
"context"
"strings"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/store/database"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/Masterminds/squirrel"
"github.com/guregu/null"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
)
const (
gitspaceConfigInsertColumns = `
gconf_uid,
gconf_display_name,
gconf_ide,
gconf_infra_provider_resource_id,
gconf_code_auth_type,
gconf_code_auth_id,
gconf_code_repo_type,
gconf_code_repo_is_private,
gconf_code_repo_url,
gconf_devcontainer_path,
gconf_branch,
gconf_user_uid,
gconf_space_id,
gconf_created,
gconf_updated,
gconf_is_deleted
`
gitspaceConfigsTable = `gitspace_configs`
ReturningClause = "RETURNING "
gitspaceConfigSelectColumns = "gconf_id," + gitspaceConfigInsertColumns
)
type gitspaceConfig struct {
ID int64 `db:"gconf_id"`
Identifier string `db:"gconf_uid"`
Name string `db:"gconf_display_name"`
IDE enum.IDEType `db:"gconf_ide"`
InfraProviderResourceID int64 `db:"gconf_infra_provider_resource_id"`
CodeAuthType string `db:"gconf_code_auth_type"`
CodeAuthID string `db:"gconf_code_auth_id"`
CodeRepoType enum.GitspaceCodeRepoType `db:"gconf_code_repo_type"`
CodeRepoIsPrivate bool `db:"gconf_code_repo_is_private"`
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"`
}
var _ store.GitspaceConfigStore = (*gitspaceConfigStore)(nil)
// TODO Stubbed Impl
// NewGitspaceConfigStore returns a new GitspaceConfigStore.
func NewGitspaceConfigStore(db *sqlx.DB) store.GitspaceConfigStore {
return &gitspaceConfigStore{
@ -37,42 +87,204 @@ type gitspaceConfigStore struct {
db *sqlx.DB
}
func (g gitspaceConfigStore) Find(_ context.Context, _ int64) (*types.GitspaceConfig, error) {
// TODO implement me
panic("implement me")
func (s gitspaceConfigStore) Count(ctx context.Context, filter *types.GitspaceFilter) (int64, error) {
db := dbtx.GetAccessor(ctx, s.db)
countStmt := database.Builder.
Select("COUNT(*)").
From(gitspaceConfigsTable).
Where(squirrel.Eq{"gconf_is_deleted": false}).
Where(squirrel.Eq{"gconf_user_uid": filter.UserID}).
Where(squirrel.Eq{"gconf_space_id": filter.SpaceIDs})
sql, args, err := countStmt.ToSql()
if err != nil {
return 0, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
var count int64
err = db.QueryRowContext(ctx, sql, args...).Scan(&count)
if err != nil {
return 0, database.ProcessSQLErrorf(ctx, err, "Failed executing custom count query")
}
return count, nil
}
func (g gitspaceConfigStore) FindByIdentifier(_ context.Context, _ int64, _ string) (*types.GitspaceConfig, error) {
// TODO implement me
panic("implement me")
func (s gitspaceConfigStore) Find(ctx context.Context, id int64) (*types.GitspaceConfig, error) {
stmt := database.Builder.
Select(gitspaceConfigSelectColumns).
From(gitspaceConfigsTable).
Where("gconf_id = $1", id). //nolint:goconst
Where("gconf_is_deleted = $2", false)
dst := new(gitspaceConfig)
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, s.db)
if err := db.GetContext(ctx, dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to find gitspace config")
}
return s.mapToGitspaceConfig(ctx, dst)
}
func (g gitspaceConfigStore) Create(_ context.Context, _ *types.GitspaceConfig) error {
// TODO implement me
panic("implement me")
func (s gitspaceConfigStore) FindByIdentifier(
ctx context.Context,
spaceID int64,
identifier string,
) (*types.GitspaceConfig, error) {
stmt := database.Builder.
Select(gitspaceConfigSelectColumns).
From(gitspaceConfigsTable).
Where("LOWER(gconf_uid) = $1", strings.ToLower(identifier)).
Where("gconf_space_id = $2", spaceID).
Where("gconf_is_deleted = $3", false)
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
dst := new(gitspaceConfig)
db := dbtx.GetAccessor(ctx, s.db)
if err := db.GetContext(ctx, dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to find gitspace config")
}
return s.mapToGitspaceConfig(ctx, dst)
}
func (g gitspaceConfigStore) Update(_ context.Context, _ *types.GitspaceConfig) (*types.GitspaceConfig, error) {
// TODO implement me
panic("implement me")
func (s gitspaceConfigStore) Create(ctx context.Context, gitspaceConfig *types.GitspaceConfig) error {
stmt := database.Builder.
Insert(gitspaceConfigsTable).
Columns(gitspaceConfigInsertColumns).
Values(
gitspaceConfig.Identifier,
gitspaceConfig.Name,
gitspaceConfig.IDE,
gitspaceConfig.InfraProviderResourceID,
gitspaceConfig.CodeAuthType,
gitspaceConfig.CodeAuthID,
gitspaceConfig.CodeRepoType,
gitspaceConfig.CodeRepoIsPrivate,
gitspaceConfig.CodeRepoURL,
gitspaceConfig.DevcontainerPath,
gitspaceConfig.Branch,
gitspaceConfig.UserID,
gitspaceConfig.SpaceID,
gitspaceConfig.Created,
gitspaceConfig.Updated,
gitspaceConfig.IsDeleted,
).
Suffix(ReturningClause + "gconf_id")
sql, args, err := stmt.ToSql()
if err != nil {
return errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, s.db)
if err = db.QueryRowContext(ctx, sql, args...).Scan(&gitspaceConfig.ID); err != nil {
return database.ProcessSQLErrorf(ctx, err, "gitspace config query failed")
}
return nil
}
func (g gitspaceConfigStore) List(_ context.Context, _ *types.GitspaceFilter) ([]*types.GitspaceConfig, error) {
// TODO implement me
panic("implement me")
func (s gitspaceConfigStore) Update(ctx context.Context,
gitspaceConfig *types.GitspaceConfig) error {
dbGitspaceConfig := mapToInternalGitspaceConfig(gitspaceConfig)
stmt := database.Builder.
Update(gitspaceConfigsTable).
Set("gconf_display_name", dbGitspaceConfig.Name).
Set("gconf_ide", dbGitspaceConfig.IDE).
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)
sql, args, err := stmt.ToSql()
if err != nil {
return errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, s.db)
if _, err := db.ExecContext(ctx, sql, args...); err != nil {
return database.ProcessSQLErrorf(ctx, err, "Failed to update gitspace config")
}
return nil
}
func (g gitspaceConfigStore) Count(_ context.Context, _ *types.GitspaceFilter) (int64, error) {
// TODO implement me
panic("implement me")
func mapToInternalGitspaceConfig(config *types.GitspaceConfig) *gitspaceConfig {
return &gitspaceConfig{
ID: config.ID,
Identifier: config.Identifier,
Name: config.Name,
IDE: config.IDE,
InfraProviderResourceID: config.InfraProviderResourceID,
CodeAuthType: config.CodeAuthType,
CodeAuthID: config.CodeAuthID,
CodeRepoIsPrivate: config.CodeRepoIsPrivate,
CodeRepoType: config.CodeRepoType,
CodeRepoURL: config.CodeRepoURL,
DevcontainerPath: null.StringFromPtr(config.DevcontainerPath),
Branch: config.Branch,
UserUID: config.UserID,
SpaceID: config.SpaceID,
IsDeleted: config.IsDeleted,
Created: config.Created,
Updated: config.Updated,
}
}
func (g gitspaceConfigStore) Delete(_ context.Context, _ int64) error {
// TODO implement me
panic("implement me")
func (s gitspaceConfigStore) List(ctx context.Context, filter *types.GitspaceFilter) ([]*types.GitspaceConfig, error) {
stmt := database.Builder.
Select(gitspaceConfigSelectColumns).
From(gitspaceConfigsTable).
Where(squirrel.Eq{"gconf_is_deleted": false}).
Where(squirrel.Eq{"gconf_user_uid": filter.UserID}).
Where(squirrel.Eq{"gconf_space_id": filter.SpaceIDs})
queryFilter := filter.QueryFilter
stmt = stmt.Limit(database.Limit(queryFilter.Size))
stmt = stmt.Offset(database.Offset(queryFilter.Page, queryFilter.Size))
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
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 custom list query")
}
return s.mapToGitspaceConfigs(ctx, dst)
}
func (g gitspaceConfigStore) DeleteByIdentifier(_ context.Context, _ int64, _ string) error {
// TODO implement me
panic("implement me")
func (s *gitspaceConfigStore) mapToGitspaceConfig(
_ context.Context,
in *gitspaceConfig,
) (*types.GitspaceConfig, error) {
var res = &types.GitspaceConfig{
ID: in.ID,
Identifier: in.Identifier,
Name: in.Name,
InfraProviderResourceID: in.InfraProviderResourceID,
IDE: in.IDE,
CodeRepoType: in.CodeRepoType,
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,
}
return res, nil
}
func (s *gitspaceConfigStore) mapToGitspaceConfigs(ctx context.Context,
configs []*gitspaceConfig) ([]*types.GitspaceConfig, error) {
var err error
res := make([]*types.GitspaceConfig, len(configs))
for i := range configs {
res[i], err = s.mapToGitspaceConfig(ctx, configs[i])
if err != nil {
return nil, err
}
}
return res, nil
}

View File

@ -16,16 +16,63 @@ package database
import (
"context"
"fmt"
"strings"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/store/database"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/Masterminds/squirrel"
"github.com/guregu/null"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
)
var _ store.GitspaceInstanceStore = (*gitspaceInstanceStore)(nil)
// TODO Stubbed Impl
const (
gitspaceInstanceInsertColumns = `
gits_gitspace_config_id,
gits_url,
gits_state,
gits_user_uid,
gits_resource_usage,
gits_space_id,
gits_created,
gits_updated,
gits_last_used,
gits_total_time_used,
gits_tracked_changes,
gits_access_key,
gits_access_type,
gits_machine_user,
gits_uid`
gitspaceInstanceSelectColumns = "gits_id," + gitspaceInstanceInsertColumns
gitspaceInstanceTable = `gitspaces`
)
type gitspaceInstance struct {
ID int64 `db:"gits_id"`
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"`
AccessKey null.String `db:"gits_access_key"`
AccessType enum.GitspaceAccessType `db:"gits_access_type"`
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.
func NewGitspaceInstanceStore(db *sqlx.DB) store.GitspaceInstanceStore {
return &gitspaceInstanceStore{
@ -37,35 +84,194 @@ type gitspaceInstanceStore struct {
db *sqlx.DB
}
func (g *gitspaceInstanceStore) Find(_ context.Context, _ int64) (*types.GitspaceInstance, error) {
// TODO implement me
panic("implement me")
func (g gitspaceInstanceStore) Find(ctx context.Context, id int64) (*types.GitspaceInstance, error) {
stmt := database.Builder.
Select(gitspaceInstanceSelectColumns).
From(gitspaceInstanceTable).
Where("gits_id = $1", id)
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
gitspace := new(gitspaceInstance)
db := dbtx.GetAccessor(ctx, g.db)
if err := db.GetContext(ctx, gitspace, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to find gitspace")
}
return g.mapToGitspaceInstance(ctx, gitspace)
}
func (g *gitspaceInstanceStore) FindLatestByGitspaceConfigID(
func (g gitspaceInstanceStore) Create(ctx context.Context, gitspaceInstance *types.GitspaceInstance) error {
stmt := database.Builder.
Insert(gitspaceInstanceTable).
Columns(gitspaceInstanceInsertColumns).
Values(
gitspaceInstance.GitSpaceConfigID,
gitspaceInstance.URL,
gitspaceInstance.State,
gitspaceInstance.UserID,
gitspaceInstance.ResourceUsage,
gitspaceInstance.SpaceID,
gitspaceInstance.Created,
gitspaceInstance.Updated,
gitspaceInstance.LastUsed,
gitspaceInstance.TotalTimeUsed,
gitspaceInstance.TrackedChanges,
gitspaceInstance.AccessKey,
gitspaceInstance.AccessType,
gitspaceInstance.MachineUser,
gitspaceInstance.Identifier,
).
Suffix(ReturningClause + "gits_id")
sql, args, err := stmt.ToSql()
if err != nil {
return errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, g.db)
if err = db.QueryRowContext(ctx, sql, args...).Scan(&gitspaceInstance.ID); err != nil {
return database.ProcessSQLErrorf(ctx, err, "gitspace query failed")
}
return nil
}
func (g gitspaceInstanceStore) Update(
ctx context.Context,
gitspaceInstance *types.GitspaceInstance,
) error {
stmt := database.Builder.
Update(gitspaceInstanceTable).
Set("gits_state", gitspaceInstance.State).
Set("gits_last_used", gitspaceInstance.LastUsed).
Set("gits_url", gitspaceInstance.URL).
Set("gits_updated", gitspaceInstance.Updated).
Where("gits_id = $5", gitspaceInstance.ID)
sql, args, err := stmt.ToSql()
if err != nil {
return errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, g.db)
if _, err := db.ExecContext(ctx, sql, args...); err != nil {
return database.ProcessSQLErrorf(ctx, err, "Failed to update gitspace")
}
return nil
}
func (g gitspaceInstanceStore) FindLatestByGitspaceConfigID(
ctx context.Context,
gitspaceConfigID int64,
spaceID int64,
) (*types.GitspaceInstance, error) {
stmt := database.Builder.
Select(gitspaceInstanceSelectColumns).
From(gitspaceInstanceTable).
Where("gits_gitspace_config_id = $1", gitspaceConfigID).
Where("gits_space_id = $2", spaceID).
OrderBy("gits_created DESC")
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
gitspace := new(gitspaceInstance)
db := dbtx.GetAccessor(ctx, g.db)
if err := db.GetContext(ctx, gitspace, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to find gitspace")
}
return g.mapToGitspaceInstance(ctx, gitspace)
}
func (g gitspaceInstanceStore) List(
ctx context.Context,
filter *types.GitspaceFilter,
) ([]*types.GitspaceInstance, error) {
stmt := database.Builder.
Select(gitspaceInstanceSelectColumns).
From(gitspaceInstanceTable).
Where(squirrel.Eq{"gits_space_id": filter.SpaceIDs}).
Where(squirrel.Eq{"gits_user_uid": filter.UserID}).
OrderBy("gits_created ASC")
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, g.db)
var dst []*gitspaceInstance
if err := db.SelectContext(ctx, &dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing custom list query")
}
return g.mapToGitspaceInstances(ctx, dst)
}
func (g gitspaceInstanceStore) FindAllLatestByGitspaceConfigID(
ctx context.Context,
gitspaceConfigIDs []int64,
) ([]*types.GitspaceInstance, error) {
var whereClause = "(1=0)"
if len(gitspaceConfigIDs) > 0 {
whereClause = fmt.Sprintf("gits_gitspace_config_id IN (%s)",
strings.Trim(strings.Join(strings.Split(fmt.Sprint(gitspaceConfigIDs), " "), ","), "[]"))
}
baseSelect := squirrel.Select("*",
"ROW_NUMBER() OVER (PARTITION BY gits_gitspace_config_id "+
"ORDER BY gits_created DESC) AS rn").
From(gitspaceInstanceTable).
Where(whereClause)
// Use the base select query in a common table expression (CTE)
stmt := squirrel.Select(gitspaceConfigSelectColumns).
FromSelect(baseSelect, "RankedRows").
Where("rn = 1")
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, g.db)
var dst []*gitspaceInstance
if err := db.SelectContext(ctx, &dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing custom list query")
}
return g.mapToGitspaceInstances(ctx, dst)
}
func (g gitspaceInstanceStore) mapToGitspaceInstance(
_ context.Context,
_ int64,
_ int64) (*types.GitspaceInstance, error) {
// TODO implement me
panic("implement me")
in *gitspaceInstance,
) (*types.GitspaceInstance, error) {
var res = &types.GitspaceInstance{
ID: in.ID,
Identifier: in.Identifier,
GitSpaceConfigID: in.GitSpaceConfigID,
URL: in.URL.Ptr(),
State: in.State,
UserID: in.UserUID,
ResourceUsage: in.ResourceUsage.Ptr(),
LastUsed: in.LastUsed,
TotalTimeUsed: in.TotalTimeUsed,
TrackedChanges: in.TrackedChanges.Ptr(),
AccessKey: in.AccessKey.Ptr(),
AccessType: in.AccessType,
MachineUser: in.MachineUser.Ptr(),
SpaceID: in.SpaceID,
Created: in.Created,
Updated: in.Updated,
}
return res, nil
}
func (g *gitspaceInstanceStore) Create(_ context.Context, _ *types.GitspaceInstance) error {
// TODO implement me
panic("implement me")
}
func (g *gitspaceInstanceStore) Update(_ context.Context, _ *types.GitspaceInstance) (*types.GitspaceInstance, error) {
// TODO implement me
panic("implement me")
}
func (g *gitspaceInstanceStore) List(_ context.Context, _ *types.GitspaceFilter) ([]*types.GitspaceInstance, error) {
// TODO implement me
panic("implement me")
}
func (g *gitspaceInstanceStore) Delete(_ context.Context, _ int64) error {
// TODO implement me
panic("implement me")
func (g gitspaceInstanceStore) mapToGitspaceInstances(
ctx context.Context,
instances []*gitspaceInstance,
) ([]*types.GitspaceInstance, error) {
var err error
res := make([]*types.GitspaceInstance, len(instances))
for i := range instances {
res[i], err = g.mapToGitspaceInstance(ctx, instances[i])
if err != nil {
return nil, err
}
}
return res, nil
}

View File

@ -18,14 +18,41 @@ import (
"context"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/infraprovider/enum"
"github.com/harness/gitness/store/database"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
)
const (
infraProviderConfigIDColumn = `ipconf_id`
infraProviderConfigInsertColumns = `
ipconf_uid,
ipconf_display_name,
ipconf_type,
ipconf_space_id,
ipconf_created,
ipconf_updated
`
infraProviderConfigSelectColumns = "ipconf_id," + infraProviderConfigInsertColumns
infraProviderConfigTable = `infra_provider_configs`
)
type infraProviderConfig struct {
ID int64 `db:"ipconf_id"`
Identifier string `db:"ipconf_uid"`
Name string `db:"ipconf_display_name"`
Type enum.InfraProviderType `db:"ipconf_type"`
SpaceID int64 `db:"ipconf_space_id"`
Created int64 `db:"ipconf_created"`
Updated int64 `db:"ipconf_updated"`
}
var _ store.InfraProviderConfigStore = (*infraProviderConfigStore)(nil)
// TODO Stubbed Impl
// NewGitspaceConfigStore returns a new GitspaceConfigStore.
func NewInfraProviderConfigStore(db *sqlx.DB) store.InfraProviderConfigStore {
return &infraProviderConfigStore{
@ -37,23 +64,80 @@ type infraProviderConfigStore struct {
db *sqlx.DB
}
func (i infraProviderConfigStore) Find(_ context.Context, _ int64) (*types.InfraProviderConfig, error) {
// TODO implement me
panic("implement me")
func (i infraProviderConfigStore) Find(ctx context.Context, id int64) (*types.InfraProviderConfig, error) {
stmt := database.Builder.
Select(infraProviderConfigSelectColumns).
From(infraProviderConfigTable).
Where(infraProviderConfigIDColumn+" = $1", id)
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
dst := new(infraProviderConfig)
db := dbtx.GetAccessor(ctx, i.db)
if err := db.GetContext(ctx, dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to find infraProviderConfig")
}
return i.mapToInfraProviderConfig(ctx, dst)
}
func (i infraProviderConfigStore) FindByIdentifier(_ context.Context, _ int64,
_ string) (*types.InfraProviderConfig, error) {
// TODO implement me
panic("implement me")
func (i infraProviderConfigStore) FindByIdentifier(
ctx context.Context,
spaceID int64,
identifier string,
) (*types.InfraProviderConfig, error) {
stmt := database.Builder.
Select(infraProviderConfigSelectColumns).
From(infraProviderConfigTable).
Where("ipconf_uid = $1", identifier).
Where("ipconf_space_id = $2", spaceID)
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
dst := new(infraProviderConfig)
db := dbtx.GetAccessor(ctx, i.db)
if err := db.GetContext(ctx, dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to find infraProviderConfig")
}
return i.mapToInfraProviderConfig(ctx, dst)
}
func (i infraProviderConfigStore) Create(_ context.Context, _ *types.InfraProviderConfig) error {
// TODO implement me
panic("implement me")
func (i infraProviderConfigStore) Create(ctx context.Context, infraProviderConfig *types.InfraProviderConfig) error {
stmt := database.Builder.
Insert(infraProviderConfigTable).
Columns(infraProviderConfigInsertColumns).
Values(
infraProviderConfig.Identifier,
infraProviderConfig.Name,
infraProviderConfig.Type,
infraProviderConfig.SpaceID,
infraProviderConfig.Created,
infraProviderConfig.Updated,
).
Suffix(ReturningClause + infraProviderConfigIDColumn)
sql, args, err := stmt.ToSql()
if err != nil {
return errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, i.db)
if err = db.QueryRowContext(ctx, sql, args...).Scan(&infraProviderConfig.ID); err != nil {
return database.ProcessSQLErrorf(ctx, err, "infra config query failed")
}
return nil
}
func (i infraProviderConfigStore) DeleteByIdentifier(_ context.Context, _ int64, _ string) error {
// TODO implement me
panic("implement me")
func (i infraProviderConfigStore) mapToInfraProviderConfig(
_ context.Context,
in *infraProviderConfig) (*types.InfraProviderConfig, error) {
infraProviderConfigEntity := &types.InfraProviderConfig{
ID: in.ID,
Identifier: in.Identifier,
Name: in.Name,
Type: in.Type,
SpaceID: in.SpaceID,
Created: in.Created,
Updated: in.Updated,
}
return infraProviderConfigEntity, nil
}

View File

@ -16,16 +16,65 @@ package database
import (
"context"
"encoding/json"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/infraprovider/enum"
"github.com/harness/gitness/store/database"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/guregu/null"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
)
const (
infraProviderResourceIDColumn = `ipreso_id`
infraProviderResourceInsertColumns = `
ipreso_uid,
ipreso_display_name,
ipreso_infra_provider_config_id,
ipreso_type,
ipreso_space_id,
ipreso_created,
ipreso_updated,
ipreso_cpu,
ipreso_memory,
ipreso_disk,
ipreso_network,
ipreso_region,
ipreso_opentofu_params,
ipreso_gateway_host,
ipreso_gateway_port,
ipreso_infra_provider_template_id
`
infraProviderResourceSelectColumns = "ipreso_id," + infraProviderResourceInsertColumns
infraProviderResourceTable = `infra_provider_resources`
)
type infraProviderResource struct {
ID int64 `db:"ipreso_id"`
Identifier string `db:"ipreso_uid"`
Name string `db:"ipreso_display_name"`
InfraProviderConfigID int64 `db:"ipreso_infra_provider_config_id"`
InfraProviderType enum.InfraProviderType `db:"ipreso_type"`
SpaceID int64 `db:"ipreso_space_id"`
CPU null.String `db:"ipreso_cpu"`
Memory null.String `db:"ipreso_memory"`
Disk null.String `db:"ipreso_disk"`
Network null.String `db:"ipreso_network"`
Region string `db:"ipreso_region"` // need list maybe
OpenTofuParams []byte `db:"ipreso_opentofu_params"`
GatewayHost null.String `db:"ipreso_gateway_host"`
GatewayPort null.String `db:"ipreso_gateway_port"`
TemplateID null.Int `db:"ipreso_infra_provider_template_id"`
Created int64 `db:"ipreso_created"`
Updated int64 `db:"ipreso_updated"`
}
var _ store.InfraProviderResourceStore = (*infraProviderResourceStore)(nil)
// TODO Stubbed Impl
// NewGitspaceConfigStore returns a new GitspaceConfigStore.
func NewInfraProviderResourceStore(db *sqlx.DB) store.InfraProviderResourceStore {
return &infraProviderResourceStore{
@ -37,35 +86,161 @@ type infraProviderResourceStore struct {
db *sqlx.DB
}
func (i infraProviderResourceStore) Find(_ context.Context, _ int64) (*types.InfraProviderResource, error) {
// TODO implement me
panic("implement me")
}
func (i infraProviderResourceStore) FindByIdentifier(_ context.Context, _ int64,
_ string) (*types.InfraProviderResource, error) {
// TODO implement me
panic("implement me")
}
func (i infraProviderResourceStore) Create(_ context.Context, _ int64, _ *types.InfraProviderResource) error {
// TODO implement me
panic("implement me")
}
func (i infraProviderResourceStore) List(_ context.Context, _ int64,
func (s infraProviderResourceStore) List(ctx context.Context, infraProviderConfigID int64,
_ types.ListQueryFilter) ([]*types.InfraProviderResource, error) {
// TODO implement me
panic("implement me")
stmt := database.Builder.
Select(infraProviderResourceSelectColumns).
From(infraProviderResourceTable).
Where("ipreso_infra_provider_config_id = $1", infraProviderConfigID)
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, s.db)
dst := new([]infraProviderResource)
if err := db.SelectContext(ctx, dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing custom list query")
}
return s.mapToInfraProviderResources(ctx, *dst)
}
func (i infraProviderResourceStore) ListAll(_ context.Context, _ int64,
_ types.ListQueryFilter) ([]*types.InfraProviderResource, error) {
// TODO implement me
panic("implement me")
func (s infraProviderResourceStore) mapToInfraProviderResource(_ context.Context,
in *infraProviderResource) (*types.InfraProviderResource, error) {
openTofuParamsMap := make(map[string]string)
marshalErr := json.Unmarshal(in.OpenTofuParams, &openTofuParamsMap)
if marshalErr != nil {
return nil, marshalErr
}
return &types.InfraProviderResource{
Identifier: in.Identifier,
InfraProviderConfigID: in.InfraProviderConfigID,
ID: in.ID,
InfraProviderType: in.InfraProviderType,
Name: in.Name,
SpaceID: in.SpaceID,
CPU: in.CPU.Ptr(),
Memory: in.Memory.Ptr(),
Disk: in.Disk.Ptr(),
Network: in.Network.Ptr(),
Region: in.Region,
Metadata: openTofuParamsMap,
GatewayHost: in.GatewayHost.Ptr(),
GatewayPort: in.GatewayPort.Ptr(),
TemplateID: in.TemplateID.Ptr(),
Created: in.Created,
Updated: in.Updated,
}, nil
}
func (i infraProviderResourceStore) DeleteByIdentifier(_ context.Context, _ int64, _ string) error {
// TODO implement me
panic("implement me")
func (s infraProviderResourceStore) Find(ctx context.Context, id int64) (*types.InfraProviderResource, error) {
stmt := database.Builder.
Select(infraProviderResourceSelectColumns).
From(infraProviderResourceTable).
Where(infraProviderResourceIDColumn+" = $1", id)
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
dst := new(infraProviderResource)
db := dbtx.GetAccessor(ctx, s.db)
if err := db.GetContext(ctx, dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to find infraProviderResource")
}
return s.mapToInfraProviderResource(ctx, dst)
}
func (s infraProviderResourceStore) FindByIdentifier(
ctx context.Context,
spaceID int64,
identifier string,
) (*types.InfraProviderResource, error) {
stmt := database.Builder.
Select(infraProviderResourceSelectColumns).
From(infraProviderResourceTable).
Where("ipreso_uid = $1", identifier).
Where("ipreso_space_id = $2", spaceID)
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
dst := new(infraProviderResource)
db := dbtx.GetAccessor(ctx, s.db)
if err := db.GetContext(ctx, dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to find infraProviderResource")
}
return s.mapToInfraProviderResource(ctx, dst)
}
func (s infraProviderResourceStore) Create(
ctx context.Context,
infraProviderConfigID int64,
infraProviderResource *types.InfraProviderResource,
) error {
// TODO move this to proper place, maybe create mapper
jsonBytes, marshalErr := json.Marshal(infraProviderResource.Metadata)
if marshalErr != nil {
return marshalErr
}
stmt := database.Builder.
Insert(infraProviderResourceTable).
Columns(infraProviderResourceInsertColumns).
Values(
infraProviderResource.Identifier,
infraProviderResource.Name,
infraProviderConfigID,
infraProviderResource.InfraProviderType,
infraProviderResource.SpaceID,
infraProviderResource.Created,
infraProviderResource.Updated,
infraProviderResource.CPU,
infraProviderResource.Memory,
infraProviderResource.Disk,
infraProviderResource.Network,
infraProviderResource.Region,
jsonBytes,
infraProviderResource.GatewayHost,
infraProviderResource.GatewayPort,
infraProviderResource.TemplateID,
).
Suffix(ReturningClause + infraProviderResourceIDColumn)
sql, args, err := stmt.ToSql()
if err != nil {
return errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, s.db)
if err = db.QueryRowContext(ctx, sql, args...).Scan(&infraProviderResource.ID); err != nil {
return database.ProcessSQLErrorf(ctx, err, "infra provider resource query failed")
}
return nil
}
func (s infraProviderResourceStore) DeleteByIdentifier(ctx context.Context, spaceID int64, identifier string) error {
stmt := database.Builder.
Delete(infraProviderResourceTable).
Where("ipreso_uid = $1", identifier).
Where("ipreso_space_id = $2", spaceID)
sql, args, err := stmt.ToSql()
if err != nil {
return errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, s.db)
if _, err := db.ExecContext(ctx, sql, args...); err != nil {
return database.ProcessSQLErrorf(ctx, err, "Failed to delete infra provider resource")
}
return nil
}
func (s infraProviderResourceStore) mapToInfraProviderResources(ctx context.Context,
resources []infraProviderResource) ([]*types.InfraProviderResource, error) {
var err error
res := make([]*types.InfraProviderResource, len(resources))
for i := range resources {
res[i], err = s.mapToInfraProviderResource(ctx, &resources[i])
if err != nil {
return nil, err
}
}
return res, nil
}

View File

@ -14,7 +14,8 @@ import (
"github.com/harness/gitness/app/api/controller/connector"
"github.com/harness/gitness/app/api/controller/execution"
githookCtrl "github.com/harness/gitness/app/api/controller/githook"
gitspacecontroller "github.com/harness/gitness/app/api/controller/gitspace"
gitspaceCtrl "github.com/harness/gitness/app/api/controller/gitspace"
infraproviderCtrl "github.com/harness/gitness/app/api/controller/infraprovider"
controllerkeywordsearch "github.com/harness/gitness/app/api/controller/keywordsearch"
"github.com/harness/gitness/app/api/controller/limiter"
controllerlogs "github.com/harness/gitness/app/api/controller/logs"
@ -40,8 +41,13 @@ import (
"github.com/harness/gitness/app/auth/authz"
"github.com/harness/gitness/app/bootstrap"
gitevents "github.com/harness/gitness/app/events/git"
gitspaceevents "github.com/harness/gitness/app/events/gitspace"
pullreqevents "github.com/harness/gitness/app/events/pullreq"
repoevents "github.com/harness/gitness/app/events/repo"
infrastructure "github.com/harness/gitness/app/gitspace/infrastructure"
"github.com/harness/gitness/app/gitspace/orchestrator"
containerorchestrator "github.com/harness/gitness/app/gitspace/orchestrator/container"
"github.com/harness/gitness/app/gitspace/scm"
"github.com/harness/gitness/app/pipeline/canceler"
"github.com/harness/gitness/app/pipeline/commit"
"github.com/harness/gitness/app/pipeline/converter"
@ -87,6 +93,7 @@ import (
"github.com/harness/gitness/git"
"github.com/harness/gitness/git/api"
"github.com/harness/gitness/git/storage"
infraproviderpkg "github.com/harness/gitness/infraprovider"
"github.com/harness/gitness/job"
"github.com/harness/gitness/livelog"
"github.com/harness/gitness/lock"
@ -132,6 +139,7 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
system.WireSet,
authn.WireSet,
authz.WireSet,
gitspaceevents.WireSet,
gitevents.WireSet,
pullreqevents.WireSet,
repoevents.WireSet,
@ -200,7 +208,16 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
ssh.WireSet,
publickey.WireSet,
migrate.WireSet,
gitspacecontroller.WireSet,
gitspaceCtrl.WireSet,
infraproviderCtrl.WireSet,
infraproviderpkg.WireSet,
scm.WireSet,
orchestrator.WireSet,
containerorchestrator.WireSet,
infrastructure.WireSet,
cliserver.ProvideIDEVSCodeWebConfig,
cliserver.ProvideDockerConfig,
cliserver.ProvideGitspaceContainerOrchestratorConfig,
)
return &cliserver.System{}, nil
}

View File

@ -14,6 +14,7 @@ import (
"github.com/harness/gitness/app/api/controller/execution"
"github.com/harness/gitness/app/api/controller/githook"
"github.com/harness/gitness/app/api/controller/gitspace"
infraprovider2 "github.com/harness/gitness/app/api/controller/infraprovider"
keywordsearch2 "github.com/harness/gitness/app/api/controller/keywordsearch"
"github.com/harness/gitness/app/api/controller/limiter"
logs2 "github.com/harness/gitness/app/api/controller/logs"
@ -39,8 +40,13 @@ import (
"github.com/harness/gitness/app/auth/authz"
"github.com/harness/gitness/app/bootstrap"
events4 "github.com/harness/gitness/app/events/git"
events5 "github.com/harness/gitness/app/events/gitspace"
events3 "github.com/harness/gitness/app/events/pullreq"
events2 "github.com/harness/gitness/app/events/repo"
"github.com/harness/gitness/app/gitspace/infrastructure"
"github.com/harness/gitness/app/gitspace/orchestrator"
"github.com/harness/gitness/app/gitspace/orchestrator/container"
"github.com/harness/gitness/app/gitspace/scm"
"github.com/harness/gitness/app/pipeline/canceler"
"github.com/harness/gitness/app/pipeline/commit"
"github.com/harness/gitness/app/pipeline/converter"
@ -86,6 +92,7 @@ import (
"github.com/harness/gitness/git"
"github.com/harness/gitness/git/api"
"github.com/harness/gitness/git/storage"
"github.com/harness/gitness/infraprovider"
"github.com/harness/gitness/job"
"github.com/harness/gitness/livelog"
"github.com/harness/gitness/lock"
@ -234,7 +241,8 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
return nil, err
}
gitspaceConfigStore := database.ProvideGitspaceConfigStore(db)
spaceController := space.ProvideController(config, transactor, provider, streamer, spaceIdentifier, authorizer, spacePathStore, pipelineStore, secretStore, connectorStore, templateStore, spaceStore, repoStore, principalStore, repoController, membershipStore, repository, exporterRepository, resourceLimiter, publicaccessService, auditService, gitspaceConfigStore)
gitspaceInstanceStore := database.ProvideGitspaceInstanceStore(db)
spaceController := space.ProvideController(config, transactor, provider, streamer, spaceIdentifier, authorizer, spacePathStore, pipelineStore, secretStore, connectorStore, templateStore, spaceStore, repoStore, principalStore, repoController, membershipStore, repository, exporterRepository, resourceLimiter, publicaccessService, auditService, gitspaceConfigStore, gitspaceInstanceStore)
pipelineController := pipeline.ProvideController(repoStore, triggerStore, authorizer, pipelineStore)
secretController := secret.ProvideController(encrypter, secretStore, authorizer, spaceStore)
triggerController := trigger.ProvideController(authorizer, triggerStore, pipelineStore, repoStore)
@ -310,11 +318,31 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
searcher := keywordsearch.ProvideSearcher(localIndexSearcher)
keywordsearchController := keywordsearch2.ProvideController(authorizer, searcher, repoController, spaceController)
infraProviderResourceStore := database.ProvideInfraProviderResourceStore(db)
gitspaceInstanceStore := database.ProvideGitspaceInstanceStore(db)
infraProviderConfigStore := database.ProvideInfraProviderConfigStore(db)
dockerConfig := server.ProvideDockerConfig(config)
dockerClientFactory := infraprovider.ProvideDockerClientFactory(dockerConfig)
dockerProvider := infraprovider.ProvideDockerProvider(dockerClientFactory)
factory := infraprovider.ProvideFactory(dockerProvider)
infraproviderController := infraprovider2.ProvideController(authorizer, infraProviderResourceStore, infraProviderConfigStore, spaceStore, factory)
reporter3, err := events5.ProvideReporter(eventsSystem)
if err != nil {
return nil, err
}
scmSCM := scm.ProvideSCM()
infraProvisioner := infrastructure.ProvideInfraProvisionerService(infraProviderConfigStore, infraProviderResourceStore, factory)
vsCode := container.ProvideVSCodeService()
vsCodeWebConfig := server.ProvideIDEVSCodeWebConfig(config)
vsCodeWeb := container.ProvideVSCodeWebService(vsCodeWebConfig)
containerConfig, err := server.ProvideGitspaceContainerOrchestratorConfig(config)
if err != nil {
return nil, err
}
containerOrchestrator := container.ProvideEmbeddedDockerOrchestrator(dockerClientFactory, vsCode, vsCodeWeb, containerConfig)
orchestratorOrchestrator := orchestrator.ProvideOrchestrator(scmSCM, infraProviderResourceStore, infraProvisioner, containerOrchestrator)
gitspaceEventStore := database.ProvideGitspaceEventStore(db)
gitspaceController := gitspace.ProvideController(authorizer, infraProviderResourceStore, gitspaceConfigStore, gitspaceInstanceStore, spaceStore, gitspaceEventStore)
gitspaceController := gitspace.ProvideController(authorizer, infraProviderResourceStore, gitspaceConfigStore, gitspaceInstanceStore, spaceStore, reporter3, orchestratorOrchestrator, gitspaceEventStore)
migrateController := migrate.ProvideController(authorizer, principalStore)
apiHandler := router.ProvideAPIHandler(ctx, config, authenticator, repoController, reposettingsController, executionController, logsController, spaceController, pipelineController, secretController, triggerController, connectorController, templateController, pluginController, pullreqController, webhookController, githookController, gitInterface, serviceaccountController, controller, principalController, checkController, systemController, uploadController, keywordsearchController, gitspaceController, migrateController)
apiHandler := router.ProvideAPIHandler(ctx, config, authenticator, repoController, reposettingsController, executionController, logsController, spaceController, pipelineController, secretController, triggerController, connectorController, templateController, pluginController, pullreqController, webhookController, githookController, gitInterface, serviceaccountController, controller, principalController, checkController, systemController, uploadController, keywordsearchController, infraproviderController, gitspaceController, migrateController)
gitHandler := router.ProvideGitHandler(provider, authenticator, repoController)
openapiService := openapi.ProvideOpenAPIService()
webHandler := router.ProvideWebHandler(config, openapiService)

View File

@ -14,6 +14,8 @@
package enum
import "fmt"
type GitspaceStateType string
func (GitspaceStateType) Enum() []interface{} {
@ -30,3 +32,16 @@ const (
GitspaceStateError GitspaceStateType = "error"
GitspaceStateUninitialized GitspaceStateType = "uninitialized"
)
func GetGitspaceStateFromInstance(
instanceState GitspaceInstanceStateType) (GitspaceStateType, error) {
switch instanceState { //nolint:exhaustive
case GitspaceInstanceStateRunning:
return GitspaceStateRunning, nil
case GitspaceInstanceStateUninitialized,
GitspaceInstanceStateDeleted:
return GitspaceStateStopped, nil
default:
return GitspaceStateError, fmt.Errorf("unsupported gitspace instance state %s", string(instanceState))
}
}

View File

@ -39,6 +39,7 @@ var membershipRoleReaderPermissions = slices.Clip(slices.Insert([]Permission{},
PermissionConnectorView,
PermissionTemplateView,
PermissionGitspaceView,
PermissionInfraProviderView,
))
var membershipRoleExecutorPermissions = slices.Clip(slices.Insert(membershipRoleReaderPermissions, 0,
@ -48,6 +49,7 @@ var membershipRoleExecutorPermissions = slices.Clip(slices.Insert(membershipRole
PermissionConnectorAccess,
PermissionTemplateAccess,
PermissionGitspaceAccess,
PermissionInfraProviderAccess,
))
var membershipRoleContributorPermissions = slices.Clip(slices.Insert(membershipRoleReaderPermissions, 0,
@ -87,6 +89,10 @@ var membershipRoleSpaceOwnerPermissions = slices.Clip(slices.Insert(membershipRo
PermissionGitspaceEdit,
PermissionGitspaceDelete,
PermissionGitspaceAccess,
PermissionInfraProviderEdit,
PermissionInfraProviderDelete,
PermissionInfraProviderAccess,
))
func init() {

View File

@ -28,6 +28,7 @@ const (
ResourceTypeConnector ResourceType = "CONNECTOR"
ResourceTypeTemplate ResourceType = "TEMPLATE"
ResourceTypeGitspace ResourceType = "GITSPACE"
ResourceTypeInfraProvider ResourceType = "INFRAPROVIDER"
)
// Permission represents the different types of permissions a principal can have.
@ -132,3 +133,13 @@ const (
PermissionGitspaceDelete Permission = "gitspace_delete"
PermissionGitspaceAccess Permission = "gitspace_access"
)
const (
/*
----- INFRAPROVIDER -----
*/
PermissionInfraProviderView Permission = "infraprovider_view"
PermissionInfraProviderEdit Permission = "infraprovider_edit"
PermissionInfraProviderDelete Permission = "infraprovider_delete"
PermissionInfraProviderAccess Permission = "infraprovider_access"
)

View File

@ -16,8 +16,6 @@ package types
import (
"github.com/harness/gitness/types/enum"
"github.com/guregu/null"
)
type GitspaceConfig struct {
@ -31,14 +29,14 @@ type GitspaceConfig struct {
CodeRepoURL string `json:"code_repo_url"`
CodeRepoType enum.GitspaceCodeRepoType `json:"code_repo_type"`
Branch string `json:"branch"`
DevcontainerPath string `json:"devcontainer_path,omitempty"`
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,omitempty"`
GitspaceInstance *GitspaceInstance `json:"instance"`
SpacePath string `json:"space_path"`
Created int64 `json:"created"`
Updated int64 `json:"updated"`
@ -48,16 +46,16 @@ type GitspaceInstance struct {
ID int64 `json:"-"`
GitSpaceConfigID int64 `json:"-"`
Identifier string `json:"identifier"`
URL null.String `json:"url,omitempty"`
URL *string `json:"url,omitempty"`
State enum.GitspaceInstanceStateType `json:"state"`
UserID string `json:"-"`
ResourceUsage null.String `json:"resource_usage"`
ResourceUsage *string `json:"resource_usage"`
LastUsed int64 `json:"last_used,omitempty"`
TotalTimeUsed int64 `json:"total_time_used"`
TrackedChanges string `json:"tracked_changes"`
AccessKey null.String `json:"access_key,omitempty"`
TrackedChanges *string `json:"tracked_changes"`
AccessKey *string `json:"access_key,omitempty"`
AccessType enum.GitspaceAccessType `json:"access_type"`
MachineUser null.String `json:"machine_user,omitempty"`
MachineUser *string `json:"machine_user,omitempty"`
SpacePath string `json:"space_path"`
SpaceID int64 `json:"-"`
Created int64 `json:"created"`

View File

@ -16,8 +16,6 @@ package types
import (
"github.com/harness/gitness/infraprovider/enum"
"github.com/guregu/null"
)
type InfraProviderConfig struct {
@ -39,16 +37,16 @@ type InfraProviderResource struct {
Name string `json:"name"`
InfraProviderConfigID int64 `json:"-"`
InfraProviderConfigIdentifier string `json:"config_identifier"`
CPU null.String `json:"cpu"`
Memory null.String `json:"memory"`
Disk null.String `json:"disk"`
Network null.String `json:"network"`
CPU *string `json:"cpu"`
Memory *string `json:"memory"`
Disk *string `json:"disk"`
Network *string `json:"network"`
Region string `json:"region"`
Metadata map[string]string `json:"metadata"`
GatewayHost null.String `json:"gateway_host"`
GatewayPort null.String `json:"gateway_port"`
TemplateID null.Int `json:"-"`
TemplateIdentifier null.String `json:"template_identifier"`
GatewayHost *string `json:"gateway_host"`
GatewayPort *string `json:"gateway_port"`
TemplateID *int64 `json:"-"`
TemplateIdentifier *string `json:"template_identifier"`
SpaceID int64 `json:"-"`
SpacePath string `json:"space_path"`
InfraProviderType enum.InfraProviderType `json:"infra_provider_type"`