* feat: [CDE-194]: Reverting docker port range changes.
* feat: [CDE-194]: Removing extra types.
* feat: [CDE-194]: Restructuring code around port publishing and forwarding.
* WIP
* WIP
* WIP
* WIP
pull/3545/head
Dhruv Dhruv 2024-07-26 06:26:22 +00:00 committed by Harness
parent eeb4c50af1
commit 9232029c74
34 changed files with 293 additions and 174 deletions

View File

@ -4,4 +4,5 @@ GITNESS_PRINCIPAL_ADMIN_EMAIL=admin@gitness.io
GITNESS_PRINCIPAL_ADMIN_PASSWORD=changeit
GITNESS_WEBHOOK_ALLOW_LOOPBACK=true
GITNESS_METRIC_ENABLED=false
GITNESS_GITSPACE_ENABLE=true
GITNESS_GITSPACE_ENABLE=true
GITNESS_DEBUG=true

View File

@ -30,6 +30,7 @@ type InfraProvisioner interface {
ctx context.Context,
infraProviderResource *types.InfraProviderResource,
gitspaceConfig *types.GitspaceConfig,
requiredPorts []int,
) (*infraprovider.Infrastructure, error)
// Stop unprovisions those resources which can be stopped without losing the gitspace data.

View File

@ -48,6 +48,7 @@ func (i infraProvisioner) Provision(
ctx context.Context,
infraProviderResource *types.InfraProviderResource,
gitspaceConfig *types.GitspaceConfig,
requiredPorts []int,
) (*infraprovider.Infrastructure, error) {
infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource)
if err != nil {
@ -69,6 +70,7 @@ func (i infraProvisioner) Provision(
if err != nil {
return nil, err
}
allParams = append(allParams, templateParams...)
params := i.paramsFromResource(infraProviderResource)
@ -80,7 +82,13 @@ func (i infraProvisioner) Provision(
return nil, fmt.Errorf("invalid provisioning params %v: %w", infraProviderResource.Metadata, err)
}
provisionedInfra, err := infraProvider.Provision(ctx, gitspaceConfig.SpacePath, gitspaceConfig.Identifier, allParams)
provisionedInfra, err := infraProvider.Provision(
ctx,
gitspaceConfig.SpacePath,
gitspaceConfig.Identifier,
requiredPorts,
allParams,
)
if err != nil {
return nil, fmt.Errorf(
"unable to provision infrastructure for gitspaceConfigIdentifier %v: %w",

View File

@ -17,6 +17,7 @@ package container
import (
"context"
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
"github.com/harness/gitness/infraprovider"
"github.com/harness/gitness/types"
)
@ -31,6 +32,8 @@ type Orchestrator interface {
devcontainerConfig *types.DevcontainerConfig,
infra *infraprovider.Infrastructure,
repoName string,
defaultBaseImage string,
ideService ide.IDE,
) (*StartResponse, error)
// StopGitspace stops the gitspace container.

View File

@ -18,11 +18,15 @@ import (
"context"
"fmt"
"io"
"strconv"
"strings"
"github.com/harness/gitness/app/gitspace/logutil"
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
"github.com/harness/gitness/app/gitspace/orchestrator/template"
"github.com/harness/gitness/infraprovider"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
dockerTypes "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
@ -36,40 +40,25 @@ import (
var _ Orchestrator = (*EmbeddedDockerOrchestrator)(nil)
const (
loggingKey = "gitspace.container"
catchAllIP = "0.0.0.0"
catchAllPort = "0"
containerStateRunning = "running"
containerStateRemoved = "removed"
containerStateStopped = "exited"
templateCloneGit = "clone_git.sh"
templateSetupSSHServer = "setup_ssh_server.sh"
loggingKey = "gitspace.container"
catchAllIP = "0.0.0.0"
containerStateRunning = "running"
containerStateRemoved = "removed"
containerStateStopped = "exited"
templateCloneGit = "clone_git.sh"
)
type Config struct {
DefaultBaseImage string
}
type EmbeddedDockerOrchestrator struct {
dockerClientFactory *infraprovider.DockerClientFactory
vsCodeService *VSCode
vsCodeWebService *VSCodeWeb
config *Config
statefulLogger *logutil.StatefulLogger
}
func NewEmbeddedDockerOrchestrator(
dockerClientFactory *infraprovider.DockerClientFactory,
vsCodeService *VSCode,
vsCodeWebService *VSCodeWeb,
config *Config,
statefulLogger *logutil.StatefulLogger,
) Orchestrator {
return &EmbeddedDockerOrchestrator{
dockerClientFactory: dockerClientFactory,
vsCodeService: vsCodeService,
vsCodeWebService: vsCodeWebService,
config: config,
statefulLogger: statefulLogger,
}
}
@ -84,6 +73,8 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
devcontainerConfig *types.DevcontainerConfig,
infra *infraprovider.Infrastructure,
repoName string,
defaultBaseImage string,
ideService ide.IDE,
) (*StartResponse, error) {
containerName := getGitspaceContainerName(gitspaceConfig)
@ -107,11 +98,6 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
return nil, err
}
ideService, err := e.getIDEService(gitspaceConfig)
if err != nil {
return nil, err
}
switch state {
case containerStateRunning:
log.Debug().Msg("gitspace is already running")
@ -136,7 +122,7 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
return nil, startErr
}
devcontainer := &Devcontainer{
devcontainer := &devcontainer.Devcontainer{
ContainerName: containerName,
WorkingDir: e.getWorkingDir(repoName),
DockerClient: dockerClient,
@ -175,6 +161,8 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
logStreamInstance,
infra.Storage,
e.getWorkingDir(repoName),
infra.PortMappings,
defaultBaseImage,
)
if startErr != nil {
return nil, fmt.Errorf("failed to start gitspace %s: %w", containerName, startErr)
@ -187,15 +175,15 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
return nil, fmt.Errorf("gitspace %s is in a bad state: %s", containerName, state)
}
id, ports, startErr := e.getContainerInfo(ctx, containerName, dockerClient, ideService)
id, ports, startErr := e.getContainerInfo(ctx, containerName, dockerClient, infra.PortMappings)
if startErr != nil {
return nil, startErr
}
return &StartResponse{
ContainerID: id,
ContainerName: containerName,
PortsUsed: ports,
ContainerID: id,
ContainerName: containerName,
PublishedPorts: ports,
}, nil
}
@ -209,14 +197,16 @@ func (e *EmbeddedDockerOrchestrator) startGitspace(
devcontainerConfig *types.DevcontainerConfig,
containerName string,
dockerClient *client.Client,
ideService IDE,
ideService ide.IDE,
logStreamInstance *logutil.LogStreamInstance,
volumeName string,
workingDirectory string,
portMappings map[int]*infraprovider.PortMapping,
defaultBaseImage string,
) error {
var imageName = devcontainerConfig.Image
if imageName == "" {
imageName = e.config.DefaultBaseImage
imageName = defaultBaseImage
}
err := e.pullImage(ctx, imageName, dockerClient, logStreamInstance)
@ -229,10 +219,10 @@ func (e *EmbeddedDockerOrchestrator) startGitspace(
dockerClient,
imageName,
containerName,
ideService,
logStreamInstance,
volumeName,
workingDirectory,
portMappings,
)
if err != nil {
return err
@ -243,7 +233,7 @@ func (e *EmbeddedDockerOrchestrator) startGitspace(
return err
}
var devcontainer = &Devcontainer{
var devcontainer = &devcontainer.Devcontainer{
ContainerName: containerName,
DockerClient: dockerClient,
WorkingDir: workingDirectory,
@ -259,7 +249,7 @@ func (e *EmbeddedDockerOrchestrator) startGitspace(
return err
}
err = e.cloneCode(ctx, gitspaceConfig, devcontainer, logStreamInstance)
err = e.cloneCode(ctx, gitspaceConfig, devcontainer, defaultBaseImage, logStreamInstance)
if err != nil {
return err
}
@ -276,8 +266,8 @@ func (e *EmbeddedDockerOrchestrator) startGitspace(
func (e *EmbeddedDockerOrchestrator) runIDE(
ctx context.Context,
devcontainer *Devcontainer,
ideService IDE,
devcontainer *devcontainer.Devcontainer,
ideService ide.IDE,
logStreamInstance *logutil.LogStreamInstance,
) error {
loggingErr := logStreamInstance.Write("Running the IDE inside container: " + string(ideService.Type()))
@ -314,8 +304,8 @@ func (e *EmbeddedDockerOrchestrator) runIDE(
func (e *EmbeddedDockerOrchestrator) setupIDE(
ctx context.Context,
gitspaceInstance *types.GitspaceInstance,
devcontainer *Devcontainer,
ideService IDE,
devcontainer *devcontainer.Devcontainer,
ideService ide.IDE,
logStreamInstance *logutil.LogStreamInstance,
) error {
loggingErr := logStreamInstance.Write("Setting up IDE inside container: " + string(ideService.Type()))
@ -353,48 +343,40 @@ func (e *EmbeddedDockerOrchestrator) getContainerInfo(
ctx context.Context,
containerName string,
dockerClient *client.Client,
ideService IDE,
) (string, map[enum.IDEType]string, error) {
portMappings map[int]*infraprovider.PortMapping,
) (string, map[int]string, error) {
inspectResp, err := dockerClient.ContainerInspect(ctx, containerName)
if err != nil {
return "", nil, fmt.Errorf("could not inspect container %s: %w", containerName, err)
}
usedPorts := map[enum.IDEType]string{}
for port, bindings := range inspectResp.NetworkSettings.Ports {
if port == nat.Port(ideService.PortAndProtocol()) {
usedPorts[ideService.Type()] = bindings[0].HostPort
var usedPorts = make(map[int]string)
for portAndProtocol, bindings := range inspectResp.NetworkSettings.Ports {
portRaw := strings.Split(string(portAndProtocol), "/")[0]
port, conversionErr := strconv.Atoi(portRaw)
if conversionErr != nil {
return "", nil, fmt.Errorf("could not convert port %s to int: %w", portRaw, err)
}
if portMappings[port] != nil {
usedPorts[port] = bindings[0].HostPort
}
}
return inspectResp.ID, usedPorts, nil
}
func (e *EmbeddedDockerOrchestrator) getIDEService(gitspaceConfig *types.GitspaceConfig) (IDE, error) {
var ideService IDE
switch gitspaceConfig.IDE {
case enum.IDETypeVSCode:
ideService = e.vsCodeService
case enum.IDETypeVSCodeWeb:
ideService = e.vsCodeWebService
default:
return nil, fmt.Errorf("unsupported IDE: %s", gitspaceConfig.IDE)
}
return ideService, nil
}
func (e *EmbeddedDockerOrchestrator) cloneCode(
ctx context.Context,
gitspaceConfig *types.GitspaceConfig,
devcontainer *Devcontainer,
devcontainer *devcontainer.Devcontainer,
defaultBaseImage string,
logStreamInstance *logutil.LogStreamInstance,
) error {
gitCloneScript, err := GenerateScriptFromTemplate(
templateCloneGit, &CloneGitPayload{
gitCloneScript, err := template.GenerateScriptFromTemplate(
templateCloneGit, &template.CloneGitPayload{
RepoURL: gitspaceConfig.CodeRepoURL,
Image: e.config.DefaultBaseImage,
Image: defaultBaseImage,
Branch: gitspaceConfig.Branch,
})
if err != nil {
@ -436,7 +418,7 @@ func (e *EmbeddedDockerOrchestrator) cloneCode(
func (e *EmbeddedDockerOrchestrator) executePostCreateCommand(
ctx context.Context,
devcontainerConfig *types.DevcontainerConfig,
devcontainer *Devcontainer,
devcontainer *devcontainer.Devcontainer,
logStreamInstance *logutil.LogStreamInstance,
) error {
if devcontainerConfig.PostCreateCommand == "" {
@ -516,25 +498,22 @@ func (e *EmbeddedDockerOrchestrator) createContainer(
dockerClient *client.Client,
imageName string,
containerName string,
ideService IDE,
logStreamInstance *logutil.LogStreamInstance,
volumeName string,
workingDirectory string,
portMappings map[int]*infraprovider.PortMapping,
) error {
portUsedByIDE := ideService.PortAndProtocol()
hostPortBindings := []nat.PortBinding{
{
HostIP: catchAllIP,
HostPort: catchAllPort,
},
}
exposedPorts := nat.PortSet{}
portBindings := nat.PortMap{}
if portUsedByIDE != "" {
natPort := nat.Port(portUsedByIDE)
for port, mapping := range portMappings {
natPort := nat.Port(strconv.Itoa(port) + "/tcp")
hostPortBindings := []nat.PortBinding{
{
HostIP: catchAllIP,
HostPort: strconv.Itoa(mapping.PublishedPort),
},
}
exposedPorts[natPort] = struct{}{}
portBindings[natPort] = hostPortBindings
}

View File

@ -14,11 +14,8 @@
package container
import "github.com/harness/gitness/types/enum"
type StartResponse struct {
ContainerID string
ContainerName string
WorkingDirectory string
PortsUsed map[enum.IDEType]string
ContainerID string
ContainerName string
PublishedPorts map[int]string
}

View File

@ -23,30 +23,14 @@ import (
var WireSet = wire.NewSet(
ProvideEmbeddedDockerOrchestrator,
ProvideVSCodeWebService,
ProvideVSCodeService,
)
func ProvideEmbeddedDockerOrchestrator(
dockerClientFactory *infraprovider.DockerClientFactory,
vsCodeService *VSCode,
vsCodeWebService *VSCodeWeb,
config *Config,
statefulLogger *logutil.StatefulLogger,
) Orchestrator {
return NewEmbeddedDockerOrchestrator(
dockerClientFactory,
vsCodeService,
vsCodeWebService,
config,
statefulLogger,
)
}
func ProvideVSCodeWebService(config *VSCodeWebConfig) *VSCodeWeb {
return NewVsCodeWebService(config)
}
func ProvideVSCodeService() *VSCode {
return NewVsCodeService()
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package container
package devcontainer
import (
"context"

View File

@ -12,11 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package container
package ide
import (
"context"
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
@ -24,13 +25,17 @@ 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.
Setup(ctx context.Context, containerParams *Devcontainer, gitspaceInstance *types.GitspaceInstance) ([]byte, error)
Setup(
ctx context.Context,
devcontainer *devcontainer.Devcontainer,
gitspaceInstance *types.GitspaceInstance,
) ([]byte, error)
// Run runs the IDE and supporting services.
Run(ctx context.Context, containerParams *Devcontainer) ([]byte, error)
Run(ctx context.Context, devcontainer *devcontainer.Devcontainer) ([]byte, error)
// PortAndProtocol provides the port with protocol which will be used by this IDE.
PortAndProtocol() string
// Port provides the port which will be used by this IDE.
Port() int
// Type provides the IDE type to which the service belongs.
Type() enum.IDEType

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 987 B

After

Width:  |  Height:  |  Size: 987 B

View File

Before

Width:  |  Height:  |  Size: 987 B

After

Width:  |  Height:  |  Size: 987 B

View File

Before

Width:  |  Height:  |  Size: 987 B

After

Width:  |  Height:  |  Size: 987 B

View File

@ -12,12 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package container
package ide
import (
"context"
"fmt"
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
"github.com/harness/gitness/app/gitspace/orchestrator/template"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
@ -29,7 +31,8 @@ var _ IDE = (*VSCode)(nil)
//go:embed script/run_ssh_server.sh
var runSSHScript string
const sshPort = "22/tcp"
const sshPort int = 22
const templateSetupSSHServer string = "setup_ssh_server.sh"
type VSCode struct{}
@ -40,11 +43,11 @@ func NewVsCodeService() *VSCode {
// Setup installs the SSH server inside the container.
func (v *VSCode) Setup(
ctx context.Context,
devcontainer *Devcontainer,
devcontainer *devcontainer.Devcontainer,
gitspaceInstance *types.GitspaceInstance,
) ([]byte, error) {
sshServerScript, err := GenerateScriptFromTemplate(
templateSetupSSHServer, &SetupSSHServerPayload{
sshServerScript, err := template.GenerateScriptFromTemplate(
templateSetupSSHServer, &template.SetupSSHServerPayload{
Username: "harness",
Password: *gitspaceInstance.AccessKey,
WorkingDirectory: devcontainer.WorkingDir,
@ -67,7 +70,7 @@ func (v *VSCode) Setup(
}
// Run runs the SSH server inside the container.
func (v *VSCode) Run(ctx context.Context, devcontainer *Devcontainer) ([]byte, error) {
func (v *VSCode) Run(ctx context.Context, devcontainer *devcontainer.Devcontainer) ([]byte, error) {
var output = ""
execOutput, err := devcontainer.ExecuteCommand(ctx, runSSHScript, false)
@ -80,8 +83,8 @@ func (v *VSCode) Run(ctx context.Context, devcontainer *Devcontainer) ([]byte, e
return []byte(output), nil
}
// PortAndProtocol returns the port on which the ssh-server is listening.
func (v *VSCode) PortAndProtocol() string {
// Port returns the port on which the ssh-server is listening.
func (v *VSCode) Port() int {
return sshPort
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package container
package ide
import (
"archive/tar"
@ -22,8 +22,11 @@ import (
"fmt"
"io"
"path/filepath"
"strconv"
"strings"
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
"github.com/harness/gitness/app/gitspace/orchestrator/template"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
@ -46,7 +49,7 @@ const startMarker = "START_MARKER"
const endMarker = "END_MARKER"
type VSCodeWebConfig struct {
Port string
Port int
}
type VSCodeWeb struct {
@ -58,10 +61,14 @@ func NewVsCodeWebService(config *VSCodeWebConfig) *VSCodeWeb {
}
// 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) {
installScript, err := GenerateScriptFromTemplate(
templateInstallVSCodeWeb, &InstallVSCodeWebPayload{
Port: v.config.Port,
func (v *VSCodeWeb) Setup(
ctx context.Context,
devcontainer *devcontainer.Devcontainer,
_ *types.GitspaceInstance,
) ([]byte, error) {
installScript, err := template.GenerateScriptFromTemplate(
templateInstallVSCodeWeb, &template.InstallVSCodeWebPayload{
Port: strconv.Itoa(v.config.Port),
})
if err != nil {
return nil, fmt.Errorf(
@ -102,7 +109,7 @@ func (v *VSCodeWeb) Setup(ctx context.Context, devcontainer *Devcontainer, _ *ty
}
// Run runs the code-server binary.
func (v *VSCodeWeb) Run(ctx context.Context, devcontainer *Devcontainer) ([]byte, error) {
func (v *VSCodeWeb) Run(ctx context.Context, devcontainer *devcontainer.Devcontainer) ([]byte, error) {
var output []byte
_, err := devcontainer.ExecuteCommand(ctx, runScript, true)
@ -113,15 +120,19 @@ func (v *VSCodeWeb) Run(ctx context.Context, devcontainer *Devcontainer) ([]byte
}
// PortAndProtocol returns the port on which the code-server is listening.
func (v *VSCodeWeb) PortAndProtocol() string {
return v.config.Port + "/tcp"
func (v *VSCodeWeb) Port() int {
return v.config.Port
}
func (v *VSCodeWeb) Type() enum.IDEType {
return enum.IDETypeVSCodeWeb
}
func (v *VSCodeWeb) copyMediaToContainer(ctx context.Context, devcontainer *Devcontainer, path string) error {
func (v *VSCodeWeb) copyMediaToContainer(
ctx context.Context,
devcontainer *devcontainer.Devcontainer,
path string,
) error {
// Create a buffer to hold the tar data
var tarBuffer bytes.Buffer
tarWriter := tar.NewWriter(&tarBuffer)

View File

@ -0,0 +1,32 @@
// 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 ide
import (
"github.com/google/wire"
)
var WireSet = wire.NewSet(
ProvideVSCodeWebService,
ProvideVSCodeService,
)
func ProvideVSCodeWebService(config *VSCodeWebConfig) *VSCodeWeb {
return NewVsCodeWebService(config)
}
func ProvideVSCodeService() *VSCode {
return NewVsCodeService()
}

View File

@ -19,11 +19,13 @@ import (
"fmt"
"net/url"
"path/filepath"
"strconv"
"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/orchestrator/ide"
"github.com/harness/gitness/app/gitspace/scm"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/infraprovider"
@ -33,12 +35,19 @@ import (
"github.com/rs/zerolog/log"
)
type Config struct {
DefaultBaseImage string
}
type orchestrator struct {
scm scm.SCM
infraProviderResourceStore store.InfraProviderResourceStore
infraProvisioner infrastructure.InfraProvisioner
containerOrchestrator container.Orchestrator
eventReporter *events.Reporter
config *Config
vsCodeService *ide.VSCode
vsCodeWebService *ide.VSCodeWeb
}
var _ Orchestrator = (*orchestrator)(nil)
@ -49,6 +58,9 @@ func NewOrchestrator(
infraProvisioner infrastructure.InfraProvisioner,
containerOrchestrator container.Orchestrator,
eventReporter *events.Reporter,
config *Config,
vsCodeService *ide.VSCode,
vsCodeWebService *ide.VSCodeWeb,
) Orchestrator {
return orchestrator{
scm: scm,
@ -56,6 +68,9 @@ func NewOrchestrator(
infraProvisioner: infraProvisioner,
containerOrchestrator: containerOrchestrator,
eventReporter: eventReporter,
config: config,
vsCodeService: vsCodeService,
vsCodeWebService: vsCodeWebService,
}
}
@ -88,9 +103,16 @@ func (o orchestrator) StartGitspace(
gitspaceConfig.InfraProviderResourceID, err)
}
ideSvc, err := o.getIDEService(gitspaceConfig)
if err != nil {
return err
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningStart)
infra, err := o.infraProvisioner.Provision(ctx, infraProviderResource, gitspaceConfig)
idePort := ideSvc.Port()
infra, err := o.infraProvisioner.Provision(ctx, infraProviderResource, gitspaceConfig, []int{idePort})
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningFailed)
@ -115,7 +137,7 @@ func (o orchestrator) StartGitspace(
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationStart)
startResponse, err := o.containerOrchestrator.CreateAndStartGitspace(
ctx, gitspaceConfig, devcontainerConfig, infra, repoName)
ctx, gitspaceConfig, devcontainerConfig, infra, repoName, o.config.DefaultBaseImage, ideSvc)
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationFailed)
@ -124,14 +146,20 @@ func (o orchestrator) StartGitspace(
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationCompleted)
port := startResponse.PortsUsed[gitspaceConfig.IDE]
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 + ":" + port,
Host: infra.Host + ":" + forwardedPort,
RawQuery: filepath.Join("folder=", repoName),
}
} else if gitspaceConfig.IDE == enum.IDETypeVSCode {
@ -144,7 +172,7 @@ func (o orchestrator) StartGitspace(
"ssh-remote+%s@%s:%s",
userID,
infra.Host,
filepath.Join(port, repoName),
filepath.Join(forwardedPort, repoName),
),
}
}
@ -317,3 +345,18 @@ func (o orchestrator) emitGitspaceEvent(
Timestamp: time.Now().UnixNano(),
})
}
func (o orchestrator) getIDEService(gitspaceConfig *types.GitspaceConfig) (ide.IDE, error) {
var ideService ide.IDE
switch gitspaceConfig.IDE {
case enum.IDETypeVSCode:
ideService = o.vsCodeService
case enum.IDETypeVSCodeWeb:
ideService = o.vsCodeWebService
default:
return nil, fmt.Errorf("unsupported IDE: %s", gitspaceConfig.IDE)
}
return ideService, nil
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package container
package template
import (
"bytes"
@ -24,11 +24,11 @@ import (
)
const (
templatesDir = "template"
templatesDir = "templates"
)
var (
//go:embed template/*
//go:embed templates/*
files embed.FS
scriptTemplates map[string]*template.Template
)

View File

@ -18,6 +18,7 @@ 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/orchestrator/ide"
"github.com/harness/gitness/app/gitspace/scm"
"github.com/harness/gitness/app/store"
@ -35,6 +36,18 @@ func ProvideOrchestrator(
infraProvisioner infrastructure.InfraProvisioner,
containerOrchestrator container.Orchestrator,
reporter *events.Reporter,
config *Config,
vsCodeService *ide.VSCode,
vsCodeWebService *ide.VSCodeWeb,
) Orchestrator {
return NewOrchestrator(scm, infraProviderResourceStore, infraProvisioner, containerOrchestrator, reporter)
return NewOrchestrator(
scm,
infraProviderResourceStore,
infraProvisioner,
containerOrchestrator,
reporter,
config,
vsCodeService,
vsCodeWebService,
)
}

View File

@ -22,7 +22,8 @@ import (
"strings"
"unicode"
"github.com/harness/gitness/app/gitspace/orchestrator/container"
"github.com/harness/gitness/app/gitspace/orchestrator"
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
"github.com/harness/gitness/app/services/cleanup"
"github.com/harness/gitness/app/services/codeowners"
"github.com/harness/gitness/app/services/gitspaceevent"
@ -398,15 +399,15 @@ func ProvideDockerConfig(config *types.Config) (*infraprovider.DockerConfig, err
}
// ProvideIDEVSCodeWebConfig loads the VSCode Web IDE config from the main config.
func ProvideIDEVSCodeWebConfig(config *types.Config) *container.VSCodeWebConfig {
return &container.VSCodeWebConfig{
func ProvideIDEVSCodeWebConfig(config *types.Config) *ide.VSCodeWebConfig {
return &ide.VSCodeWebConfig{
Port: config.IDE.VSCodeWeb.Port,
}
}
// ProvideGitspaceContainerOrchestratorConfig loads the Gitspace container orchestrator config from the main config.
func ProvideGitspaceContainerOrchestratorConfig(config *types.Config) *container.Config {
return &container.Config{
// ProvideGitspaceOrchestratorConfig loads the Gitspace orchestrator config from the main config.
func ProvideGitspaceOrchestratorConfig(config *types.Config) *orchestrator.Config {
return &orchestrator.Config{
DefaultBaseImage: config.Gitspace.DefaultBaseImage,
}
}

View File

@ -48,6 +48,7 @@ import (
"github.com/harness/gitness/app/gitspace/logutil"
"github.com/harness/gitness/app/gitspace/orchestrator"
containerorchestrator "github.com/harness/gitness/app/gitspace/orchestrator/container"
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
"github.com/harness/gitness/app/gitspace/scm"
"github.com/harness/gitness/app/pipeline/canceler"
"github.com/harness/gitness/app/pipeline/commit"
@ -226,9 +227,10 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
containerorchestrator.WireSet,
cliserver.ProvideIDEVSCodeWebConfig,
cliserver.ProvideDockerConfig,
cliserver.ProvideGitspaceContainerOrchestratorConfig,
cliserver.ProvideGitspaceEventConfig,
logutil.WireSet,
cliserver.ProvideGitspaceOrchestratorConfig,
ide.WireSet,
)
return &cliserver.System{}, nil
}

View File

@ -47,6 +47,7 @@ import (
"github.com/harness/gitness/app/gitspace/logutil"
"github.com/harness/gitness/app/gitspace/orchestrator"
"github.com/harness/gitness/app/gitspace/orchestrator/container"
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
"github.com/harness/gitness/app/gitspace/scm"
"github.com/harness/gitness/app/pipeline/canceler"
"github.com/harness/gitness/app/pipeline/commit"
@ -344,13 +345,13 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
}
scmSCM := scm.ProvideSCM()
infraProvisioner := infrastructure.ProvideInfraProvisionerService(infraProviderConfigStore, infraProviderResourceStore, factory)
vsCode := container.ProvideVSCodeService()
vsCodeWebConfig := server.ProvideIDEVSCodeWebConfig(config)
vsCodeWeb := container.ProvideVSCodeWebService(vsCodeWebConfig)
containerConfig := server.ProvideGitspaceContainerOrchestratorConfig(config)
statefulLogger := logutil.ProvideStatefulLogger(logStream)
containerOrchestrator := container.ProvideEmbeddedDockerOrchestrator(dockerClientFactory, vsCode, vsCodeWeb, containerConfig, statefulLogger)
orchestratorOrchestrator := orchestrator.ProvideOrchestrator(scmSCM, infraProviderResourceStore, infraProvisioner, containerOrchestrator, reporter3)
containerOrchestrator := container.ProvideEmbeddedDockerOrchestrator(dockerClientFactory, statefulLogger)
orchestratorConfig := server.ProvideGitspaceOrchestratorConfig(config)
vsCode := ide.ProvideVSCodeService()
vsCodeWebConfig := server.ProvideIDEVSCodeWebConfig(config)
vsCodeWeb := ide.ProvideVSCodeWebService(vsCodeWebConfig)
orchestratorOrchestrator := orchestrator.ProvideOrchestrator(scmSCM, infraProviderResourceStore, infraProvisioner, containerOrchestrator, reporter3, orchestratorConfig, vsCode, vsCodeWeb)
gitspaceEventStore := database.ProvideGitspaceEventStore(db)
gitspaceController := gitspace2.ProvideController(transactor, authorizer, infraproviderService, gitspaceConfigStore, gitspaceInstanceStore, spaceStore, reporter3, orchestratorOrchestrator, gitspaceEventStore, statefulLogger, scmSCM)
migrateController := migrate.ProvideController(authorizer, principalStore)

View File

@ -17,7 +17,6 @@ package infraprovider
import (
"context"
"fmt"
"io"
"strings"
"github.com/harness/gitness/infraprovider/enum"
@ -50,6 +49,7 @@ func (d DockerProvider) Provision(
ctx context.Context,
spacePath string,
resourceKey string,
requiredPorts []int,
params []Parameter,
) (*Infrastructure, error) {
dockerClient, err := d.dockerClientFactory.NewDockerClient(ctx, &Infrastructure{
@ -59,6 +59,7 @@ func (d DockerProvider) Provision(
if err != nil {
return nil, fmt.Errorf("error getting docker client from docker client factory: %w", err)
}
defer func() {
closingErr := dockerClient.Close()
if closingErr != nil {
@ -70,11 +71,27 @@ func (d DockerProvider) Provision(
if err != nil {
return nil, err
}
volumeName, err := d.createNamedVolume(ctx, spacePath, resourceKey, dockerClient)
infrastructure.Storage = volumeName
storageName, err := d.createNamedVolume(ctx, spacePath, resourceKey, dockerClient)
if err != nil {
return nil, err
}
infrastructure.Storage = storageName
var portMappings = make(map[int]*PortMapping, len(requiredPorts))
for _, requiredPort := range requiredPorts {
portMapping := &PortMapping{
PublishedPort: 0,
ForwardedPort: 0,
}
portMappings[requiredPort] = portMapping
}
infrastructure.PortMappings = portMappings
return infrastructure, nil
}
@ -158,11 +175,6 @@ func (d DockerProvider) ProvisioningType() enum.InfraProvisioningType {
return enum.InfraProvisioningTypeExisting
}
func (d DockerProvider) Exec(_ context.Context, _ *Infrastructure, _ []string) (io.Reader, io.Reader, error) {
// TODO implement me
panic("implement me")
}
func (d DockerProvider) dockerHostInfo(ctx context.Context, dockerClient *client.Client) (*Infrastructure, error) {
info, err := dockerClient.Info(ctx)
if err != nil {

View File

@ -16,14 +16,19 @@ package infraprovider
import (
"context"
"io"
"github.com/harness/gitness/infraprovider/enum"
)
type InfraProvider interface {
// Provision provisions infrastructure against a resourceKey with the provided parameters.
Provision(ctx context.Context, spacePath string, resourceKey string, parameters []Parameter) (*Infrastructure, error)
Provision(
ctx context.Context,
spacePath string,
resourceKey string,
requiredPorts []int,
parameters []Parameter,
) (*Infrastructure, error)
// Find finds infrastructure provisioned against a resourceKey.
Find(ctx context.Context, spacePath string, resourceKey string, parameters []Parameter) (*Infrastructure, error)
// Stop frees up the resources allocated against a resourceKey, which can be freed.
@ -38,6 +43,4 @@ type InfraProvider interface {
TemplateParams() []ParameterSchema
// ProvisioningType specifies whether the provider will provision new infra resources or it will reuse existing.
ProvisioningType() enum.InfraProvisioningType
// Exec executes a shell command in the infrastructure.
Exec(ctx context.Context, infra *Infrastructure, cmd []string) (io.Reader, io.Reader, error)
}

View File

@ -30,14 +30,34 @@ type Parameter struct {
Value string
}
type Infrastructure struct {
Identifier string
ResourceKey string
SpacePath string
ProviderType enum.InfraProviderType
Parameters []Parameter
Status enum.InfraStatus
Host string
Port int
Storage string
type PortMapping struct {
// PublishedPort is the port on which the container will be listening.
PublishedPort int
// ForwardedPort is the port on the infra to which the PublishedPort is forwarded.
ForwardedPort int
}
type Infrastructure struct {
// Identifier identifies the provisioned infra.
Identifier string
// ResourceKey is the key for which the infra is provisioned.
ResourceKey string
// SpaceID for the resource key.
SpaceID int64
// SpacePath for the resource key.
SpacePath string
// ProviderType specifies the type of the infra provider.
ProviderType enum.InfraProviderType
// Parameters which are required by the provider to provision the infra.
Parameters []Parameter
// Status of the infra.
Status enum.InfraStatus
// Host through which the infra can be accessed for all purposes.
Host string
// Port on which the infra can be accessed to orchestrate containers.
Port int
// Storage is the name of the volume or disk created for the resource.
Storage string
// PortMappings contains the ports assigned for every requested port.
PortMappings map[int]*PortMapping
}

View File

@ -392,8 +392,8 @@ type Config struct {
IDE struct {
VSCodeWeb struct {
// PortAndProtocol is the port on which the VS Code Web will be accessible.
Port string `envconfig:"GITNESS_IDE_VSCODEWEB_PORT" default:"8089"`
// Port is the port on which the VS Code Web will be accessible.
Port int `envconfig:"GITNESS_IDE_VSCODEWEB_PORT" default:"8089"`
}
}