feat: [CDE-94]: Adding events for gitspace transitions. (#2195)

* feat: [CDE-94]: Fixing gitspace url.
* feat: [CDE-94]: Linting
* feat: [CDE-94]: Adding events for gitspace transitions.
unified-ui
Dhruv Dhruv 2024-07-10 13:06:38 +00:00 committed by Harness
parent 61f1bc55fe
commit e712903728
8 changed files with 159 additions and 8 deletions

View File

@ -251,7 +251,8 @@ func (c *Controller) sanitizeActionInput(in *ActionInput) error {
func (c *Controller) emitGitspaceConfigEvent(
ctx context.Context,
config *types.GitspaceConfig,
eventType enum.GitspaceEventType) {
eventType enum.GitspaceEventType,
) {
c.eventReporter.EmitGitspaceEvent(ctx, events.GitspaceEvent, &events.GitspaceEventPayload{
QueryKey: config.Identifier,
EntityID: config.ID,

View File

@ -81,6 +81,10 @@ func eventsMessageMapping() map[enum.GitspaceEventType]string {
gitspaceConfigsMap[enum.GitspaceEventTypeGitspaceActionStopCompleted] = "Stopped Gitspace"
gitspaceConfigsMap[enum.GitspaceEventTypeGitspaceActionStopFailed] = "Stopping Gitspace Failed"
gitspaceConfigsMap[enum.GitspaceEventTypeFetchDevcontainerStart] = "Fetching devcontainer config..."
gitspaceConfigsMap[enum.GitspaceEventTypeFetchDevcontainerCompleted] = "Fetched devcontainer config"
gitspaceConfigsMap[enum.GitspaceEventTypeFetchDevcontainerFailed] = "Fetching devcontainer config failed"
gitspaceConfigsMap[enum.GitspaceEventTypeInfraProvisioningStart] = "Provisioning Infrastructure..."
gitspaceConfigsMap[enum.GitspaceEventTypeInfraProvisioningCompleted] = "Provisioning Infrastructure Completed"
gitspaceConfigsMap[enum.GitspaceEventTypeInfraProvisioningFailed] = "Provisioning Infrastructure Failed"
@ -97,6 +101,10 @@ func eventsMessageMapping() map[enum.GitspaceEventType]string {
gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceCreationCompleted] = "Successfully setup the gitspace"
gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceCreationFailed] = "Failed to setup the gitspace"
gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceDeletionStart] = "Removing the gitspace..."
gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceDeletionCompleted] = "Successfully removed the gitspace"
gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceDeletionFailed] = "Failed to remove the gitspace"
gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceStateReportRunning] = "Gitspace is running"
gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceStateReportStopped] = "Gitspace is stopped"
gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceStateReportUnknown] = "Gitspace is in unknown state"

View File

