feat: [CDE-173]: Running IDE and related services on boot up. Changing entrypoint cmd for quicker stopping. (#2240)

* feat: [CDE-173]: Running IDE and related services on boot up. Changing entrypoint cmd for quicker stopping.
unified-ui
Dhruv Dhruv 2024-07-17 13:12:49 +00:00 committed by Harness
parent 1af6be80e9
commit ed92f75f68
10 changed files with 131 additions and 45 deletions

View File

@ -136,6 +136,17 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
return nil, startErr
}
devcontainer := &Devcontainer{
ContainerName: containerName,
WorkingDir: e.getWorkingDir(repoName),
DockerClient: dockerClient,
}
err = e.runIDE(ctx, devcontainer, ideService, logStreamInstance)
if err != nil {
return nil, err
}
// TODO: Add gitspace status reporting.
log.Debug().Msg("started gitspace")
@ -154,8 +165,6 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
}
}()
workingDirectory := "/" + repoName
startErr := e.startGitspace(
ctx,
gitspaceConfig,
@ -165,7 +174,7 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
ideService,
logStreamInstance,
infra.Storage,
workingDirectory,
e.getWorkingDir(repoName),
)
if startErr != nil {
return nil, fmt.Errorf("failed to start gitspace %s: %w", containerName, startErr)
@ -190,6 +199,10 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
}, nil
}
func (e *EmbeddedDockerOrchestrator) getWorkingDir(repoName string) string {
return "/" + repoName
}
func (e *EmbeddedDockerOrchestrator) startGitspace(
ctx context.Context,
gitspaceConfig *types.GitspaceConfig,
@ -246,6 +259,11 @@ func (e *EmbeddedDockerOrchestrator) startGitspace(
return err
}
err = e.runIDE(ctx, devcontainer, ideService, logStreamInstance)
if err != nil {
return err
}
err = e.executePostCreateCommand(ctx, devcontainerConfig, devcontainer, logStreamInstance)
if err != nil {
return err
@ -254,6 +272,45 @@ func (e *EmbeddedDockerOrchestrator) startGitspace(
return nil
}
// TODO: Instead of explicitly running IDE related processes, we can explore service to run the service on boot.
func (e *EmbeddedDockerOrchestrator) runIDE(
ctx context.Context,
devcontainer *Devcontainer,
ideService IDE,
logStreamInstance *logutil.LogStreamInstance,
) error {
loggingErr := logStreamInstance.Write("Running the IDE inside container: " + string(ideService.Type()))
if loggingErr != nil {
return fmt.Errorf("logging error: %w", loggingErr)
}
output, err := ideService.Run(ctx, devcontainer)
if err != nil {
loggingErr = logStreamInstance.Write("Error while running IDE inside container: " + err.Error())
err = fmt.Errorf("failed to run the IDE for gitspace %s: %w", devcontainer.ContainerName, err)
if loggingErr != nil {
err = fmt.Errorf("original error: %w; logging error: %w", err, loggingErr)
}
return err
}
loggingErr = logStreamInstance.Write("IDE run output...\n" + string(output))
if loggingErr != nil {
return fmt.Errorf("logging error: %w", loggingErr)
}
loggingErr = logStreamInstance.Write("Successfully run the IDE inside container")
if loggingErr != nil {
return fmt.Errorf("logging error: %w", loggingErr)
}
return nil
}
func (e *EmbeddedDockerOrchestrator) setupIDE(
ctx context.Context,
gitspaceInstance *types.GitspaceInstance,
@ -489,8 +546,6 @@ func (e *EmbeddedDockerOrchestrator) createContainer(
portBindings[natPort] = hostPortBindings
}
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)
@ -498,7 +553,8 @@ func (e *EmbeddedDockerOrchestrator) createContainer(
_, err := dockerClient.ContainerCreate(ctx, &container.Config{
Image: imageName,
Entrypoint: entryPoint,
Entrypoint: []string{"/bin/bash"},
Cmd: []string{"-c", "trap \"exit 0\" 15;\n sleep infinity & wait $!"},
ExposedPorts: exposedPorts,
}, &container.HostConfig{
PortBindings: portBindings,

View File

@ -23,9 +23,12 @@ import (
type IDE interface {
// Setup is responsible for doing all the operations for setting up the IDE in the container e.g. installation,
// copying settings and configurations, ensuring SSH server is running etc.
// copying settings and configurations.
Setup(ctx context.Context, containerParams *Devcontainer, gitspaceInstance *types.GitspaceInstance) ([]byte, error)
// Run runs the IDE and supporting services.
Run(ctx context.Context, containerParams *Devcontainer) ([]byte, error)
// PortAndProtocol provides the port with protocol which will be used by this IDE.
PortAndProtocol() string

View File

@ -40,7 +40,7 @@ type CloneGitPayload struct {
Branch string
}
type RunVSCodeWebPayload struct {
type InstallVSCodeWebPayload struct {
Port string
}

View File

@ -45,6 +45,4 @@ EOL
fi
else
echo "devcontainer_present is set to true. Skipping .devcontainer creation."
fi
echo "Script completed."
fi

View File

@ -1,5 +1,17 @@
#!/bin/bash
echo "Installing code-server"
echo "Installing VSCode Web"
curl -fsSL https://code-server.dev/install.sh | sh
curl -fsSL https://code-server.dev/install.sh | sh
port={{ .Port }}
# Ensure the configuration directory exists
mkdir -p /root/.config/code-server
# Create or overwrite the config file with new settings
cat > /root/.config/code-server/config.yaml <<EOF
bind-addr: 0.0.0.0:$port
auth: none
cert: false
EOF

View File

@ -0,0 +1,5 @@
#!/bin/bash
echo "Running SSH Server"
/usr/sbin/sshd

View File

@ -1,17 +1,5 @@
#!/bin/bash
echo "Running code-server"
port={{ .Port }}
# Ensure the configuration directory exists
mkdir -p /root/.config/code-server
# Create or overwrite the config file with new settings
cat > /root/.config/code-server/config.yaml <<EOF
bind-addr: 0.0.0.0:$port
auth: none
cert: false
EOF
echo "Running VSCode Web"
code-server

View File

@ -48,5 +48,4 @@ fi
# Changing ownership of everything inside user home to the newly created user
chown -R $username .
mkdir /var/run/sshd
/usr/sbin/sshd
mkdir /var/run/sshd

View File

@ -20,10 +20,15 @@ import (
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
_ "embed"
)
var _ IDE = (*VSCode)(nil)
//go:embed template/run_ssh_server.sh
var runSSHScript string
const sshPort = "22/tcp"
type VSCode struct{}
@ -32,7 +37,7 @@ func NewVsCodeService() *VSCode {
return &VSCode{}
}
// Setup installs and runs SSH server inside the container.
// Setup installs the SSH server inside the container.
func (v *VSCode) Setup(
ctx context.Context,
devcontainer *Devcontainer,
@ -63,6 +68,20 @@ func (v *VSCode) Setup(
return []byte(output), nil
}
// Run runs the SSH server inside the container.
func (v *VSCode) Run(ctx context.Context, devcontainer *Devcontainer) ([]byte, error) {
var output = ""
execOutput, err := devcontainer.ExecuteCommand(ctx, runSSHScript, false)
if err != nil {
return nil, fmt.Errorf("failed to run SSH serverr: %w", err)
}
output += "SSH server run output...\n" + string(execOutput) + "\nSuccessfully run ssh-server\n"
return []byte(output), nil
}
// PortAndProtocol returns the port on which the ssh-server is listening.
func (v *VSCode) PortAndProtocol() string {
return sshPort

View File

@ -26,10 +26,10 @@ import (
var _ IDE = (*VSCodeWeb)(nil)
//go:embed template/install_vscode_web.sh
var installScript string
//go:embed template/run_vscode_web.sh
var runScript string
const templateRunVSCodeWeb = "run_vscode_web.sh"
const templateInstallVSCodeWeb = "install_vscode_web.sh"
type VSCodeWebConfig struct {
Port string
@ -43,33 +43,39 @@ func NewVsCodeWebService(config *VSCodeWebConfig) *VSCodeWeb {
return &VSCodeWeb{config: config}
}
// Setup runs the installScript which downloads the required version of the code-server binary and runs it.
// Setup runs the installScript which downloads the required version of the code-server binary.
func (v *VSCodeWeb) Setup(ctx context.Context, devcontainer *Devcontainer, _ *types.GitspaceInstance) ([]byte, error) {
output, err := devcontainer.ExecuteCommand(ctx, installScript, false)
if err != nil {
return nil, fmt.Errorf("failed to install code-server: %w", err)
}
runScript, err := GenerateScriptFromTemplate(
templateRunVSCodeWeb, &RunVSCodeWebPayload{
installScript, err := GenerateScriptFromTemplate(
templateInstallVSCodeWeb, &InstallVSCodeWebPayload{
Port: v.config.Port,
})
if err != nil {
return output, fmt.Errorf(
"failed to generate scipt to run code-server from template %s: %w",
templateRunVSCodeWeb,
return nil, fmt.Errorf(
"failed to generate scipt to install VSCode Web from template %s: %w",
templateInstallVSCodeWeb,
err,
)
}
_, err = devcontainer.ExecuteCommand(ctx, runScript, true)
output, err := devcontainer.ExecuteCommand(ctx, installScript, false)
if err != nil {
return output, fmt.Errorf("failed to run code-server: %w", err)
return nil, fmt.Errorf("failed to install VSCode Web: %w", err)
}
return output, nil
}
// Run runs the code-server binary.
func (v *VSCodeWeb) Run(ctx context.Context, devcontainer *Devcontainer) ([]byte, error) {
var output []byte
_, err := devcontainer.ExecuteCommand(ctx, runScript, true)
if err != nil {
return nil, fmt.Errorf("failed to run VSCode Web: %w", err)
}
return output, nil
}
// PortAndProtocol returns the port on which the code-server is listening.
func (v *VSCodeWeb) PortAndProtocol() string {
return v.config.Port + "/tcp"