mirror of
https://github.com/harness/drone.git
synced 2025-05-07 08:22:59 +00:00
feat: [CDE-461]: gitspaces expose the container methods (#2974)
* feat: [CDE-461]: gitspaces expose the container methods * feat: [CDE-461]: gitspaces expose the container methods * feat: [CDE-461]: gitspaces expose the container methods * feat: [CDE-461]: gitspaces expose the container methods * feat: [CDE-461]: gitspaces expose the container methods * feat: [CDE-461]: gitspaces expose the container methods
This commit is contained in:
parent
c635effd2f
commit
4d4917eddc
@ -22,10 +22,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
|
|
||||||
orchestratorTypes "github.com/harness/gitness/app/gitspace/orchestrator/types"
|
orchestratorTypes "github.com/harness/gitness/app/gitspace/orchestrator/types"
|
||||||
"github.com/harness/gitness/app/gitspace/scm"
|
|
||||||
"github.com/harness/gitness/types"
|
"github.com/harness/gitness/types"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
@ -42,6 +39,14 @@ const (
|
|||||||
catchAllIP = "0.0.0.0"
|
catchAllIP = "0.0.0.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var containerStateMapping = map[string]State{
|
||||||
|
"running": ContainerStateRunning,
|
||||||
|
"exited": ContainerStateStopped,
|
||||||
|
"dead": ContainerStateDead,
|
||||||
|
"created": ContainerStateCreated,
|
||||||
|
"paused": ContainerStatePaused,
|
||||||
|
}
|
||||||
|
|
||||||
// Helper function to log messages and handle error wrapping.
|
// Helper function to log messages and handle error wrapping.
|
||||||
func logStreamWrapError(gitspaceLogger orchestratorTypes.GitspaceLogger, msg string, err error) error {
|
func logStreamWrapError(gitspaceLogger orchestratorTypes.GitspaceLogger, msg string, err error) error {
|
||||||
gitspaceLogger.Error(msg, err)
|
gitspaceLogger.Error(msg, err)
|
||||||
@ -49,7 +54,7 @@ func logStreamWrapError(gitspaceLogger orchestratorTypes.GitspaceLogger, msg str
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generalized Docker Container Management.
|
// Generalized Docker Container Management.
|
||||||
func (e *EmbeddedDockerOrchestrator) manageContainer(
|
func ManageContainer(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
action Action,
|
action Action,
|
||||||
containerName string,
|
containerName string,
|
||||||
@ -83,7 +88,7 @@ func (e *EmbeddedDockerOrchestrator) manageContainer(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EmbeddedDockerOrchestrator) containerState(
|
func FetchContainerState(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
containerName string,
|
containerName string,
|
||||||
dockerClient *client.Client,
|
dockerClient *client.Client,
|
||||||
@ -99,12 +104,22 @@ func (e *EmbeddedDockerOrchestrator) containerState(
|
|||||||
if len(containers) == 0 {
|
if len(containers) == 0 {
|
||||||
return ContainerStateRemoved, nil
|
return ContainerStateRemoved, nil
|
||||||
}
|
}
|
||||||
|
containerState := ContainerStateUnknown
|
||||||
|
for _, value := range containers {
|
||||||
|
name, _ := strings.CutPrefix(value.Names[0], "/")
|
||||||
|
if name == containerName {
|
||||||
|
if state, ok := containerStateMapping[value.State]; ok {
|
||||||
|
containerState = state
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return State(containers[0].State), nil
|
return containerState, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new Docker container.
|
// Create a new Docker container.
|
||||||
func (e *EmbeddedDockerOrchestrator) createContainer(
|
func CreateContainer(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
dockerClient *client.Client,
|
dockerClient *client.Client,
|
||||||
imageName string,
|
imageName string,
|
||||||
@ -174,7 +189,7 @@ func prepareHostConfig(volumeName, homeDir string, portBindings nat.PortMap) *co
|
|||||||
|
|
||||||
return hostConfig
|
return hostConfig
|
||||||
}
|
}
|
||||||
func (e *EmbeddedDockerOrchestrator) getContainerInfo(
|
func GetContainerInfo(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
containerName string,
|
containerName string,
|
||||||
dockerClient *client.Client,
|
dockerClient *client.Client,
|
||||||
@ -201,7 +216,7 @@ func (e *EmbeddedDockerOrchestrator) getContainerInfo(
|
|||||||
return inspectResp.ID, usedPorts, nil
|
return inspectResp.ID, usedPorts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EmbeddedDockerOrchestrator) pullImage(
|
func PullImage(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
imageName string,
|
imageName string,
|
||||||
dockerClient *client.Client,
|
dockerClient *client.Client,
|
||||||
@ -230,101 +245,15 @@ func (e *EmbeddedDockerOrchestrator) pullImage(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EmbeddedDockerOrchestrator) runGitspaceSetupSteps(
|
|
||||||
ctx context.Context,
|
|
||||||
gitspaceConfig types.GitspaceConfig,
|
|
||||||
dockerClient *client.Client,
|
|
||||||
ideService ide.IDE,
|
|
||||||
infrastructure types.Infrastructure,
|
|
||||||
resolvedRepoDetails scm.ResolvedDetails,
|
|
||||||
defaultBaseImage string,
|
|
||||||
gitspaceLogger orchestratorTypes.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
homeDir := GetUserHomeDir(gitspaceConfig.GitspaceUser.Identifier)
|
|
||||||
containerName := GetGitspaceContainerName(gitspaceConfig)
|
|
||||||
|
|
||||||
devcontainerConfig := resolvedRepoDetails.DevcontainerConfig
|
|
||||||
imageName := devcontainerConfig.Image
|
|
||||||
if imageName == "" {
|
|
||||||
imageName = defaultBaseImage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pull the required image
|
|
||||||
if err := e.pullImage(ctx, imageName, dockerClient, gitspaceLogger); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
portMappings := infrastructure.GitspacePortMappings
|
|
||||||
forwardPorts := ExtractForwardPorts(devcontainerConfig)
|
|
||||||
if len(forwardPorts) > 0 {
|
|
||||||
for _, port := range forwardPorts {
|
|
||||||
portMappings[port] = &types.PortMapping{
|
|
||||||
PublishedPort: port,
|
|
||||||
ForwardedPort: port,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gitspaceLogger.Info(fmt.Sprintf("Forwarding ports : %v", forwardPorts))
|
|
||||||
}
|
|
||||||
|
|
||||||
storage := infrastructure.Storage
|
|
||||||
environment := ExtractEnv(devcontainerConfig)
|
|
||||||
if len(environment) > 0 {
|
|
||||||
gitspaceLogger.Info(fmt.Sprintf("Setting Environment : %v", environment))
|
|
||||||
}
|
|
||||||
// Create the container
|
|
||||||
err := e.createContainer(
|
|
||||||
ctx,
|
|
||||||
dockerClient,
|
|
||||||
imageName,
|
|
||||||
containerName,
|
|
||||||
gitspaceLogger,
|
|
||||||
storage,
|
|
||||||
homeDir,
|
|
||||||
portMappings,
|
|
||||||
environment,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the container
|
|
||||||
if err := e.manageContainer(ctx, ContainerActionStart, containerName, dockerClient, gitspaceLogger); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup and run commands
|
|
||||||
exec := &devcontainer.Exec{
|
|
||||||
ContainerName: containerName,
|
|
||||||
DockerClient: dockerClient,
|
|
||||||
HomeDir: homeDir,
|
|
||||||
UserIdentifier: gitspaceConfig.GitspaceUser.Identifier,
|
|
||||||
AccessKey: *gitspaceConfig.GitspaceInstance.AccessKey,
|
|
||||||
AccessType: gitspaceConfig.GitspaceInstance.AccessType,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := e.setupGitspaceAndIDE(
|
|
||||||
ctx,
|
|
||||||
exec,
|
|
||||||
gitspaceLogger,
|
|
||||||
ideService,
|
|
||||||
gitspaceConfig,
|
|
||||||
resolvedRepoDetails,
|
|
||||||
defaultBaseImage,
|
|
||||||
); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getContainerResponse retrieves container information and prepares the start response.
|
// getContainerResponse retrieves container information and prepares the start response.
|
||||||
func (e *EmbeddedDockerOrchestrator) getContainerResponse(
|
func GetContainerResponse(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
dockerClient *client.Client,
|
dockerClient *client.Client,
|
||||||
containerName string,
|
containerName string,
|
||||||
portMappings map[int]*types.PortMapping,
|
portMappings map[int]*types.PortMapping,
|
||||||
codeRepoDir string,
|
codeRepoDir string,
|
||||||
) (*StartResponse, error) {
|
) (*StartResponse, error) {
|
||||||
id, ports, err := e.getContainerInfo(ctx, containerName, dockerClient, portMappings)
|
id, ports, err := GetContainerInfo(ctx, containerName, dockerClient, portMappings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
@ -156,6 +156,9 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
|
|||||||
ideService); err != nil {
|
ideService); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
case ContainerStatePaused, ContainerStateCreated, ContainerStateUnknown, ContainerStateDead:
|
||||||
|
// TODO handle the following states
|
||||||
|
return nil, fmt.Errorf("gitspace %s is in a unhandled state: %s", containerName, state)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("gitspace %s is in a bad state: %s", containerName, state)
|
return nil, fmt.Errorf("gitspace %s is in a bad state: %s", containerName, state)
|
||||||
@ -165,7 +168,7 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
|
|||||||
codeRepoDir := filepath.Join(homeDir, resolvedRepoDetails.RepoName)
|
codeRepoDir := filepath.Join(homeDir, resolvedRepoDetails.RepoName)
|
||||||
|
|
||||||
// Step 5: Retrieve container information and return response
|
// Step 5: Retrieve container information and return response
|
||||||
return e.getContainerResponse(ctx, dockerClient, containerName, infra.GitspacePortMappings, codeRepoDir)
|
return GetContainerResponse(ctx, dockerClient, containerName, infra.GitspacePortMappings, codeRepoDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
// startStoppedGitspace starts the Gitspace container if it was stopped.
|
// startStoppedGitspace starts the Gitspace container if it was stopped.
|
||||||
@ -185,7 +188,7 @@ func (e *EmbeddedDockerOrchestrator) startStoppedGitspace(
|
|||||||
}
|
}
|
||||||
defer e.flushLogStream(logStreamInstance, gitspaceConfig.ID)
|
defer e.flushLogStream(logStreamInstance, gitspaceConfig.ID)
|
||||||
|
|
||||||
startErr := e.manageContainer(ctx, ContainerActionStart, containerName, dockerClient, logStreamInstance)
|
startErr := ManageContainer(ctx, ContainerActionStart, containerName, dockerClient, logStreamInstance)
|
||||||
if startErr != nil {
|
if startErr != nil {
|
||||||
return startErr
|
return startErr
|
||||||
}
|
}
|
||||||
@ -260,7 +263,9 @@ func (e *EmbeddedDockerOrchestrator) StopGitspace(
|
|||||||
if err := e.stopRunningGitspace(ctx, gitspaceConfig, containerName, dockerClient); err != nil {
|
if err := e.stopRunningGitspace(ctx, gitspaceConfig, containerName, dockerClient); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case ContainerStatePaused, ContainerStateCreated, ContainerStateUnknown, ContainerStateDead:
|
||||||
|
// TODO handle the following states
|
||||||
|
return fmt.Errorf("gitspace %s is in a unhandled state: %s", containerName, state)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("gitspace %s is in a bad state: %s", containerName, state)
|
return fmt.Errorf("gitspace %s is in a bad state: %s", containerName, state)
|
||||||
}
|
}
|
||||||
@ -284,7 +289,7 @@ func (e *EmbeddedDockerOrchestrator) stopRunningGitspace(
|
|||||||
defer e.flushLogStream(logStreamInstance, gitspaceConfig.ID)
|
defer e.flushLogStream(logStreamInstance, gitspaceConfig.ID)
|
||||||
|
|
||||||
// Step 5: Stop the container
|
// Step 5: Stop the container
|
||||||
return e.manageContainer(ctx, ContainerActionStop, containerName, dockerClient, logStreamInstance)
|
return ManageContainer(ctx, ContainerActionStop, containerName, dockerClient, logStreamInstance)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
@ -331,7 +336,7 @@ func (e *EmbeddedDockerOrchestrator) StopAndRemoveGitspace(
|
|||||||
// Step 5: Stop the container if it's not already stopped
|
// Step 5: Stop the container if it's not already stopped
|
||||||
if state != ContainerStateStopped {
|
if state != ContainerStateStopped {
|
||||||
logger.Debug().Msg("stopping gitspace")
|
logger.Debug().Msg("stopping gitspace")
|
||||||
if err := e.manageContainer(
|
if err := ManageContainer(
|
||||||
ctx, ContainerActionStop, containerName, dockerClient, logStreamInstance); err != nil {
|
ctx, ContainerActionStop, containerName, dockerClient, logStreamInstance); err != nil {
|
||||||
return fmt.Errorf("failed to stop gitspace %s: %w", containerName, err)
|
return fmt.Errorf("failed to stop gitspace %s: %w", containerName, err)
|
||||||
}
|
}
|
||||||
@ -340,7 +345,7 @@ func (e *EmbeddedDockerOrchestrator) StopAndRemoveGitspace(
|
|||||||
|
|
||||||
// Step 6: Remove the container
|
// Step 6: Remove the container
|
||||||
logger.Debug().Msg("removing gitspace")
|
logger.Debug().Msg("removing gitspace")
|
||||||
if err := e.manageContainer(
|
if err := ManageContainer(
|
||||||
ctx, ContainerActionRemove, containerName, dockerClient, logStreamInstance); err != nil {
|
ctx, ContainerActionRemove, containerName, dockerClient, logStreamInstance); err != nil {
|
||||||
return fmt.Errorf("failed to remove gitspace %s: %w", containerName, err)
|
return fmt.Errorf("failed to remove gitspace %s: %w", containerName, err)
|
||||||
}
|
}
|
||||||
@ -364,6 +369,92 @@ func (e *EmbeddedDockerOrchestrator) getAccessKey(gitspaceConfig types.GitspaceC
|
|||||||
return "", fmt.Errorf("no access key is configured: %s", gitspaceConfig.Identifier)
|
return "", fmt.Errorf("no access key is configured: %s", gitspaceConfig.Identifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *EmbeddedDockerOrchestrator) runGitspaceSetupSteps(
|
||||||
|
ctx context.Context,
|
||||||
|
gitspaceConfig types.GitspaceConfig,
|
||||||
|
dockerClient *client.Client,
|
||||||
|
ideService ide.IDE,
|
||||||
|
infrastructure types.Infrastructure,
|
||||||
|
resolvedRepoDetails scm.ResolvedDetails,
|
||||||
|
defaultBaseImage string,
|
||||||
|
gitspaceLogger orchestratorTypes.GitspaceLogger,
|
||||||
|
) error {
|
||||||
|
homeDir := GetUserHomeDir(gitspaceConfig.GitspaceUser.Identifier)
|
||||||
|
containerName := GetGitspaceContainerName(gitspaceConfig)
|
||||||
|
|
||||||
|
devcontainerConfig := resolvedRepoDetails.DevcontainerConfig
|
||||||
|
imageName := devcontainerConfig.Image
|
||||||
|
if imageName == "" {
|
||||||
|
imageName = defaultBaseImage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pull the required image
|
||||||
|
if err := PullImage(ctx, imageName, dockerClient, gitspaceLogger); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
portMappings := infrastructure.GitspacePortMappings
|
||||||
|
forwardPorts := ExtractForwardPorts(devcontainerConfig)
|
||||||
|
if len(forwardPorts) > 0 {
|
||||||
|
for _, port := range forwardPorts {
|
||||||
|
portMappings[port] = &types.PortMapping{
|
||||||
|
PublishedPort: port,
|
||||||
|
ForwardedPort: port,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gitspaceLogger.Info(fmt.Sprintf("Forwarding ports : %v", forwardPorts))
|
||||||
|
}
|
||||||
|
|
||||||
|
storage := infrastructure.Storage
|
||||||
|
environment := ExtractEnv(devcontainerConfig)
|
||||||
|
if len(environment) > 0 {
|
||||||
|
gitspaceLogger.Info(fmt.Sprintf("Setting Environment : %v", environment))
|
||||||
|
}
|
||||||
|
// Create the container
|
||||||
|
err := CreateContainer(
|
||||||
|
ctx,
|
||||||
|
dockerClient,
|
||||||
|
imageName,
|
||||||
|
containerName,
|
||||||
|
gitspaceLogger,
|
||||||
|
storage,
|
||||||
|
homeDir,
|
||||||
|
portMappings,
|
||||||
|
environment,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the container
|
||||||
|
if err := ManageContainer(ctx, ContainerActionStart, containerName, dockerClient, gitspaceLogger); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup and run commands
|
||||||
|
exec := &devcontainer.Exec{
|
||||||
|
ContainerName: containerName,
|
||||||
|
DockerClient: dockerClient,
|
||||||
|
HomeDir: homeDir,
|
||||||
|
UserIdentifier: gitspaceConfig.GitspaceUser.Identifier,
|
||||||
|
AccessKey: *gitspaceConfig.GitspaceInstance.AccessKey,
|
||||||
|
AccessType: gitspaceConfig.GitspaceInstance.AccessType,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := e.setupGitspaceAndIDE(
|
||||||
|
ctx,
|
||||||
|
exec,
|
||||||
|
gitspaceLogger,
|
||||||
|
ideService,
|
||||||
|
gitspaceConfig,
|
||||||
|
resolvedRepoDetails,
|
||||||
|
defaultBaseImage,
|
||||||
|
); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// getDockerClient creates and returns a new Docker client using the factory.
|
// getDockerClient creates and returns a new Docker client using the factory.
|
||||||
func (e *EmbeddedDockerOrchestrator) getDockerClient(
|
func (e *EmbeddedDockerOrchestrator) getDockerClient(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
@ -390,7 +481,7 @@ func (e *EmbeddedDockerOrchestrator) checkContainerState(
|
|||||||
containerName string,
|
containerName string,
|
||||||
) (State, error) {
|
) (State, error) {
|
||||||
log.Debug().Msg("checking current state of gitspace")
|
log.Debug().Msg("checking current state of gitspace")
|
||||||
state, err := e.containerState(ctx, containerName, dockerClient)
|
state, err := FetchContainerState(ctx, containerName, dockerClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,11 @@ type State string
|
|||||||
const (
|
const (
|
||||||
ContainerStateRunning = State("running")
|
ContainerStateRunning = State("running")
|
||||||
ContainerStateRemoved = State("removed")
|
ContainerStateRemoved = State("removed")
|
||||||
|
ContainerStateDead = State("dead")
|
||||||
ContainerStateStopped = State("exited")
|
ContainerStateStopped = State("exited")
|
||||||
|
ContainerStatePaused = State("paused")
|
||||||
|
ContainerStateUnknown = State("unknown")
|
||||||
|
ContainerStateCreated = State("created")
|
||||||
)
|
)
|
||||||
|
|
||||||
type Action string
|
type Action string
|
||||||
|
Loading…
x
Reference in New Issue
Block a user