@ -20,6 +20,7 @@ import (
"net/url"
"time"
events "github.com/harness/gitness/app/events/gitspace"
"github.com/harness/gitness/app/gitspace/infrastructure"
"github.com/harness/gitness/app/gitspace/orchestrator/container"
"github.com/harness/gitness/app/gitspace/scm"
@ -35,6 +36,7 @@ type orchestrator struct {
infraProviderResourceStore store.InfraProviderResourceStore
infraProvisioner infrastructure.InfraProvisioner
containerOrchestrator container.Orchestrator
eventReporter *events.Reporter
}
var _ Orchestrator = (*orchestrator)(nil)
@ -44,12 +46,14 @@ func NewOrchestrator(
infraProviderResourceStore store.InfraProviderResourceStore,
infraProvisioner infrastructure.InfraProvisioner,
containerOrchestrator container.Orchestrator,
eventReporter *events.Reporter,
) Orchestrator {
return orchestrator{
scm: scm,
infraProviderResourceStore: infraProviderResourceStore,
infraProvisioner: infraProvisioner,
containerOrchestrator: containerOrchestrator,
eventReporter: eventReporter,
}
}
@ -59,8 +63,13 @@ func (o orchestrator) StartGitspace(
) (*types.GitspaceInstance, error) {
gitspaceInstance := gitspaceConfig.GitspaceInstance
gitspaceInstance.State = enum.GitspaceInstanceStateError
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeFetchDevcontainerStart)
devcontainerConfig, err := o.scm.DevcontainerConfig(ctx, gitspaceConfig)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeFetchDevcontainerFailed)
log.Warn().Err(err).Msg("devcontainerConfig fetch failed.")
}
@ -69,26 +78,49 @@ func (o orchestrator) StartGitspace(
devcontainerConfig = &types.DevcontainerConfig{}
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeFetchDevcontainerCompleted)
infraProviderResource, err := o.infraProviderResourceStore.Find(ctx, gitspaceConfig.InfraProviderResourceID)
if err != nil {
return gitspaceInstance, fmt.Errorf("cannot get the infraProviderResource for ID %d: %w",
gitspaceConfig.InfraProviderResourceID, err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningStart)
infra, err := o.infraProvisioner.Provision(ctx, infraProviderResource, gitspaceConfig)
if err != nil {
return gitspaceInstance, fmt.Errorf("cannot provision infrastructure for ID %d: %w",
gitspaceConfig.InfraProviderResourceID, err)
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.GitspaceEventTypeAgentConnectStart)
err = o.containerOrchestrator.Status(ctx, infra)
gitspaceInstance.State = enum.GitspaceInstanceStateError
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.StartGitspace(ctx, gitspaceConfig, devcontainerConfig, infra)
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)
repoName, err := o.scm.RepositoryName(ctx, gitspaceConfig)
if err != nil {
log.Warn().Err(err).Msg("failed to fetch repository name.")
@ -99,8 +131,8 @@ func (o orchestrator) StartGitspace(
var ideURL url.URL
if infra.Host == "" {
// TODO: This fix does not cover all use-cases. Ideally, we need to read the host name on which this docker is
// running and set it as the infra.Host. Remove once that change is done.
// TODO: This fix does not cover all use-cases. Ideally, we need to read the host name
// on which this docker is running and set it as the infra.Host. Remove once that change is done.
infra.Host = "localhost"
}
@ -108,7 +140,7 @@ func (o orchestrator) StartGitspace(
ideURL = url.URL{
Scheme: "http",
Host: infra.Host + ":" + port,
RawQuery: "folder=/" + startResponse.WorkingDirectory + "/" + repoName,
RawQuery: "folder=" + startResponse.WorkingDirectory + "/" + repoName,
}
} else if gitspaceConfig.IDE == enum.IDETypeVSCode {
// TODO: the following user ID is hard coded and should be changed.
@ -131,6 +163,8 @@ func (o orchestrator) StartGitspace(
gitspaceInstance.LastUsed = time.Now().UnixMilli()
gitspaceInstance.State = enum.GitspaceInstanceStateRunning
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStartCompleted)
return gitspaceInstance, nil
}
@ -140,6 +174,7 @@ func (o orchestrator) StopGitspace(
) (*types.GitspaceInstance, error) {
gitspaceInstance := gitspaceConfig.GitspaceInstance
gitspaceInstance.State = enum.GitspaceInstanceStateError
infraProviderResource, err := o.infraProviderResourceStore.Find(ctx, gitspaceConfig.InfraProviderResourceID)
if err != nil {
return nil, fmt.Errorf(
@ -151,17 +186,44 @@ func (o orchestrator) StopGitspace(
return gitspaceInstance, fmt.Errorf("cannot find the provisioned infra: %w", err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectStart)
err = o.containerOrchestrator.Status(ctx, infra)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectFailed)
return gitspaceConfig.GitspaceInstance, fmt.Errorf("couldn't call the agent health API: %w", err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectCompleted)
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceDeletionStart)
err = o.containerOrchestrator.StopGitspace(ctx, gitspaceConfig, infra)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceDeletionFailed)
return gitspaceInstance, fmt.Errorf("error stopping the Gitspace container: %w", err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceDeletionCompleted)
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraUnprovisioningStart)
_, err = o.infraProvisioner.Stop(ctx, infraProviderResource, gitspaceConfig)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraUnprovisioningFailed)
return gitspaceInstance, fmt.Errorf(
"cannot stop provisioned infrastructure with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraUnprovisioningCompleted)
gitspaceInstance.State = enum.GitspaceInstanceStateDeleted
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStopCompleted)
return gitspaceInstance, err
}
@ -172,11 +234,13 @@ func (o orchestrator) DeleteGitspace(
gitspaceInstance := gitspaceConfig.GitspaceInstance
currentState := gitspaceInstance.State
gitspaceInstance.State = enum.GitspaceInstanceStateError
infraProviderResource, err := o.infraProviderResourceStore.Find(ctx, gitspaceConfig.InfraProviderResourceID)
if err != nil {
return nil, fmt.Errorf(
"cannot get the infraProviderResource with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err)
}
if currentState == enum.GitspaceInstanceStateRunning ||
currentState == enum.GitspaceInstanceStateUnknown {
infra, err := o.infraProvisioner.Find(ctx, infraProviderResource, gitspaceConfig)
@ -184,16 +248,61 @@ func (o orchestrator) DeleteGitspace(
return nil, fmt.Errorf("cannot find the provisioned infra: %w", err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectStart)
err = o.containerOrchestrator.Status(ctx, infra)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectFailed)
return gitspaceConfig.GitspaceInstance, fmt.Errorf("couldn't call the agent health API: %w", err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectCompleted)
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceDeletionStart)
err = o.containerOrchestrator.StopGitspace(ctx, gitspaceConfig, infra)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceDeletionFailed)
return nil, fmt.Errorf("error stopping the Gitspace container: %w", err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceDeletionCompleted)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraUnprovisioningStart)
_, err = o.infraProvisioner.Unprovision(ctx, infraProviderResource, gitspaceConfig)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraUnprovisioningFailed)
return nil, fmt.Errorf(
"cannot stop provisioned infrastructure with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err)
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraUnprovisioningCompleted)
gitspaceInstance.State = enum.GitspaceInstanceStateDeleted
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStopCompleted)
return gitspaceInstance, nil
}
func (o orchestrator) emitGitspaceEvent(
ctx context.Context,
config *types.GitspaceConfig,
eventType enum.GitspaceEventType,
) {
o.eventReporter.EmitGitspaceEvent(
ctx,
events.GitspaceEvent,
&events.GitspaceEventPayload{
QueryKey: config.Identifier,
EntityID: config.GitspaceInstance.ID,
EntityType: enum.GitspaceEntityTypeGitspaceInstance,
EventType: eventType,
Created: time.Now().UnixMilli(),
})
}

