feat: [CDE-137]: add a service layer for infraproviders, autoadd infraprovider (#2204)

* feat: [CDE-137]: add missing type.
* feat: [CDE-137]: add missing type.
* feat: [CDE-137]: add missing type.
* feat: [CDE-137]: add missing type.
* feat: [CDE-137]: add a service layer for infraproviders, autoadd infraprovider
unified-ui
Ansuman Satapathy 2024-07-12 08:45:10 +00:00 committed by Harness
parent 75f4e9e932
commit 050415afdf
17 changed files with 342 additions and 176 deletions

View File

@ -68,18 +68,12 @@ func (c *Controller) Action(
switch in.Action {
case enum.GitspaceActionTypeStart:
c.emitGitspaceConfigEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStart)
gitspace, err := c.startGitspaceAction(ctx, gitspaceConfig)
if err != nil {
c.emitGitspaceConfigEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStartFailed)
}
return gitspace, err
err = c.startGitspaceAction(ctx, gitspaceConfig)
return gitspaceConfig, err
case enum.GitspaceActionTypeStop:
c.emitGitspaceConfigEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStop)
gitspace, err := c.stopGitspaceAction(ctx, gitspaceConfig)
if err != nil {
c.emitGitspaceConfigEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStopFailed)
}
return gitspace, err
err = c.stopGitspaceAction(ctx, gitspaceConfig)
return gitspaceConfig, err
default:
return nil, fmt.Errorf("unknown action %s on gitspace : %s", string(in.Action), gitspaceConfig.Identifier)
}
@ -88,41 +82,42 @@ func (c *Controller) Action(
func (c *Controller) startGitspaceAction(
ctx context.Context,
config *types.GitspaceConfig,
) (*types.GitspaceConfig, error) {
) 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 instance for config ID : %s %w", config.Identifier, err)
if err != nil && err.Error() != resourceNotFoundErr {
return fmt.Errorf("failed to find gitspace instance for config ID : %s %w", config.Identifier, err)
}
config.GitspaceInstance = savedGitspaceInstance
_, err = c.gitspaceBusyOperation(ctx, config)
err = c.gitspaceBusyOperation(ctx, config)
if err != nil {
return nil, err
return err
}
if savedGitspaceInstance == nil || savedGitspaceInstance.State.IsFinalStatus() {
gitspaceInstance, err := c.createGitspaceInstance(config)
if err != nil {
return nil, err
return err
}
if err = c.gitspaceInstanceStore.Create(ctx, gitspaceInstance); err != nil {
return nil, fmt.Errorf("failed to create gitspace instance for %s %w", config.Identifier, err)
return 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)
return fmt.Errorf("failed to find gitspace with config ID : %s %w", config.Identifier, err)
}
config.GitspaceInstance = newGitspaceInstance
config.State, _ = enum.GetGitspaceStateFromInstance(newGitspaceInstance.State)
ctx2 := context.WithoutCancel(ctx)
contextWithoutCancel := context.WithoutCancel(ctx)
go func() {
err := c.startAsyncOperation(ctx2, config)
err := c.startAsyncOperation(contextWithoutCancel, config)
if err != nil {
c.emitGitspaceConfigEvent(contextWithoutCancel, config, enum.GitspaceEventTypeGitspaceActionStartFailed)
log.Err(err).Msg("start operation failed")
}
}()
return config, nil
return nil
}
func (c *Controller) startAsyncOperation(
@ -170,52 +165,53 @@ func (c *Controller) createGitspaceInstance(config *types.GitspaceConfig) (*type
func (c *Controller) gitspaceBusyOperation(
ctx context.Context,
config *types.GitspaceConfig,
) (*types.GitspaceConfig, error) {
) error {
if config.GitspaceInstance == nil {
return config, nil
return nil
}
if config.GitspaceInstance.State.IsBusyStatus() &&
time.Since(time.UnixMilli(config.GitspaceInstance.Updated)).Milliseconds() <= (gitspaceTimedOutInMintues*60*1000) {
return nil, fmt.Errorf("gitspace start/stop is already pending for : %q", config.Identifier)
return fmt.Errorf("gitspace start/stop is already pending for : %q", config.Identifier)
} else if config.GitspaceInstance.State.IsBusyStatus() {
config.GitspaceInstance.State = enum.GitspaceInstanceStateError
if err := c.gitspaceInstanceStore.Update(ctx, config.GitspaceInstance); err != nil {
return nil, fmt.Errorf("failed to update gitspace config for %s %w", config.Identifier, err)
return fmt.Errorf("failed to update gitspace config for %s %w", config.Identifier, err)
}
}
return config, nil
return nil
}
func (c *Controller) stopGitspaceAction(
ctx context.Context,
config *types.GitspaceConfig,
) (*types.GitspaceConfig, error) {
savedGitspace, err := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, config.ID, config.SpaceID)
) error {
savedGitspaceInstance, 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)
return 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)
if savedGitspaceInstance.State.IsFinalStatus() {
return fmt.Errorf(
"gitspace instance cannot be stopped with ID %s %w", savedGitspaceInstance.Identifier, err)
}
config.GitspaceInstance = savedGitspace
config, err = c.gitspaceBusyOperation(ctx, config)
config.GitspaceInstance = savedGitspaceInstance
err = c.gitspaceBusyOperation(ctx, config)
if err != nil {
return nil, err
return err
}
config.GitspaceInstance.State = enum.GitspaceInstanceStateStopping
if err = c.gitspaceInstanceStore.Update(ctx, config.GitspaceInstance); err != nil {
return nil, fmt.Errorf("failed to update gitspace config for stopping %s %w", config.Identifier, err)
return fmt.Errorf("failed to update gitspace config for stopping %s %w", config.Identifier, err)
}
config.State, _ = enum.GetGitspaceStateFromInstance(savedGitspace.State)
ctx2 := context.WithoutCancel(ctx)
config.State, _ = enum.GetGitspaceStateFromInstance(savedGitspaceInstance.State)
contextWithoutCancel := context.WithoutCancel(ctx)
go func() {
err := c.stopAsyncOperation(ctx2, config)
err := c.stopAsyncOperation(contextWithoutCancel, config)
if err != nil {
c.emitGitspaceConfigEvent(contextWithoutCancel, config, enum.GitspaceEventTypeGitspaceActionStopFailed)
log.Err(err).Msg("stop operation failed")
}
}()
return config, err
return err
}
func (c *Controller) stopAsyncOperation(

View File

@ -20,28 +20,29 @@ import (
"github.com/harness/gitness/app/gitspace/logutil"
"github.com/harness/gitness/app/gitspace/orchestrator"
"github.com/harness/gitness/app/gitspace/scm"
"github.com/harness/gitness/app/services/infraprovider"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/store/database/dbtx"
)
type Controller struct {
authorizer authz.Authorizer
infraProviderResourceStore store.InfraProviderResourceStore
gitspaceConfigStore store.GitspaceConfigStore
gitspaceInstanceStore store.GitspaceInstanceStore
spaceStore store.SpaceStore
eventReporter *gitspaceevents.Reporter
orchestrator orchestrator.Orchestrator
gitspaceEventStore store.GitspaceEventStore
tx dbtx.Transactor
statefulLogger *logutil.StatefulLogger
scm scm.SCM
authorizer authz.Authorizer
infraProviderSvc infraprovider.ProviderService
gitspaceConfigStore store.GitspaceConfigStore
gitspaceInstanceStore store.GitspaceInstanceStore
spaceStore store.SpaceStore
eventReporter *gitspaceevents.Reporter
orchestrator orchestrator.Orchestrator
gitspaceEventStore store.GitspaceEventStore
tx dbtx.Transactor
statefulLogger *logutil.StatefulLogger
scm scm.SCM
}
func NewController(
tx dbtx.Transactor,
authorizer authz.Authorizer,
infraProviderResourceStore store.InfraProviderResourceStore,
infraProviderSvc infraprovider.ProviderService,
gitspaceConfigStore store.GitspaceConfigStore,
gitspaceInstanceStore store.GitspaceInstanceStore,
spaceStore store.SpaceStore,
@ -52,16 +53,16 @@ func NewController(
scm scm.SCM,
) *Controller {
return &Controller{
tx: tx,
authorizer: authorizer,
infraProviderResourceStore: infraProviderResourceStore,
gitspaceConfigStore: gitspaceConfigStore,
gitspaceInstanceStore: gitspaceInstanceStore,
spaceStore: spaceStore,
eventReporter: eventReporter,
orchestrator: orchestrator,
gitspaceEventStore: gitspaceEventStore,
statefulLogger: statefulLogger,
scm: scm,
tx: tx,
authorizer: authorizer,
infraProviderSvc: infraProviderSvc,
gitspaceConfigStore: gitspaceConfigStore,
gitspaceInstanceStore: gitspaceInstanceStore,
spaceStore: spaceStore,
eventReporter: eventReporter,
orchestrator: orchestrator,
gitspaceEventStore: gitspaceEventStore,
statefulLogger: statefulLogger,
scm: scm,
}
}

View File

@ -24,6 +24,7 @@ import (
apiauth "github.com/harness/gitness/app/api/auth"
"github.com/harness/gitness/app/api/usererror"
"github.com/harness/gitness/app/auth"
infraproviderenum "github.com/harness/gitness/infraprovider/enum"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/check"
"github.com/harness/gitness/types/enum"
@ -32,6 +33,8 @@ import (
)
const allowedUIDAlphabet = "abcdefghijklmnopqrstuvwxyz0123456789"
const defaultResourceIdentifier = "default"
const infraProviderResourceMissingErr = "Failed to find infraProviderResource: resource not found"
var (
// errSecretRequiresParent if the user tries to create a secret without a parent space.
@ -81,13 +84,19 @@ func (c *Controller) Create(
}
now := time.Now().UnixMilli()
var gitspaceConfig *types.GitspaceConfig
resourceIdentifier := in.ResourceIdentifier
err = c.createOrFindInfraProviderResource(ctx, parentSpace, resourceIdentifier, now)
if err != nil {
return nil, err
}
// TODO figure out how to flush the DB txn above before we proceed.
err = c.tx.WithTx(ctx, func(ctx context.Context) error {
infraProviderResource, err := c.infraProviderResourceStore.FindByIdentifier(
infraProviderResource, err := c.infraProviderSvc.FindResourceByIdentifier(
ctx,
parentSpace.ID,
in.ResourceIdentifier)
resourceIdentifier)
if err != nil {
return fmt.Errorf("could not find infra provider resource : %q %w", in.ResourceIdentifier, err)
return fmt.Errorf("could not find infra provider resource : %q %w", resourceIdentifier, err)
}
gitspaceConfig = &types.GitspaceConfig{
Identifier: identifier,
@ -95,7 +104,7 @@ func (c *Controller) Create(
IDE: in.IDE,
InfraProviderResourceID: infraProviderResource.ID,
InfraProviderResourceIdentifier: infraProviderResource.Identifier,
CodeRepoType: enum.CodeRepoTypeUnknown, // TODO fix this
CodeRepoType: enum.CodeRepoTypeUnknown,
State: enum.GitspaceStateUninitialized,
CodeRepoURL: in.CodeRepoURL,
Branch: in.Branch,
@ -118,13 +127,77 @@ func (c *Controller) Create(
return gitspaceConfig, nil
}
func (c *Controller) createOrFindInfraProviderResource(
ctx context.Context,
parentSpace *types.Space,
resourceIdentifier string,
now int64,
) error {
_, err := c.infraProviderSvc.FindResourceByIdentifier(
ctx,
parentSpace.ID,
resourceIdentifier)
if err != nil &&
err.Error() == infraProviderResourceMissingErr &&
resourceIdentifier == defaultResourceIdentifier {
err2 := c.autoCreateDefaultResource(ctx, parentSpace, now)
if err2 != nil {
return err2
}
}
if err != nil {
return fmt.Errorf("could not find infra provider resource : %q %w", resourceIdentifier, err)
}
return err
}
func (c *Controller) autoCreateDefaultResource(ctx context.Context, parentSpace *types.Space, now int64) error {
infraProviderConfig := &types.InfraProviderConfig{
Identifier: defaultResourceIdentifier,
Name: "default docker infrastructure",
Type: infraproviderenum.InfraProviderTypeDocker,
SpaceID: parentSpace.ID,
SpacePath: parentSpace.Path,
Created: now,
Updated: now,
}
defaultResource := &types.InfraProviderResource{
Identifier: defaultResourceIdentifier,
Name: "Standard Docker Resource",
InfraProviderConfigIdentifier: infraProviderConfig.Identifier,
InfraProviderType: infraproviderenum.InfraProviderTypeDocker,
CPU: wrapString("any"),
Memory: wrapString("any"),
Disk: wrapString("any"),
Network: wrapString("standard"),
SpaceID: parentSpace.ID,
SpacePath: parentSpace.Path,
Created: now,
Updated: now,
}
infraProviderConfig.Resources = []*types.InfraProviderResource{defaultResource}
err := c.infraProviderSvc.CreateInfraProvider(ctx, infraProviderConfig)
if err != nil {
return fmt.Errorf("could not autocreate the resources: %w", err)
}
return nil
}
func wrapString(str string) *string {
return &str
}
func (c *Controller) sanitizeCreateInput(in *CreateInput) error {
if err := check.Identifier(in.Identifier); err != nil {
return err
}
if err := check.Identifier(in.ResourceIdentifier); 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

@ -20,6 +20,7 @@ import (
apiauth "github.com/harness/gitness/app/api/auth"
"github.com/harness/gitness/app/auth"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
@ -45,9 +46,7 @@ func (c *Controller) Find(
if err != nil {
return fmt.Errorf("failed to find gitspace config: %w", err)
}
infraProviderResource, err := c.infraProviderResourceStore.Find(
ctx,
gitspaceConfig.InfraProviderResourceID)
infraProviderResource, err := c.infraProviderSvc.FindResource(ctx, gitspaceConfig.InfraProviderResourceID)
if err != nil {
return fmt.Errorf("failed to find infra provider resource for gitspace config: %w", err)
}
@ -69,7 +68,7 @@ func (c *Controller) Find(
gitspaceConfig.State = enum.GitspaceStateUninitialized
}
return nil
})
}, dbtx.TxDefaultReadOnly)
if err != nil {
return nil, err
}

View File

@ -20,6 +20,7 @@ import (
"github.com/harness/gitness/app/gitspace/logutil"
"github.com/harness/gitness/app/gitspace/orchestrator"
"github.com/harness/gitness/app/gitspace/scm"
"github.com/harness/gitness/app/services/infraprovider"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/store/database/dbtx"
@ -34,7 +35,7 @@ var WireSet = wire.NewSet(
func ProvideController(
tx dbtx.Transactor,
authorizer authz.Authorizer,
resourceStore store.InfraProviderResourceStore,
infraProviderSvc infraprovider.ProviderService,
configStore store.GitspaceConfigStore,
instanceStore store.GitspaceInstanceStore,
spaceStore store.SpaceStore,
@ -47,7 +48,7 @@ func ProvideController(
return NewController(
tx,
authorizer,
resourceStore,
infraProviderSvc,
configStore,
instanceStore,
spaceStore,

View File

@ -16,34 +16,24 @@ package infraprovider
import (
"github.com/harness/gitness/app/auth/authz"
"github.com/harness/gitness/app/services/infraprovider"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/infraprovider"
"github.com/harness/gitness/store/database/dbtx"
)
type Controller struct {
authorizer authz.Authorizer
infraProviderResourceStore store.InfraProviderResourceStore
infraProviderConfigStore store.InfraProviderConfigStore
infraProviderFactory infraprovider.Factory
spaceStore store.SpaceStore
tx dbtx.Transactor
authorizer authz.Authorizer
spaceStore store.SpaceStore
infraproviderSvc infraprovider.ProviderService
}
func NewController(
tx dbtx.Transactor,
authorizer authz.Authorizer,
infraProviderResourceStore store.InfraProviderResourceStore,
infraProviderConfigStore store.InfraProviderConfigStore,
factory infraprovider.Factory,
spaceStore store.SpaceStore,
infraproviderSvc infraprovider.ProviderService,
) *Controller {
return &Controller{
tx: tx,
authorizer: authorizer,
infraProviderResourceStore: infraProviderResourceStore,
infraProviderConfigStore: infraProviderConfigStore,
infraProviderFactory: factory,
spaceStore: spaceStore,
authorizer: authorizer,
spaceStore: spaceStore,
infraproviderSvc: infraproviderSvc,
}
}

View File

@ -22,7 +22,6 @@ import (
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"
@ -62,7 +61,6 @@ func (c *Controller) Create(
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)
@ -76,6 +74,7 @@ func (c *Controller) Create(
enum.PermissionInfraProviderEdit); err != nil {
return nil, err
}
now := time.Now().UnixMilli()
infraProviderConfig := &types.InfraProviderConfig{
Identifier: in.Identifier,
Name: in.Name,
@ -84,64 +83,30 @@ func (c *Controller) Create(
Created: now,
Updated: now,
}
err = c.tx.WithTx(ctx, func(ctx context.Context) error {
err = c.infraProviderConfigStore.Create(ctx, infraProviderConfig)
if err != nil {
return fmt.Errorf("failed to create infraprovider config for : %q %w", infraProviderConfig.Identifier, err)
var resources []*types.InfraProviderResource
for _, res := range in.Resources {
infraProviderResource := &types.InfraProviderResource{
Identifier: res.Identifier,
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,
}
infraProviderConfiginDB, err := c.infraProviderConfigStore.FindByIdentifier(
ctx,
parentSpace.ID,
infraProviderConfig.Identifier)
if err != nil {
return err
}
infraProvider, err := c.infraProviderFactory.GetInfraProvider(infraProviderConfiginDB.Type)
if err != nil {
return err
}
if len(infraProvider.TemplateParams()) > 0 {
return 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 fmt.Errorf("failed to validate infraprovider templates")
}
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 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 fmt.Errorf(
"error creating infra provider resource for config : %q %w", infraProviderConfiginDB.Identifier, err)
}
return nil
})
resources = append(resources, infraProviderResource)
}
infraProviderConfig.Resources = resources
err = c.infraproviderSvc.CreateInfraProvider(ctx, infraProviderConfig)
if err != nil {
return nil, err
return nil, fmt.Errorf("unable to create the infraprovider: %w", err)
}
return infraProviderConfig, nil
}

View File

@ -38,15 +38,5 @@ func (c *Controller) Find(
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.SpacePath = space.Path
infraProviderConfig.Resources = resources
return infraProviderConfig, nil
return c.infraproviderSvc.Find(ctx, space, identifier)
}

View File

@ -16,9 +16,8 @@ package infraprovider
import (
"github.com/harness/gitness/app/auth/authz"
"github.com/harness/gitness/app/services/infraprovider"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/infraprovider"
"github.com/harness/gitness/store/database/dbtx"
"github.com/google/wire"
)
@ -29,12 +28,9 @@ var WireSet = wire.NewSet(
)
func ProvideController(
tx dbtx.Transactor,
authorizer authz.Authorizer,
resourceStore store.InfraProviderResourceStore,
configStore store.InfraProviderConfigStore,
spaceStore store.SpaceStore,
factory infraprovider.Factory,
infraproviderSvc infraprovider.ProviderService,
) *Controller {
return NewController(tx, authorizer, resourceStore, configStore, factory, spaceStore)
return NewController(authorizer, spaceStore, infraproviderSvc)
}

View File

@ -20,6 +20,7 @@ import (
apiauth "github.com/harness/gitness/app/api/auth"
"github.com/harness/gitness/app/auth"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
@ -81,7 +82,7 @@ func (c *Controller) ListGitspaces(
}
}
return nil
})
}, dbtx.TxDefaultReadOnly)
if err != nil {
return nil, 0, err
}

View File

@ -0,0 +1,115 @@
// Copyright 2023 Harness, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package infraprovider
import (
"context"
"fmt"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/infraprovider"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
)
func NewService(
tx dbtx.Transactor,
infraProviderResourceStore store.InfraProviderResourceStore,
infraProviderConfigStore store.InfraProviderConfigStore,
factory infraprovider.Factory,
spaceStore store.SpaceStore,
) ProviderService {
return ProviderService{
tx: tx,
infraProviderResourceStore: infraProviderResourceStore,
infraProviderConfigStore: infraProviderConfigStore,
infraProviderFactory: factory,
spaceStore: spaceStore,
}
}
type ProviderService struct {
infraProviderResourceStore store.InfraProviderResourceStore
infraProviderConfigStore store.InfraProviderConfigStore
infraProviderFactory infraprovider.Factory
spaceStore store.SpaceStore
tx dbtx.Transactor
}
func (c ProviderService) Find(
ctx context.Context,
space *types.Space,
identifier string,
) (*types.InfraProviderConfig, error) {
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.SpacePath = space.Path
infraProviderConfig.Resources = resources
return infraProviderConfig, nil
}
func (c ProviderService) FindResourceByIdentifier(
ctx context.Context,
spaceID int64,
identifier string) (*types.InfraProviderResource, error) {
return c.infraProviderResourceStore.FindByIdentifier(ctx, spaceID, identifier)
}
func (c ProviderService) FindResource(ctx context.Context, id int64) (*types.InfraProviderResource, error) {
return c.infraProviderResourceStore.Find(ctx, id)
}
func (c ProviderService) CreateInfraProvider(
ctx context.Context,
infraProviderConfig *types.InfraProviderConfig,
) error {
err := c.tx.WithTx(ctx, func(ctx context.Context) error {
err := c.infraProviderConfigStore.Create(ctx, infraProviderConfig)
if err != nil {
return fmt.Errorf("failed to create infraprovider config for : %q %w", infraProviderConfig.Identifier, err)
}
infraProvider, err := c.infraProviderFactory.GetInfraProvider(infraProviderConfig.Type)
if err != nil {
return fmt.Errorf("failed to fetch infrastructure impl for type : %q %w", infraProviderConfig.Type, err)
}
if len(infraProvider.TemplateParams()) > 0 {
return 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 fmt.Errorf("failed to validate infraprovider templates")
}
for _, res := range infraProviderConfig.Resources {
res.InfraProviderConfigID = infraProviderConfig.ID
err = c.infraProviderResourceStore.Create(ctx, res)
if err != nil {
return fmt.Errorf("failed to create infraprovider resource for : %q %w", res.Identifier, err)
}
}
return nil
})
if err != nil {
return fmt.Errorf("failed to complete txn for the infraprovider resource : %w", err)
}
return nil
}

View File

@ -0,0 +1,37 @@
// 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 (
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/infraprovider"
"github.com/harness/gitness/store/database/dbtx"
"github.com/google/wire"
)
var WireSet = wire.NewSet(
ProvideInfraProvider,
)
func ProvideInfraProvider(
infraProviderResourceStore store.InfraProviderResourceStore,
infraProviderConfigStore store.InfraProviderConfigStore,
infraProviderFactory infraprovider.Factory,
spaceStore store.SpaceStore,
tx dbtx.Transactor,
) ProviderService {
return NewService(tx, infraProviderResourceStore, infraProviderConfigStore, infraProviderFactory, spaceStore)
}

View File

@ -624,7 +624,7 @@ type (
FindByIdentifier(ctx context.Context, spaceID int64, identifier string) (*types.InfraProviderResource, error)
// Create creates a new infra provider resource in the datastore.
Create(ctx context.Context, infraProviderConfigID int64, infraProviderResource *types.InfraProviderResource) error
Create(ctx context.Context, infraProviderResource *types.InfraProviderResource) error
// List lists the infra provider resource present for the gitspace config in a parent space ID in the datastore.
List(ctx context.Context,

View File

@ -175,10 +175,8 @@ func (s infraProviderResourceStore) FindByIdentifier(
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
@ -189,7 +187,7 @@ func (s infraProviderResourceStore) Create(
Values(
infraProviderResource.Identifier,
infraProviderResource.Name,
infraProviderConfigID,
infraProviderResource.InfraProviderConfigID,
infraProviderResource.InfraProviderType,
infraProviderResource.SpaceID,
infraProviderResource.Created,

View File

@ -67,6 +67,7 @@ import (
"github.com/harness/gitness/app/services/exporter"
"github.com/harness/gitness/app/services/gitspaceevent"
"github.com/harness/gitness/app/services/importer"
"github.com/harness/gitness/app/services/infraprovider"
"github.com/harness/gitness/app/services/keywordsearch"
locker "github.com/harness/gitness/app/services/locker"
"github.com/harness/gitness/app/services/metric"
@ -210,6 +211,7 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
audit.WireSet,
ssh.WireSet,
publickey.WireSet,
infraprovider.WireSet,
migrate.WireSet,
gitspaceCtrl.WireSet,
infraproviderCtrl.WireSet,

View File

@ -14,7 +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"
infraprovider3 "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"
@ -66,6 +66,7 @@ import (
"github.com/harness/gitness/app/services/exporter"
"github.com/harness/gitness/app/services/gitspaceevent"
"github.com/harness/gitness/app/services/importer"
infraprovider2 "github.com/harness/gitness/app/services/infraprovider"
"github.com/harness/gitness/app/services/keywordsearch"
"github.com/harness/gitness/app/services/locker"
"github.com/harness/gitness/app/services/metric"
@ -325,7 +326,8 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
dockerClientFactory := infraprovider.ProvideDockerClientFactory(dockerConfig)
dockerProvider := infraprovider.ProvideDockerProvider(dockerClientFactory)
factory := infraprovider.ProvideFactory(dockerProvider)
infraproviderController := infraprovider2.ProvideController(transactor, authorizer, infraProviderResourceStore, infraProviderConfigStore, spaceStore, factory)
providerService := infraprovider2.ProvideInfraProvider(infraProviderResourceStore, infraProviderConfigStore, factory, spaceStore, transactor)
infraproviderController := infraprovider3.ProvideController(authorizer, spaceStore, providerService)
reporter3, err := events5.ProvideReporter(eventsSystem)
if err != nil {
return nil, err
@ -343,7 +345,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
containerOrchestrator := container.ProvideEmbeddedDockerOrchestrator(dockerClientFactory, vsCode, vsCodeWeb, containerConfig, statefulLogger)
orchestratorOrchestrator := orchestrator.ProvideOrchestrator(scmSCM, infraProviderResourceStore, infraProvisioner, containerOrchestrator, reporter3)
gitspaceEventStore := database.ProvideGitspaceEventStore(db)
gitspaceController := gitspace.ProvideController(transactor, authorizer, infraProviderResourceStore, gitspaceConfigStore, gitspaceInstanceStore, spaceStore, reporter3, orchestratorOrchestrator, gitspaceEventStore, statefulLogger, scmSCM)
gitspaceController := gitspace.ProvideController(transactor, authorizer, providerService, gitspaceConfigStore, gitspaceInstanceStore, spaceStore, reporter3, orchestratorOrchestrator, gitspaceEventStore, statefulLogger, scmSCM)
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, infraproviderController, gitspaceController, migrateController)
gitHandler := router.ProvideGitHandler(provider, authenticator, repoController)

View File

@ -27,7 +27,7 @@ type GitspaceConfig struct {
InfraProviderResourceID int64 `json:"-"`
InfraProviderResourceIdentifier string `json:"resource_identifier"`
CodeRepoURL string `json:"code_repo_url"`
CodeRepoType enum.GitspaceCodeRepoType `json:"code_repo_type"`
CodeRepoType enum.GitspaceCodeRepoType `json:"-"`
Branch string `json:"branch"`
DevcontainerPath *string `json:"devcontainer_path,omitempty"`
UserID string `json:"user_id"`