feat: [CDE-203]: Making infra processing async. (#2325)

* Cleaning the flow around gitspace instance update.
* Renaming params and param schema types.
* Correcting comments.
* feat: [CDE-203]: Making infra processing async.
* feat: [CDE-203]: Making infra processing async.
* feat: [CDE-203]: Making infra processing async.
pull/3545/head
Dhruv Dhruv 2024-08-01 10:01:31 +00:00 committed by Harness
parent bd9cfce3ab
commit 9d5071b45c
52 changed files with 1300 additions and 455 deletions

View File

@ -34,7 +34,7 @@ import (
const defaultAccessKey = "Harness@123" const defaultAccessKey = "Harness@123"
const defaultMachineUser = "harness" const defaultMachineUser = "harness"
const gitspaceTimedOutInMintues = 10 const gitspaceTimedOutInMintues = 5
type ActionInput struct { type ActionInput struct {
Action enum.GitspaceActionType `json:"action"` Action enum.GitspaceActionType `json:"action"`
@ -135,21 +135,28 @@ func (c *Controller) startGitspaceAction(
func (c *Controller) asyncOperation( func (c *Controller) asyncOperation(
ctxWithTimedOut context.Context, ctxWithTimedOut context.Context,
config *types.GitspaceConfig, config types.GitspaceConfig,
action enum.GitspaceActionType, action enum.GitspaceActionType,
stateChannel chan enum.GitspaceInstanceStateType,
errChannel chan error, errChannel chan error,
) { ) {
defer close(stateChannel)
defer close(errChannel)
var orchestrateErr error var orchestrateErr error
var instanceState enum.GitspaceInstanceStateType
switch action { switch action {
case enum.GitspaceActionTypeStart: case enum.GitspaceActionTypeStart:
orchestrateErr = c.orchestrator.StartGitspace(ctxWithTimedOut, config) instanceState, orchestrateErr = c.orchestrator.TriggerStartGitspace(ctxWithTimedOut, config)
case enum.GitspaceActionTypeStop: case enum.GitspaceActionTypeStop:
orchestrateErr = c.orchestrator.StopGitspace(ctxWithTimedOut, config) instanceState, orchestrateErr = c.orchestrator.TriggerStopGitspace(ctxWithTimedOut, config)
} }
if orchestrateErr != nil { if orchestrateErr != nil {
errChannel <- fmt.Errorf("failed to find start/stop gitspace : %s %w", config.Identifier, orchestrateErr) errChannel <- fmt.Errorf("failed to start/stop gitspace: %s %w", config.Identifier, orchestrateErr)
} }
close(errChannel) stateChannel <- instanceState
} }
func (c *Controller) submitAsyncOps( func (c *Controller) submitAsyncOps(
@ -157,21 +164,25 @@ func (c *Controller) submitAsyncOps(
config *types.GitspaceConfig, config *types.GitspaceConfig,
action enum.GitspaceActionType, action enum.GitspaceActionType,
) { ) {
errChannel := make(chan error)
stateChannel := make(chan enum.GitspaceInstanceStateType)
submitCtx := context.WithoutCancel(ctx) submitCtx := context.WithoutCancel(ctx)
ttlExecuteContext, cancel := context.WithTimeout(submitCtx, gitspaceTimedOutInMintues*time.Minute) ttlExecuteContext, cancel := context.WithTimeout(submitCtx, gitspaceTimedOutInMintues*time.Minute)
// submit an async task with a TTL
errChannel := make(chan error) go c.asyncOperation(ttlExecuteContext, *config, action, stateChannel, errChannel)
go c.asyncOperation(ttlExecuteContext, config, action, errChannel)
// wait execution completion for the specified time or mark it as an error
var err error var err error
var instanceState enum.GitspaceInstanceStateType
go func() { go func() {
defer c.updateGitspaceInstance(submitCtx, config)
select { select {
case <-ttlExecuteContext.Done(): case <-ttlExecuteContext.Done():
if ttlExecuteContext.Err() != nil { if ttlExecuteContext.Err() != nil {
err = ttlExecuteContext.Err() err = ttlExecuteContext.Err()
} }
case err = <-errChannel: case err = <-errChannel:
case instanceState = <-stateChannel:
} }
if err != nil { if err != nil {
log.Err(err).Msgf("error during async execution for %s", config.GitspaceInstance.Identifier) log.Err(err).Msgf("error during async execution for %s", config.GitspaceInstance.Identifier)
@ -182,6 +193,15 @@ func (c *Controller) submitAsyncOps(
c.emitGitspaceConfigEvent(ttlExecuteContext, config, enum.GitspaceEventTypeGitspaceActionStopFailed) c.emitGitspaceConfigEvent(ttlExecuteContext, config, enum.GitspaceEventTypeGitspaceActionStopFailed)
} }
} }
if instanceState == "" {
instanceState = enum.GitspaceInstanceStateError
}
config.GitspaceInstance.State = instanceState
c.updateGitspaceInstance(submitCtx, config.GitspaceInstance)
cancel() cancel()
}() }()
} }
@ -286,11 +306,11 @@ func (c *Controller) emitGitspaceConfigEvent(
func (c *Controller) updateGitspaceInstance( func (c *Controller) updateGitspaceInstance(
ctx context.Context, ctx context.Context,
config *types.GitspaceConfig, instance *types.GitspaceInstance,
) { ) {
err := c.gitspaceInstanceStore.Update(ctx, config.GitspaceInstance) err := c.gitspaceInstanceStore.Update(ctx, instance)
if err != nil { if err != nil {
log.Err(err).Msgf( log.Err(err).Msgf(
"failed to update gitspace instance during exec %q", config.GitspaceInstance.Identifier) "failed to update gitspace instance during exec %q", instance.Identifier)
} }
} }

View File

@ -20,6 +20,7 @@ import (
"github.com/harness/gitness/app/gitspace/logutil" "github.com/harness/gitness/app/gitspace/logutil"
"github.com/harness/gitness/app/gitspace/orchestrator" "github.com/harness/gitness/app/gitspace/orchestrator"
"github.com/harness/gitness/app/gitspace/scm" "github.com/harness/gitness/app/gitspace/scm"
"github.com/harness/gitness/app/services/gitspace"
"github.com/harness/gitness/app/services/infraprovider" "github.com/harness/gitness/app/services/infraprovider"
"github.com/harness/gitness/app/store" "github.com/harness/gitness/app/store"
"github.com/harness/gitness/store/database/dbtx" "github.com/harness/gitness/store/database/dbtx"
@ -38,6 +39,7 @@ type Controller struct {
statefulLogger *logutil.StatefulLogger statefulLogger *logutil.StatefulLogger
scm scm.SCM scm scm.SCM
repoStore store.RepoStore repoStore store.RepoStore
gitspaceSvc *gitspace.Service
} }
func NewController( func NewController(
@ -53,6 +55,7 @@ func NewController(
statefulLogger *logutil.StatefulLogger, statefulLogger *logutil.StatefulLogger,
scm scm.SCM, scm scm.SCM,
repoStore store.RepoStore, repoStore store.RepoStore,
gitspaceSvc *gitspace.Service,
) *Controller { ) *Controller {
return &Controller{ return &Controller{
tx: tx, tx: tx,
@ -67,5 +70,6 @@ func NewController(
statefulLogger: statefulLogger, statefulLogger: statefulLogger,
scm: scm, scm: scm,
repoStore: repoStore, repoStore: repoStore,
gitspaceSvc: gitspaceSvc,
} }
} }

View File

@ -24,7 +24,6 @@ import (
apiauth "github.com/harness/gitness/app/api/auth" apiauth "github.com/harness/gitness/app/api/auth"
"github.com/harness/gitness/app/api/usererror" "github.com/harness/gitness/app/api/usererror"
"github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth"
infraproviderenum "github.com/harness/gitness/infraprovider/enum"
"github.com/harness/gitness/types" "github.com/harness/gitness/types"
"github.com/harness/gitness/types/check" "github.com/harness/gitness/types/check"
"github.com/harness/gitness/types/enum" "github.com/harness/gitness/types/enum"
@ -189,7 +188,7 @@ func (c *Controller) autoCreateDefaultResource(ctx context.Context, parentSpace
infraProviderConfig := &types.InfraProviderConfig{ infraProviderConfig := &types.InfraProviderConfig{
Identifier: defaultResourceIdentifier, Identifier: defaultResourceIdentifier,
Name: "default docker infrastructure", Name: "default docker infrastructure",
Type: infraproviderenum.InfraProviderTypeDocker, Type: enum.InfraProviderTypeDocker,
SpaceID: parentSpace.ID, SpaceID: parentSpace.ID,
SpacePath: parentSpace.Path, SpacePath: parentSpace.Path,
Created: now, Created: now,
@ -199,7 +198,7 @@ func (c *Controller) autoCreateDefaultResource(ctx context.Context, parentSpace
Identifier: defaultResourceIdentifier, Identifier: defaultResourceIdentifier,
Name: "Standard Docker Resource", Name: "Standard Docker Resource",
InfraProviderConfigIdentifier: infraProviderConfig.Identifier, InfraProviderConfigIdentifier: infraProviderConfig.Identifier,
InfraProviderType: infraproviderenum.InfraProviderTypeDocker, InfraProviderType: enum.InfraProviderTypeDocker,
CPU: wrapString("any"), CPU: wrapString("any"),
Memory: wrapString("any"), Memory: wrapString("any"),
Disk: wrapString("any"), Disk: wrapString("any"),

View File

@ -51,26 +51,34 @@ func (c *Controller) Delete(
instance, _ := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, gitspaceConfig.ID, gitspaceConfig.SpaceID) instance, _ := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, gitspaceConfig.ID, gitspaceConfig.SpaceID)
gitspaceConfig.GitspaceInstance = instance gitspaceConfig.GitspaceInstance = instance
gitspaceConfig.SpacePath = space.Path gitspaceConfig.SpacePath = space.Path
if instance != nil { if instance == nil {
if stopErr := c.stopRunningGitspace(ctx, gitspaceConfig); stopErr != nil { gitspaceConfig.IsDeleted = true
err = c.gitspaceConfigStore.Update(ctx, gitspaceConfig)
if err != nil {
return fmt.Errorf("failed to mark gitspace config as deleted: %w", err)
}
} else {
instanceState, stopErr := c.stopRunningGitspace(ctx, *gitspaceConfig)
if stopErr != nil {
return stopErr return stopErr
} }
instance.State = instanceState
err = c.gitspaceInstanceStore.Update(ctx, instance)
if err != nil {
return fmt.Errorf("failed to update instance: %w", err)
} }
gitspaceConfig.IsDeleted = true
if err = c.gitspaceConfigStore.Update(ctx, gitspaceConfig); err != nil {
return fmt.Errorf("failed to delete gitspace config with ID: %s %w", gitspaceConfig.Identifier, err)
} }
return nil return nil
} }
func (c *Controller) stopRunningGitspace( func (c *Controller) stopRunningGitspace(
ctx context.Context, ctx context.Context,
config *types.GitspaceConfig, config types.GitspaceConfig,
) error { ) (enum.GitspaceInstanceStateType, error) {
if instanceUpdated, err := c.orchestrator.DeleteGitspace(ctx, config); err != nil { instanceState, err := c.orchestrator.TriggerDeleteGitspace(ctx, config)
return err if err != nil {
} else if err = c.gitspaceInstanceStore.Update(ctx, instanceUpdated); err != nil { return instanceState, err
return err
} }
return nil return instanceState, nil
} }

View File

@ -20,7 +20,6 @@ import (
apiauth "github.com/harness/gitness/app/api/auth" apiauth "github.com/harness/gitness/app/api/auth"
"github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types" "github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum" "github.com/harness/gitness/types/enum"
) )
@ -32,45 +31,18 @@ func (c *Controller) Find(
identifier string, identifier string,
) (*types.GitspaceConfig, error) { ) (*types.GitspaceConfig, error) {
space, err := c.spaceStore.FindByRef(ctx, spaceRef) space, err := c.spaceStore.FindByRef(ctx, spaceRef)
const resourceNotFoundErr = "Failed to find gitspace: resource not found"
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to find space: %w", err) return nil, fmt.Errorf("failed to find space: %w", err)
} }
err = apiauth.CheckGitspace(ctx, c.authorizer, session, space.Path, identifier, enum.PermissionGitspaceView) err = apiauth.CheckGitspace(ctx, c.authorizer, session, space.Path, identifier, enum.PermissionGitspaceView)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to authorize: %w", err) return nil, fmt.Errorf("failed to authorize: %w", err)
} }
var gitspaceConfig *types.GitspaceConfig
err = c.tx.WithTx(ctx, func(ctx context.Context) error { res, err := c.gitspaceSvc.Find(ctx, space.ID, space.Path, identifier)
gitspaceConfig, err = c.gitspaceConfigStore.FindByIdentifier(ctx, space.ID, identifier)
if err != nil { if err != nil {
return fmt.Errorf("failed to find gitspace config: %w", err) return nil, fmt.Errorf("failed to find gitspace: %w", err)
} }
infraProviderResource, err := c.infraProviderSvc.FindResource(ctx, gitspaceConfig.InfraProviderResourceID) return res, nil
if err != nil {
return 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 && err.Error() != resourceNotFoundErr { // TODO fix this
return fmt.Errorf("failed to find gitspace instance for config ID : %s %w", gitspaceConfig.Identifier, err)
}
if instance != nil {
gitspaceConfig.GitspaceInstance = instance
instance.SpacePath = gitspaceConfig.SpacePath
gitspaceStateType, err := enum.GetGitspaceStateFromInstance(instance.State)
if err != nil {
return err
}
gitspaceConfig.State = gitspaceStateType
} else {
gitspaceConfig.State = enum.GitspaceStateUninitialized
}
return nil
}, dbtx.TxDefaultReadOnly)
if err != nil {
return nil, err
}
return gitspaceConfig, nil
} }

View File

@ -20,6 +20,7 @@ import (
"github.com/harness/gitness/app/gitspace/logutil" "github.com/harness/gitness/app/gitspace/logutil"
"github.com/harness/gitness/app/gitspace/orchestrator" "github.com/harness/gitness/app/gitspace/orchestrator"
"github.com/harness/gitness/app/gitspace/scm" "github.com/harness/gitness/app/gitspace/scm"
"github.com/harness/gitness/app/services/gitspace"
"github.com/harness/gitness/app/services/infraprovider" "github.com/harness/gitness/app/services/infraprovider"
"github.com/harness/gitness/app/store" "github.com/harness/gitness/app/store"
"github.com/harness/gitness/store/database/dbtx" "github.com/harness/gitness/store/database/dbtx"
@ -45,6 +46,7 @@ func ProvideController(
statefulLogger *logutil.StatefulLogger, statefulLogger *logutil.StatefulLogger,
scm scm.SCM, scm scm.SCM,
repoStore store.RepoStore, repoStore store.RepoStore,
gitspaceSvc *gitspace.Service,
) *Controller { ) *Controller {
return NewController( return NewController(
tx, tx,
@ -59,5 +61,6 @@ func ProvideController(
statefulLogger, statefulLogger,
scm, scm,
repoStore, repoStore,
gitspaceSvc,
) )
} }

View File

@ -22,7 +22,6 @@ import (
apiauth "github.com/harness/gitness/app/api/auth" apiauth "github.com/harness/gitness/app/api/auth"
"github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth"
infraproviderenum "github.com/harness/gitness/infraprovider/enum"
"github.com/harness/gitness/types" "github.com/harness/gitness/types"
"github.com/harness/gitness/types/check" "github.com/harness/gitness/types/check"
"github.com/harness/gitness/types/enum" "github.com/harness/gitness/types/enum"
@ -32,7 +31,7 @@ type CreateInput struct {
Identifier string `json:"identifier"` Identifier string `json:"identifier"`
SpaceRef string `json:"space_ref"` // Ref of the parent space SpaceRef string `json:"space_ref"` // Ref of the parent space
Name string `json:"name"` Name string `json:"name"`
Type infraproviderenum.InfraProviderType `json:"type"` Type enum.InfraProviderType `json:"type"`
Metadata map[string]string `json:"metadata"` Metadata map[string]string `json:"metadata"`
Resources []ResourceInput `json:"resources"` Resources []ResourceInput `json:"resources"`
} }
@ -40,7 +39,7 @@ type CreateInput struct {
type ResourceInput struct { type ResourceInput struct {
Identifier string `json:"identifier"` Identifier string `json:"identifier"`
Name string `json:"name"` Name string `json:"name"`
InfraProviderType infraproviderenum.InfraProviderType `json:"infra_provider_type"` InfraProviderType enum.InfraProviderType `json:"infra_provider_type"`
CPU *string `json:"cpu"` CPU *string `json:"cpu"`
Memory *string `json:"memory"` Memory *string `json:"memory"`
Disk *string `json:"disk"` Disk *string `json:"disk"`

View File

@ -12,12 +12,9 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package enum package events
func toInterfaceSlice[T interface{}](vals []T) []interface{} { const (
res := make([]interface{}, len(vals)) // category defines the event category used for this package.
for i := range vals { category = "gitspace_infra"
res[i] = vals[i] )
}
return res
}

View File

@ -0,0 +1,62 @@
// 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 events
import (
"context"
"github.com/harness/gitness/events"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/rs/zerolog/log"
)
const (
// List all Gitspace Infra events below.
GitspaceInfraEvent events.EventType = "gitspace_infra_event"
)
type (
GitspaceInfraEventPayload struct {
Infra *types.Infrastructure `json:"infra,omitempty"`
Type enum.InfraEvent `json:"type"`
}
)
func (r *Reporter) EmitGitspaceInfraEvent(
ctx context.Context,
event events.EventType,
payload *GitspaceInfraEventPayload,
) {
if payload == nil {
return
}
eventID, err := events.ReporterSendEvent(r.innerReporter, ctx, event, payload)
if err != nil {
log.Ctx(ctx).Err(err).Msgf("failed to send %v event", event)
return
}
log.Ctx(ctx).Debug().Msgf("reported %v event with id '%s'", event, eventID)
}
func (r *Reader) RegisterGitspaceInfraEvent(
fn events.HandlerFunc[*GitspaceInfraEventPayload],
opts ...events.HandlerOption,
) error {
return events.ReaderRegisterEvent(r.innerReader, GitspaceInfraEvent, fn, opts...)
}

View File

@ -0,0 +1,38 @@
// 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 events
import (
"github.com/harness/gitness/events"
)
func NewReaderFactory(eventsSystem *events.System) (*events.ReaderFactory[*Reader], error) {
readerFactoryFunc := func(innerReader *events.GenericReader) (*Reader, error) {
return &Reader{
innerReader: innerReader,
}, nil
}
return events.NewReaderFactory(eventsSystem, category, readerFactoryFunc)
}
// Reader is the event reader for this package.
type Reader struct {
innerReader *events.GenericReader
}
func (r *Reader) Configure(opts ...events.ReaderOption) {
r.innerReader.Configure(opts...)
}

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 events
import (
"errors"
"github.com/harness/gitness/events"
)
// Reporter is the event reporter for this package.
type Reporter struct {
innerReporter *events.GenericReporter
}
func NewReporter(eventsSystem *events.System) (*Reporter, error) {
innerReporter, err := events.NewReporter(eventsSystem, category)
if err != nil {
return nil, errors.New("failed to create new GenericReporter from event system")
}
return &Reporter{
innerReporter: innerReporter,
}, nil
}

View File

@ -0,0 +1,35 @@
// 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 events
import (
"github.com/harness/gitness/events"
"github.com/google/wire"
)
// WireSet provides a wire set for this package.
var WireSet = wire.NewSet(
ProvideReaderFactory,
ProvideReporter,
)
func ProvideReaderFactory(eventsSystem *events.System) (*events.ReaderFactory[*Reader], error) {
return NewReaderFactory(eventsSystem)
}
func ProvideReporter(eventsSystem *events.System) (*Reporter, error) {
return NewReporter(eventsSystem)
}

View File

@ -17,40 +17,64 @@ package infrastructure
import ( import (
"context" "context"
"github.com/harness/gitness/infraprovider"
"github.com/harness/gitness/types" "github.com/harness/gitness/types"
) )
// TODO Check if the interface can be discarded // TODO Check if the interface can be discarded
type InfraProvisioner interface { type InfraProvisioner interface {
// Provision provisions infra resources using the infraProviderResource with different infra providers and // TriggerProvision triggers the provisionining of infra resources using the infraProviderResource with different
// stores the details in the db depending on the provisioning type. // infra providers.
Provision( TriggerProvision(
ctx context.Context, ctx context.Context,
infraProviderResource *types.InfraProviderResource, infraProviderResource *types.InfraProviderResource,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
requiredPorts []int, requiredPorts []int,
) (*infraprovider.Infrastructure, error) ) error
// Stop unprovisions those resources which can be stopped without losing the gitspace data. // ResumeProvision stores the provisioned infra details in the db depending on the provisioning type.
Stop( ResumeProvision(
ctx context.Context, ctx context.Context,
infraProviderResource *types.InfraProviderResource, infraProviderResource *types.InfraProviderResource,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
) (*infraprovider.Infrastructure, error) requiredPorts []int,
provisionedInfra *types.Infrastructure,
) (*types.Infrastructure, error)
// Deprovision removes all the resources created for the gitspace. // TriggerStop triggers deprovisioning of those resources which can be stopped without losing the Gitspace data.
Deprovision( TriggerStop(
ctx context.Context, ctx context.Context,
infraProviderResource *types.InfraProviderResource, infraProviderResource *types.InfraProviderResource,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
) (*infraprovider.Infrastructure, error) ) error
// ResumeStop stores the deprovisioned infra details in the db depending on the provisioning type.
ResumeStop(
ctx context.Context,
infraProviderResource *types.InfraProviderResource,
gitspaceConfig types.GitspaceConfig,
deprovisionedInfra *types.Infrastructure,
) (*types.Infrastructure, error)
// TriggerDeprovision triggers deprovisionign of all the resources created for the Gitspace.
TriggerDeprovision(
ctx context.Context,
infraProviderResource *types.InfraProviderResource,
gitspaceConfig types.GitspaceConfig,
) error
// ResumeDeprovision stores the deprovisioned infra details in the db depending on the provisioning type.
ResumeDeprovision(
ctx context.Context,
infraProviderResource *types.InfraProviderResource,
gitspaceConfig types.GitspaceConfig,
deprovisionedInfra *types.Infrastructure,
) (*types.Infrastructure, error)
// Find finds the provisioned infra resources for the gitspace instance. // Find finds the provisioned infra resources for the gitspace instance.
Find( Find(
ctx context.Context, ctx context.Context,
infraProviderResource *types.InfraProviderResource, infraProviderResource *types.InfraProviderResource,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
) (*infraprovider.Infrastructure, error) ) (*types.Infrastructure, error)
} }

View File

@ -20,8 +20,8 @@ import (
"github.com/harness/gitness/app/store" "github.com/harness/gitness/app/store"
"github.com/harness/gitness/infraprovider" "github.com/harness/gitness/infraprovider"
"github.com/harness/gitness/infraprovider/enum"
"github.com/harness/gitness/types" "github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
) )
var _ InfraProvisioner = (*infraProvisioner)(nil) var _ InfraProvisioner = (*infraProvisioner)(nil)
@ -44,31 +44,31 @@ func NewInfraProvisionerService(
} }
} }
func (i infraProvisioner) Provision( func (i infraProvisioner) TriggerProvision(
ctx context.Context, ctx context.Context,
infraProviderResource *types.InfraProviderResource, infraProviderResource *types.InfraProviderResource,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
requiredPorts []int, requiredPorts []int,
) (*infraprovider.Infrastructure, error) { ) error {
infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource) infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource)
if err != nil { if err != nil {
return nil, err return err
} }
infraProvider, err := i.getInfraProvider(infraProviderEntity) infraProvider, err := i.getInfraProvider(infraProviderEntity.Type)
if err != nil { if err != nil {
return nil, err return err
} }
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive,staticcheck if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive,staticcheck
// TODO: Check if any existing infra is provisioned, its status and create new infraProvisioned record // TODO: Check if any existing infra is provisioned, its status and create new infraProvisioned record
} }
var allParams []infraprovider.Parameter var allParams []types.InfraProviderParameter
templateParams, err := i.getTemplateParams(infraProvider, infraProviderResource) templateParams, err := i.getTemplateParams(infraProvider, infraProviderResource)
if err != nil { if err != nil {
return nil, err return err
} }
allParams = append(allParams, templateParams...) allParams = append(allParams, templateParams...)
@ -79,47 +79,44 @@ func (i infraProvisioner) Provision(
err = infraProvider.ValidateParams(allParams) err = infraProvider.ValidateParams(allParams)
if err != nil { if err != nil {
return nil, fmt.Errorf("invalid provisioning params %v: %w", infraProviderResource.Metadata, err) return fmt.Errorf("invalid provisioning params %v: %w", infraProviderResource.Metadata, err)
} }
provisionedInfra, err := infraProvider.Provision( err = infraProvider.Provision(
ctx, ctx,
gitspaceConfig.SpaceID,
gitspaceConfig.SpacePath, gitspaceConfig.SpacePath,
gitspaceConfig.Identifier, gitspaceConfig.Identifier,
requiredPorts, requiredPorts,
allParams, allParams,
) )
if err != nil { if err != nil {
return nil, fmt.Errorf( return fmt.Errorf(
"unable to provision infrastructure for gitspaceConfigIdentifier %v: %w", "unable to trigger provision infrastructure for gitspaceConfigIdentifier %v: %w",
gitspaceConfig.Identifier, gitspaceConfig.Identifier,
err, err,
) )
} }
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive,staticcheck return nil
// TODO: Update the infraProvisioned record
}
return provisionedInfra, nil
} }
func (i infraProvisioner) Stop( func (i infraProvisioner) TriggerStop(
ctx context.Context, ctx context.Context,
infraProviderResource *types.InfraProviderResource, infraProviderResource *types.InfraProviderResource,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
) (*infraprovider.Infrastructure, error) { ) error {
infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource) infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource)
if err != nil { if err != nil {
return nil, err return err
} }
infraProvider, err := i.getInfraProvider(infraProviderEntity) infraProvider, err := i.getInfraProvider(infraProviderEntity.Type)
if err != nil { if err != nil {
return nil, err return err
} }
var allParams []infraprovider.Parameter var allParams []types.InfraProviderParameter
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive
// TODO: Fetch and check existing infraProvisioned record // TODO: Fetch and check existing infraProvisioned record
@ -127,7 +124,7 @@ func (i infraProvisioner) Stop(
} else { } else {
templateParams, err2 := i.getTemplateParams(infraProvider, infraProviderResource) templateParams, err2 := i.getTemplateParams(infraProvider, infraProviderResource)
if err2 != nil { if err2 != nil {
return nil, err2 return err2
} }
allParams = append(allParams, templateParams...) allParams = append(allParams, templateParams...)
@ -138,48 +135,46 @@ func (i infraProvisioner) Stop(
err = infraProvider.ValidateParams(allParams) err = infraProvider.ValidateParams(allParams)
if err != nil { if err != nil {
return nil, fmt.Errorf("invalid provisioning params %+v: %w", infraProviderResource.Metadata, err) return fmt.Errorf("invalid provisioning params %+v: %w", infraProviderResource.Metadata, err)
} }
var provisionedInfra *infraprovider.Infrastructure var provisionedInfra *types.Infrastructure
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive
// TODO: Fetch and check existing infraProvisioned record // TODO: Fetch and check existing infraProvisioned record
} else { } else {
provisionedInfra = &infraprovider.Infrastructure{ provisionedInfra = &types.Infrastructure{
SpaceID: gitspaceConfig.SpaceID,
SpacePath: gitspaceConfig.SpacePath,
ResourceKey: gitspaceConfig.Identifier, ResourceKey: gitspaceConfig.Identifier,
ProviderType: infraProviderEntity.Type, ProviderType: infraProviderEntity.Type,
Parameters: allParams, Parameters: allParams,
} }
} }
stoppedInfra, err := infraProvider.Stop(ctx, provisionedInfra) err = infraProvider.Stop(ctx, provisionedInfra)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to stop provisioned infra %+v: %w", provisionedInfra, err) return fmt.Errorf("unable to trigger stop infra %+v: %w", provisionedInfra, err)
} }
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive,staticcheck return nil
// TODO: Update existing infraProvisioned record
}
return stoppedInfra, err
} }
func (i infraProvisioner) Deprovision( func (i infraProvisioner) TriggerDeprovision(
ctx context.Context, ctx context.Context,
infraProviderResource *types.InfraProviderResource, infraProviderResource *types.InfraProviderResource,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
) (*infraprovider.Infrastructure, error) { ) error {
infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource) infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource)
if err != nil { if err != nil {
return nil, err return err
} }
infraProvider, err := i.getInfraProvider(infraProviderEntity) infraProvider, err := i.getInfraProvider(infraProviderEntity.Type)
if err != nil { if err != nil {
return nil, err return err
} }
var allParams []infraprovider.Parameter var allParams []types.InfraProviderParameter
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive
// TODO: Fetch and check existing infraProvisioned record // TODO: Fetch and check existing infraProvisioned record
@ -187,7 +182,7 @@ func (i infraProvisioner) Deprovision(
} else { } else {
templateParams, err2 := i.getTemplateParams(infraProvider, infraProviderResource) templateParams, err2 := i.getTemplateParams(infraProvider, infraProviderResource)
if err2 != nil { if err2 != nil {
return nil, err2 return err2
} }
allParams = append(allParams, templateParams...) allParams = append(allParams, templateParams...)
@ -198,51 +193,48 @@ func (i infraProvisioner) Deprovision(
err = infraProvider.ValidateParams(allParams) err = infraProvider.ValidateParams(allParams)
if err != nil { if err != nil {
return nil, fmt.Errorf("invalid provisioning params %+v: %w", infraProviderResource.Metadata, err) return fmt.Errorf("invalid provisioning params %+v: %w", infraProviderResource.Metadata, err)
} }
var provisionedInfra *infraprovider.Infrastructure var provisionedInfra *types.Infrastructure
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive
// TODO: Fetch and check existing infraProvisioned record // TODO: Fetch and check existing infraProvisioned record
} else { } else {
provisionedInfra, err = infraProvider.Find(ctx, gitspaceConfig.SpacePath, gitspaceConfig.Identifier, allParams) provisionedInfra, err = infraProvider.Find(
ctx, gitspaceConfig.SpaceID, gitspaceConfig.SpacePath, gitspaceConfig.Identifier, allParams)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to find provisioned infra for gitspace %s: %w", return fmt.Errorf("unable to find provisioned infra for gitspace %s: %w",
gitspaceConfig.Identifier, err) gitspaceConfig.Identifier, err)
} }
} }
destroyedInfra, err := infraProvider.Deprovision(ctx, provisionedInfra) err = infraProvider.Deprovision(ctx, provisionedInfra)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to stop provisioned infra %+v: %w", provisionedInfra, err) return fmt.Errorf("unable to trigger deprovision infra %+v: %w", provisionedInfra, err)
} }
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive,staticcheck return err
// TODO: Update existing infraProvisioned record
}
return destroyedInfra, err
} }
func (i infraProvisioner) Find( func (i infraProvisioner) Find(
ctx context.Context, ctx context.Context,
infraProviderResource *types.InfraProviderResource, infraProviderResource *types.InfraProviderResource,
_ *types.GitspaceConfig, _ types.GitspaceConfig,
) (*infraprovider.Infrastructure, error) { ) (*types.Infrastructure, error) {
infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource) infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource)
if err != nil { if err != nil {
return nil, err return nil, err
} }
infraProvider, err := i.getInfraProvider(infraProviderEntity) infraProvider, err := i.getInfraProvider(infraProviderEntity.Type)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var infra infraprovider.Infrastructure var infra types.Infrastructure
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive
// TODO: Fetch existing infraProvisioned record and map to &infraprovider.Infrastructure // TODO: Fetch existing infraProvisioned record and map to &infraprovider.Infrastructure
} else { } else {
var allParams []infraprovider.Parameter var allParams []types.InfraProviderParameter
templateParams, err2 := i.getTemplateParams(infraProvider, infraProviderResource) templateParams, err2 := i.getTemplateParams(infraProvider, infraProviderResource)
if err2 != nil { if err2 != nil {
@ -254,7 +246,7 @@ func (i infraProvisioner) Find(
allParams = append(allParams, params...) allParams = append(allParams, params...)
infra = infraprovider.Infrastructure{ infra = types.Infrastructure{
ProviderType: infraProviderEntity.Type, ProviderType: infraProviderEntity.Type,
Parameters: allParams, Parameters: allParams,
Status: enum.InfraStatusProvisioned, Status: enum.InfraStatusProvisioned,
@ -277,11 +269,11 @@ func (i infraProvisioner) getConfigFromResource(
} }
func (i infraProvisioner) getInfraProvider( func (i infraProvisioner) getInfraProvider(
infraProviderEntity *types.InfraProviderConfig, infraProviderType enum.InfraProviderType,
) (infraprovider.InfraProvider, error) { ) (infraprovider.InfraProvider, error) {
infraProvider, err := i.providerFactory.GetInfraProvider(infraProviderEntity.Type) infraProvider, err := i.providerFactory.GetInfraProvider(infraProviderType)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to get infra provider of type %v: %w", infraProviderEntity.Type, err) return nil, fmt.Errorf("unable to get infra provider of type %v: %w", infraProviderType, err)
} }
return infraProvider, nil return infraProvider, nil
} }
@ -289,7 +281,7 @@ func (i infraProvisioner) getInfraProvider(
func (i infraProvisioner) getTemplateParams( func (i infraProvisioner) getTemplateParams(
infraProvider infraprovider.InfraProvider, infraProvider infraprovider.InfraProvider,
_ *types.InfraProviderResource, _ *types.InfraProviderResource,
) ([]infraprovider.Parameter, error) { //nolint:unparam ) ([]types.InfraProviderParameter, error) { //nolint:unparam
templateParams := infraProvider.TemplateParams() templateParams := infraProvider.TemplateParams()
if len(templateParams) > 0 { //nolint:revive,staticcheck if len(templateParams) > 0 { //nolint:revive,staticcheck
// TODO: Fetch templates and convert into []Parameters // TODO: Fetch templates and convert into []Parameters
@ -299,14 +291,14 @@ func (i infraProvisioner) getTemplateParams(
func (i infraProvisioner) paramsFromResource( func (i infraProvisioner) paramsFromResource(
infraProviderResource *types.InfraProviderResource, infraProviderResource *types.InfraProviderResource,
) []infraprovider.Parameter { ) []types.InfraProviderParameter {
params := make([]infraprovider.Parameter, len(infraProviderResource.Metadata)) params := make([]types.InfraProviderParameter, len(infraProviderResource.Metadata))
counter := 0 counter := 0
for key, value := range infraProviderResource.Metadata { for key, value := range infraProviderResource.Metadata {
if key == "" || value == "" { if key == "" || value == "" {
continue continue
} }
params[counter] = infraprovider.Parameter{ params[counter] = types.InfraProviderParameter{
Name: key, Name: key,
Value: value, Value: value,
} }
@ -314,3 +306,58 @@ func (i infraProvisioner) paramsFromResource(
} }
return params return params
} }
func (i infraProvisioner) ResumeProvision(
_ context.Context,
_ *types.InfraProviderResource,
_ types.GitspaceConfig,
_ []int,
provisionedInfra *types.Infrastructure,
) (*types.Infrastructure, error) {
infraProvider, err := i.getInfraProvider(provisionedInfra.ProviderType)
if err != nil {
return nil, err
}
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive,staticcheck
// TODO: Update the infraProvisioned record
}
return provisionedInfra, nil
}
func (i infraProvisioner) ResumeStop(
_ context.Context,
_ *types.InfraProviderResource,
_ types.GitspaceConfig,
stoppedInfra *types.Infrastructure,
) (*types.Infrastructure, error) {
infraProvider, err := i.getInfraProvider(stoppedInfra.ProviderType)
if err != nil {
return nil, err
}
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive,staticcheck
// TODO: Update existing infraProvisioned record
}
return stoppedInfra, err
}
func (i infraProvisioner) ResumeDeprovision(
_ context.Context,
_ *types.InfraProviderResource,
_ types.GitspaceConfig,
deprovisionedInfra *types.Infrastructure,
) (*types.Infrastructure, error) {
infraProvider, err := i.getInfraProvider(deprovisionedInfra.ProviderType)
if err != nil {
return nil, err
}
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { //nolint:revive,staticcheck
// TODO: Update existing infraProvisioned record
}
return deprovisionedInfra, err
}

View File

@ -19,7 +19,6 @@ import (
"github.com/harness/gitness/app/gitspace/orchestrator/ide" "github.com/harness/gitness/app/gitspace/orchestrator/ide"
"github.com/harness/gitness/app/gitspace/scm" "github.com/harness/gitness/app/gitspace/scm"
"github.com/harness/gitness/infraprovider"
"github.com/harness/gitness/types" "github.com/harness/gitness/types"
) )
@ -29,19 +28,19 @@ type Orchestrator interface {
// It returns the container ID, name and ports used. // It returns the container ID, name and ports used.
CreateAndStartGitspace( CreateAndStartGitspace(
ctx context.Context, ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
infra *infraprovider.Infrastructure, infra *types.Infrastructure,
resolvedDetails *scm.ResolvedDetails, resolvedDetails *scm.ResolvedDetails,
defaultBaseImage string, defaultBaseImage string,
ideService ide.IDE, ideService ide.IDE,
) (*StartResponse, error) ) (*StartResponse, error)
// StopGitspace stops the gitspace container. // StopGitspace stops the gitspace container.
StopGitspace(ctx context.Context, config *types.GitspaceConfig, infra *infraprovider.Infrastructure) error StopGitspace(ctx context.Context, config types.GitspaceConfig, infra *types.Infrastructure) error
// StopAndRemoveGitspace stops and removes the gitspace container. // StopAndRemoveGitspace stops and removes the gitspace container.
StopAndRemoveGitspace(ctx context.Context, config *types.GitspaceConfig, infra *infraprovider.Infrastructure) error StopAndRemoveGitspace(ctx context.Context, config types.GitspaceConfig, infra *types.Infrastructure) error
// Status checks if the infra is reachable and ready to orchestrate containers. // Status checks if the infra is reachable and ready to orchestrate containers.
Status(ctx context.Context, infra *infraprovider.Infrastructure) error Status(ctx context.Context, infra *types.Infrastructure) error
} }

View File

@ -73,8 +73,8 @@ func NewEmbeddedDockerOrchestrator(
// It returns an error if the container is not running, exited or removed. // It returns an error if the container is not running, exited or removed.
func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace( func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
ctx context.Context, ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
infra *infraprovider.Infrastructure, infra *types.Infrastructure,
resolvedRepoDetails *scm.ResolvedDetails, resolvedRepoDetails *scm.ResolvedDetails,
defaultBaseImage string, defaultBaseImage string,
ideService ide.IDE, ideService ide.IDE,
@ -202,7 +202,7 @@ func (e *EmbeddedDockerOrchestrator) getWorkingDir(repoName string) string {
func (e *EmbeddedDockerOrchestrator) startGitspace( func (e *EmbeddedDockerOrchestrator) startGitspace(
ctx context.Context, ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
containerName string, containerName string,
dockerClient *client.Client, dockerClient *client.Client,
ideService ide.IDE, ideService ide.IDE,
@ -210,7 +210,7 @@ func (e *EmbeddedDockerOrchestrator) startGitspace(
volumeName string, volumeName string,
workingDirectory string, workingDirectory string,
resolvedRepoDetails *scm.ResolvedDetails, resolvedRepoDetails *scm.ResolvedDetails,
portMappings map[int]*infraprovider.PortMapping, portMappings map[int]*types.PortMapping,
defaultBaseImage string, defaultBaseImage string,
) error { ) error {
var imageName = resolvedRepoDetails.DevcontainerConfig.Image var imageName = resolvedRepoDetails.DevcontainerConfig.Image
@ -357,7 +357,7 @@ func (e *EmbeddedDockerOrchestrator) getContainerInfo(
ctx context.Context, ctx context.Context,
containerName string, containerName string,
dockerClient *client.Client, dockerClient *client.Client,
portMappings map[int]*infraprovider.PortMapping, portMappings map[int]*types.PortMapping,
) (string, map[int]string, error) { ) (string, map[int]string, error) {
inspectResp, err := dockerClient.ContainerInspect(ctx, containerName) inspectResp, err := dockerClient.ContainerInspect(ctx, containerName)
if err != nil { if err != nil {
@ -592,7 +592,7 @@ func (e *EmbeddedDockerOrchestrator) createContainer(
logStreamInstance *logutil.LogStreamInstance, logStreamInstance *logutil.LogStreamInstance,
volumeName string, volumeName string,
workingDirectory string, workingDirectory string,
portMappings map[int]*infraprovider.PortMapping, portMappings map[int]*types.PortMapping,
) error { ) error {
exposedPorts := nat.PortSet{} exposedPorts := nat.PortSet{}
portBindings := nat.PortMap{} portBindings := nat.PortMap{}
@ -707,8 +707,8 @@ func (e *EmbeddedDockerOrchestrator) pullImage(
// StopGitspace stops a container. If it is removed, it returns an error. // StopGitspace stops a container. If it is removed, it returns an error.
func (e EmbeddedDockerOrchestrator) StopGitspace( func (e EmbeddedDockerOrchestrator) StopGitspace(
ctx context.Context, ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
infra *infraprovider.Infrastructure, infra *types.Infrastructure,
) error { ) error {
containerName := getGitspaceContainerName(gitspaceConfig) containerName := getGitspaceContainerName(gitspaceConfig)
@ -797,12 +797,12 @@ func (e EmbeddedDockerOrchestrator) stopContainer(
return nil return nil
} }
func getGitspaceContainerName(config *types.GitspaceConfig) string { func getGitspaceContainerName(config types.GitspaceConfig) string {
return "gitspace-" + config.UserID + "-" + config.Identifier return "gitspace-" + config.UserID + "-" + config.Identifier
} }
// Status is NOOP for EmbeddedDockerOrchestrator as the docker host is verified by the infra provisioner. // Status is NOOP for EmbeddedDockerOrchestrator as the docker host is verified by the infra provisioner.
func (e *EmbeddedDockerOrchestrator) Status(_ context.Context, _ *infraprovider.Infrastructure) error { func (e *EmbeddedDockerOrchestrator) Status(_ context.Context, _ *types.Infrastructure) error {
return nil return nil
} }
@ -830,8 +830,8 @@ func (e *EmbeddedDockerOrchestrator) containerState(
// If the container is already removed, it returns. // If the container is already removed, it returns.
func (e *EmbeddedDockerOrchestrator) StopAndRemoveGitspace( func (e *EmbeddedDockerOrchestrator) StopAndRemoveGitspace(
ctx context.Context, ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
infra *infraprovider.Infrastructure, infra *types.Infrastructure,
) error { ) error {
containerName := getGitspaceContainerName(gitspaceConfig) containerName := getGitspaceContainerName(gitspaceConfig)

View File

@ -18,19 +18,39 @@ import (
"context" "context"
"github.com/harness/gitness/types" "github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
) )
type Orchestrator interface { type Orchestrator interface {
// StartGitspace is responsible for all the operations necessary to create the Gitspace container. It fetches the // TriggerStartGitspace fetches the infra resources configured for the gitspace and triggers the infra provisioning.
// devcontainer.json from the code repo, provisions infra using the infra provisioner and setting up the Gitspace TriggerStartGitspace(ctx context.Context, gitspaceConfig types.GitspaceConfig) (enum.GitspaceInstanceStateType, error)
// through the container orchestrator.
StartGitspace(ctx context.Context, gitspaceConfig *types.GitspaceConfig) error
// StopGitspace is responsible for stopping a running Gitspace. It stops the Gitspace container and unprovisions // ResumeStartGitspace saves the provisioned infra, resolves the code repo details & creates the Gitspace container.
ResumeStartGitspace(
ctx context.Context,
gitspaceConfig types.GitspaceConfig,
provisionedInfra *types.Infrastructure,
) (types.GitspaceInstance, error)
// TriggerStopGitspace stops the Gitspace container and triggers infra deprovisioning to deprovision
// all the infra resources which are not required to restart the Gitspace. // all the infra resources which are not required to restart the Gitspace.
StopGitspace(ctx context.Context, gitspaceConfig *types.GitspaceConfig) error TriggerStopGitspace(ctx context.Context, gitspaceConfig types.GitspaceConfig) (enum.GitspaceInstanceStateType, error)
// DeleteGitspace is responsible for deleting a Gitspace. It stops the Gitspace container and unprovisions // ResumeStopGitspace saves the deprovisioned infra details.
ResumeStopGitspace(
ctx context.Context,
gitspaceConfig types.GitspaceConfig,
stoppedInfra *types.Infrastructure,
) (enum.GitspaceInstanceStateType, error)
// TriggerDeleteGitspace removes the Gitspace container and triggers infra deprovisioning to deprovision
// all the infra resources. // all the infra resources.
DeleteGitspace(ctx context.Context, gitspaceConfig *types.GitspaceConfig) (*types.GitspaceInstance, error) TriggerDeleteGitspace(ctx context.Context, gitspaceConfig types.GitspaceConfig) (enum.GitspaceInstanceStateType, error)
// ResumeDeleteGitspace saves the deprovisioned infra details.
ResumeDeleteGitspace(
ctx context.Context,
gitspaceConfig types.GitspaceConfig,
deprovisionedInfra *types.Infrastructure,
) (enum.GitspaceInstanceStateType, error)
} }

View File

@ -28,7 +28,6 @@ import (
"github.com/harness/gitness/app/gitspace/orchestrator/ide" "github.com/harness/gitness/app/gitspace/orchestrator/ide"
"github.com/harness/gitness/app/gitspace/scm" "github.com/harness/gitness/app/gitspace/scm"
"github.com/harness/gitness/app/store" "github.com/harness/gitness/app/store"
"github.com/harness/gitness/infraprovider"
"github.com/harness/gitness/types" "github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum" "github.com/harness/gitness/types/enum"
@ -74,166 +73,80 @@ func NewOrchestrator(
} }
} }
func (o orchestrator) StartGitspace( func (o orchestrator) TriggerStartGitspace(
ctx context.Context, ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
) error { ) (enum.GitspaceInstanceStateType, error) {
gitspaceInstance := gitspaceConfig.GitspaceInstance instanceState := enum.GitspaceInstanceStateError
gitspaceInstance.State = enum.GitspaceInstanceStateError
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeFetchDevcontainerStart)
scmResolvedDetails, err := o.scm.GetSCMRepoDetails(ctx, gitspaceConfig)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeFetchDevcontainerFailed)
return fmt.Errorf("failed to fetch code repo details for gitspace config ID %w %d", err, gitspaceConfig.ID)
}
devcontainerConfig := scmResolvedDetails.DevcontainerConfig
repoName := scmResolvedDetails.RepoName
if devcontainerConfig == nil {
log.Warn().Err(err).Msg("devcontainer config is nil, using empty config")
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeFetchDevcontainerCompleted)
infraProviderResource, err := o.infraProviderResourceStore.Find(ctx, gitspaceConfig.InfraProviderResourceID) infraProviderResource, err := o.infraProviderResourceStore.Find(ctx, gitspaceConfig.InfraProviderResourceID)
if err != nil { if err != nil {
return fmt.Errorf("cannot get the infraprovider resource for ID %d: %w", return instanceState, fmt.Errorf("cannot get the infraprovider resource for ID %d: %w",
gitspaceConfig.InfraProviderResourceID, err) gitspaceConfig.InfraProviderResourceID, err)
} }
ideSvc, err := o.getIDEService(gitspaceConfig) ideSvc, err := o.getIDEService(gitspaceConfig)
if err != nil { if err != nil {
return err return instanceState, err
} }
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningStart) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningStart)
idePort := ideSvc.Port() idePort := ideSvc.Port()
infra, err := o.infraProvisioner.Provision(ctx, infraProviderResource, gitspaceConfig, []int{idePort}) err = o.infraProvisioner.TriggerProvision(ctx, infraProviderResource, gitspaceConfig, []int{idePort})
if err != nil { if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningFailed) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningFailed)
return fmt.Errorf( return instanceState, fmt.Errorf(
"cannot provision infrastructure for ID %d: %w", gitspaceConfig.InfraProviderResourceID, err) "cannot trigger provision infrastructure for ID %d: %w", gitspaceConfig.InfraProviderResourceID, err)
} }
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningCompleted) instanceState = enum.GitspaceInstanceStateStarting
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectStart) return instanceState, nil
err = o.containerOrchestrator.Status(ctx, infra)
gitspaceInstance.State = enum.GitspaceInstanceStateError
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectFailed)
return fmt.Errorf("couldn't call the agent health API: %w", err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectCompleted)
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationStart)
startResponse, err := o.containerOrchestrator.CreateAndStartGitspace(
ctx, gitspaceConfig, infra, scmResolvedDetails, o.config.DefaultBaseImage, ideSvc)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationFailed)
return fmt.Errorf("couldn't call the agent start API: %w", err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationCompleted)
var ideURL url.URL
var forwardedPort string
if infra.PortMappings[idePort].PublishedPort == 0 {
forwardedPort = startResponse.PublishedPorts[idePort]
} else {
forwardedPort = strconv.Itoa(infra.PortMappings[idePort].ForwardedPort)
}
if gitspaceConfig.IDE == enum.IDETypeVSCodeWeb {
ideURL = url.URL{
Scheme: "http",
Host: infra.Host + ":" + forwardedPort,
RawQuery: filepath.Join("folder=", repoName),
}
} else if gitspaceConfig.IDE == enum.IDETypeVSCode {
// TODO: the following userID is hard coded and should be changed.
userID := "harness"
ideURL = url.URL{
Scheme: "vscode-remote",
Host: "", // Empty since we include the host and port in the path
Path: fmt.Sprintf(
"ssh-remote+%s@%s:%s",
userID,
infra.Host,
filepath.Join(forwardedPort, repoName),
),
}
}
ideURLString := ideURL.String()
gitspaceInstance.URL = &ideURLString
gitspaceInstance.LastUsed = time.Now().UnixMilli()
gitspaceInstance.State = enum.GitspaceInstanceStateRunning
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStartCompleted)
return nil
} }
func (o orchestrator) StopGitspace( func (o orchestrator) TriggerStopGitspace(
ctx context.Context, ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
) error { ) (enum.GitspaceInstanceStateType, error) {
gitspaceInstance := gitspaceConfig.GitspaceInstance instanceState := enum.GitspaceInstanceStateError
gitspaceInstance.State = enum.GitspaceInstanceStateError
infraProviderResource, err := o.infraProviderResourceStore.Find(ctx, gitspaceConfig.InfraProviderResourceID) infraProviderResource, err := o.infraProviderResourceStore.Find(ctx, gitspaceConfig.InfraProviderResourceID)
if err != nil { if err != nil {
return fmt.Errorf( return instanceState, fmt.Errorf(
"cannot get the infraProviderResource with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err) "cannot get the infraProviderResource with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err)
} }
infra, err := o.infraProvisioner.Find(ctx, infraProviderResource, gitspaceConfig) infra, err := o.infraProvisioner.Find(ctx, infraProviderResource, gitspaceConfig)
if err != nil { if err != nil {
return fmt.Errorf("cannot find the provisioned infra: %w", err) return instanceState, fmt.Errorf("cannot find the provisioned infra: %w", err)
} }
err = o.stopGitspaceContainer(ctx, gitspaceConfig, infra) err = o.stopGitspaceContainer(ctx, gitspaceConfig, infra)
if err != nil { if err != nil {
return err return instanceState, err
} }
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraStopStart) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraStopStart)
_, err = o.infraProvisioner.Stop(ctx, infraProviderResource, gitspaceConfig) err = o.infraProvisioner.TriggerStop(ctx, infraProviderResource, gitspaceConfig)
if err != nil { if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraStopFailed) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraStopFailed)
return fmt.Errorf( return instanceState, fmt.Errorf(
"cannot stop provisioned infrastructure with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err) "cannot trigger stop infrastructure with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err)
} }
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraStopCompleted) instanceState = enum.GitspaceInstanceStateStopping
gitspaceInstance.State = enum.GitspaceInstanceStateDeleted return instanceState, nil
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStopCompleted)
return err
} }
func (o orchestrator) stopGitspaceContainer( func (o orchestrator) stopGitspaceContainer(
ctx context.Context, ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
infra *infraprovider.Infrastructure, infra *types.Infrastructure,
) error { ) error {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectStart) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectStart)
@ -261,8 +174,8 @@ func (o orchestrator) stopGitspaceContainer(
func (o orchestrator) stopAndRemoveGitspaceContainer( func (o orchestrator) stopAndRemoveGitspaceContainer(
ctx context.Context, ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
infra *infraprovider.Infrastructure, infra *types.Infrastructure,
) error { ) error {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectStart) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectStart)
@ -288,51 +201,45 @@ func (o orchestrator) stopAndRemoveGitspaceContainer(
return nil return nil
} }
func (o orchestrator) DeleteGitspace( func (o orchestrator) TriggerDeleteGitspace(
ctx context.Context, ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
) (*types.GitspaceInstance, error) { ) (enum.GitspaceInstanceStateType, error) {
gitspaceInstance := gitspaceConfig.GitspaceInstance instanceState := enum.GitspaceInstanceStateError
gitspaceInstance.State = enum.GitspaceInstanceStateError
infraProviderResource, err := o.infraProviderResourceStore.Find(ctx, gitspaceConfig.InfraProviderResourceID) infraProviderResource, err := o.infraProviderResourceStore.Find(ctx, gitspaceConfig.InfraProviderResourceID)
if err != nil { if err != nil {
return nil, fmt.Errorf( return instanceState, fmt.Errorf(
"cannot get the infraProviderResource with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err) "cannot get the infraProviderResource with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err)
} }
infra, err := o.infraProvisioner.Find(ctx, infraProviderResource, gitspaceConfig) infra, err := o.infraProvisioner.Find(ctx, infraProviderResource, gitspaceConfig)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot find the provisioned infra: %w", err) return instanceState, fmt.Errorf("cannot find the provisioned infra: %w", err)
} }
err = o.stopAndRemoveGitspaceContainer(ctx, gitspaceConfig, infra) err = o.stopAndRemoveGitspaceContainer(ctx, gitspaceConfig, infra)
if err != nil { if err != nil {
return nil, err return instanceState, err
} }
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningStart) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningStart)
_, err = o.infraProvisioner.Deprovision(ctx, infraProviderResource, gitspaceConfig) err = o.infraProvisioner.TriggerDeprovision(ctx, infraProviderResource, gitspaceConfig)
if err != nil { if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningFailed) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningFailed)
return nil, fmt.Errorf( return instanceState, fmt.Errorf(
"cannot deprovision infrastructure with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err) "cannot trigger deprovision infrastructure with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err)
} }
instanceState = enum.GitspaceInstanceStateStopping
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningCompleted) return instanceState, nil
gitspaceInstance.State = enum.GitspaceInstanceStateDeleted
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStopCompleted)
return gitspaceInstance, nil
} }
func (o orchestrator) emitGitspaceEvent( func (o orchestrator) emitGitspaceEvent(
ctx context.Context, ctx context.Context,
config *types.GitspaceConfig, config types.GitspaceConfig,
eventType enum.GitspaceEventType, eventType enum.GitspaceEventType,
) { ) {
o.eventReporter.EmitGitspaceEvent( o.eventReporter.EmitGitspaceEvent(
@ -347,7 +254,7 @@ func (o orchestrator) emitGitspaceEvent(
}) })
} }
func (o orchestrator) getIDEService(gitspaceConfig *types.GitspaceConfig) (ide.IDE, error) { func (o orchestrator) getIDEService(gitspaceConfig types.GitspaceConfig) (ide.IDE, error) {
var ideService ide.IDE var ideService ide.IDE
switch gitspaceConfig.IDE { switch gitspaceConfig.IDE {
@ -361,3 +268,180 @@ func (o orchestrator) getIDEService(gitspaceConfig *types.GitspaceConfig) (ide.I
return ideService, nil return ideService, nil
} }
func (o orchestrator) ResumeStartGitspace(
ctx context.Context,
gitspaceConfig types.GitspaceConfig,
provisionedInfra *types.Infrastructure,
) (types.GitspaceInstance, error) {
gitspaceInstance := *gitspaceConfig.GitspaceInstance
gitspaceInstance.State = enum.GitspaceInstanceStateError
infraProviderResource, err := o.infraProviderResourceStore.Find(ctx, gitspaceConfig.InfraProviderResourceID)
if err != nil {
return gitspaceInstance, fmt.Errorf("cannot get the infraprovider resource for ID %d: %w",
gitspaceConfig.InfraProviderResourceID, err)
}
ideSvc, err := o.getIDEService(gitspaceConfig)
if err != nil {
return gitspaceInstance, err
}
idePort := ideSvc.Port()
provisionedInfra, err = o.infraProvisioner.ResumeProvision(
ctx, infraProviderResource, gitspaceConfig, []int{idePort}, provisionedInfra)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningFailed)
return gitspaceInstance, fmt.Errorf(
"cannot provision infrastructure for ID %d: %w", gitspaceConfig.InfraProviderResourceID, err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningCompleted)
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeFetchDevcontainerStart)
scmResolvedDetails, err := o.scm.GetSCMRepoDetails(ctx, gitspaceConfig)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeFetchDevcontainerFailed)
return gitspaceInstance, fmt.Errorf(
"failed to fetch code repo details for gitspace config ID %w %d", err, gitspaceConfig.ID)
}
devcontainerConfig := scmResolvedDetails.DevcontainerConfig
repoName := scmResolvedDetails.RepoName
if devcontainerConfig == nil {
log.Warn().Err(err).Msg("devcontainer config is nil, using empty config")
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeFetchDevcontainerCompleted)
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectStart)
err = o.containerOrchestrator.Status(ctx, provisionedInfra)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectFailed)
return gitspaceInstance, fmt.Errorf("couldn't call the agent health API: %w", err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectCompleted)
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationStart)
startResponse, err := o.containerOrchestrator.CreateAndStartGitspace(
ctx, gitspaceConfig, provisionedInfra, scmResolvedDetails, o.config.DefaultBaseImage, ideSvc)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationFailed)
return gitspaceInstance, fmt.Errorf("couldn't call the agent start API: %w", err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationCompleted)
var ideURL url.URL
var forwardedPort string
if provisionedInfra.PortMappings[idePort].PublishedPort == 0 {
forwardedPort = startResponse.PublishedPorts[idePort]
} else {
forwardedPort = strconv.Itoa(provisionedInfra.PortMappings[idePort].ForwardedPort)
}
host := provisionedInfra.Host
if provisionedInfra.ProxyHost != "" {
host = provisionedInfra.ProxyHost
}
if gitspaceConfig.IDE == enum.IDETypeVSCodeWeb {
ideURL = url.URL{
Scheme: "http",
Host: host + ":" + forwardedPort,
RawQuery: filepath.Join("folder=", repoName),
}
} else if gitspaceConfig.IDE == enum.IDETypeVSCode {
// TODO: the following userID is hard coded and should be changed.
userID := "harness"
ideURL = url.URL{
Scheme: "vscode-remote",
Host: "", // Empty since we include the host and port in the path
Path: fmt.Sprintf(
"ssh-remote+%s@%s:%s",
userID,
host,
filepath.Join(forwardedPort, repoName),
),
}
}
ideURLString := ideURL.String()
gitspaceInstance.URL = &ideURLString
gitspaceInstance.LastUsed = time.Now().UnixMilli()
gitspaceInstance.State = enum.GitspaceInstanceStateRunning
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStartCompleted)
return gitspaceInstance, nil
}
func (o orchestrator) ResumeStopGitspace(
ctx context.Context,
gitspaceConfig types.GitspaceConfig,
stoppedInfra *types.Infrastructure,
) (enum.GitspaceInstanceStateType, error) {
instanceState := enum.GitspaceInstanceStateError
infraProviderResource, err := o.infraProviderResourceStore.Find(ctx, gitspaceConfig.InfraProviderResourceID)
if err != nil {
return instanceState, fmt.Errorf(
"cannot get the infraProviderResource with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err)
}
_, err = o.infraProvisioner.ResumeStop(ctx, infraProviderResource, gitspaceConfig, stoppedInfra)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraStopFailed)
return instanceState, fmt.Errorf(
"cannot stop provisioned infrastructure with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraStopCompleted)
instanceState = enum.GitspaceInstanceStateDeleted
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStopCompleted)
return instanceState, nil
}
func (o orchestrator) ResumeDeleteGitspace(
ctx context.Context,
gitspaceConfig types.GitspaceConfig,
deprovisionedInfra *types.Infrastructure,
) (enum.GitspaceInstanceStateType, error) {
instanceState := enum.GitspaceInstanceStateError
infraProviderResource, err := o.infraProviderResourceStore.Find(ctx, gitspaceConfig.InfraProviderResourceID)
if err != nil {
return instanceState, fmt.Errorf(
"cannot get the infraProviderResource with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err)
}
_, err = o.infraProvisioner.ResumeDeprovision(ctx, infraProviderResource, gitspaceConfig, deprovisionedInfra)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningFailed)
return instanceState, fmt.Errorf(
"cannot deprovision infrastructure with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningCompleted)
instanceState = enum.GitspaceInstanceStateDeleted
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStopCompleted)
return instanceState, nil
}