View File

@ -15,6 +15,7 @@
package orchestrator
import (
events "github.com/harness/gitness/app/events/gitspace"
"github.com/harness/gitness/app/gitspace/infrastructure"
"github.com/harness/gitness/app/gitspace/orchestrator/container"
"github.com/harness/gitness/app/gitspace/scm"
@ -33,6 +34,7 @@ func ProvideOrchestrator(
infraProviderResourceStore store.InfraProviderResourceStore,
infraProvisioner infrastructure.InfraProvisioner,
containerOrchestrator container.Orchestrator,
reporter *events.Reporter,
) Orchestrator {
return NewOrchestrator(scm, infraProviderResourceStore, infraProvisioner, containerOrchestrator)
return NewOrchestrator(scm, infraProviderResourceStore, infraProvisioner, containerOrchestrator, reporter)
}

View File

@ -52,17 +52,21 @@ func (s scm) DevcontainerConfig(
gitspaceConfig *types.GitspaceConfig,
) (*types.DevcontainerConfig, error) {
gitWorkingDirectory := "/tmp/git/"
cloneDir := gitWorkingDirectory + uuid.New().String()
err := os.MkdirAll(cloneDir, os.ModePerm)
if err != nil {
return nil, fmt.Errorf("error creating directory %s: %w", cloneDir, err)
}
defer func() {
err = os.RemoveAll(cloneDir)
if err != nil {
log.Ctx(ctx).Warn().Err(err).Msg("Unable to remove working directory")
}
}()
filePath := ".devcontainer/devcontainer.json"
err = validateArgs(gitspaceConfig)
if err != nil {

View File

@ -119,6 +119,8 @@ func (g gitspaceEventStore) List(
queryStmt = g.setQueryFilter(queryStmt, filter)
queryStmt = g.setSortFilter(queryStmt, filter)
queryStmt = g.setPaginationFilter(queryStmt, filter)
sql, args, err := queryStmt.ToSql()
@ -171,6 +173,13 @@ func (g gitspaceEventStore) setQueryFilter(
return stmt
}
func (g gitspaceEventStore) setSortFilter(
stmt squirrel.SelectBuilder,
_ *types.GitspaceEventFilter,
) squirrel.SelectBuilder {
return stmt.OrderBy("geven_created ASC")
}
func (g gitspaceEventStore) setPaginationFilter(
stmt squirrel.SelectBuilder,
filter *types.GitspaceEventFilter,

View File

@ -341,7 +341,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
}
statefulLogger := logutil.ProvideStatefulLogger(logStream)
containerOrchestrator := container.ProvideEmbeddedDockerOrchestrator(dockerClientFactory, vsCode, vsCodeWeb, containerConfig, statefulLogger)
orchestratorOrchestrator := orchestrator.ProvideOrchestrator(scmSCM, infraProviderResourceStore, infraProvisioner, containerOrchestrator)
orchestratorOrchestrator := orchestrator.ProvideOrchestrator(scmSCM, infraProviderResourceStore, infraProvisioner, containerOrchestrator, reporter3)
gitspaceEventStore := database.ProvideGitspaceEventStore(db)
gitspaceController := gitspace.ProvideController(transactor, authorizer, infraProviderResourceStore, gitspaceConfigStore, gitspaceInstanceStore, spaceStore, reporter3, orchestratorOrchestrator, gitspaceEventStore, statefulLogger)
migrateController := migrate.ProvideController(authorizer, principalStore)

View File

@ -29,6 +29,10 @@ var gitspaceEventTypes = []GitspaceEventType{
GitspaceEventTypeGitspaceActionStopCompleted,
GitspaceEventTypeGitspaceActionStopFailed,
GitspaceEventTypeFetchDevcontainerStart,
GitspaceEventTypeFetchDevcontainerCompleted,
GitspaceEventTypeFetchDevcontainerFailed,
GitspaceEventTypeInfraProvisioningStart,
GitspaceEventTypeInfraProvisioningCompleted,
GitspaceEventTypeInfraProvisioningFailed,
@ -45,6 +49,10 @@ var gitspaceEventTypes = []GitspaceEventType{
GitspaceEventTypeAgentGitspaceCreationCompleted,
GitspaceEventTypeAgentGitspaceCreationFailed,
GitspaceEventTypeAgentGitspaceDeletionStart,
GitspaceEventTypeAgentGitspaceDeletionCompleted,
GitspaceEventTypeAgentGitspaceDeletionFailed,
GitspaceEventTypeAgentGitspaceStateReportRunning,
GitspaceEventTypeAgentGitspaceStateReportError,
GitspaceEventTypeAgentGitspaceStateReportStopped,
@ -62,6 +70,11 @@ const (
GitspaceEventTypeGitspaceActionStopCompleted GitspaceEventType = "gitspace_action_stop_completed"
GitspaceEventTypeGitspaceActionStopFailed GitspaceEventType = "gitspace_action_stop_failed"
// Fetch devcontainer config events.
GitspaceEventTypeFetchDevcontainerStart GitspaceEventType = "fetch_devcontainer_start"
GitspaceEventTypeFetchDevcontainerCompleted GitspaceEventType = "fetch_devcontainer_completed"
GitspaceEventTypeFetchDevcontainerFailed GitspaceEventType = "fetch_devcontainer_failed"
// Infra provisioning events.
GitspaceEventTypeInfraProvisioningStart GitspaceEventType = "infra_provisioning_start"
GitspaceEventTypeInfraProvisioningCompleted GitspaceEventType = "infra_provisioning_completed"
@ -82,6 +95,11 @@ const (
GitspaceEventTypeAgentGitspaceCreationCompleted GitspaceEventType = "agent_gitspace_creation_completed"
GitspaceEventTypeAgentGitspaceCreationFailed GitspaceEventType = "agent_gitspace_creation_failed"
// Gitspace deletion events.
GitspaceEventTypeAgentGitspaceDeletionStart GitspaceEventType = "agent_gitspace_deletion_start"
GitspaceEventTypeAgentGitspaceDeletionCompleted GitspaceEventType = "agent_gitspace_deletion_completed"
GitspaceEventTypeAgentGitspaceDeletionFailed GitspaceEventType = "agent_gitspace_deletion_failed"
// Gitspace state events.
GitspaceEventTypeAgentGitspaceStateReportRunning GitspaceEventType = "agent_gitspace_state_report_running"
GitspaceEventTypeAgentGitspaceStateReportError GitspaceEventType = "agent_gitspace_state_report_error"