diff --git a/app/api/controller/gitspace/events.go b/app/api/controller/gitspace/events.go index 47ef651f9..7e188418c 100644 --- a/app/api/controller/gitspace/events.go +++ b/app/api/controller/gitspace/events.go @@ -89,9 +89,13 @@ func eventsMessageMapping() map[enum.GitspaceEventType]string { gitspaceConfigsMap[enum.GitspaceEventTypeInfraProvisioningCompleted] = "Provisioning Infrastructure Completed" gitspaceConfigsMap[enum.GitspaceEventTypeInfraProvisioningFailed] = "Provisioning Infrastructure Failed" - gitspaceConfigsMap[enum.GitspaceEventTypeInfraUnprovisioningStart] = "Unprovisioning Infrastructure..." - gitspaceConfigsMap[enum.GitspaceEventTypeInfraUnprovisioningCompleted] = "Unprovisioning Infrastructure Completed" - gitspaceConfigsMap[enum.GitspaceEventTypeInfraUnprovisioningFailed] = "Unprovisioning Infrastructure Failed" + gitspaceConfigsMap[enum.GitspaceEventTypeInfraStopStart] = "Stopping Infrastructure..." + gitspaceConfigsMap[enum.GitspaceEventTypeInfraStopCompleted] = "Stopping Infrastructure Completed" + gitspaceConfigsMap[enum.GitspaceEventTypeInfraStopFailed] = "Stopping Infrastructure Failed" + + gitspaceConfigsMap[enum.GitspaceEventTypeInfraDeprovisioningStart] = "Deprovisioning Infrastructure..." + gitspaceConfigsMap[enum.GitspaceEventTypeInfraDeprovisioningCompleted] = "Deprovisioning Infrastructure Completed" + gitspaceConfigsMap[enum.GitspaceEventTypeInfraDeprovisioningFailed] = "Deprovisioning Infrastructure Failed" gitspaceConfigsMap[enum.GitspaceEventTypeAgentConnectStart] = "Connecting to the gitspace agent..." gitspaceConfigsMap[enum.GitspaceEventTypeAgentConnectCompleted] = "Connected to the gitspace agent" @@ -101,6 +105,10 @@ func eventsMessageMapping() map[enum.GitspaceEventType]string { gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceCreationCompleted] = "Successfully setup the gitspace" gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceCreationFailed] = "Failed to setup the gitspace" + gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceStopStart] = "Stopping the gitspace..." + gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceStopCompleted] = "Successfully stopped the gitspace" + gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceStopFailed] = "Failed to stop the gitspace" + gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceDeletionStart] = "Removing the gitspace..." gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceDeletionCompleted] = "Successfully removed the gitspace" gitspaceConfigsMap[enum.GitspaceEventTypeAgentGitspaceDeletionFailed] = "Failed to remove the gitspace" diff --git a/app/gitspace/orchestrator/container/container_orchestrator.go b/app/gitspace/orchestrator/container/container_orchestrator.go index ad7df5885..5fc40a643 100644 --- a/app/gitspace/orchestrator/container/container_orchestrator.go +++ b/app/gitspace/orchestrator/container/container_orchestrator.go @@ -22,9 +22,10 @@ import ( ) type Orchestrator interface { - // StartGitspace starts the gitspace container using the specified image or default image, clones the code, - // runs SSH server and installs the IDE inside the container. It returns a map of the ports used by the Gitspace. - StartGitspace( + // CreateAndStartGitspace starts an exited container and starts a new container if the container is removed. + // If the container is newly created, it clones the code, sets up the IDE and executes the postCreateCommand. + // It returns the container ID, name and ports used. + CreateAndStartGitspace( ctx context.Context, gitspaceConfig *types.GitspaceConfig, devcontainerConfig *types.DevcontainerConfig, @@ -32,9 +33,12 @@ type Orchestrator interface { repoName string, ) (*StartResponse, error) - // StopGitspace stops and removes the gitspace container. - StopGitspace(ctx context.Context, gitspaceConfig *types.GitspaceConfig, infra *infraprovider.Infrastructure) error + // StopGitspace stops the gitspace container. + StopGitspace(ctx context.Context, config *types.GitspaceConfig, infra *infraprovider.Infrastructure) error - // Status checks if the infra is reachable and ready to begin container creation. + // StopAndRemoveGitspace stops and removes the gitspace container. + StopAndRemoveGitspace(ctx context.Context, config *types.GitspaceConfig, infra *infraprovider.Infrastructure) error + + // Status checks if the infra is reachable and ready to orchestrate containers. Status(ctx context.Context, infra *infraprovider.Infrastructure) error } diff --git a/app/gitspace/orchestrator/container/embedded_docker.go b/app/gitspace/orchestrator/container/embedded_docker.go index f671b5adf..b01cde30c 100644 --- a/app/gitspace/orchestrator/container/embedded_docker.go +++ b/app/gitspace/orchestrator/container/embedded_docker.go @@ -28,7 +28,6 @@ import ( "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/mount" - "github.com/docker/docker/api/types/strslice" "github.com/docker/docker/client" "github.com/docker/go-connections/nat" "github.com/rs/zerolog/log" @@ -42,6 +41,7 @@ const ( catchAllPort = "0" containerStateRunning = "running" containerStateRemoved = "removed" + containerStateStopped = "exited" templateCloneGit = "clone_git.sh" templateSetupSSHServer = "setup_ssh_server.sh" ) @@ -74,12 +74,11 @@ func NewEmbeddedDockerOrchestrator( } } -// StartGitspace checks if the Gitspace is already running by checking its entry in a map. If is it running, -// it returns, else, it creates a new Gitspace container by using the provided image. If the provided image is -// nil, it uses a default image read from Gitness config. Post creation it runs the postCreate command and clones -// the code inside the container. It uses the IDE service to setup the relevant IDE and install the SSH server -// inside the container. -func (e *EmbeddedDockerOrchestrator) StartGitspace( +// CreateAndStartGitspace starts an exited container and starts a new container if the container is removed. +// If the container is newly created, it clones the code, sets up the IDE and executes the postCreateCommand. +// It returns the container ID, name and ports used. +// It returns an error if the container is not running, exited or removed. +func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace( ctx context.Context, gitspaceConfig *types.GitspaceConfig, devcontainerConfig *types.DevcontainerConfig, @@ -108,32 +107,17 @@ func (e *EmbeddedDockerOrchestrator) StartGitspace( return nil, err } - var usedPorts map[enum.IDEType]string - var containerID string + ideService, err := e.getIDEService(gitspaceConfig) + if err != nil { + return nil, err + } + switch state { case containerStateRunning: log.Debug().Msg("gitspace is already running") - ideService, startErr := e.getIDEService(gitspaceConfig) - if startErr != nil { - return nil, startErr - } - - id, ports, startErr := e.getContainerInfo(ctx, containerName, dockerClient, ideService) - if startErr != nil { - return nil, startErr - } - - usedPorts = ports - containerID = id - - case containerStateRemoved: - log.Debug().Msg("gitspace is not running, starting it...") - - ideService, startErr := e.getIDEService(gitspaceConfig) - if startErr != nil { - return nil, startErr - } + case containerStateStopped: + log.Debug().Msg("gitspace is stopped, starting it") logStreamInstance, loggerErr := e.statefulLogger.CreateLogStream(ctx, gitspaceConfig.ID) if loggerErr != nil { @@ -146,8 +130,33 @@ func (e *EmbeddedDockerOrchestrator) StartGitspace( log.Warn().Err(loggerErr).Msgf("failed to flush log stream for gitspace ID %d", gitspaceConfig.ID) } }() + + startErr := e.startContainer(ctx, dockerClient, containerName, logStreamInstance) + if startErr != nil { + return nil, startErr + } + + // TODO: Add gitspace status reporting. + log.Debug().Msg("started gitspace") + + case containerStateRemoved: + log.Debug().Msg("gitspace is removed, creating it...") + + logStreamInstance, loggerErr := e.statefulLogger.CreateLogStream(ctx, gitspaceConfig.ID) + if loggerErr != nil { + return nil, fmt.Errorf("error getting log stream for gitspace ID %d: %w", gitspaceConfig.ID, loggerErr) + } + + defer func() { + loggerErr = logStreamInstance.Flush() + if loggerErr != nil { + log.Warn().Err(loggerErr).Msgf("failed to flush log stream for gitspace ID %d", gitspaceConfig.ID) + } + }() + workingDirectory := "/" + repoName - startErr = e.startGitspace( + + startErr := e.startGitspace( ctx, gitspaceConfig, devcontainerConfig, @@ -161,13 +170,6 @@ func (e *EmbeddedDockerOrchestrator) StartGitspace( if startErr != nil { return nil, fmt.Errorf("failed to start gitspace %s: %w", containerName, startErr) } - id, ports, startErr := e.getContainerInfo(ctx, containerName, dockerClient, ideService) - if startErr != nil { - return nil, startErr - } - - containerID = id - usedPorts = ports // TODO: Add gitspace status reporting. log.Debug().Msg("started gitspace") @@ -176,10 +178,15 @@ func (e *EmbeddedDockerOrchestrator) StartGitspace( return nil, fmt.Errorf("gitspace %s is in a bad state: %s", containerName, state) } + id, ports, startErr := e.getContainerInfo(ctx, containerName, dockerClient, ideService) + if startErr != nil { + return nil, startErr + } + return &StartResponse{ - ContainerID: containerID, + ContainerID: id, ContainerName: containerName, - PortsUsed: usedPorts, + PortsUsed: ports, }, nil } @@ -218,6 +225,11 @@ func (e *EmbeddedDockerOrchestrator) startGitspace( return err } + err = e.startContainer(ctx, dockerClient, containerName, logStreamInstance) + if err != nil { + return err + } + var devcontainer = &Devcontainer{ ContainerName: containerName, DockerClient: dockerClient, @@ -417,6 +429,38 @@ func (e *EmbeddedDockerOrchestrator) executePostCreateCommand( return nil } +func (e *EmbeddedDockerOrchestrator) startContainer( + ctx context.Context, + dockerClient *client.Client, + containerName string, + logStreamInstance *logutil.LogStreamInstance, +) error { + loggingErr := logStreamInstance.Write("Starting container: " + containerName) + if loggingErr != nil { + return fmt.Errorf("logging error: %w", loggingErr) + } + + err := dockerClient.ContainerStart(ctx, containerName, dockerTypes.ContainerStartOptions{}) + if err != nil { + loggingErr = logStreamInstance.Write("Error while creating container: " + err.Error()) + + err = fmt.Errorf("could not start container %s: %w", containerName, err) + + if loggingErr != nil { + err = fmt.Errorf("original error: %w; logging error: %w", err, loggingErr) + } + + return err + } + + loggingErr = logStreamInstance.Write("Successfully started container") + if loggingErr != nil { + return fmt.Errorf("logging error: %w", loggingErr) + } + + return nil +} + func (e *EmbeddedDockerOrchestrator) createContainer( ctx context.Context, dockerClient *client.Client, @@ -445,21 +489,16 @@ func (e *EmbeddedDockerOrchestrator) createContainer( portBindings[natPort] = hostPortBindings } - entryPoint := make(strslice.StrSlice, 0) - entryPoint = append(entryPoint, "sleep") - - commands := make(strslice.StrSlice, 0) - commands = append(commands, "infinity") + entryPoint := []string{"/bin/bash", "-c", `trap "exit 0" 15; sleep infinity`} loggingErr := logStreamInstance.Write("Creating container: " + containerName) if loggingErr != nil { return fmt.Errorf("logging error: %w", loggingErr) } - resp2, err := dockerClient.ContainerCreate(ctx, &container.Config{ + _, err := dockerClient.ContainerCreate(ctx, &container.Config{ Image: imageName, Entrypoint: entryPoint, - Cmd: commands, ExposedPorts: exposedPorts, }, &container.HostConfig{ PortBindings: portBindings, @@ -483,34 +522,6 @@ func (e *EmbeddedDockerOrchestrator) createContainer( return err } - loggingErr = logStreamInstance.Write("Successfully created container") - if loggingErr != nil { - return fmt.Errorf("logging error: %w", loggingErr) - } - - loggingErr = logStreamInstance.Write("Starting container: " + containerName) - if loggingErr != nil { - return fmt.Errorf("logging error: %w", loggingErr) - } - - err = dockerClient.ContainerStart(ctx, resp2.ID, dockerTypes.ContainerStartOptions{}) - if err != nil { - loggingErr = logStreamInstance.Write("Error while creating container: " + err.Error()) - - err = fmt.Errorf("could not start container %s: %w", containerName, err) - - if loggingErr != nil { - err = fmt.Errorf("original error: %w; logging error: %w", err, loggingErr) - } - - return err - } - - loggingErr = logStreamInstance.Write("Successfully started container") - if loggingErr != nil { - return fmt.Errorf("logging error: %w", loggingErr) - } - return nil } @@ -574,8 +585,7 @@ func (e *EmbeddedDockerOrchestrator) pullImage( return nil } -// StopGitspace checks if the Gitspace container is running. If yes, it stops and removes the container. -// Else it returns. +// StopGitspace stops a container. If it is removed, it returns an error. func (e EmbeddedDockerOrchestrator) StopGitspace( ctx context.Context, gitspaceConfig *types.GitspaceConfig, @@ -604,6 +614,10 @@ func (e EmbeddedDockerOrchestrator) StopGitspace( } if state == containerStateRemoved { + return fmt.Errorf("gitspace %s is removed", containerName) + } + + if state == containerStateStopped { log.Debug().Msg("gitspace is already stopped") return nil } @@ -622,7 +636,7 @@ func (e EmbeddedDockerOrchestrator) StopGitspace( } }() - err = e.stopGitspace(ctx, containerName, dockerClient, logStreamInstance) + err = e.stopContainer(ctx, containerName, dockerClient, logStreamInstance) if err != nil { return fmt.Errorf("failed to stop gitspace %s: %w", containerName, err) } @@ -632,7 +646,7 @@ func (e EmbeddedDockerOrchestrator) StopGitspace( return nil } -func (e EmbeddedDockerOrchestrator) stopGitspace( +func (e EmbeddedDockerOrchestrator) stopContainer( ctx context.Context, containerName string, dockerClient *client.Client, @@ -661,29 +675,6 @@ func (e EmbeddedDockerOrchestrator) stopGitspace( return fmt.Errorf("logging error: %w", loggingErr) } - loggingErr = logStreamInstance.Write("Removing container: " + containerName) - if loggingErr != nil { - return fmt.Errorf("logging error: %w", loggingErr) - } - - err = dockerClient.ContainerRemove(ctx, containerName, dockerTypes.ContainerRemoveOptions{Force: true}) - if err != nil { - loggingErr = logStreamInstance.Write("Error while removing container: " + err.Error()) - - err = fmt.Errorf("could not remove container %s: %w", containerName, err) - - if loggingErr != nil { - err = fmt.Errorf("original error: %w; logging error: %w", err, loggingErr) - } - - return err - } - - loggingErr = logStreamInstance.Write("Successfully removed container") - if loggingErr != nil { - return fmt.Errorf("logging error: %w", loggingErr) - } - return nil } @@ -715,3 +706,104 @@ func (e *EmbeddedDockerOrchestrator) containerState( return containers[0].State, nil } + +// StopAndRemoveGitspace stops the container if not stopped and removes it. +// If the container is already removed, it returns. +func (e *EmbeddedDockerOrchestrator) StopAndRemoveGitspace( + ctx context.Context, + gitspaceConfig *types.GitspaceConfig, + infra *infraprovider.Infrastructure, +) error { + containerName := getGitspaceContainerName(gitspaceConfig) + + log := log.Ctx(ctx).With().Str(loggingKey, containerName).Logger() + + dockerClient, err := e.dockerClientFactory.NewDockerClient(ctx, infra) + if err != nil { + return fmt.Errorf("error getting docker client from docker client factory: %w", err) + } + + defer func() { + closingErr := dockerClient.Close() + if closingErr != nil { + log.Warn().Err(closingErr).Msg("failed to close docker client") + } + }() + + log.Debug().Msg("checking current state of gitspace") + state, err := e.containerState(ctx, containerName, dockerClient) + if err != nil { + return err + } + + if state == containerStateRemoved { + log.Debug().Msg("gitspace is already removed") + return nil + } + + logStreamInstance, loggerErr := e.statefulLogger.CreateLogStream(ctx, gitspaceConfig.ID) + if loggerErr != nil { + return fmt.Errorf("error getting log stream for gitspace ID %d: %w", gitspaceConfig.ID, loggerErr) + } + + defer func() { + loggerErr = logStreamInstance.Flush() + if loggerErr != nil { + log.Warn().Err(loggerErr).Msgf("failed to flush log stream for gitspace ID %d", gitspaceConfig.ID) + } + }() + + if state != containerStateStopped { + log.Debug().Msg("stopping gitspace") + + err = e.stopContainer(ctx, containerName, dockerClient, logStreamInstance) + if err != nil { + return fmt.Errorf("failed to stop gitspace %s: %w", containerName, err) + } + + log.Debug().Msg("stopped gitspace") + } + + log.Debug().Msg("removing gitspace") + + err = e.removeContainer(ctx, containerName, dockerClient, logStreamInstance) + if err != nil { + return fmt.Errorf("failed to remove gitspace %s: %w", containerName, err) + } + + log.Debug().Msg("removed gitspace") + + return nil +} + +func (e EmbeddedDockerOrchestrator) removeContainer( + ctx context.Context, + containerName string, + dockerClient *client.Client, + logStreamInstance *logutil.LogStreamInstance, +) error { + loggingErr := logStreamInstance.Write("Removing container: " + containerName) + if loggingErr != nil { + return fmt.Errorf("logging error: %w", loggingErr) + } + + err := dockerClient.ContainerRemove(ctx, containerName, dockerTypes.ContainerRemoveOptions{Force: true}) + if err != nil { + loggingErr = logStreamInstance.Write("Error while removing container: " + err.Error()) + + err = fmt.Errorf("could not remove container %s: %w", containerName, err) + + if loggingErr != nil { + err = fmt.Errorf("original error: %w; logging error: %w", err, loggingErr) + } + + return err + } + + loggingErr = logStreamInstance.Write("Successfully removed container") + if loggingErr != nil { + return fmt.Errorf("logging error: %w", loggingErr) + } + + return nil +} diff --git a/app/gitspace/orchestrator/orchestrator_impl.go b/app/gitspace/orchestrator/orchestrator_impl.go index 83158668f..9657d766f 100644 --- a/app/gitspace/orchestrator/orchestrator_impl.go +++ b/app/gitspace/orchestrator/orchestrator_impl.go @@ -26,6 +26,7 @@ import ( "github.com/harness/gitness/app/gitspace/orchestrator/container" "github.com/harness/gitness/app/gitspace/scm" "github.com/harness/gitness/app/store" + "github.com/harness/gitness/infraprovider" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" @@ -113,7 +114,8 @@ func (o orchestrator) StartGitspace( o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationStart) - startResponse, err := o.containerOrchestrator.StartGitspace(ctx, gitspaceConfig, devcontainerConfig, infra, repoName) + startResponse, err := o.containerOrchestrator.CreateAndStartGitspace( + ctx, gitspaceConfig, devcontainerConfig, infra, repoName) if err != nil { o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationFailed) @@ -175,9 +177,67 @@ func (o orchestrator) StopGitspace( return fmt.Errorf("cannot find the provisioned infra: %w", err) } + err = o.stopGitspaceContainer(ctx, gitspaceConfig, infra) + if err != nil { + return err + } + + o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraStopStart) + + _, err = o.infraProvisioner.Stop(ctx, infraProviderResource, gitspaceConfig) + if err != nil { + o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraStopFailed) + + return fmt.Errorf( + "cannot stop provisioned infrastructure with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err) + } + + o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraStopCompleted) + + gitspaceInstance.State = enum.GitspaceInstanceStateDeleted + + o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStopCompleted) + + return err +} + +func (o orchestrator) stopGitspaceContainer( + ctx context.Context, + gitspaceConfig *types.GitspaceConfig, + infra *infraprovider.Infrastructure, +) error { o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectStart) - err = o.containerOrchestrator.Status(ctx, infra) + err := o.containerOrchestrator.Status(ctx, infra) + 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.GitspaceEventTypeAgentGitspaceStopStart) + + err = o.containerOrchestrator.StopGitspace(ctx, gitspaceConfig, infra) + if err != nil { + o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceStopFailed) + + return fmt.Errorf("error stopping the Gitspace container: %w", err) + } + + o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceStopCompleted) + return nil +} + +func (o orchestrator) stopAndRemoveGitspaceContainer( + ctx context.Context, + gitspaceConfig *types.GitspaceConfig, + infra *infraprovider.Infrastructure, +) error { + o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectStart) + + err := o.containerOrchestrator.Status(ctx, infra) if err != nil { o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectFailed) @@ -188,7 +248,7 @@ func (o orchestrator) StopGitspace( o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceDeletionStart) - err = o.containerOrchestrator.StopGitspace(ctx, gitspaceConfig, infra) + err = o.containerOrchestrator.StopAndRemoveGitspace(ctx, gitspaceConfig, infra) if err != nil { o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceDeletionFailed) @@ -196,24 +256,7 @@ func (o orchestrator) StopGitspace( } 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 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 err + return nil } func (o orchestrator) DeleteGitspace( @@ -221,7 +264,6 @@ func (o orchestrator) DeleteGitspace( gitspaceConfig *types.GitspaceConfig, ) (*types.GitspaceInstance, error) { gitspaceInstance := gitspaceConfig.GitspaceInstance - currentState := gitspaceInstance.State gitspaceInstance.State = enum.GitspaceInstanceStateError infraProviderResource, err := o.infraProviderResourceStore.Find(ctx, gitspaceConfig.InfraProviderResourceID) @@ -230,47 +272,27 @@ func (o orchestrator) DeleteGitspace( "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) - if err != nil { - 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) + infra, err := o.infraProvisioner.Find(ctx, infraProviderResource, gitspaceConfig) + if err != nil { + return nil, fmt.Errorf("cannot find the provisioned infra: %w", err) } - o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraUnprovisioningStart) + err = o.stopAndRemoveGitspaceContainer(ctx, gitspaceConfig, infra) + if err != nil { + return nil, err + } + + o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningStart) _, err = o.infraProvisioner.Deprovision(ctx, infraProviderResource, gitspaceConfig) if err != nil { - o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraUnprovisioningFailed) + o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningFailed) return nil, fmt.Errorf( - "cannot stop provisioned infrastructure with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err) + "cannot deprovision infrastructure with ID %d: %w", gitspaceConfig.InfraProviderResourceID, err) } - o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraUnprovisioningCompleted) + o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningCompleted) gitspaceInstance.State = enum.GitspaceInstanceStateDeleted diff --git a/types/enum/gitspace_event_type.go b/types/enum/gitspace_event_type.go index 36f48b5df..e8aaea245 100644 --- a/types/enum/gitspace_event_type.go +++ b/types/enum/gitspace_event_type.go @@ -37,9 +37,13 @@ var gitspaceEventTypes = []GitspaceEventType{ GitspaceEventTypeInfraProvisioningCompleted, GitspaceEventTypeInfraProvisioningFailed, - GitspaceEventTypeInfraUnprovisioningStart, - GitspaceEventTypeInfraUnprovisioningCompleted, - GitspaceEventTypeInfraUnprovisioningFailed, + GitspaceEventTypeInfraStopStart, + GitspaceEventTypeInfraStopCompleted, + GitspaceEventTypeInfraStopFailed, + + GitspaceEventTypeInfraDeprovisioningStart, + GitspaceEventTypeInfraDeprovisioningCompleted, + GitspaceEventTypeInfraDeprovisioningFailed, GitspaceEventTypeAgentConnectStart, GitspaceEventTypeAgentConnectCompleted, @@ -49,6 +53,10 @@ var gitspaceEventTypes = []GitspaceEventType{ GitspaceEventTypeAgentGitspaceCreationCompleted, GitspaceEventTypeAgentGitspaceCreationFailed, + GitspaceEventTypeAgentGitspaceStopStart, + GitspaceEventTypeAgentGitspaceStopCompleted, + GitspaceEventTypeAgentGitspaceStopFailed, + GitspaceEventTypeAgentGitspaceDeletionStart, GitspaceEventTypeAgentGitspaceDeletionCompleted, GitspaceEventTypeAgentGitspaceDeletionFailed, @@ -80,10 +88,15 @@ const ( GitspaceEventTypeInfraProvisioningCompleted GitspaceEventType = "infra_provisioning_completed" GitspaceEventTypeInfraProvisioningFailed GitspaceEventType = "infra_provisioning_failed" - // Infra unprovisioning events. - GitspaceEventTypeInfraUnprovisioningStart GitspaceEventType = "infra_unprovisioning_start" - GitspaceEventTypeInfraUnprovisioningCompleted GitspaceEventType = "infra_unprovisioning_completed" - GitspaceEventTypeInfraUnprovisioningFailed GitspaceEventType = "infra_unprovisioning_failed" + // Infra stop events. + GitspaceEventTypeInfraStopStart GitspaceEventType = "infra_stop_start" + GitspaceEventTypeInfraStopCompleted GitspaceEventType = "infra_stop_completed" + GitspaceEventTypeInfraStopFailed GitspaceEventType = "infra_stop_failed" + + // Infra deprovisioning events. + GitspaceEventTypeInfraDeprovisioningStart GitspaceEventType = "infra_deprovisioning_start" + GitspaceEventTypeInfraDeprovisioningCompleted GitspaceEventType = "infra_deprovisioning_completed" + GitspaceEventTypeInfraDeprovisioningFailed GitspaceEventType = "infra_deprovisioning_failed" // Agent connection events. GitspaceEventTypeAgentConnectStart GitspaceEventType = "agent_connect_start" @@ -95,6 +108,11 @@ const ( GitspaceEventTypeAgentGitspaceCreationCompleted GitspaceEventType = "agent_gitspace_creation_completed" GitspaceEventTypeAgentGitspaceCreationFailed GitspaceEventType = "agent_gitspace_creation_failed" + // Gitspace stop events. + GitspaceEventTypeAgentGitspaceStopStart GitspaceEventType = "agent_gitspace_stop_start" + GitspaceEventTypeAgentGitspaceStopCompleted GitspaceEventType = "agent_gitspace_stop_completed" + GitspaceEventTypeAgentGitspaceStopFailed GitspaceEventType = "agent_gitspace_stop_failed" + // Gitspace deletion events. GitspaceEventTypeAgentGitspaceDeletionStart GitspaceEventType = "agent_gitspace_deletion_start" GitspaceEventTypeAgentGitspaceDeletionCompleted GitspaceEventType = "agent_gitspace_deletion_completed"