mirror of https://github.com/harness/drone.git
feat: [CDE-286]: Moving user and git mgmt to respective services. (#2634)
* feat: [CDE-286]: Moving user and git mgmt to respective services.pull/3558/head
parent
a2d2ba07aa
commit
38023da2db
|
@ -25,8 +25,9 @@ import (
|
||||||
|
|
||||||
"github.com/harness/gitness/app/gitspace/logutil"
|
"github.com/harness/gitness/app/gitspace/logutil"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
||||||
|
"github.com/harness/gitness/app/gitspace/orchestrator/git"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
|
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/template"
|
"github.com/harness/gitness/app/gitspace/orchestrator/user"
|
||||||
"github.com/harness/gitness/app/gitspace/scm"
|
"github.com/harness/gitness/app/gitspace/scm"
|
||||||
"github.com/harness/gitness/infraprovider"
|
"github.com/harness/gitness/infraprovider"
|
||||||
"github.com/harness/gitness/types"
|
"github.com/harness/gitness/types"
|
||||||
|
@ -43,29 +44,32 @@ import (
|
||||||
var _ Orchestrator = (*EmbeddedDockerOrchestrator)(nil)
|
var _ Orchestrator = (*EmbeddedDockerOrchestrator)(nil)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
loggingKey = "gitspace.container"
|
loggingKey = "gitspace.container"
|
||||||
catchAllIP = "0.0.0.0"
|
catchAllIP = "0.0.0.0"
|
||||||
containerStateRunning = "running"
|
containerStateRunning = "running"
|
||||||
containerStateRemoved = "removed"
|
containerStateRemoved = "removed"
|
||||||
containerStateStopped = "exited"
|
containerStateStopped = "exited"
|
||||||
templateCloneGit = "clone_git.sh"
|
mountType = mount.TypeVolume
|
||||||
templateAuthenticateGit = "authenticate_git.sh"
|
|
||||||
templateManageUser = "manage_user.sh"
|
|
||||||
mountType = mount.TypeVolume
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type EmbeddedDockerOrchestrator struct {
|
type EmbeddedDockerOrchestrator struct {
|
||||||
dockerClientFactory *infraprovider.DockerClientFactory
|
dockerClientFactory *infraprovider.DockerClientFactory
|
||||||
statefulLogger *logutil.StatefulLogger
|
statefulLogger *logutil.StatefulLogger
|
||||||
|
gitService git.Service
|
||||||
|
userService user.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEmbeddedDockerOrchestrator(
|
func NewEmbeddedDockerOrchestrator(
|
||||||
dockerClientFactory *infraprovider.DockerClientFactory,
|
dockerClientFactory *infraprovider.DockerClientFactory,
|
||||||
statefulLogger *logutil.StatefulLogger,
|
statefulLogger *logutil.StatefulLogger,
|
||||||
|
gitService git.Service,
|
||||||
|
userService user.Service,
|
||||||
) Orchestrator {
|
) Orchestrator {
|
||||||
return &EmbeddedDockerOrchestrator{
|
return &EmbeddedDockerOrchestrator{
|
||||||
dockerClientFactory: dockerClientFactory,
|
dockerClientFactory: dockerClientFactory,
|
||||||
statefulLogger: statefulLogger,
|
statefulLogger: statefulLogger,
|
||||||
|
gitService: gitService,
|
||||||
|
userService: userService,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +152,7 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
|
||||||
}
|
}
|
||||||
|
|
||||||
if resolvedRepoDetails.Credentials != nil {
|
if resolvedRepoDetails.Credentials != nil {
|
||||||
authErr := e.authenticateGit(ctx, exec, resolvedRepoDetails, codeRepoDir)
|
authErr := e.setupGitCredentials(ctx, exec, resolvedRepoDetails, logStreamInstance)
|
||||||
if authErr != nil {
|
if authErr != nil {
|
||||||
return nil, authErr
|
return nil, authErr
|
||||||
}
|
}
|
||||||
|
@ -285,6 +289,18 @@ func (e *EmbeddedDockerOrchestrator) startGitspace(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = e.installGit(ctx, exec, logStreamInstance)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resolvedRepoDetails.Credentials != nil {
|
||||||
|
err = e.setupGitCredentials(ctx, exec, resolvedRepoDetails, logStreamInstance)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = e.cloneCode(ctx, exec, defaultBaseImage, resolvedRepoDetails, logStreamInstance)
|
err = e.cloneCode(ctx, exec, defaultBaseImage, resolvedRepoDetails, logStreamInstance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -401,75 +417,77 @@ func (e *EmbeddedDockerOrchestrator) getContainerInfo(
|
||||||
return inspectResp.ID, usedPorts, nil
|
return inspectResp.ID, usedPorts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EmbeddedDockerOrchestrator) authenticateGit(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
resolvedRepoDetails scm.ResolvedDetails,
|
|
||||||
codeRepoDir string,
|
|
||||||
) error {
|
|
||||||
data := &template.AuthenticateGitPayload{
|
|
||||||
Email: resolvedRepoDetails.Credentials.Email,
|
|
||||||
Name: resolvedRepoDetails.Credentials.Name,
|
|
||||||
Password: resolvedRepoDetails.Credentials.Password,
|
|
||||||
Host: resolvedRepoDetails.Credentials.Host,
|
|
||||||
Protocol: resolvedRepoDetails.Credentials.Protocol,
|
|
||||||
Path: resolvedRepoDetails.Credentials.Path,
|
|
||||||
}
|
|
||||||
gitAuthenticateScript, err := template.GenerateScriptFromTemplate(
|
|
||||||
templateAuthenticateGit, data)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to generate scipt to authenticate git from template %s: %w", templateAuthenticateGit, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = exec.ExecuteCommand(ctx, gitAuthenticateScript, false, false, codeRepoDir)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("failed to authenticate git in container: %w", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *EmbeddedDockerOrchestrator) manageUser(
|
func (e *EmbeddedDockerOrchestrator) manageUser(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
exec *devcontainer.Exec,
|
exec *devcontainer.Exec,
|
||||||
logStreamInstance *logutil.LogStreamInstance,
|
logStreamInstance *logutil.LogStreamInstance,
|
||||||
) error {
|
) error {
|
||||||
data := template.SetupUserPayload{
|
output, err := e.userService.Manage(ctx, exec)
|
||||||
Username: exec.UserIdentifier,
|
|
||||||
AccessKey: exec.AccessKey,
|
|
||||||
AccessType: exec.AccessType,
|
|
||||||
HomeDir: exec.HomeDir,
|
|
||||||
}
|
|
||||||
manageUserScript, err := template.GenerateScriptFromTemplate(
|
|
||||||
templateManageUser, data)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to generate scipt to manage user from template %s: %w", templateManageUser, err)
|
loggingErr := logStreamInstance.Write("Error while creating user inside container: " + err.Error())
|
||||||
}
|
|
||||||
loggingErr := logStreamInstance.Write(
|
|
||||||
"Creating user inside container: " + data.Username)
|
|
||||||
if loggingErr != nil {
|
|
||||||
return fmt.Errorf("logging error: %w", loggingErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
output, err := exec.ExecuteCommandInHomeDirectory(ctx, manageUserScript, true, false)
|
err = fmt.Errorf("failed to create user gitspace %s: %w", exec.ContainerName, err)
|
||||||
if err != nil {
|
|
||||||
loggingErr = logStreamInstance.Write("Error while creating user inside container : " + err.Error())
|
|
||||||
|
|
||||||
err = fmt.Errorf("failed to create user: %w", err)
|
|
||||||
|
|
||||||
if loggingErr != nil {
|
if loggingErr != nil {
|
||||||
err = fmt.Errorf("original error: %w; logging error: %w", err, loggingErr)
|
err = fmt.Errorf("original error: %w; logging error: %w", err, loggingErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
loggingErr = logStreamInstance.Write("Managing user output...\n" + string(output))
|
loggingErr := logStreamInstance.Write("Managing user output...\n" + string(output))
|
||||||
if loggingErr != nil {
|
if loggingErr != nil {
|
||||||
return fmt.Errorf("logging error: %w", loggingErr)
|
return fmt.Errorf("logging error: %w", loggingErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
loggingErr = logStreamInstance.Write("Successfully created user inside container")
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EmbeddedDockerOrchestrator) installGit(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
logStreamInstance *logutil.LogStreamInstance,
|
||||||
|
) error {
|
||||||
|
output, err := e.gitService.Install(ctx, exec)
|
||||||
|
if err != nil {
|
||||||
|
loggingErr := logStreamInstance.Write("Error while installing git inside container: " + err.Error())
|
||||||
|
|
||||||
|
err = fmt.Errorf("failed to install git for gitspace %s: %w", exec.ContainerName, err)
|
||||||
|
|
||||||
|
if loggingErr != nil {
|
||||||
|
err = fmt.Errorf("original error: %w; logging error: %w", err, loggingErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
loggingErr := logStreamInstance.Write("Install git output...\n" + string(output))
|
||||||
|
if loggingErr != nil {
|
||||||
|
return fmt.Errorf("logging error: %w", loggingErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (e *EmbeddedDockerOrchestrator) setupGitCredentials(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
resolvedRepoDetails scm.ResolvedDetails,
|
||||||
|
logStreamInstance *logutil.LogStreamInstance,
|
||||||
|
) error {
|
||||||
|
output, err := e.gitService.SetupCredentials(ctx, exec, resolvedRepoDetails)
|
||||||
|
if err != nil {
|
||||||
|
loggingErr := logStreamInstance.Write("Error while setting up git credentials inside container: " + err.Error())
|
||||||
|
|
||||||
|
err = fmt.Errorf("failed to setup git credentials for gitspace %s: %w", exec.ContainerName, err)
|
||||||
|
|
||||||
|
if loggingErr != nil {
|
||||||
|
err = fmt.Errorf("original error: %w; logging error: %w", err, loggingErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
loggingErr := logStreamInstance.Write("Setting up git credentials output...\n" + string(output))
|
||||||
if loggingErr != nil {
|
if loggingErr != nil {
|
||||||
return fmt.Errorf("logging error: %w", loggingErr)
|
return fmt.Errorf("logging error: %w", loggingErr)
|
||||||
}
|
}
|
||||||
|
@ -484,35 +502,11 @@ func (e *EmbeddedDockerOrchestrator) cloneCode(
|
||||||
resolvedRepoDetails scm.ResolvedDetails,
|
resolvedRepoDetails scm.ResolvedDetails,
|
||||||
logStreamInstance *logutil.LogStreamInstance,
|
logStreamInstance *logutil.LogStreamInstance,
|
||||||
) error {
|
) error {
|
||||||
data := &template.CloneGitPayload{
|
output, err := e.gitService.CloneCode(ctx, exec, resolvedRepoDetails, defaultBaseImage)
|
||||||
RepoURL: resolvedRepoDetails.CloneURL,
|
|
||||||
Image: defaultBaseImage,
|
|
||||||
Branch: resolvedRepoDetails.Branch,
|
|
||||||
RepoName: resolvedRepoDetails.RepoName,
|
|
||||||
}
|
|
||||||
if resolvedRepoDetails.Credentials != nil {
|
|
||||||
data.Email = resolvedRepoDetails.Credentials.Email
|
|
||||||
data.Name = resolvedRepoDetails.Credentials.Name
|
|
||||||
data.Password = resolvedRepoDetails.Credentials.Password
|
|
||||||
data.Host = resolvedRepoDetails.Credentials.Host
|
|
||||||
data.Protocol = resolvedRepoDetails.Credentials.Protocol
|
|
||||||
data.Path = resolvedRepoDetails.Credentials.Path
|
|
||||||
}
|
|
||||||
gitCloneScript, err := template.GenerateScriptFromTemplate(templateCloneGit, data)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to generate scipt to clone git from template %s: %w", templateCloneGit, err)
|
loggingErr := logStreamInstance.Write("Error while cloning code inside container: " + err.Error())
|
||||||
}
|
|
||||||
loggingErr := logStreamInstance.Write(
|
|
||||||
"Cloning git repo inside container: " + resolvedRepoDetails.CloneURL + " branch: " + resolvedRepoDetails.Branch)
|
|
||||||
if loggingErr != nil {
|
|
||||||
return fmt.Errorf("logging error: %w", loggingErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
output, err := exec.ExecuteCommandInHomeDirectory(ctx, gitCloneScript, false, false)
|
err = fmt.Errorf("failed to clone code gitspace %s: %w", exec.ContainerName, err)
|
||||||
if err != nil {
|
|
||||||
loggingErr = logStreamInstance.Write("Error while cloning git repo inside container: " + err.Error())
|
|
||||||
|
|
||||||
err = fmt.Errorf("failed to clone code: %w", err)
|
|
||||||
|
|
||||||
if loggingErr != nil {
|
if loggingErr != nil {
|
||||||
err = fmt.Errorf("original error: %w; logging error: %w", err, loggingErr)
|
err = fmt.Errorf("original error: %w; logging error: %w", err, loggingErr)
|
||||||
|
@ -521,12 +515,7 @@ func (e *EmbeddedDockerOrchestrator) cloneCode(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
loggingErr = logStreamInstance.Write("Cloning git repo output...\n" + string(output))
|
loggingErr := logStreamInstance.Write("Clone output...\n" + string(output))
|
||||||
if loggingErr != nil {
|
|
||||||
return fmt.Errorf("logging error: %w", loggingErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
loggingErr = logStreamInstance.Write("Successfully cloned git repo inside container")
|
|
||||||
if loggingErr != nil {
|
if loggingErr != nil {
|
||||||
return fmt.Errorf("logging error: %w", loggingErr)
|
return fmt.Errorf("logging error: %w", loggingErr)
|
||||||
}
|
}
|
||||||
|
@ -744,7 +733,7 @@ func (e *EmbeddedDockerOrchestrator) pullImage(
|
||||||
}
|
}
|
||||||
|
|
||||||
// StopGitspace stops a container. If it is removed, it returns an error.
|
// StopGitspace stops a container. If it is removed, it returns an error.
|
||||||
func (e EmbeddedDockerOrchestrator) StopGitspace(
|
func (e *EmbeddedDockerOrchestrator) StopGitspace(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
infra types.Infrastructure,
|
infra types.Infrastructure,
|
||||||
|
@ -804,7 +793,7 @@ func (e EmbeddedDockerOrchestrator) StopGitspace(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e EmbeddedDockerOrchestrator) stopContainer(
|
func (e *EmbeddedDockerOrchestrator) stopContainer(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
containerName string,
|
containerName string,
|
||||||
dockerClient *client.Client,
|
dockerClient *client.Client,
|
||||||
|
@ -930,7 +919,7 @@ func (e *EmbeddedDockerOrchestrator) StopAndRemoveGitspace(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e EmbeddedDockerOrchestrator) removeContainer(
|
func (e *EmbeddedDockerOrchestrator) removeContainer(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
containerName string,
|
containerName string,
|
||||||
dockerClient *client.Client,
|
dockerClient *client.Client,
|
||||||
|
|
|
@ -16,6 +16,8 @@ package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/harness/gitness/app/gitspace/logutil"
|
"github.com/harness/gitness/app/gitspace/logutil"
|
||||||
|
"github.com/harness/gitness/app/gitspace/orchestrator/git"
|
||||||
|
"github.com/harness/gitness/app/gitspace/orchestrator/user"
|
||||||
"github.com/harness/gitness/infraprovider"
|
"github.com/harness/gitness/infraprovider"
|
||||||
|
|
||||||
"github.com/google/wire"
|
"github.com/google/wire"
|
||||||
|
@ -28,9 +30,13 @@ var WireSet = wire.NewSet(
|
||||||
func ProvideEmbeddedDockerOrchestrator(
|
func ProvideEmbeddedDockerOrchestrator(
|
||||||
dockerClientFactory *infraprovider.DockerClientFactory,
|
dockerClientFactory *infraprovider.DockerClientFactory,
|
||||||
statefulLogger *logutil.StatefulLogger,
|
statefulLogger *logutil.StatefulLogger,
|
||||||
|
gitService git.Service,
|
||||||
|
userService user.Service,
|
||||||
) Orchestrator {
|
) Orchestrator {
|
||||||
return NewEmbeddedDockerOrchestrator(
|
return NewEmbeddedDockerOrchestrator(
|
||||||
dockerClientFactory,
|
dockerClientFactory,
|
||||||
statefulLogger,
|
statefulLogger,
|
||||||
|
gitService,
|
||||||
|
userService,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
// 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 git
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
||||||
|
"github.com/harness/gitness/app/gitspace/scm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Service interface {
|
||||||
|
// Install ensures git is installed in the container.
|
||||||
|
Install(ctx context.Context, exec *devcontainer.Exec) ([]byte, error)
|
||||||
|
|
||||||
|
// SetupCredentials sets the user's git credentials inside the container.
|
||||||
|
SetupCredentials(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
resolvedRepoDetails scm.ResolvedDetails,
|
||||||
|
) ([]byte, error)
|
||||||
|
|
||||||
|
// CloneCode clones the code and ensures devcontainer file is present.
|
||||||
|
CloneCode(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
resolvedRepoDetails scm.ResolvedDetails,
|
||||||
|
defaultBaseImage string,
|
||||||
|
) ([]byte, error)
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
// 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 git
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
||||||
|
"github.com/harness/gitness/app/gitspace/orchestrator/template"
|
||||||
|
"github.com/harness/gitness/app/gitspace/scm"
|
||||||
|
|
||||||
|
_ "embed"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ Service = (*ServiceImpl)(nil)
|
||||||
|
|
||||||
|
//go:embed script/install_git.sh
|
||||||
|
var installScript string
|
||||||
|
|
||||||
|
const templateSetupGitCredentials = "setup_git_credentials.sh" // nolint:gosec
|
||||||
|
const templateCloneCode = "clone_code.sh"
|
||||||
|
|
||||||
|
type ServiceImpl struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGitServiceImpl() Service {
|
||||||
|
return &ServiceImpl{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *ServiceImpl) Install(ctx context.Context, exec *devcontainer.Exec) ([]byte, error) {
|
||||||
|
output := "Setting up git inside container\n"
|
||||||
|
|
||||||
|
_, err := exec.ExecuteCommandInHomeDirectory(ctx, installScript, false, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to setup git: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
output += "Successfully setup git\n"
|
||||||
|
|
||||||
|
return []byte(output), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *ServiceImpl) SetupCredentials(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
resolvedRepoDetails scm.ResolvedDetails,
|
||||||
|
) ([]byte, error) {
|
||||||
|
script, err := template.GenerateScriptFromTemplate(
|
||||||
|
templateSetupGitCredentials, &template.SetupGitCredentialsPayload{
|
||||||
|
Email: resolvedRepoDetails.Credentials.Email,
|
||||||
|
Name: resolvedRepoDetails.Credentials.Name,
|
||||||
|
Password: resolvedRepoDetails.Credentials.Password,
|
||||||
|
Host: resolvedRepoDetails.Credentials.Host,
|
||||||
|
Protocol: resolvedRepoDetails.Credentials.Protocol,
|
||||||
|
Path: resolvedRepoDetails.Credentials.Path,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"failed to generate scipt to setup git credentials from template %s: %w", templateSetupGitCredentials, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
output := "Setting up git credentials inside container\n"
|
||||||
|
|
||||||
|
_, err = exec.ExecuteCommandInHomeDirectory(ctx, script, false, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to setup git credentials: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
output += "Successfully setup git credentials\n"
|
||||||
|
|
||||||
|
return []byte(output), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *ServiceImpl) CloneCode(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
resolvedRepoDetails scm.ResolvedDetails,
|
||||||
|
defaultBaseImage string,
|
||||||
|
) ([]byte, error) {
|
||||||
|
script, err := template.GenerateScriptFromTemplate(
|
||||||
|
templateCloneCode, &template.CloneCodePayload{
|
||||||
|
RepoURL: resolvedRepoDetails.CloneURL,
|
||||||
|
Image: defaultBaseImage,
|
||||||
|
Branch: resolvedRepoDetails.Branch,
|
||||||
|
RepoName: resolvedRepoDetails.RepoName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"failed to generate scipt to clone code from template %s: %w", templateCloneCode, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
output := "Cloning code inside container\n"
|
||||||
|
|
||||||
|
_, err = exec.ExecuteCommandInHomeDirectory(ctx, script, false, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to clone code: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
output += "Successfully clone code\n"
|
||||||
|
|
||||||
|
return []byte(output), nil
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Check if Git is installed
|
||||||
|
if ! command -v git >/dev/null 2>&1; then
|
||||||
|
echo "Git is not installed. Installing Git..."
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y git
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v git >/dev/null 2>&1; then
|
||||||
|
echo "Git is not installed. Exiting..."
|
||||||
|
exit 1
|
||||||
|
fi
|
|
@ -0,0 +1,27 @@
|
||||||
|
// 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 git
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/wire"
|
||||||
|
)
|
||||||
|
|
||||||
|
var WireSet = wire.NewSet(
|
||||||
|
ProvideGitServiceImpl,
|
||||||
|
)
|
||||||
|
|
||||||
|
func ProvideGitServiceImpl() Service {
|
||||||
|
return NewGitServiceImpl()
|
||||||
|
}
|
|
@ -35,15 +35,14 @@ var (
|
||||||
scriptTemplates map[string]*template.Template
|
scriptTemplates map[string]*template.Template
|
||||||
)
|
)
|
||||||
|
|
||||||
type CloneGitPayload struct {
|
type CloneCodePayload struct {
|
||||||
RepoURL string
|
RepoURL string
|
||||||
Image string
|
Image string
|
||||||
Branch string
|
Branch string
|
||||||
RepoName string
|
RepoName string
|
||||||
AuthenticateGitPayload
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthenticateGitPayload struct {
|
type SetupGitCredentialsPayload struct {
|
||||||
Email string
|
Email string
|
||||||
Name string
|
Name string
|
||||||
Password string
|
Password string
|
||||||
|
|
|
@ -5,42 +5,6 @@ image={{ .Image }}
|
||||||
branch={{ .Branch }}
|
branch={{ .Branch }}
|
||||||
repo_name={{ .RepoName }}
|
repo_name={{ .RepoName }}
|
||||||
|
|
||||||
password={{ .Password }}
|
|
||||||
email={{ .Email }}
|
|
||||||
name={{ .Name }}
|
|
||||||
host={{ .Host }}
|
|
||||||
protocol={{ .Protocol }}
|
|
||||||
path={{ .Path }}
|
|
||||||
|
|
||||||
# Check if Git is installed
|
|
||||||
if ! command -v git >/dev/null 2>&1; then
|
|
||||||
echo "Git is not installed. Installing Git..."
|
|
||||||
apt-get update
|
|
||||||
apt-get install -y git
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! command -v git >/dev/null 2>&1; then
|
|
||||||
echo "Git is not installed. Exiting..."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if [ -z "$password" ]; then
|
|
||||||
echo "setting up without credentials"
|
|
||||||
else
|
|
||||||
git config --global credential.helper 'cache --timeout=2592000'
|
|
||||||
git config --global user.email "$email"
|
|
||||||
git config --global user.name "$name"
|
|
||||||
touch .gitcontext
|
|
||||||
echo "host="$host >> .gitcontext
|
|
||||||
echo "protocol="$protocol >> .gitcontext
|
|
||||||
echo "path="$path >> .gitcontext
|
|
||||||
echo "username="$email >> .gitcontext
|
|
||||||
echo "password="$password >> .gitcontext
|
|
||||||
echo "" >> .gitcontext
|
|
||||||
|
|
||||||
cat .gitcontext | git credential approve
|
|
||||||
rm .gitcontext
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Clone the repository inside the working directory if it doesn't exist
|
# Clone the repository inside the working directory if it doesn't exist
|
||||||
if [ ! -d "$HOME/$repo_name/.git" ]; then
|
if [ ! -d "$HOME/$repo_name/.git" ]; then
|
||||||
echo "Cloning the repository..."
|
echo "Cloning the repository..."
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
username={{ .Username }}
|
username={{ .Username }}
|
||||||
accessKey={{ .AccessKey }}
|
accessKey="{{ .AccessKey }}"
|
||||||
homeDir={{ .HomeDir }}
|
homeDir={{ .HomeDir }}
|
||||||
accessType={{ .AccessType }}
|
accessType={{ .AccessType }}
|
||||||
|
|
||||||
|
@ -29,6 +29,10 @@ if [ "ssh_key" = "$accessType" ] ; then
|
||||||
echo $accessKey > $homeDir/.ssh/authorized_keys
|
echo $accessKey > $homeDir/.ssh/authorized_keys
|
||||||
chmod 600 $homeDir/.ssh/authorized_keys
|
chmod 600 $homeDir/.ssh/authorized_keys
|
||||||
chown -R $username:$username $homeDir/.ssh
|
chown -R $username:$username $homeDir/.ssh
|
||||||
else
|
echo "$username:$username" | chpasswd
|
||||||
|
elif [ "user_credentials" = "$accessType" ] ; then
|
||||||
echo "$username:$accessKey" | chpasswd
|
echo "$username:$accessKey" | chpasswd
|
||||||
|
else
|
||||||
|
echo "Unsupported accessType $accessType" >&2
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
|
@ -0,0 +1,26 @@
|
||||||
|
// 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 user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Service interface {
|
||||||
|
// Manage manager the linux user in the container.
|
||||||
|
Manage(ctx context.Context, exec *devcontainer.Exec) ([]byte, error)
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
// 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 user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
||||||
|
"github.com/harness/gitness/app/gitspace/orchestrator/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ Service = (*ServiceImpl)(nil)
|
||||||
|
|
||||||
|
const templateManagerUser = "manage_user.sh"
|
||||||
|
|
||||||
|
type ServiceImpl struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUserServiceImpl() Service {
|
||||||
|
return &ServiceImpl{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *ServiceImpl) Manage(ctx context.Context, exec *devcontainer.Exec) ([]byte, error) {
|
||||||
|
script, err := template.GenerateScriptFromTemplate(
|
||||||
|
templateManagerUser, &template.SetupUserPayload{
|
||||||
|
Username: exec.UserIdentifier,
|
||||||
|
AccessKey: exec.AccessKey,
|
||||||
|
AccessType: exec.AccessType,
|
||||||
|
HomeDir: exec.HomeDir,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"failed to generate scipt to manager user from template %s: %w", templateManagerUser, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
output := "Setting up user inside container\n"
|
||||||
|
_, err = exec.ExecuteCommandInHomeDirectory(ctx, script, true, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to setup user: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
output += "Successfully setup user\n"
|
||||||
|
|
||||||
|
return []byte(output), nil
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
// 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 user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/wire"
|
||||||
|
)
|
||||||
|
|
||||||
|
var WireSet = wire.NewSet(
|
||||||
|
ProvideUserServiceImpl,
|
||||||
|
)
|
||||||
|
|
||||||
|
func ProvideUserServiceImpl() Service {
|
||||||
|
return NewUserServiceImpl()
|
||||||
|
}
|
|
@ -24,6 +24,8 @@ import (
|
||||||
"github.com/harness/gitness/events"
|
"github.com/harness/gitness/events"
|
||||||
"github.com/harness/gitness/types"
|
"github.com/harness/gitness/types"
|
||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Service) handleGitspaceInfraEvent(
|
func (s *Service) handleGitspaceInfraEvent(
|
||||||
|
@ -43,44 +45,49 @@ func (s *Service) handleGitspaceInfraEvent(
|
||||||
|
|
||||||
switch payload.Type {
|
switch payload.Type {
|
||||||
case enum.InfraEventProvision:
|
case enum.InfraEventProvision:
|
||||||
updatedInstance, err := s.orchestrator.ResumeStartGitspace(ctx, *config, payload.Infra)
|
updatedInstance, resumeStartErr := s.orchestrator.ResumeStartGitspace(ctx, *config, payload.Infra)
|
||||||
if err != nil {
|
if resumeStartErr != nil {
|
||||||
s.emitGitspaceConfigEvent(ctx, config, enum.GitspaceEventTypeGitspaceActionStartFailed)
|
s.emitGitspaceConfigEvent(ctx, config, enum.GitspaceEventTypeGitspaceActionStartFailed)
|
||||||
|
|
||||||
return fmt.Errorf("failed to resume start gitspace: %w", err)
|
err = fmt.Errorf("failed to resume start gitspace: %w", resumeStartErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
instance = &updatedInstance
|
instance = &updatedInstance
|
||||||
|
|
||||||
case enum.InfraEventStop:
|
case enum.InfraEventStop:
|
||||||
instanceState, err := s.orchestrator.ResumeStopGitspace(ctx, *config, payload.Infra)
|
instanceState, resumeStopErr := s.orchestrator.ResumeStopGitspace(ctx, *config, payload.Infra)
|
||||||
if err != nil {
|
if resumeStopErr != nil {
|
||||||
s.emitGitspaceConfigEvent(ctx, config, enum.GitspaceEventTypeGitspaceActionStopFailed)
|
s.emitGitspaceConfigEvent(ctx, config, enum.GitspaceEventTypeGitspaceActionStopFailed)
|
||||||
|
|
||||||
return fmt.Errorf("failed to resume stop gitspace: %w", err)
|
err = fmt.Errorf("failed to resume stop gitspace: %w", resumeStopErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.State = instanceState
|
instance.State = instanceState
|
||||||
|
|
||||||
case enum.InfraEventDeprovision:
|
case enum.InfraEventDeprovision:
|
||||||
instanceState, err := s.orchestrator.ResumeDeleteGitspace(ctx, *config, payload.Infra)
|
instanceState, resumeDeleteErr := s.orchestrator.ResumeDeleteGitspace(ctx, *config, payload.Infra)
|
||||||
if err != nil {
|
if resumeDeleteErr != nil {
|
||||||
return fmt.Errorf("failed to resume delete gitspace: %w", err)
|
err = fmt.Errorf("failed to resume delete gitspace: %w", resumeDeleteErr)
|
||||||
|
} else {
|
||||||
|
config.IsDeleted = true
|
||||||
|
updateErr := s.gitspaceSvc.UpdateConfig(ctx, config)
|
||||||
|
if updateErr != nil {
|
||||||
|
err = fmt.Errorf("failed to delete gitspace config with ID: %s %w", config.Identifier, updateErr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.State = instanceState
|
instance.State = instanceState
|
||||||
|
|
||||||
config.IsDeleted = true
|
|
||||||
if err = s.gitspaceSvc.UpdateConfig(ctx, config); err != nil {
|
|
||||||
return fmt.Errorf("failed to delete gitspace config with ID: %s %w", config.Identifier, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown event type: %s", event.Payload.Type)
|
return fmt.Errorf("unknown event type: %s", event.Payload.Type)
|
||||||
}
|
}
|
||||||
err = s.gitspaceSvc.UpdateInstance(ctx, instance)
|
|
||||||
|
updateErr := s.gitspaceSvc.UpdateInstance(ctx, instance)
|
||||||
|
if updateErr != nil {
|
||||||
|
log.Err(updateErr).Msgf("failed to update gitspace instance")
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to update gitspace instance: %w", err)
|
log.Err(err).Msgf("error while handling gitspace infra event")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -63,7 +63,9 @@ import (
|
||||||
"github.com/harness/gitness/app/gitspace/logutil"
|
"github.com/harness/gitness/app/gitspace/logutil"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator"
|
"github.com/harness/gitness/app/gitspace/orchestrator"
|
||||||
containerorchestrator "github.com/harness/gitness/app/gitspace/orchestrator/container"
|
containerorchestrator "github.com/harness/gitness/app/gitspace/orchestrator/container"
|
||||||
|
containerGit "github.com/harness/gitness/app/gitspace/orchestrator/git"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
|
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
|
||||||
|
containerUser "github.com/harness/gitness/app/gitspace/orchestrator/user"
|
||||||
"github.com/harness/gitness/app/gitspace/scm"
|
"github.com/harness/gitness/app/gitspace/scm"
|
||||||
gitspacesecret "github.com/harness/gitness/app/gitspace/secret"
|
gitspacesecret "github.com/harness/gitness/app/gitspace/secret"
|
||||||
"github.com/harness/gitness/app/pipeline/canceler"
|
"github.com/harness/gitness/app/pipeline/canceler"
|
||||||
|
@ -264,6 +266,8 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
|
||||||
capabilities.WireSet,
|
capabilities.WireSet,
|
||||||
capabilitiesservice.WireSet,
|
capabilitiesservice.WireSet,
|
||||||
secretservice.WireSet,
|
secretservice.WireSet,
|
||||||
|
containerGit.WireSet,
|
||||||
|
containerUser.WireSet,
|
||||||
)
|
)
|
||||||
return &cliserver.System{}, nil
|
return &cliserver.System{}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,9 @@ import (
|
||||||
"github.com/harness/gitness/app/gitspace/logutil"
|
"github.com/harness/gitness/app/gitspace/logutil"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator"
|
"github.com/harness/gitness/app/gitspace/orchestrator"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/container"
|
"github.com/harness/gitness/app/gitspace/orchestrator/container"
|
||||||
|
git2 "github.com/harness/gitness/app/gitspace/orchestrator/git"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
|
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
|
||||||
|
user2 "github.com/harness/gitness/app/gitspace/orchestrator/user"
|
||||||
"github.com/harness/gitness/app/gitspace/scm"
|
"github.com/harness/gitness/app/gitspace/scm"
|
||||||
secret2 "github.com/harness/gitness/app/gitspace/secret"
|
secret2 "github.com/harness/gitness/app/gitspace/secret"
|
||||||
"github.com/harness/gitness/app/pipeline/canceler"
|
"github.com/harness/gitness/app/pipeline/canceler"
|
||||||
|
@ -384,7 +386,9 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
||||||
infrastructureConfig := server.ProvideGitspaceInfraProvisionerConfig(config)
|
infrastructureConfig := server.ProvideGitspaceInfraProvisionerConfig(config)
|
||||||
infraProvisioner := infrastructure.ProvideInfraProvisionerService(infraProviderConfigStore, infraProviderResourceStore, factory, infraProviderTemplateStore, infraProvisionedStore, infrastructureConfig)
|
infraProvisioner := infrastructure.ProvideInfraProvisionerService(infraProviderConfigStore, infraProviderResourceStore, factory, infraProviderTemplateStore, infraProvisionedStore, infrastructureConfig)
|
||||||
statefulLogger := logutil.ProvideStatefulLogger(logStream)
|
statefulLogger := logutil.ProvideStatefulLogger(logStream)
|
||||||
containerOrchestrator := container.ProvideEmbeddedDockerOrchestrator(dockerClientFactory, statefulLogger)
|
gitService := git2.ProvideGitServiceImpl()
|
||||||
|
userService := user2.ProvideUserServiceImpl()
|
||||||
|
containerOrchestrator := container.ProvideEmbeddedDockerOrchestrator(dockerClientFactory, statefulLogger, gitService, userService)
|
||||||
orchestratorConfig := server.ProvideGitspaceOrchestratorConfig(config)
|
orchestratorConfig := server.ProvideGitspaceOrchestratorConfig(config)
|
||||||
vsCodeConfig := server.ProvideIDEVSCodeConfig(config)
|
vsCodeConfig := server.ProvideIDEVSCodeConfig(config)
|
||||||
vsCode := ide.ProvideVSCodeService(vsCodeConfig)
|
vsCode := ide.ProvideVSCodeService(vsCodeConfig)
|
||||||
|
|
Loading…
Reference in New Issue