View File

@ -62,7 +62,7 @@ func NewGitnessSCM(repoStore store.RepoStore, git git.Interface,
func (s GitnessSCM) ResolveCredentials( func (s GitnessSCM) ResolveCredentials(
ctx context.Context, ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
) (*ResolvedCredentials, error) { ) (*ResolvedCredentials, error) {
repoURL, err := url.Parse(gitspaceConfig.CodeRepoURL) repoURL, err := url.Parse(gitspaceConfig.CodeRepoURL)
if err != nil { if err != nil {
@ -116,7 +116,7 @@ func (s GitnessSCM) ResolveCredentials(
} }
func (s GitnessSCM) GetFileContent(ctx context.Context, func (s GitnessSCM) GetFileContent(ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
filePath string, filePath string,
) ([]byte, error) { ) ([]byte, error) {
repo, err := s.repoStore.FindByRef(ctx, *gitspaceConfig.CodeRepoRef) repo, err := s.repoStore.FindByRef(ctx, *gitspaceConfig.CodeRepoRef)

View File

@ -39,7 +39,7 @@ func NewGenericSCM() *GenericSCM {
} }
func (s GenericSCM) GetFileContent(ctx context.Context, func (s GenericSCM) GetFileContent(ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
filePath string, filePath string,
) ([]byte, error) { ) ([]byte, error) {
gitWorkingDirectory := "/tmp/git/" gitWorkingDirectory := "/tmp/git/"
@ -102,7 +102,7 @@ func (s GenericSCM) GetFileContent(ctx context.Context,
func (s GenericSCM) ResolveCredentials( func (s GenericSCM) ResolveCredentials(
_ context.Context, _ context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
) (*ResolvedCredentials, error) { ) (*ResolvedCredentials, error) {
var resolvedCredentials = &ResolvedCredentials{ var resolvedCredentials = &ResolvedCredentials{
Branch: gitspaceConfig.Branch, Branch: gitspaceConfig.Branch,

View File

@ -41,7 +41,7 @@ type SCM interface {
// GetSCMRepoDetails fetches repository name, credentials & devcontainer config file from the given repo and branch. // GetSCMRepoDetails fetches repository name, credentials & devcontainer config file from the given repo and branch.
GetSCMRepoDetails( GetSCMRepoDetails(
ctx context.Context, ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
) (*ResolvedDetails, error) ) (*ResolvedDetails, error)
// CheckValidCodeRepo checks if the current URL is a valid and accessible code repo, // CheckValidCodeRepo checks if the current URL is a valid and accessible code repo,
@ -86,7 +86,7 @@ func (s scm) CheckValidCodeRepo(
func (s scm) GetSCMRepoDetails( func (s scm) GetSCMRepoDetails(
ctx context.Context, ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
) (*ResolvedDetails, error) { ) (*ResolvedDetails, error) {
filePath := devcontainerDefaultPath filePath := devcontainerDefaultPath
if gitspaceConfig.CodeRepoType == "" { if gitspaceConfig.CodeRepoType == "" {

View File

@ -23,10 +23,10 @@ import (
) )
type Provider interface { type Provider interface {
ResolveCredentials(ctx context.Context, gitspaceConfig *types.GitspaceConfig) (*ResolvedCredentials, error) ResolveCredentials(ctx context.Context, gitspaceConfig types.GitspaceConfig) (*ResolvedCredentials, error)
GetFileContent( GetFileContent(
ctx context.Context, ctx context.Context,
gitspaceConfig *types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
filePath string, filePath string,
) ([]byte, error) ) ([]byte, error)
} }

View File

@ -0,0 +1,68 @@
// 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 gitspace
import (
"context"
"fmt"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
const resourceNotFoundErr = "Failed to find gitspace: resource not found"
func (c *Service) Find(
ctx context.Context,
spaceID int64,
spacePath string,
identifier string,
) (*types.GitspaceConfig, error) {
var gitspaceConfigResult *types.GitspaceConfig
txErr := c.tx.WithTx(ctx, func(ctx context.Context) error {
gitspaceConfig, err := c.gitspaceConfigStore.FindByIdentifier(ctx, spaceID, identifier)
if err != nil {
return fmt.Errorf("failed to find gitspace config: %w", err)
}
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)
}
gitspaceConfig.SpacePath = spacePath
gitspaceConfig.InfraProviderResourceIdentifier = infraProviderResource.Identifier
instance, err := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, gitspaceConfig.ID, gitspaceConfig.SpaceID)
if err != nil && err.Error() != resourceNotFoundErr { // TODO fix this
return fmt.Errorf("failed to find gitspace instance for config ID : %s %w", gitspaceConfig.Identifier, err)
}
if instance != nil {
gitspaceConfig.GitspaceInstance = instance
instance.SpacePath = gitspaceConfig.SpacePath
gitspaceStateType, err := enum.GetGitspaceStateFromInstance(instance.State)
if err != nil {
return err
}
gitspaceConfig.State = gitspaceStateType
} else {
gitspaceConfig.State = enum.GitspaceStateUninitialized
}
gitspaceConfigResult = gitspaceConfig
return nil
}, dbtx.TxDefaultReadOnly)
if txErr != nil {
return nil, txErr
}
return gitspaceConfigResult, nil
}

View File

@ -18,6 +18,7 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/harness/gitness/app/services/infraprovider"
"github.com/harness/gitness/app/store" "github.com/harness/gitness/app/store"
"github.com/harness/gitness/store/database/dbtx" "github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types" "github.com/harness/gitness/types"
@ -29,12 +30,14 @@ func NewService(
gitspaceStore store.GitspaceConfigStore, gitspaceStore store.GitspaceConfigStore,
gitspaceInstanceStore store.GitspaceInstanceStore, gitspaceInstanceStore store.GitspaceInstanceStore,
spaceStore store.SpaceStore, spaceStore store.SpaceStore,
infraProviderSvc *infraprovider.Service,
) *Service { ) *Service {
return &Service{ return &Service{
tx: tx, tx: tx,
gitspaceConfigStore: gitspaceStore, gitspaceConfigStore: gitspaceStore,
gitspaceInstanceStore: gitspaceInstanceStore, gitspaceInstanceStore: gitspaceInstanceStore,
spaceStore: spaceStore, spaceStore: spaceStore,
infraProviderSvc: infraProviderSvc,
} }
} }
@ -43,6 +46,7 @@ type Service struct {
gitspaceInstanceStore store.GitspaceInstanceStore gitspaceInstanceStore store.GitspaceInstanceStore
spaceStore store.SpaceStore spaceStore store.SpaceStore
tx dbtx.Transactor tx dbtx.Transactor
infraProviderSvc *infraprovider.Service
} }
func (c *Service) ListGitspacesForSpace( func (c *Service) ListGitspacesForSpace(

View File

@ -0,0 +1,33 @@
// 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 gitspace
import (
"context"
"fmt"
"github.com/harness/gitness/types"
)
func (c *Service) UpdateConfig(
ctx context.Context,
gitspaceConfig *types.GitspaceConfig,
) error {
err := c.gitspaceConfigStore.Update(ctx, gitspaceConfig)
if err != nil {
return fmt.Errorf("failed to update gitspace config: %w", err)
}
return nil
}

View File

@ -0,0 +1,33 @@
// 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 gitspace
import (
"context"
"fmt"
"github.com/harness/gitness/types"
)
func (c *Service) UpdateInstance(
ctx context.Context,
gitspaceInstance *types.GitspaceInstance,
) error {
err := c.gitspaceInstanceStore.Update(ctx, gitspaceInstance)
if err != nil {
return fmt.Errorf("failed to update gitspace instance: %w", err)
}
return nil
}

View File

@ -15,6 +15,7 @@
package gitspace package gitspace
import ( import (
"github.com/harness/gitness/app/services/infraprovider"
"github.com/harness/gitness/app/store" "github.com/harness/gitness/app/store"
"github.com/harness/gitness/store/database/dbtx" "github.com/harness/gitness/store/database/dbtx"
@ -30,6 +31,7 @@ func ProvideGitspace(
gitspaceStore store.GitspaceConfigStore, gitspaceStore store.GitspaceConfigStore,
gitspaceInstanceStore store.GitspaceInstanceStore, gitspaceInstanceStore store.GitspaceInstanceStore,
spaceStore store.SpaceStore, spaceStore store.SpaceStore,
infraProviderSvc *infraprovider.Service,
) *Service { ) *Service {
return NewService(tx, gitspaceStore, gitspaceInstanceStore, spaceStore) return NewService(tx, gitspaceStore, gitspaceInstanceStore, spaceStore, infraProviderSvc)
} }

View File

@ -51,13 +51,13 @@ func (c *Config) Sanitize() error {
} }
type Service struct { type Service struct {
config Config config *Config
gitspaceEventStore store.GitspaceEventStore gitspaceEventStore store.GitspaceEventStore
} }
func NewService( func NewService(
ctx context.Context, ctx context.Context,
config Config, config *Config,
gitspaceEventReaderFactory *events.ReaderFactory[*gitspaceevents.Reader], gitspaceEventReaderFactory *events.ReaderFactory[*gitspaceevents.Reader],
gitspaceEventStore store.GitspaceEventStore, gitspaceEventStore store.GitspaceEventStore,
) (*Service, error) { ) (*Service, error) {

View File

@ -30,7 +30,7 @@ var WireSet = wire.NewSet(
) )
func ProvideService(ctx context.Context, func ProvideService(ctx context.Context,
config Config, config *Config,
gitspaceEventReaderFactory *events.ReaderFactory[*gitspaceevents.Reader], gitspaceEventReaderFactory *events.ReaderFactory[*gitspaceevents.Reader],
gitspaceEventStore store.GitspaceEventStore, gitspaceEventStore store.GitspaceEventStore,
) (*Service, error) { ) (*Service, error) {

View File

@ -0,0 +1,114 @@
// Copyright 2023 Harness, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package gitspaceinfraevent
import (
"context"
"fmt"
"time"
gitspaceEvents "github.com/harness/gitness/app/events/gitspace"
gitspaceInfraEvents "github.com/harness/gitness/app/events/gitspaceinfra"
"github.com/harness/gitness/events"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
func (s *Service) handleGitspaceInfraEvent(
ctx context.Context,
event *events.Event[*gitspaceInfraEvents.GitspaceInfraEventPayload],
) error {
payload := event.Payload
config, fetchErr := s.getConfig(ctx, payload.Infra.SpaceID, payload.Infra.SpacePath, payload.Infra.ResourceKey)
if fetchErr != nil {
return fetchErr
}
var instance = config.GitspaceInstance
var err error
switch payload.Type {
case enum.InfraEventProvision:
updatedInstance, err := s.orchestrator.ResumeStartGitspace(ctx, *config, payload.Infra)
if err != nil {
s.emitGitspaceConfigEvent(ctx, config, enum.GitspaceEventTypeGitspaceActionStartFailed)
return fmt.Errorf("failed to resume start gitspace: %w", err)
}
instance = &updatedInstance
case enum.InfraEventStop:
instanceState, err := s.orchestrator.ResumeStopGitspace(ctx, *config, payload.Infra)
if err != nil {
s.emitGitspaceConfigEvent(ctx, config, enum.GitspaceEventTypeGitspaceActionStopFailed)
return fmt.Errorf("failed to resume stop gitspace: %w", err)
}
instance.State = instanceState
case enum.InfraEventDeprovision:
instanceState, err := s.orchestrator.ResumeDeleteGitspace(ctx, *config, payload.Infra)
if err != nil {
return fmt.Errorf("failed to resume delete gitspace: %w", err)
}
instance.State = instanceState
config.IsDeleted = true
if err = s.gitspaceSvc.UpdateConfig(ctx, config); err != nil {
return fmt.Errorf("failed to delete gitspace config with ID: %s %w", config.Identifier, err)
}
default:
return fmt.Errorf("unknown event type: %s", event.Payload.Type)
}
err = s.gitspaceSvc.UpdateInstance(ctx, instance)
if err != nil {
return fmt.Errorf("failed to update gitspace instance: %w", err)
}
return nil
}
func (s *Service) getConfig(
ctx context.Context,
spaceID int64,
spacePath string,
identifier string,
) (*types.GitspaceConfig, error) {
config, err := s.gitspaceSvc.Find(ctx, spaceID, spacePath, identifier)
if err != nil {
return nil, fmt.Errorf(
"failed to find gitspace config during infra event handling, identifier %s: %w", identifier, err)
}
return config, nil
}
func (s *Service) emitGitspaceConfigEvent(ctx context.Context,
config *types.GitspaceConfig,
eventType enum.GitspaceEventType,
) {
s.eventReporter.EmitGitspaceEvent(ctx, gitspaceEvents.GitspaceEvent, &gitspaceEvents.GitspaceEventPayload{
QueryKey: config.Identifier,
EntityID: config.ID,
EntityType: enum.GitspaceEntityTypeGitspaceConfig,
EventType: eventType,
Timestamp: time.Now().UnixNano(),
})
}

View File

@ -0,0 +1,77 @@
// 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 gitspaceinfraevent
import (
"context"
"fmt"
"time"
gitspaceevents "github.com/harness/gitness/app/events/gitspace"
gitspaceinfraevents "github.com/harness/gitness/app/events/gitspaceinfra"
"github.com/harness/gitness/app/gitspace/orchestrator"
"github.com/harness/gitness/app/services/gitspace"
"github.com/harness/gitness/app/services/gitspaceevent"
"github.com/harness/gitness/events"
"github.com/harness/gitness/stream"
)
const groupGitspaceInfraEvents = "gitness:gitspaceinfra"
type Service struct {
config *gitspaceevent.Config
orchestrator orchestrator.Orchestrator
gitspaceSvc *gitspace.Service
eventReporter *gitspaceevents.Reporter
}
func NewService(
ctx context.Context,
config *gitspaceevent.Config,
gitspaceInfraEventReaderFactory *events.ReaderFactory[*gitspaceinfraevents.Reader],
orchestrator orchestrator.Orchestrator,
gitspaceSvc *gitspace.Service,
eventReporter *gitspaceevents.Reporter,
) (*Service, error) {
if err := config.Sanitize(); err != nil {
return nil, fmt.Errorf("provided gitspace infra event service config is invalid: %w", err)
}
service := &Service{
config: config,
orchestrator: orchestrator,
gitspaceSvc: gitspaceSvc,
eventReporter: eventReporter,
}
_, err := gitspaceInfraEventReaderFactory.Launch(ctx, groupGitspaceInfraEvents, config.EventReaderName,
func(r *gitspaceinfraevents.Reader) error {
const idleTimeout = 1 * time.Minute
r.Configure(
stream.WithConcurrency(config.Concurrency),
stream.WithHandlerOptions(
stream.WithIdleTimeout(idleTimeout),
stream.WithMaxRetries(config.MaxRetries),
))
_ = r.RegisterGitspaceInfraEvent(service.handleGitspaceInfraEvent)
return nil
})
if err != nil {
return nil, fmt.Errorf("failed to launch gitspace infra event reader: %w", err)
}
return service, 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 gitspaceinfraevent
import (
"context"
gitspaceevents "github.com/harness/gitness/app/events/gitspace"
gitspaceinfraevents "github.com/harness/gitness/app/events/gitspaceinfra"
"github.com/harness/gitness/app/gitspace/orchestrator"
"github.com/harness/gitness/app/services/gitspace"
"github.com/harness/gitness/app/services/gitspaceevent"
"github.com/harness/gitness/events"
"github.com/google/wire"
)
// WireSet provides a wire set for this package.
var WireSet = wire.NewSet(
ProvideService,
)
func ProvideService(
ctx context.Context,
config *gitspaceevent.Config,
gitspaceInfraEventReaderFactory *events.ReaderFactory[*gitspaceinfraevents.Reader],
orchestrator orchestrator.Orchestrator,
gitspaceSvc *gitspace.Service,
eventReporter *gitspaceevents.Reporter,
) (*Service, error) {
return NewService(
ctx,
config,
gitspaceInfraEventReaderFactory,
orchestrator,
gitspaceSvc,
eventReporter,
)
}

View File

@ -93,7 +93,7 @@ func (c *Service) CreateInfraProvider(
if len(infraProvider.TemplateParams()) > 0 { if len(infraProvider.TemplateParams()) > 0 {
return fmt.Errorf("failed to fetch templates") // TODO Implement return fmt.Errorf("failed to fetch templates") // TODO Implement
} }
parameters := []infraprovider.Parameter{} parameters := []types.InfraProviderParameter{}
// TODO logic to populate paramteters as per the provider type // TODO logic to populate paramteters as per the provider type
err = infraProvider.ValidateParams(parameters) err = infraProvider.ValidateParams(parameters)
if err != nil { if err != nil {

View File

@ -18,6 +18,7 @@ import (
"github.com/harness/gitness/app/services/cleanup" "github.com/harness/gitness/app/services/cleanup"
"github.com/harness/gitness/app/services/gitspace" "github.com/harness/gitness/app/services/gitspace"
"github.com/harness/gitness/app/services/gitspaceevent" "github.com/harness/gitness/app/services/gitspaceevent"
"github.com/harness/gitness/app/services/gitspaceinfraevent"
"github.com/harness/gitness/app/services/infraprovider" "github.com/harness/gitness/app/services/infraprovider"
"github.com/harness/gitness/app/services/keywordsearch" "github.com/harness/gitness/app/services/keywordsearch"
"github.com/harness/gitness/app/services/metric" "github.com/harness/gitness/app/services/metric"
@ -49,6 +50,7 @@ type Services struct {
GitspaceEvent *gitspaceevent.Service GitspaceEvent *gitspaceevent.Service
infraProvider *infraprovider.Service infraProvider *infraprovider.Service
gitspace *gitspace.Service gitspace *gitspace.Service
gitspaceInfraEventSvc *gitspaceinfraevent.Service
} }
func ProvideServices( func ProvideServices(
@ -65,6 +67,7 @@ func ProvideServices(
gitspaceEventSvc *gitspaceevent.Service, gitspaceEventSvc *gitspaceevent.Service,
infraProviderSvc *infraprovider.Service, infraProviderSvc *infraprovider.Service,
gitspaceSvc *gitspace.Service, gitspaceSvc *gitspace.Service,
gitspaceInfraEventSvc *gitspaceinfraevent.Service,
) Services { ) Services {
return Services{ return Services{
Webhook: webhooksSvc, Webhook: webhooksSvc,
@ -80,5 +83,6 @@ func ProvideServices(
GitspaceEvent: gitspaceEventSvc, GitspaceEvent: gitspaceEventSvc,
infraProvider: infraProviderSvc, infraProvider: infraProviderSvc,
gitspace: gitspaceSvc, gitspace: gitspaceSvc,
gitspaceInfraEventSvc: gitspaceInfraEventSvc,
} }
} }

View File

@ -18,10 +18,10 @@ import (
"context" "context"
"github.com/harness/gitness/app/store" "github.com/harness/gitness/app/store"
"github.com/harness/gitness/infraprovider/enum"
"github.com/harness/gitness/store/database" "github.com/harness/gitness/store/database"
"github.com/harness/gitness/store/database/dbtx" "github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types" "github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/pkg/errors" "github.com/pkg/errors"

View File

@ -19,10 +19,10 @@ import (
"encoding/json" "encoding/json"
"github.com/harness/gitness/app/store" "github.com/harness/gitness/app/store"
"github.com/harness/gitness/infraprovider/enum"
"github.com/harness/gitness/store/database" "github.com/harness/gitness/store/database"
"github.com/harness/gitness/store/database/dbtx" "github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types" "github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/guregu/null" "github.com/guregu/null"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"

View File

@ -413,8 +413,8 @@ func ProvideGitspaceOrchestratorConfig(config *types.Config) *orchestrator.Confi
} }
// ProvideGitspaceEventConfig loads the gitspace event service config from the main config. // ProvideGitspaceEventConfig loads the gitspace event service config from the main config.
func ProvideGitspaceEventConfig(config *types.Config) gitspaceevent.Config { func ProvideGitspaceEventConfig(config *types.Config) *gitspaceevent.Config {
return gitspaceevent.Config{ return &gitspaceevent.Config{
EventReaderName: config.InstanceID, EventReaderName: config.InstanceID,
Concurrency: config.Gitspace.Events.Concurrency, Concurrency: config.Gitspace.Events.Concurrency,
MaxRetries: config.Gitspace.Events.MaxRetries, MaxRetries: config.Gitspace.Events.MaxRetries,

View File

@ -42,6 +42,7 @@ import (
"github.com/harness/gitness/app/bootstrap" "github.com/harness/gitness/app/bootstrap"
gitevents "github.com/harness/gitness/app/events/git" gitevents "github.com/harness/gitness/app/events/git"
gitspaceevents "github.com/harness/gitness/app/events/gitspace" gitspaceevents "github.com/harness/gitness/app/events/gitspace"
gitspaceinfraevents "github.com/harness/gitness/app/events/gitspaceinfra"
pullreqevents "github.com/harness/gitness/app/events/pullreq" pullreqevents "github.com/harness/gitness/app/events/pullreq"
repoevents "github.com/harness/gitness/app/events/repo" repoevents "github.com/harness/gitness/app/events/repo"
infrastructure "github.com/harness/gitness/app/gitspace/infrastructure" infrastructure "github.com/harness/gitness/app/gitspace/infrastructure"
@ -68,6 +69,7 @@ import (
"github.com/harness/gitness/app/services/exporter" "github.com/harness/gitness/app/services/exporter"
gitspaceSvc "github.com/harness/gitness/app/services/gitspace" gitspaceSvc "github.com/harness/gitness/app/services/gitspace"
"github.com/harness/gitness/app/services/gitspaceevent" "github.com/harness/gitness/app/services/gitspaceevent"
gitspaceInfraEventSvc "github.com/harness/gitness/app/services/gitspaceinfraevent"
"github.com/harness/gitness/app/services/importer" "github.com/harness/gitness/app/services/importer"
infraproviderSvc "github.com/harness/gitness/app/services/infraprovider" infraproviderSvc "github.com/harness/gitness/app/services/infraprovider"
"github.com/harness/gitness/app/services/keywordsearch" "github.com/harness/gitness/app/services/keywordsearch"
@ -153,6 +155,7 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
gitspaceCtrl.WireSet, gitspaceCtrl.WireSet,
infraproviderSvc.WireSet, infraproviderSvc.WireSet,
gitspaceSvc.WireSet, gitspaceSvc.WireSet,
gitspaceInfraEventSvc.WireSet,
gitevents.WireSet, gitevents.WireSet,
pullreqevents.WireSet, pullreqevents.WireSet,
repoevents.WireSet, repoevents.WireSet,
@ -231,6 +234,7 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
logutil.WireSet, logutil.WireSet,
cliserver.ProvideGitspaceOrchestratorConfig, cliserver.ProvideGitspaceOrchestratorConfig,
ide.WireSet, ide.WireSet,
gitspaceinfraevents.WireSet,
) )
return &cliserver.System{}, nil return &cliserver.System{}, nil
} }

View File

@ -39,9 +39,10 @@ import (
"github.com/harness/gitness/app/auth/authn" "github.com/harness/gitness/app/auth/authn"
"github.com/harness/gitness/app/auth/authz" "github.com/harness/gitness/app/auth/authz"
"github.com/harness/gitness/app/bootstrap" "github.com/harness/gitness/app/bootstrap"
events4 "github.com/harness/gitness/app/events/git" events5 "github.com/harness/gitness/app/events/git"
events5 "github.com/harness/gitness/app/events/gitspace" events6 "github.com/harness/gitness/app/events/gitspace"
events3 "github.com/harness/gitness/app/events/pullreq" events3 "github.com/harness/gitness/app/events/gitspaceinfra"
events4 "github.com/harness/gitness/app/events/pullreq"
events2 "github.com/harness/gitness/app/events/repo" events2 "github.com/harness/gitness/app/events/repo"
"github.com/harness/gitness/app/gitspace/infrastructure" "github.com/harness/gitness/app/gitspace/infrastructure"
"github.com/harness/gitness/app/gitspace/logutil" "github.com/harness/gitness/app/gitspace/logutil"
@ -67,6 +68,7 @@ import (
"github.com/harness/gitness/app/services/exporter" "github.com/harness/gitness/app/services/exporter"
"github.com/harness/gitness/app/services/gitspace" "github.com/harness/gitness/app/services/gitspace"
"github.com/harness/gitness/app/services/gitspaceevent" "github.com/harness/gitness/app/services/gitspaceevent"
"github.com/harness/gitness/app/services/gitspaceinfraevent"
"github.com/harness/gitness/app/services/importer" "github.com/harness/gitness/app/services/importer"
infraprovider2 "github.com/harness/gitness/app/services/infraprovider" infraprovider2 "github.com/harness/gitness/app/services/infraprovider"
"github.com/harness/gitness/app/services/keywordsearch" "github.com/harness/gitness/app/services/keywordsearch"
@ -252,7 +254,21 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
} }
gitspaceConfigStore := database.ProvideGitspaceConfigStore(db) gitspaceConfigStore := database.ProvideGitspaceConfigStore(db)
gitspaceInstanceStore := database.ProvideGitspaceInstanceStore(db) gitspaceInstanceStore := database.ProvideGitspaceInstanceStore(db)
gitspaceService := gitspace.ProvideGitspace(transactor, gitspaceConfigStore, gitspaceInstanceStore, spaceStore) infraProviderResourceStore := database.ProvideInfraProviderResourceStore(db)
infraProviderConfigStore := database.ProvideInfraProviderConfigStore(db)
dockerConfig, err := server.ProvideDockerConfig(config)
if err != nil {
return nil, err
}
dockerClientFactory := infraprovider.ProvideDockerClientFactory(dockerConfig)
eventsReporter, err := events3.ProvideReporter(eventsSystem)
if err != nil {
return nil, err
}
dockerProvider := infraprovider.ProvideDockerProvider(dockerConfig, dockerClientFactory, eventsReporter)
factory := infraprovider.ProvideFactory(dockerProvider)
infraproviderService := infraprovider2.ProvideInfraProvider(transactor, infraProviderResourceStore, infraProviderConfigStore, factory, spaceStore)
gitspaceService := gitspace.ProvideGitspace(transactor, gitspaceConfigStore, gitspaceInstanceStore, spaceStore, infraproviderService)
spaceController := space.ProvideController(config, transactor, provider, streamer, spaceIdentifier, authorizer, spacePathStore, pipelineStore, secretStore, connectorStore, templateStore, spaceStore, repoStore, principalStore, repoController, membershipStore, repository, exporterRepository, resourceLimiter, publicaccessService, auditService, gitspaceService, gitspaceConfigStore, gitspaceInstanceStore, labelService) spaceController := space.ProvideController(config, transactor, provider, streamer, spaceIdentifier, authorizer, spacePathStore, pipelineStore, secretStore, connectorStore, templateStore, spaceStore, repoStore, principalStore, repoController, membershipStore, repository, exporterRepository, resourceLimiter, publicaccessService, auditService, gitspaceService, gitspaceConfigStore, gitspaceInstanceStore, labelService)
pipelineController := pipeline.ProvideController(repoStore, triggerStore, authorizer, pipelineStore) pipelineController := pipeline.ProvideController(repoStore, triggerStore, authorizer, pipelineStore)
secretController := secret.ProvideController(encrypter, secretStore, authorizer, spaceStore) secretController := secret.ProvideController(encrypter, secretStore, authorizer, spaceStore)
@ -266,27 +282,27 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
pullReqReviewStore := database.ProvidePullReqReviewStore(db) pullReqReviewStore := database.ProvidePullReqReviewStore(db)
pullReqReviewerStore := database.ProvidePullReqReviewerStore(db, principalInfoCache) pullReqReviewerStore := database.ProvidePullReqReviewerStore(db, principalInfoCache)
pullReqFileViewStore := database.ProvidePullReqFileViewStore(db) pullReqFileViewStore := database.ProvidePullReqFileViewStore(db)
eventsReporter, err := events3.ProvideReporter(eventsSystem) reporter2, err := events4.ProvideReporter(eventsSystem)
if err != nil { if err != nil {
return nil, err return nil, err
} }
migrator := codecomments.ProvideMigrator(gitInterface) migrator := codecomments.ProvideMigrator(gitInterface)
readerFactory, err := events4.ProvideReaderFactory(eventsSystem) readerFactory, err := events5.ProvideReaderFactory(eventsSystem)
if err != nil { if err != nil {
return nil, err return nil, err
} }
eventsReaderFactory, err := events3.ProvideReaderFactory(eventsSystem) eventsReaderFactory, err := events4.ProvideReaderFactory(eventsSystem)
if err != nil { if err != nil {
return nil, err return nil, err
} }
repoGitInfoView := database.ProvideRepoGitInfoView(db) repoGitInfoView := database.ProvideRepoGitInfoView(db)
repoGitInfoCache := cache.ProvideRepoGitInfoCache(repoGitInfoView) repoGitInfoCache := cache.ProvideRepoGitInfoCache(repoGitInfoView)
pullreqService, err := pullreq.ProvideService(ctx, config, readerFactory, eventsReaderFactory, eventsReporter, gitInterface, repoGitInfoCache, repoStore, pullReqStore, pullReqActivityStore, codeCommentView, migrator, pullReqFileViewStore, pubSub, provider, streamer) pullreqService, err := pullreq.ProvideService(ctx, config, readerFactory, eventsReaderFactory, reporter2, gitInterface, repoGitInfoCache, repoStore, pullReqStore, pullReqActivityStore, codeCommentView, migrator, pullReqFileViewStore, pubSub, provider, streamer)
if err != nil { if err != nil {
return nil, err return nil, err
} }
pullReq := importer.ProvidePullReqImporter(provider, gitInterface, principalStore, repoStore, pullReqStore, pullReqActivityStore, transactor) pullReq := importer.ProvidePullReqImporter(provider, gitInterface, principalStore, repoStore, pullReqStore, pullReqActivityStore, transactor)
pullreqController := pullreq2.ProvideController(transactor, provider, authorizer, pullReqStore, pullReqActivityStore, codeCommentView, pullReqReviewStore, pullReqReviewerStore, repoStore, principalStore, principalInfoCache, pullReqFileViewStore, membershipStore, checkStore, gitInterface, eventsReporter, migrator, pullreqService, protectionManager, streamer, codeownersService, lockerLocker, pullReq, labelService) pullreqController := pullreq2.ProvideController(transactor, provider, authorizer, pullReqStore, pullReqActivityStore, codeCommentView, pullReqReviewStore, pullReqReviewerStore, repoStore, principalStore, principalInfoCache, pullReqFileViewStore, membershipStore, checkStore, gitInterface, reporter2, migrator, pullreqService, protectionManager, streamer, codeownersService, lockerLocker, pullReq, labelService)
webhookConfig := server.ProvideWebhookConfig(config) webhookConfig := server.ProvideWebhookConfig(config)
webhookStore := database.ProvideWebhookStore(db) webhookStore := database.ProvideWebhookStore(db)
webhookExecutionStore := database.ProvideWebhookExecutionStore(db) webhookExecutionStore := database.ProvideWebhookExecutionStore(db)
@ -295,7 +311,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
return nil, err return nil, err
} }
webhookController := webhook2.ProvideController(webhookConfig, authorizer, webhookStore, webhookExecutionStore, repoStore, webhookService, encrypter) webhookController := webhook2.ProvideController(webhookConfig, authorizer, webhookStore, webhookExecutionStore, repoStore, webhookService, encrypter)
reporter2, err := events4.ProvideReporter(eventsSystem) reporter3, err := events5.ProvideReporter(eventsSystem)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -311,7 +327,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
if err != nil { if err != nil {
return nil, err return nil, err
} }
githookController := githook.ProvideController(authorizer, principalStore, repoStore, reporter2, reporter, gitInterface, pullReqStore, provider, protectionManager, clientFactory, resourceLimiter, settingsService, preReceiveExtender, updateExtender, postReceiveExtender) githookController := githook.ProvideController(authorizer, principalStore, repoStore, reporter3, reporter, gitInterface, pullReqStore, provider, protectionManager, clientFactory, resourceLimiter, settingsService, preReceiveExtender, updateExtender, postReceiveExtender)
serviceaccountController := serviceaccount.NewController(principalUID, authorizer, principalStore, spaceStore, repoStore, tokenStore) serviceaccountController := serviceaccount.NewController(principalUID, authorizer, principalStore, spaceStore, repoStore, tokenStore)
principalController := principal.ProvideController(principalStore, authorizer) principalController := principal.ProvideController(principalStore, authorizer)
v := check2.ProvideCheckSanitizers() v := check2.ProvideCheckSanitizers()
@ -328,18 +344,8 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
uploadController := upload.ProvideController(authorizer, repoStore, blobStore) uploadController := upload.ProvideController(authorizer, repoStore, blobStore)
searcher := keywordsearch.ProvideSearcher(localIndexSearcher) searcher := keywordsearch.ProvideSearcher(localIndexSearcher)
keywordsearchController := keywordsearch2.ProvideController(authorizer, searcher, repoController, spaceController) keywordsearchController := keywordsearch2.ProvideController(authorizer, searcher, repoController, spaceController)
infraProviderResourceStore := database.ProvideInfraProviderResourceStore(db)
infraProviderConfigStore := database.ProvideInfraProviderConfigStore(db)
dockerConfig, err := server.ProvideDockerConfig(config)
if err != nil {
return nil, err
}
dockerClientFactory := infraprovider.ProvideDockerClientFactory(dockerConfig)
dockerProvider := infraprovider.ProvideDockerProvider(dockerConfig, dockerClientFactory)
factory := infraprovider.ProvideFactory(dockerProvider)
infraproviderService := infraprovider2.ProvideInfraProvider(transactor, infraProviderResourceStore, infraProviderConfigStore, factory, spaceStore)
infraproviderController := infraprovider3.ProvideController(authorizer, spaceStore, infraproviderService) infraproviderController := infraprovider3.ProvideController(authorizer, spaceStore, infraproviderService)
reporter3, err := events5.ProvideReporter(eventsSystem) reporter4, err := events6.ProvideReporter(eventsSystem)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -354,9 +360,9 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
vsCode := ide.ProvideVSCodeService() vsCode := ide.ProvideVSCodeService()
vsCodeWebConfig := server.ProvideIDEVSCodeWebConfig(config) vsCodeWebConfig := server.ProvideIDEVSCodeWebConfig(config)
vsCodeWeb := ide.ProvideVSCodeWebService(vsCodeWebConfig) vsCodeWeb := ide.ProvideVSCodeWebService(vsCodeWebConfig)
orchestratorOrchestrator := orchestrator.ProvideOrchestrator(scmSCM, infraProviderResourceStore, infraProvisioner, containerOrchestrator, reporter3, orchestratorConfig, vsCode, vsCodeWeb) orchestratorOrchestrator := orchestrator.ProvideOrchestrator(scmSCM, infraProviderResourceStore, infraProvisioner, containerOrchestrator, reporter4, orchestratorConfig, vsCode, vsCodeWeb)
gitspaceEventStore := database.ProvideGitspaceEventStore(db) gitspaceEventStore := database.ProvideGitspaceEventStore(db)
gitspaceController := gitspace2.ProvideController(transactor, authorizer, infraproviderService, gitspaceConfigStore, gitspaceInstanceStore, spaceStore, reporter3, orchestratorOrchestrator, gitspaceEventStore, statefulLogger, scmSCM, repoStore) gitspaceController := gitspace2.ProvideController(transactor, authorizer, infraproviderService, gitspaceConfigStore, gitspaceInstanceStore, spaceStore, reporter4, orchestratorOrchestrator, gitspaceEventStore, statefulLogger, scmSCM, repoStore, gitspaceService)
migrateController := migrate.ProvideController(authorizer, principalStore) migrateController := migrate.ProvideController(authorizer, principalStore)
openapiService := openapi.ProvideOpenAPIService() openapiService := openapi.ProvideOpenAPIService()
routerRouter := router.ProvideRouter(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, provider, openapiService) routerRouter := router.ProvideRouter(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, provider, openapiService)
@ -410,7 +416,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
return nil, err return nil, err
} }
gitspaceeventConfig := server.ProvideGitspaceEventConfig(config) gitspaceeventConfig := server.ProvideGitspaceEventConfig(config)
readerFactory3, err := events5.ProvideReaderFactory(eventsSystem) readerFactory3, err := events6.ProvideReaderFactory(eventsSystem)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -418,7 +424,15 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
if err != nil { if err != nil {
return nil, err return nil, err
} }
servicesServices := services.ProvideServices(webhookService, pullreqService, triggerService, jobScheduler, collector, sizeCalculator, repoService, cleanupService, notificationService, keywordsearchService, gitspaceeventService, infraproviderService, gitspaceService) readerFactory4, err := events3.ProvideReaderFactory(eventsSystem)
if err != nil {
return nil, err
}
gitspaceinfraeventService, err := gitspaceinfraevent.ProvideService(ctx, gitspaceeventConfig, readerFactory4, orchestratorOrchestrator, gitspaceService, reporter4)
if err != nil {
return nil, err
}
servicesServices := services.ProvideServices(webhookService, pullreqService, triggerService, jobScheduler, collector, sizeCalculator, repoService, cleanupService, notificationService, keywordsearchService, gitspaceeventService, infraproviderService, gitspaceService, gitspaceinfraeventService)
serverSystem := server.NewSystem(bootstrapBootstrap, serverServer, sshServer, poller, resolverManager, servicesServices) serverSystem := server.NewSystem(bootstrapBootstrap, serverServer, sshServer, poller, resolverManager, servicesServices)
return serverSystem, nil return serverSystem, nil
} }

View File

@ -20,7 +20,8 @@ import (
"net/http" "net/http"
"path/filepath" "path/filepath"
"github.com/harness/gitness/infraprovider/enum" "github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/docker/docker/client" "github.com/docker/docker/client"
"github.com/docker/go-connections/tlsconfig" "github.com/docker/go-connections/tlsconfig"
@ -37,7 +38,7 @@ func NewDockerClientFactory(config *DockerConfig) *DockerClientFactory {
// NewDockerClient returns a new docker client created using the docker config and infra. // NewDockerClient returns a new docker client created using the docker config and infra.
func (d *DockerClientFactory) NewDockerClient( func (d *DockerClientFactory) NewDockerClient(
_ context.Context, _ context.Context,
infra *Infrastructure, infra *types.Infrastructure,
) (*client.Client, error) { ) (*client.Client, error) {
if infra.ProviderType != enum.InfraProviderTypeDocker { if infra.ProviderType != enum.InfraProviderTypeDocker {
return nil, fmt.Errorf("infra provider type %s not supported", infra.ProviderType) return nil, fmt.Errorf("infra provider type %s not supported", infra.ProviderType)
@ -49,7 +50,7 @@ func (d *DockerClientFactory) NewDockerClient(
return dockerClient, nil return dockerClient, nil
} }
func (d *DockerClientFactory) getClient(_ []Parameter) (*client.Client, error) { func (d *DockerClientFactory) getClient(_ []types.InfraProviderParameter) (*client.Client, error) {
var opts []client.Opt var opts []client.Opt
opts = append(opts, client.WithHost(d.config.DockerHost)) opts = append(opts, client.WithHost(d.config.DockerHost))

View File

@ -19,7 +19,9 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/harness/gitness/infraprovider/enum" events "github.com/harness/gitness/app/events/gitspaceinfra"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/docker/docker/api/types/volume" "github.com/docker/docker/api/types/volume"
"github.com/docker/docker/client" "github.com/docker/docker/client"
@ -31,15 +33,18 @@ var _ InfraProvider = (*DockerProvider)(nil)
type DockerProvider struct { type DockerProvider struct {
config *DockerConfig config *DockerConfig
dockerClientFactory *DockerClientFactory dockerClientFactory *DockerClientFactory
eventReporter *events.Reporter
} }
func NewDockerProvider( func NewDockerProvider(
config *DockerConfig, config *DockerConfig,
dockerClientFactory *DockerClientFactory, dockerClientFactory *DockerClientFactory,
eventReporter *events.Reporter,
) *DockerProvider { ) *DockerProvider {
return &DockerProvider{ return &DockerProvider{
config: config, config: config,
dockerClientFactory: dockerClientFactory, dockerClientFactory: dockerClientFactory,
eventReporter: eventReporter,
} }
} }
@ -47,17 +52,18 @@ func NewDockerProvider(
// It does not start docker engine. It creates a directory in the host machine using the given resource key. // It does not start docker engine. It creates a directory in the host machine using the given resource key.
func (d DockerProvider) Provision( func (d DockerProvider) Provision(
ctx context.Context, ctx context.Context,
spaceID int64,
spacePath string, spacePath string,
resourceKey string, resourceKey string,
requiredPorts []int, requiredPorts []int,
params []Parameter, params []types.InfraProviderParameter,
) (*Infrastructure, error) { ) error {
dockerClient, err := d.dockerClientFactory.NewDockerClient(ctx, &Infrastructure{ dockerClient, err := d.dockerClientFactory.NewDockerClient(ctx, &types.Infrastructure{
ProviderType: enum.InfraProviderTypeDocker, ProviderType: enum.InfraProviderTypeDocker,
Parameters: params, Parameters: params,
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("error getting docker client from docker client factory: %w", err) return fmt.Errorf("error getting docker client from docker client factory: %w", err)
} }
defer func() { defer func() {
@ -69,20 +75,24 @@ func (d DockerProvider) Provision(
infrastructure, err := d.dockerHostInfo(ctx, dockerClient) infrastructure, err := d.dockerHostInfo(ctx, dockerClient)
if err != nil { if err != nil {
return nil, err return err
} }
infrastructure.SpaceID = spaceID
infrastructure.SpacePath = spacePath
infrastructure.ResourceKey = resourceKey
storageName, err := d.createNamedVolume(ctx, spacePath, resourceKey, dockerClient) storageName, err := d.createNamedVolume(ctx, spacePath, resourceKey, dockerClient)
if err != nil { if err != nil {
return nil, err return err
} }
infrastructure.Storage = storageName infrastructure.Storage = storageName
var portMappings = make(map[int]*PortMapping, len(requiredPorts)) var portMappings = make(map[int]*types.PortMapping, len(requiredPorts))
for _, requiredPort := range requiredPorts { for _, requiredPort := range requiredPorts {
portMapping := &PortMapping{ portMapping := &types.PortMapping{
PublishedPort: 0, PublishedPort: 0,
ForwardedPort: 0, ForwardedPort: 0,
} }
@ -92,55 +102,81 @@ func (d DockerProvider) Provision(
infrastructure.PortMappings = portMappings infrastructure.PortMappings = portMappings
return infrastructure, nil event := &events.GitspaceInfraEventPayload{
Infra: infrastructure,
Type: enum.InfraEventProvision,
}
d.eventReporter.EmitGitspaceInfraEvent(ctx, events.GitspaceInfraEvent, event)
return nil
} }
// Find fetches the infrastructure with the current state, the method has no side effects on the infra. // Find fetches the infrastructure with the current state, the method has no side effects on the infra.
func (d DockerProvider) Find( func (d DockerProvider) Find(
ctx context.Context, ctx context.Context,
spaceID int64,
spacePath string, spacePath string,
resourceKey string, resourceKey string,
params []Parameter, params []types.InfraProviderParameter,
) (*Infrastructure, error) { ) (*types.Infrastructure, error) {
dockerClient, err := d.dockerClientFactory.NewDockerClient(ctx, &Infrastructure{ dockerClient, err := d.dockerClientFactory.NewDockerClient(ctx, &types.Infrastructure{
ProviderType: enum.InfraProviderTypeDocker, ProviderType: enum.InfraProviderTypeDocker,
Parameters: params, Parameters: params,
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("error getting docker client from docker client factory: %w", err) return nil, fmt.Errorf("error getting docker client from docker client factory: %w", err)
} }
defer func() { defer func() {
closingErr := dockerClient.Close() closingErr := dockerClient.Close()
if closingErr != nil { if closingErr != nil {
log.Ctx(ctx).Warn().Err(closingErr).Msg("failed to close docker client") log.Ctx(ctx).Warn().Err(closingErr).Msg("failed to close docker client")
} }
}() }()
infrastructure, err := d.dockerHostInfo(ctx, dockerClient) infrastructure, err := d.dockerHostInfo(ctx, dockerClient)
if err != nil { if err != nil {
return nil, err return nil, err
} }
infrastructure.SpaceID = spaceID
infrastructure.SpacePath = spacePath
infrastructure.ResourceKey = resourceKey
name := volumeName(spacePath, resourceKey) name := volumeName(spacePath, resourceKey)
volumeInspect, err := dockerClient.VolumeInspect(ctx, name) volumeInspect, err := dockerClient.VolumeInspect(ctx, name)
if err != nil { if err != nil {
return nil, fmt.Errorf("couldn't find the volume for %s : %w", name, err) return nil, fmt.Errorf("couldn't find the volume for %s : %w", name, err)
} }
infrastructure.Storage = volumeInspect.Name infrastructure.Storage = volumeInspect.Name
return infrastructure, nil return infrastructure, nil
} }
// Stop is NOOP as this provider uses already running docker engine. It does not stop the docker engine. // Stop is NOOP as this provider uses already running docker engine. It does not stop the docker engine.
func (d DockerProvider) Stop(_ context.Context, infra *Infrastructure) (*Infrastructure, error) { func (d DockerProvider) Stop(ctx context.Context, infra *types.Infrastructure) error {
return infra, nil event := &events.GitspaceInfraEventPayload{
Infra: infra,
Type: enum.InfraEventStop,
}
d.eventReporter.EmitGitspaceInfraEvent(ctx, events.GitspaceInfraEvent, event)
return nil
} }
// Deprovision deletes the host machine directory created by Provision. It does not stop the docker engine. // Deprovision deletes the volume created by Provision. It does not stop the docker engine.
func (d DockerProvider) Deprovision(ctx context.Context, infra *Infrastructure) (*Infrastructure, error) { func (d DockerProvider) Deprovision(ctx context.Context, infra *types.Infrastructure) error {
dockerClient, err := d.dockerClientFactory.NewDockerClient(ctx, &Infrastructure{ dockerClient, err := d.dockerClientFactory.NewDockerClient(ctx, &types.Infrastructure{
ProviderType: enum.InfraProviderTypeDocker, ProviderType: enum.InfraProviderTypeDocker,
Parameters: infra.Parameters, Parameters: infra.Parameters,
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("error getting docker client from docker client factory: %w", err) return fmt.Errorf("error getting docker client from docker client factory: %w", err)
} }
defer func() { defer func() {
closingErr := dockerClient.Close() closingErr := dockerClient.Close()
@ -150,23 +186,31 @@ func (d DockerProvider) Deprovision(ctx context.Context, infra *Infrastructure)
}() }()
err = dockerClient.VolumeRemove(ctx, infra.Storage, true) err = dockerClient.VolumeRemove(ctx, infra.Storage, true)
if err != nil { if err != nil {
return nil, fmt.Errorf("couldn't delete volume for %s : %w", infra.Storage, err) return fmt.Errorf("couldn't delete volume for %s : %w", infra.Storage, err)
} }
return infra, nil
event := &events.GitspaceInfraEventPayload{
Infra: infra,
Type: enum.InfraEventDeprovision,
}
d.eventReporter.EmitGitspaceInfraEvent(ctx, events.GitspaceInfraEvent, event)
return nil
} }
// AvailableParams returns empty slice as no params are defined. // AvailableParams returns empty slice as no params are defined.
func (d DockerProvider) AvailableParams() []ParameterSchema { func (d DockerProvider) AvailableParams() []types.InfraProviderParameterSchema {
return []ParameterSchema{} return []types.InfraProviderParameterSchema{}
} }
// ValidateParams returns nil as no params are defined. // ValidateParams returns nil as no params are defined.
func (d DockerProvider) ValidateParams(_ []Parameter) error { func (d DockerProvider) ValidateParams(_ []types.InfraProviderParameter) error {
return nil return nil
} }
// TemplateParams returns nil as no template params are used. // TemplateParams returns nil as no template params are used.
func (d DockerProvider) TemplateParams() []ParameterSchema { func (d DockerProvider) TemplateParams() []types.InfraProviderParameterSchema {
return nil return nil
} }
@ -175,12 +219,15 @@ func (d DockerProvider) ProvisioningType() enum.InfraProvisioningType {
return enum.InfraProvisioningTypeExisting return enum.InfraProvisioningTypeExisting
} }
func (d DockerProvider) dockerHostInfo(ctx context.Context, dockerClient *client.Client) (*Infrastructure, error) { func (d DockerProvider) dockerHostInfo(
ctx context.Context,
dockerClient *client.Client,
) (*types.Infrastructure, error) {
info, err := dockerClient.Info(ctx) info, err := dockerClient.Info(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to connect to docker engine: %w", err) return nil, fmt.Errorf("unable to connect to docker engine: %w", err)
} }
return &Infrastructure{ return &types.Infrastructure{
Identifier: info.ID, Identifier: info.ID,
ProviderType: enum.InfraProviderTypeDocker, ProviderType: enum.InfraProviderTypeDocker,
Status: enum.InfraStatusProvisioned, Status: enum.InfraStatusProvisioned,

View File

@ -17,30 +17,38 @@ package infraprovider
import ( import (
"context" "context"
"github.com/harness/gitness/infraprovider/enum" "github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
) )
type InfraProvider interface { type InfraProvider interface {
// Provision provisions infrastructure against a resourceKey with the provided parameters. // Provision provisions infrastructure against a resourceKey with the provided parameters.
Provision( Provision(
ctx context.Context, ctx context.Context,
spaceID int64,
spacePath string, spacePath string,
resourceKey string, resourceKey string,
requiredPorts []int, requiredPorts []int,
parameters []Parameter, parameters []types.InfraProviderParameter,
) (*Infrastructure, error) ) error
// Find finds infrastructure provisioned against a resourceKey. // Find finds infrastructure provisioned against a resourceKey.
Find(ctx context.Context, spacePath string, resourceKey string, parameters []Parameter) (*Infrastructure, error) Find(
ctx context.Context,
spaceID int64,
spacePath string,
resourceKey string,
parameters []types.InfraProviderParameter,
) (*types.Infrastructure, error)
// Stop frees up the resources allocated against a resourceKey, which can be freed. // Stop frees up the resources allocated against a resourceKey, which can be freed.
Stop(ctx context.Context, infra *Infrastructure) (*Infrastructure, error) Stop(ctx context.Context, infra *types.Infrastructure) error
// Deprovision removes all infrastructure provisioned againest the resourceKey. // Deprovision removes all infrastructure provisioned againest the resourceKey.
Deprovision(ctx context.Context, infra *Infrastructure) (*Infrastructure, error) Deprovision(ctx context.Context, infra *types.Infrastructure) error
// AvailableParams provides a schema to define the infrastructure. // AvailableParams provides a schema to define the infrastructure.
AvailableParams() []ParameterSchema AvailableParams() []types.InfraProviderParameterSchema
// ValidateParams validates the supplied params before defining the infrastructure resource . // ValidateParams validates the supplied params before defining the infrastructure resource .
ValidateParams(parameters []Parameter) error ValidateParams(parameters []types.InfraProviderParameter) error
// TemplateParams provides a list of params which are of type template. // TemplateParams provides a list of params which are of type template.
TemplateParams() []ParameterSchema TemplateParams() []types.InfraProviderParameterSchema
// ProvisioningType specifies whether the provider will provision new infra resources or it will reuse existing. // ProvisioningType specifies whether the provider will provision new infra resources or it will reuse existing.
ProvisioningType() enum.InfraProvisioningType ProvisioningType() enum.InfraProvisioningType
} }

View File

@ -17,7 +17,7 @@ package infraprovider
import ( import (
"fmt" "fmt"
"github.com/harness/gitness/infraprovider/enum" "github.com/harness/gitness/types/enum"
) )
type Factory struct { type Factory struct {

View File

@ -15,6 +15,8 @@
package infraprovider package infraprovider
import ( import (
events "github.com/harness/gitness/app/events/gitspaceinfra"
"github.com/google/wire" "github.com/google/wire"
) )
@ -28,8 +30,9 @@ var WireSet = wire.NewSet(
func ProvideDockerProvider( func ProvideDockerProvider(
config *DockerConfig, config *DockerConfig,
dockerClientFactory *DockerClientFactory, dockerClientFactory *DockerClientFactory,
eventReporter *events.Reporter,
) *DockerProvider { ) *DockerProvider {
return NewDockerProvider(config, dockerClientFactory) return NewDockerProvider(config, dockerClientFactory, eventReporter)
} }
func ProvideFactory(dockerProvider *DockerProvider) Factory { func ProvideFactory(dockerProvider *DockerProvider) Factory {

View File

@ -41,7 +41,8 @@ const (
) )
func GetGitspaceStateFromInstance( func GetGitspaceStateFromInstance(
instanceState GitspaceInstanceStateType) (GitspaceStateType, error) { instanceState GitspaceInstanceStateType,
) (GitspaceStateType, error) {
switch instanceState { switch instanceState {
case GitspaceInstanceStateRunning: case GitspaceInstanceStateRunning:
return GitspaceStateRunning, nil return GitspaceStateRunning, nil

31
types/enum/infra_event.go Normal file
View File

@ -0,0 +1,31 @@
// 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 enum
type InfraEvent string
func (InfraEvent) Enum() []interface{} {
return toInterfaceSlice(infraEvents)
}
var infraEvents = []InfraEvent{
InfraEventProvision, InfraEventStop, InfraEventDeprovision,
}
const (
InfraEventProvision InfraEvent = "provision"
InfraEventStop InfraEvent = "stop"
InfraEventDeprovision InfraEvent = "deprovision"
)

View File

@ -15,7 +15,7 @@
package types package types
import ( import (
"github.com/harness/gitness/infraprovider/enum" "github.com/harness/gitness/types/enum"
) )
type InfraProviderConfig struct { type InfraProviderConfig struct {

View File

@ -12,11 +12,11 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package infraprovider package types
import "github.com/harness/gitness/infraprovider/enum" import "github.com/harness/gitness/types/enum"
type ParameterSchema struct { type InfraProviderParameterSchema struct {
Name string Name string
Description string Description string
DefaultValue string DefaultValue string
@ -25,7 +25,7 @@ type ParameterSchema struct {
Editable bool Editable bool
} }
type Parameter struct { type InfraProviderParameter struct {
Name string Name string
Value string Value string
} }
@ -49,13 +49,15 @@ type Infrastructure struct {
// ProviderType specifies the type of the infra provider. // ProviderType specifies the type of the infra provider.
ProviderType enum.InfraProviderType ProviderType enum.InfraProviderType
// Parameters which are required by the provider to provision the infra. // Parameters which are required by the provider to provision the infra.
Parameters []Parameter Parameters []InfraProviderParameter
// Status of the infra. // Status of the infra.
Status enum.InfraStatus Status enum.InfraStatus
// Host through which the infra can be accessed for all purposes. // Host through which the infra can be accessed.
Host string Host string
// Port on which the infra can be accessed to orchestrate containers. ProxyHost string
Port int // AgentPort on which the agent can be accessed to orchestrate containers.
AgentPort int
ProxyPort int
// Storage is the name of the volume or disk created for the resource. // Storage is the name of the volume or disk created for the resource.
Storage string Storage string
// PortMappings contains the ports assigned for every requested port. // PortMappings contains the ports assigned for every requested port.