mirror of
https://github.com/harness/drone.git
synced 2025-05-04 23:22:42 +08:00
feat: [CDE-573]: refactor to reduce number of abstractions and modules. (#3199)
* feat: [CDE-573]: refactor to reduce number of abstractions and modules. * feat: [CDE-573]: refactor to reduce number of abstractions and modules. * feat: [CDE-573]: refactor to reduce number of abstractions and modules. * feat: [CDE-573]: refactor to reduce number of abstractions and modules. * feat: [CDE-573]: refactor to reduce number of abstractions and modules. * feat: [CDE-573]: refactor to reduce number of abstractions and modules. * feat: [CDE-573]: refactor to reduce number of abstractions and modules. * feat: [CDE-573]: refactor to reduce number of abstractions and modules. * feat: [CDE-573]: refactor to reduce number of abstractions and modules. * feat: [CDE-573]: refactor to reduce number of abstractions and modules. * feat: [CDE-573]: refactor to reduce number of abstractions and modules.
This commit is contained in:
parent
0a042b66e5
commit
d89825d317
@ -1,26 +0,0 @@
|
|||||||
// 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 common
|
|
||||||
|
|
||||||
import (
|
|
||||||
_ "embed"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:embed script/os_info.sh
|
|
||||||
var osDetectScript string
|
|
||||||
|
|
||||||
func GetOSInfoScript() (script string) {
|
|
||||||
return osDetectScript
|
|
||||||
}
|
|
@ -1,209 +0,0 @@
|
|||||||
// 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 common
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/template"
|
|
||||||
"github.com/harness/gitness/app/gitspace/types"
|
|
||||||
"github.com/harness/gitness/types/enum"
|
|
||||||
)
|
|
||||||
|
|
||||||
const templateSupportedOSDistribution = "supported_os_distribution.sh"
|
|
||||||
const templateVsCodeWebToolsInstallation = "install_tools_vs_code_web.sh"
|
|
||||||
const templateVsCodeToolsInstallation = "install_tools_vs_code.sh"
|
|
||||||
const templateSetEnv = "set_env.sh"
|
|
||||||
|
|
||||||
func ValidateSupportedOS(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger types.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
// TODO: Currently not supporting arch, freebsd and alpine.
|
|
||||||
// For alpine wee need to install multiple things from
|
|
||||||
// https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites
|
|
||||||
script, err := template.GenerateScriptFromTemplate(
|
|
||||||
templateSupportedOSDistribution, &template.SupportedOSDistributionPayload{
|
|
||||||
OSInfoScript: osDetectScript,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to generate scipt to validate supported os distribution from template %s: %w",
|
|
||||||
templateSupportedOSDistribution, err)
|
|
||||||
}
|
|
||||||
gitspaceLogger.Info("Validate supported OSes...")
|
|
||||||
err = ExecuteCommandInHomeDirAndLog(ctx, exec, script, true, gitspaceLogger, false)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error while detecting os distribution: %w", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func InstallTools(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
ideType enum.IDEType,
|
|
||||||
gitspaceLogger types.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
switch ideType {
|
|
||||||
case enum.IDETypeVSCodeWeb:
|
|
||||||
err := InstallToolsForVsCodeWeb(ctx, exec, gitspaceLogger)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case enum.IDETypeVSCode:
|
|
||||||
err := InstallToolsForVsCode(ctx, exec, gitspaceLogger)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case enum.IDETypeIntellij:
|
|
||||||
// not installing any tools for intellij
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func InstallToolsForVsCodeWeb(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger types.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
script, err := template.GenerateScriptFromTemplate(
|
|
||||||
templateVsCodeWebToolsInstallation, &template.InstallToolsPayload{
|
|
||||||
OSInfoScript: osDetectScript,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf(
|
|
||||||
"failed to generate scipt to install tools for vs code web from template %s: %w",
|
|
||||||
templateVsCodeWebToolsInstallation, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
gitspaceLogger.Info("Installing tools for vs code web inside container")
|
|
||||||
gitspaceLogger.Info("Tools installation output...")
|
|
||||||
err = ExecuteCommandInHomeDirAndLog(ctx, exec, script, true, gitspaceLogger, false)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to install tools for vs code web: %w", err)
|
|
||||||
}
|
|
||||||
gitspaceLogger.Info("Successfully installed tools for vs code web")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func InstallToolsForVsCode(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger types.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
script, err := template.GenerateScriptFromTemplate(
|
|
||||||
templateVsCodeToolsInstallation, &template.InstallToolsPayload{
|
|
||||||
OSInfoScript: osDetectScript,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf(
|
|
||||||
"failed to generate scipt to install tools for vs code from template %s: %w",
|
|
||||||
templateVsCodeToolsInstallation, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
gitspaceLogger.Info("Installing tools for vs code in container")
|
|
||||||
err = ExecuteCommandInHomeDirAndLog(ctx, exec, script, true, gitspaceLogger, false)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to install tools for vs code: %w", err)
|
|
||||||
}
|
|
||||||
gitspaceLogger.Info("Successfully installed tools for vs code")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetEnv(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger types.GitspaceLogger,
|
|
||||||
environment []string,
|
|
||||||
) error {
|
|
||||||
script, err := template.GenerateScriptFromTemplate(
|
|
||||||
templateSetEnv, &template.SetEnvPayload{
|
|
||||||
EnvVariables: environment,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to generate scipt to set env from template %s: %w",
|
|
||||||
templateSetEnv, err)
|
|
||||||
}
|
|
||||||
gitspaceLogger.Info("Setting env...")
|
|
||||||
err = ExecuteCommandInHomeDirAndLog(ctx, exec, script, true, gitspaceLogger, true)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error while setting env vars: %w", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExecuteCommandInHomeDirAndLog(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
script string,
|
|
||||||
root bool,
|
|
||||||
gitspaceLogger types.GitspaceLogger,
|
|
||||||
verbose bool,
|
|
||||||
) error {
|
|
||||||
// Buffer upto a thousand messages
|
|
||||||
outputCh := make(chan []byte, 1000)
|
|
||||||
err := exec.ExecuteCmdInHomeDirectoryAsyncStream(ctx, script, root, false, outputCh)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Use select to wait for the output and exit status
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case output := <-outputCh:
|
|
||||||
done, chErr := handleOutputChannel(output, verbose, gitspaceLogger)
|
|
||||||
if done {
|
|
||||||
return chErr
|
|
||||||
}
|
|
||||||
case <-ctx.Done():
|
|
||||||
// Handle context cancellation or timeout
|
|
||||||
return ctx.Err()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleOutputChannel(output []byte, verbose bool, gitspaceLogger types.GitspaceLogger) (bool, error) {
|
|
||||||
// Handle the exit status first
|
|
||||||
if strings.HasPrefix(string(output), devcontainer.ChannelExitStatus) {
|
|
||||||
// Extract the exit code from the message
|
|
||||||
exitCodeStr := strings.TrimPrefix(string(output), devcontainer.ChannelExitStatus)
|
|
||||||
exitCode, err := strconv.Atoi(exitCodeStr)
|
|
||||||
if err != nil {
|
|
||||||
return true, fmt.Errorf("invalid exit status format: %w", err)
|
|
||||||
}
|
|
||||||
if exitCode != 0 {
|
|
||||||
gitspaceLogger.Info("Process Exited with status " + exitCodeStr)
|
|
||||||
return true, fmt.Errorf("command exited with non-zero status: %d", exitCode)
|
|
||||||
}
|
|
||||||
// If exit status is zero, just continue processing
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
// Handle regular command output
|
|
||||||
msg := string(output)
|
|
||||||
if len(output) > 0 {
|
|
||||||
// Log output if verbose or if it's an error
|
|
||||||
if verbose || strings.HasPrefix(msg, devcontainer.LoggerErrorPrefix) {
|
|
||||||
gitspaceLogger.Info(msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
@ -19,11 +19,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/common"
|
|
||||||
"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/user"
|
"github.com/harness/gitness/app/gitspace/orchestrator/utils"
|
||||||
"github.com/harness/gitness/app/gitspace/scm"
|
"github.com/harness/gitness/app/gitspace/scm"
|
||||||
gitspaceTypes "github.com/harness/gitness/app/gitspace/types"
|
gitspaceTypes "github.com/harness/gitness/app/gitspace/types"
|
||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
@ -35,7 +33,7 @@ func InstallTools(
|
|||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
ideType enum.IDEType,
|
ideType enum.IDEType,
|
||||||
) error {
|
) error {
|
||||||
err := common.InstallTools(ctx, exec, ideType, gitspaceLogger)
|
err := utils.InstallTools(ctx, exec, ideType, gitspaceLogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logStreamWrapError(gitspaceLogger, "Error while installing tools inside container", err)
|
return logStreamWrapError(gitspaceLogger, "Error while installing tools inside container", err)
|
||||||
}
|
}
|
||||||
@ -47,7 +45,7 @@ func ValidateSupportedOS(
|
|||||||
exec *devcontainer.Exec,
|
exec *devcontainer.Exec,
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
err := common.ValidateSupportedOS(ctx, exec, gitspaceLogger)
|
err := utils.ValidateSupportedOS(ctx, exec, gitspaceLogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logStreamWrapError(gitspaceLogger, "Error while detecting OS inside container", err)
|
return logStreamWrapError(gitspaceLogger, "Error while detecting OS inside container", err)
|
||||||
}
|
}
|
||||||
@ -89,7 +87,7 @@ func ExecuteLifecycleCommands(
|
|||||||
// Log command execution details.
|
// Log command execution details.
|
||||||
gitspaceLogger.Info(fmt.Sprintf("%sExecuting %s command: %s", logPrefix, actionType, command))
|
gitspaceLogger.Info(fmt.Sprintf("%sExecuting %s command: %s", logPrefix, actionType, command))
|
||||||
exec.DefaultWorkingDir = codeRepoDir
|
exec.DefaultWorkingDir = codeRepoDir
|
||||||
err := common.ExecuteCommandInHomeDirAndLog(ctx, &exec, command, false, gitspaceLogger, true)
|
err := exec.ExecuteCommandInHomeDirAndLog(ctx, command, false, gitspaceLogger, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Log the error if there is any issue with executing the command.
|
// Log the error if there is any issue with executing the command.
|
||||||
_ = logStreamWrapError(gitspaceLogger, fmt.Sprintf("%sError while executing %s command: %s",
|
_ = logStreamWrapError(gitspaceLogger, fmt.Sprintf("%sError while executing %s command: %s",
|
||||||
@ -114,10 +112,9 @@ func CloneCode(
|
|||||||
exec *devcontainer.Exec,
|
exec *devcontainer.Exec,
|
||||||
defaultBaseImage string,
|
defaultBaseImage string,
|
||||||
resolvedRepoDetails scm.ResolvedDetails,
|
resolvedRepoDetails scm.ResolvedDetails,
|
||||||
gitService git.Service,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
err := gitService.CloneCode(ctx, exec, resolvedRepoDetails, defaultBaseImage, gitspaceLogger)
|
err := utils.CloneCode(ctx, exec, resolvedRepoDetails, defaultBaseImage, gitspaceLogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logStreamWrapError(gitspaceLogger, "Error while cloning code inside container", err)
|
return logStreamWrapError(gitspaceLogger, "Error while cloning code inside container", err)
|
||||||
}
|
}
|
||||||
@ -127,10 +124,9 @@ func CloneCode(
|
|||||||
func InstallGit(
|
func InstallGit(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
exec *devcontainer.Exec,
|
exec *devcontainer.Exec,
|
||||||
gitService git.Service,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
err := gitService.Install(ctx, exec, gitspaceLogger)
|
err := utils.InstallGit(ctx, exec, gitspaceLogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logStreamWrapError(gitspaceLogger, "Error while installing git inside container", err)
|
return logStreamWrapError(gitspaceLogger, "Error while installing git inside container", err)
|
||||||
}
|
}
|
||||||
@ -141,10 +137,9 @@ func SetupGitCredentials(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
exec *devcontainer.Exec,
|
exec *devcontainer.Exec,
|
||||||
resolvedRepoDetails scm.ResolvedDetails,
|
resolvedRepoDetails scm.ResolvedDetails,
|
||||||
gitService git.Service,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
err := gitService.SetupCredentials(ctx, exec, resolvedRepoDetails, gitspaceLogger)
|
err := utils.SetupGitCredentials(ctx, exec, resolvedRepoDetails, gitspaceLogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logStreamWrapError(
|
return logStreamWrapError(
|
||||||
gitspaceLogger, "Error while setting up git credentials inside container", err)
|
gitspaceLogger, "Error while setting up git credentials inside container", err)
|
||||||
@ -155,10 +150,9 @@ func SetupGitCredentials(
|
|||||||
func ManageUser(
|
func ManageUser(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
exec *devcontainer.Exec,
|
exec *devcontainer.Exec,
|
||||||
userService user.Service,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
err := userService.Manage(ctx, exec, gitspaceLogger)
|
err := utils.ManageUser(ctx, exec, gitspaceLogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logStreamWrapError(gitspaceLogger, "Error while creating user inside container", err)
|
return logStreamWrapError(gitspaceLogger, "Error while creating user inside container", err)
|
||||||
}
|
}
|
||||||
@ -202,7 +196,7 @@ func SetEnv(
|
|||||||
environment []string,
|
environment []string,
|
||||||
) error {
|
) error {
|
||||||
if len(environment) > 0 {
|
if len(environment) > 0 {
|
||||||
err := common.SetEnv(ctx, exec, gitspaceLogger, environment)
|
err := utils.SetEnv(ctx, exec, gitspaceLogger, environment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logStreamWrapError(gitspaceLogger, "Error while installing tools inside container", err)
|
return logStreamWrapError(gitspaceLogger, "Error while installing tools inside container", err)
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,8 @@ 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/runarg"
|
"github.com/harness/gitness/app/gitspace/orchestrator/runarg"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/user"
|
|
||||||
"github.com/harness/gitness/app/gitspace/scm"
|
"github.com/harness/gitness/app/gitspace/scm"
|
||||||
gitspaceTypes "github.com/harness/gitness/app/gitspace/types"
|
gitspaceTypes "github.com/harness/gitness/app/gitspace/types"
|
||||||
"github.com/harness/gitness/infraprovider"
|
"github.com/harness/gitness/infraprovider"
|
||||||
@ -44,17 +42,22 @@ const (
|
|||||||
type EmbeddedDockerOrchestrator struct {
|
type EmbeddedDockerOrchestrator struct {
|
||||||
dockerClientFactory *infraprovider.DockerClientFactory
|
dockerClientFactory *infraprovider.DockerClientFactory
|
||||||
statefulLogger *logutil.StatefulLogger
|
statefulLogger *logutil.StatefulLogger
|
||||||
gitService git.Service
|
|
||||||
userService user.Service
|
|
||||||
runArgProvider runarg.Provider
|
runArgProvider runarg.Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Step represents a single setup action.
|
||||||
|
type step struct {
|
||||||
|
Name string
|
||||||
|
Execute func(ctx context.Context, exec *devcontainer.Exec, gitspaceLogger gitspaceTypes.GitspaceLogger) error
|
||||||
|
StopOnFailure bool // Flag to control whether execution should stop on failure
|
||||||
|
}
|
||||||
|
|
||||||
// ExecuteSteps executes all registered steps in sequence, respecting stopOnFailure flag.
|
// ExecuteSteps executes all registered steps in sequence, respecting stopOnFailure flag.
|
||||||
func (e *EmbeddedDockerOrchestrator) ExecuteSteps(
|
func (e *EmbeddedDockerOrchestrator) ExecuteSteps(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
exec *devcontainer.Exec,
|
exec *devcontainer.Exec,
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
steps []gitspaceTypes.Step,
|
steps []step,
|
||||||
) error {
|
) error {
|
||||||
for _, step := range steps {
|
for _, step := range steps {
|
||||||
// Execute the step
|
// Execute the step
|
||||||
@ -73,15 +76,11 @@ func (e *EmbeddedDockerOrchestrator) ExecuteSteps(
|
|||||||
func NewEmbeddedDockerOrchestrator(
|
func NewEmbeddedDockerOrchestrator(
|
||||||
dockerClientFactory *infraprovider.DockerClientFactory,
|
dockerClientFactory *infraprovider.DockerClientFactory,
|
||||||
statefulLogger *logutil.StatefulLogger,
|
statefulLogger *logutil.StatefulLogger,
|
||||||
gitService git.Service,
|
|
||||||
userService user.Service,
|
|
||||||
runArgProvider runarg.Provider,
|
runArgProvider runarg.Provider,
|
||||||
) Orchestrator {
|
) Orchestrator {
|
||||||
return &EmbeddedDockerOrchestrator{
|
return &EmbeddedDockerOrchestrator{
|
||||||
dockerClientFactory: dockerClientFactory,
|
dockerClientFactory: dockerClientFactory,
|
||||||
statefulLogger: statefulLogger,
|
statefulLogger: statefulLogger,
|
||||||
gitService: gitService,
|
|
||||||
userService: userService,
|
|
||||||
runArgProvider: runArgProvider,
|
runArgProvider: runArgProvider,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -207,7 +206,7 @@ func (e *EmbeddedDockerOrchestrator) startStoppedGitspace(
|
|||||||
|
|
||||||
// Set up git credentials if needed
|
// Set up git credentials if needed
|
||||||
if resolvedRepoDetails.Credentials != nil {
|
if resolvedRepoDetails.Credentials != nil {
|
||||||
if err := SetupGitCredentials(ctx, exec, resolvedRepoDetails, e.gitService, logStreamInstance); err != nil {
|
if err := SetupGitCredentials(ctx, exec, resolvedRepoDetails, logStreamInstance); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -488,22 +487,16 @@ func (e *EmbeddedDockerOrchestrator) buildSetupSteps(
|
|||||||
environment []string,
|
environment []string,
|
||||||
devcontainerConfig types.DevcontainerConfig,
|
devcontainerConfig types.DevcontainerConfig,
|
||||||
codeRepoDir string,
|
codeRepoDir string,
|
||||||
) []gitspaceTypes.Step {
|
) []step {
|
||||||
return []gitspaceTypes.Step{
|
return []step{
|
||||||
{
|
{
|
||||||
Name: "Validate Supported OS",
|
Name: "Validate Supported OS",
|
||||||
Execute: ValidateSupportedOS,
|
Execute: ValidateSupportedOS,
|
||||||
StopOnFailure: true,
|
StopOnFailure: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Manage User",
|
Name: "Manage User",
|
||||||
Execute: func(
|
Execute: ManageUser,
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
return ManageUser(ctx, exec, e.userService, gitspaceLogger)
|
|
||||||
},
|
|
||||||
StopOnFailure: true,
|
StopOnFailure: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -529,14 +522,8 @@ func (e *EmbeddedDockerOrchestrator) buildSetupSteps(
|
|||||||
StopOnFailure: true,
|
StopOnFailure: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Install Git",
|
Name: "Install Git",
|
||||||
Execute: func(
|
Execute: InstallGit,
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
return InstallGit(ctx, exec, e.gitService, gitspaceLogger)
|
|
||||||
},
|
|
||||||
StopOnFailure: true,
|
StopOnFailure: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -547,7 +534,7 @@ func (e *EmbeddedDockerOrchestrator) buildSetupSteps(
|
|||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
if resolvedRepoDetails.ResolvedCredentials.Credentials != nil {
|
if resolvedRepoDetails.ResolvedCredentials.Credentials != nil {
|
||||||
return SetupGitCredentials(ctx, exec, resolvedRepoDetails, e.gitService, gitspaceLogger)
|
return SetupGitCredentials(ctx, exec, resolvedRepoDetails, gitspaceLogger)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
@ -560,7 +547,7 @@ func (e *EmbeddedDockerOrchestrator) buildSetupSteps(
|
|||||||
exec *devcontainer.Exec,
|
exec *devcontainer.Exec,
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
return CloneCode(ctx, exec, defaultBaseImage, resolvedRepoDetails, e.gitService, gitspaceLogger)
|
return CloneCode(ctx, exec, defaultBaseImage, resolvedRepoDetails, gitspaceLogger)
|
||||||
},
|
},
|
||||||
StopOnFailure: true,
|
StopOnFailure: true,
|
||||||
},
|
},
|
||||||
|
@ -16,9 +16,7 @@ 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/runarg"
|
"github.com/harness/gitness/app/gitspace/orchestrator/runarg"
|
||||||
"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"
|
||||||
@ -31,15 +29,11 @@ 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,
|
|
||||||
runArgProvdier runarg.Provider,
|
runArgProvdier runarg.Provider,
|
||||||
) Orchestrator {
|
) Orchestrator {
|
||||||
return NewEmbeddedDockerOrchestrator(
|
return NewEmbeddedDockerOrchestrator(
|
||||||
dockerClientFactory,
|
dockerClientFactory,
|
||||||
statefulLogger,
|
statefulLogger,
|
||||||
gitService,
|
|
||||||
userService,
|
|
||||||
runArgProvdier,
|
runArgProvdier,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,11 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/app/gitspace/types"
|
||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
|
|
||||||
dockerTypes "github.com/docker/docker/api/types"
|
dockerTypes "github.com/docker/docker/api/types"
|
||||||
@ -91,6 +93,34 @@ func (e *Exec) ExecuteCommand(
|
|||||||
return stdoutBuf.String(), nil
|
return stdoutBuf.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Exec) ExecuteCommandInHomeDirAndLog(
|
||||||
|
ctx context.Context,
|
||||||
|
script string,
|
||||||
|
root bool,
|
||||||
|
gitspaceLogger types.GitspaceLogger,
|
||||||
|
verbose bool,
|
||||||
|
) error {
|
||||||
|
// Buffer upto a thousand messages
|
||||||
|
outputCh := make(chan []byte, 1000)
|
||||||
|
err := e.executeCmdInHomeDirectoryAsyncStream(ctx, script, root, false, outputCh)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Use select to wait for the output and exit status
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case output := <-outputCh:
|
||||||
|
done, chErr := handleOutputChannel(output, verbose, gitspaceLogger)
|
||||||
|
if done {
|
||||||
|
return chErr
|
||||||
|
}
|
||||||
|
case <-ctx.Done():
|
||||||
|
// Handle context cancellation or timeout
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (e *Exec) createExecution(
|
func (e *Exec) createExecution(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
command string,
|
command string,
|
||||||
@ -148,7 +178,7 @@ func (e *Exec) executeCmdAsyncStream(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exec) ExecuteCmdInHomeDirectoryAsyncStream(
|
func (e *Exec) executeCmdInHomeDirectoryAsyncStream(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
command string,
|
command string,
|
||||||
root bool,
|
root bool,
|
||||||
@ -270,3 +300,30 @@ func (e *Exec) streamStdErr(stderr io.Reader, outputCh chan []byte, wg *sync.Wai
|
|||||||
log.Error().Err(err).Msg("Error reading stderr " + err.Error())
|
log.Error().Err(err).Msg("Error reading stderr " + err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleOutputChannel(output []byte, verbose bool, gitspaceLogger types.GitspaceLogger) (bool, error) {
|
||||||
|
// Handle the exit status first
|
||||||
|
if strings.HasPrefix(string(output), ChannelExitStatus) {
|
||||||
|
// Extract the exit code from the message
|
||||||
|
exitCodeStr := strings.TrimPrefix(string(output), ChannelExitStatus)
|
||||||
|
exitCode, err := strconv.Atoi(exitCodeStr)
|
||||||
|
if err != nil {
|
||||||
|
return true, fmt.Errorf("invalid exit status format: %w", err)
|
||||||
|
}
|
||||||
|
if exitCode != 0 {
|
||||||
|
gitspaceLogger.Info("Process Exited with status " + exitCodeStr)
|
||||||
|
return true, fmt.Errorf("command exited with non-zero status: %d", exitCode)
|
||||||
|
}
|
||||||
|
// If exit status is zero, just continue processing
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
// Handle regular command output
|
||||||
|
msg := string(output)
|
||||||
|
if len(output) > 0 {
|
||||||
|
// Log output if verbose or if it's an error
|
||||||
|
if verbose || strings.HasPrefix(msg, LoggerErrorPrefix) {
|
||||||
|
gitspaceLogger.Info(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
// 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"
|
|
||||||
"github.com/harness/gitness/app/gitspace/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Service interface {
|
|
||||||
// Install ensures git is installed in the container.
|
|
||||||
Install(ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger types.GitspaceLogger,
|
|
||||||
) error
|
|
||||||
|
|
||||||
// SetupCredentials sets the user's git credentials inside the container.
|
|
||||||
SetupCredentials(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
resolvedRepoDetails scm.ResolvedDetails,
|
|
||||||
gitspaceLogger types.GitspaceLogger,
|
|
||||||
) error
|
|
||||||
|
|
||||||
// CloneCode clones the code and ensures devcontainer file is present.
|
|
||||||
CloneCode(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
resolvedRepoDetails scm.ResolvedDetails,
|
|
||||||
defaultBaseImage string,
|
|
||||||
gitspaceLogger types.GitspaceLogger,
|
|
||||||
) error
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
// 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()
|
|
||||||
}
|
|
@ -20,9 +20,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/common"
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/template"
|
"github.com/harness/gitness/app/gitspace/orchestrator/utils"
|
||||||
gitspaceTypes "github.com/harness/gitness/app/gitspace/types"
|
gitspaceTypes "github.com/harness/gitness/app/gitspace/types"
|
||||||
"github.com/harness/gitness/types"
|
"github.com/harness/gitness/types"
|
||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
@ -81,19 +80,19 @@ func (v *VSCode) setupSSHServer(
|
|||||||
exec *devcontainer.Exec,
|
exec *devcontainer.Exec,
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
osInfoScript := common.GetOSInfoScript()
|
osInfoScript := utils.GetOSInfoScript()
|
||||||
payload := template.SetupSSHServerPayload{
|
payload := gitspaceTypes.SetupSSHServerPayload{
|
||||||
Username: exec.RemoteUser,
|
Username: exec.RemoteUser,
|
||||||
AccessType: exec.AccessType,
|
AccessType: exec.AccessType,
|
||||||
OSInfoScript: osInfoScript,
|
OSInfoScript: osInfoScript,
|
||||||
}
|
}
|
||||||
sshServerScript, err := template.GenerateScriptFromTemplate(
|
sshServerScript, err := utils.GenerateScriptFromTemplate(
|
||||||
templateSetupSSHServer, &payload)
|
templateSetupSSHServer, &payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"failed to generate scipt to setup ssh server from template %s: %w", templateSetupSSHServer, err)
|
"failed to generate scipt to setup ssh server from template %s: %w", templateSetupSSHServer, err)
|
||||||
}
|
}
|
||||||
err = common.ExecuteCommandInHomeDirAndLog(ctx, exec, sshServerScript, true, gitspaceLogger, false)
|
err = exec.ExecuteCommandInHomeDirAndLog(ctx, sshServerScript, true, gitspaceLogger, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to setup SSH serverr: %w", err)
|
return fmt.Errorf("failed to setup SSH serverr: %w", err)
|
||||||
}
|
}
|
||||||
@ -107,14 +106,14 @@ func (v *VSCode) setupVSCodeExtensions(
|
|||||||
args map[gitspaceTypes.IDEArg]interface{},
|
args map[gitspaceTypes.IDEArg]interface{},
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
payload := template.SetupVSCodeExtensionsPayload{
|
payload := gitspaceTypes.SetupVSCodeExtensionsPayload{
|
||||||
Username: exec.RemoteUser,
|
Username: exec.RemoteUser,
|
||||||
}
|
}
|
||||||
if err := v.updateVSCodeSetupPayload(args, gitspaceLogger, &payload); err != nil {
|
if err := v.updateVSCodeSetupPayload(args, gitspaceLogger, &payload); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
vscodeExtensionsScript, err := template.GenerateScriptFromTemplate(
|
vscodeExtensionsScript, err := utils.GenerateScriptFromTemplate(
|
||||||
templateSetupVSCodeExtensions, &payload)
|
templateSetupVSCodeExtensions, &payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
@ -124,7 +123,7 @@ func (v *VSCode) setupVSCodeExtensions(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = common.ExecuteCommandInHomeDirAndLog(ctx, exec, vscodeExtensionsScript,
|
err = exec.ExecuteCommandInHomeDirAndLog(ctx, vscodeExtensionsScript,
|
||||||
true, gitspaceLogger, false)
|
true, gitspaceLogger, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to setup vs-code extensions: %w", err)
|
return fmt.Errorf("failed to setup vs-code extensions: %w", err)
|
||||||
@ -140,17 +139,17 @@ func (v *VSCode) Run(
|
|||||||
_ map[gitspaceTypes.IDEArg]interface{},
|
_ map[gitspaceTypes.IDEArg]interface{},
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
payload := template.RunSSHServerPayload{
|
payload := gitspaceTypes.RunSSHServerPayload{
|
||||||
Port: strconv.Itoa(v.config.Port),
|
Port: strconv.Itoa(v.config.Port),
|
||||||
}
|
}
|
||||||
runSSHScript, err := template.GenerateScriptFromTemplate(
|
runSSHScript, err := utils.GenerateScriptFromTemplate(
|
||||||
templateRunSSHServer, &payload)
|
templateRunSSHServer, &payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"failed to generate scipt to run ssh server from template %s: %w", templateRunSSHServer, err)
|
"failed to generate scipt to run ssh server from template %s: %w", templateRunSSHServer, err)
|
||||||
}
|
}
|
||||||
gitspaceLogger.Info("SSH server run output...")
|
gitspaceLogger.Info("SSH server run output...")
|
||||||
err = common.ExecuteCommandInHomeDirAndLog(ctx, exec, runSSHScript, true, gitspaceLogger, true)
|
err = exec.ExecuteCommandInHomeDirAndLog(ctx, runSSHScript, true, gitspaceLogger, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to run SSH server: %w", err)
|
return fmt.Errorf("failed to run SSH server: %w", err)
|
||||||
}
|
}
|
||||||
@ -174,7 +173,7 @@ func (v *VSCode) Type() enum.IDEType {
|
|||||||
func (v *VSCode) updateVSCodeSetupPayload(
|
func (v *VSCode) updateVSCodeSetupPayload(
|
||||||
args map[gitspaceTypes.IDEArg]interface{},
|
args map[gitspaceTypes.IDEArg]interface{},
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
payload *template.SetupVSCodeExtensionsPayload,
|
payload *gitspaceTypes.SetupVSCodeExtensionsPayload,
|
||||||
) error {
|
) error {
|
||||||
if args == nil {
|
if args == nil {
|
||||||
return nil
|
return nil
|
||||||
@ -184,16 +183,22 @@ func (v *VSCode) updateVSCodeSetupPayload(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Handle Repository Name
|
// Handle Repository Name
|
||||||
if err := v.handleRepoName(args, payload); err != nil {
|
repoName, exists := args[gitspaceTypes.IDERepoNameArg]
|
||||||
return err
|
if !exists {
|
||||||
|
return nil // No repo name found, nothing to do
|
||||||
}
|
}
|
||||||
|
repoNameStr, ok := repoName.(string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("repo name is not of type string")
|
||||||
|
}
|
||||||
|
payload.RepoName = repoNameStr
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *VSCode) handleVSCodeCustomization(
|
func (v *VSCode) handleVSCodeCustomization(
|
||||||
args map[gitspaceTypes.IDEArg]interface{},
|
args map[gitspaceTypes.IDEArg]interface{},
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
payload *template.SetupVSCodeExtensionsPayload,
|
payload *gitspaceTypes.SetupVSCodeExtensionsPayload,
|
||||||
) error {
|
) error {
|
||||||
customization, exists := args[gitspaceTypes.VSCodeCustomizationArg]
|
customization, exists := args[gitspaceTypes.VSCodeCustomizationArg]
|
||||||
if !exists {
|
if !exists {
|
||||||
@ -220,21 +225,3 @@ func (v *VSCode) handleVSCodeCustomization(
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *VSCode) handleRepoName(
|
|
||||||
args map[gitspaceTypes.IDEArg]interface{},
|
|
||||||
payload *template.SetupVSCodeExtensionsPayload,
|
|
||||||
) error {
|
|
||||||
repoName, exists := args[gitspaceTypes.IDERepoNameArg]
|
|
||||||
if !exists {
|
|
||||||
return nil // No repo name found, nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
repoNameStr, ok := repoName.(string)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("repo name is not of type string")
|
|
||||||
}
|
|
||||||
payload.RepoName = repoNameStr
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@ -25,9 +25,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/common"
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/template"
|
"github.com/harness/gitness/app/gitspace/orchestrator/utils"
|
||||||
gitspaceTypes "github.com/harness/gitness/app/gitspace/types"
|
gitspaceTypes "github.com/harness/gitness/app/gitspace/types"
|
||||||
"github.com/harness/gitness/types"
|
"github.com/harness/gitness/types"
|
||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
@ -68,13 +67,13 @@ func (v *VSCodeWeb) Setup(
|
|||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
gitspaceLogger.Info("Installing VSCode Web inside container...")
|
gitspaceLogger.Info("Installing VSCode Web inside container...")
|
||||||
payload := &template.SetupVSCodeWebPayload{}
|
payload := &gitspaceTypes.SetupVSCodeWebPayload{}
|
||||||
if args != nil {
|
if args != nil {
|
||||||
if err := updateSetupPayloadFromArgs(args, payload, gitspaceLogger); err != nil {
|
if err := updateSetupPayloadFromArgs(args, payload, gitspaceLogger); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setupScript, err := template.GenerateScriptFromTemplate(templateSetupVSCodeWeb, payload)
|
setupScript, err := utils.GenerateScriptFromTemplate(templateSetupVSCodeWeb, payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"failed to generate script to setup VSCode Web from template %s: %w",
|
"failed to generate script to setup VSCode Web from template %s: %w",
|
||||||
@ -82,7 +81,7 @@ func (v *VSCodeWeb) Setup(
|
|||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
err = common.ExecuteCommandInHomeDirAndLog(ctx, exec, setupScript, false, gitspaceLogger, false)
|
err = exec.ExecuteCommandInHomeDirAndLog(ctx, setupScript, false, gitspaceLogger, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to install VSCode Web: %w", err)
|
return fmt.Errorf("failed to install VSCode Web: %w", err)
|
||||||
}
|
}
|
||||||
@ -124,17 +123,21 @@ func (v *VSCodeWeb) Run(
|
|||||||
args map[gitspaceTypes.IDEArg]interface{},
|
args map[gitspaceTypes.IDEArg]interface{},
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
payload := &template.RunVSCodeWebPayload{
|
payload := gitspaceTypes.RunVSCodeWebPayload{
|
||||||
Port: strconv.Itoa(v.config.Port),
|
Port: strconv.Itoa(v.config.Port),
|
||||||
}
|
}
|
||||||
|
|
||||||
if args != nil {
|
if args != nil {
|
||||||
err := updateRunPayloadFromArgs(args, payload, gitspaceLogger)
|
if proxyURI, exists := args[gitspaceTypes.VSCodeProxyURIArg]; exists {
|
||||||
if err != nil {
|
// Perform a type assertion to ensure proxyURI is a string
|
||||||
return err
|
proxyURIStr, ok := proxyURI.(string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("%s is not a string", gitspaceTypes.VSCodeProxyURIArg)
|
||||||
|
}
|
||||||
|
payload.ProxyURI = proxyURIStr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
runScript, err := template.GenerateScriptFromTemplate(templateRunVSCodeWeb, payload)
|
runScript, err := utils.GenerateScriptFromTemplate(templateRunVSCodeWeb, payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"failed to generate script to run VSCode Web from template %s: %w",
|
"failed to generate script to run VSCode Web from template %s: %w",
|
||||||
@ -144,32 +147,16 @@ func (v *VSCodeWeb) Run(
|
|||||||
}
|
}
|
||||||
gitspaceLogger.Info("Starting IDE ...")
|
gitspaceLogger.Info("Starting IDE ...")
|
||||||
// Execute the script in the home directory
|
// Execute the script in the home directory
|
||||||
err = common.ExecuteCommandInHomeDirAndLog(ctx, exec, runScript, false, gitspaceLogger, true)
|
err = exec.ExecuteCommandInHomeDirAndLog(ctx, runScript, false, gitspaceLogger, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to run VSCode Web: %w", err)
|
return fmt.Errorf("failed to run VSCode Web: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateRunPayloadFromArgs(
|
|
||||||
args map[gitspaceTypes.IDEArg]interface{},
|
|
||||||
payload *template.RunVSCodeWebPayload,
|
|
||||||
_ gitspaceTypes.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
if proxyURI, exists := args[gitspaceTypes.VSCodeProxyURIArg]; exists {
|
|
||||||
// Perform a type assertion to ensure proxyURI is a string
|
|
||||||
proxyURIStr, ok := proxyURI.(string)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("%s is not a string", gitspaceTypes.VSCodeProxyURIArg)
|
|
||||||
}
|
|
||||||
payload.ProxyURI = proxyURIStr
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateSetupPayloadFromArgs(
|
func updateSetupPayloadFromArgs(
|
||||||
args map[gitspaceTypes.IDEArg]interface{},
|
args map[gitspaceTypes.IDEArg]interface{},
|
||||||
payload *template.SetupVSCodeWebPayload,
|
payload *gitspaceTypes.SetupVSCodeWebPayload,
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
if customization, exists := args[gitspaceTypes.VSCodeCustomizationArg]; exists {
|
if customization, exists := args[gitspaceTypes.VSCodeCustomizationArg]; exists {
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
// 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 orchestrator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/harness/gitness/types"
|
|
||||||
"github.com/harness/gitness/types/enum"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
vscodeURLScheme = "vscode-remote"
|
|
||||||
intellijURLScheme = "jetbrains-gateway"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Orchestrator interface {
|
|
||||||
// TriggerStartGitspace fetches the infra resources configured for the gitspace and triggers the infra provisioning.
|
|
||||||
TriggerStartGitspace(ctx context.Context, gitspaceConfig types.GitspaceConfig) *types.GitspaceError
|
|
||||||
|
|
||||||
// ResumeStartGitspace saves the provisioned infra, resolves the code repo details & creates the Gitspace container.
|
|
||||||
ResumeStartGitspace(
|
|
||||||
ctx context.Context,
|
|
||||||
gitspaceConfig types.GitspaceConfig,
|
|
||||||
provisionedInfra types.Infrastructure,
|
|
||||||
) (types.GitspaceInstance, *types.GitspaceError)
|
|
||||||
|
|
||||||
// TriggerStopGitspace stops the Gitspace container and triggers infra deprovisioning to deprovision
|
|
||||||
// all the infra resources which are not required to restart the Gitspace.
|
|
||||||
TriggerStopGitspace(ctx context.Context, gitspaceConfig types.GitspaceConfig) *types.GitspaceError
|
|
||||||
|
|
||||||
// ResumeStopGitspace saves the deprovisioned infra details.
|
|
||||||
ResumeStopGitspace(
|
|
||||||
ctx context.Context,
|
|
||||||
gitspaceConfig types.GitspaceConfig,
|
|
||||||
stoppedInfra types.Infrastructure,
|
|
||||||
) (enum.GitspaceInstanceStateType, *types.GitspaceError)
|
|
||||||
|
|
||||||
// TriggerCleanupInstanceResources cleans up all the resources exclusive to gitspace instance.
|
|
||||||
TriggerCleanupInstanceResources(ctx context.Context, gitspaceConfig types.GitspaceConfig) error
|
|
||||||
|
|
||||||
// ResumeCleanupInstanceResources saves the cleaned up infra details.
|
|
||||||
ResumeCleanupInstanceResources(
|
|
||||||
ctx context.Context,
|
|
||||||
gitspaceConfig types.GitspaceConfig,
|
|
||||||
cleanedUpInfra types.Infrastructure,
|
|
||||||
) (enum.GitspaceInstanceStateType, error)
|
|
||||||
|
|
||||||
// TriggerDeleteGitspace removes the Gitspace container and triggers infra deprovisioning to deprovision
|
|
||||||
// the infra resources.
|
|
||||||
// canDeleteUserData = false -> trigger deprovision of all resources except storage associated to user data.
|
|
||||||
// canDeleteUserData = true -> trigger deprovision of all resources.
|
|
||||||
TriggerDeleteGitspace(ctx context.Context, gitspaceConfig types.GitspaceConfig, canDeleteUserData bool) error
|
|
||||||
|
|
||||||
// ResumeDeleteGitspace saves the deprovisioned infra details.
|
|
||||||
ResumeDeleteGitspace(
|
|
||||||
ctx context.Context,
|
|
||||||
gitspaceConfig types.GitspaceConfig,
|
|
||||||
deprovisionedInfra types.Infrastructure,
|
|
||||||
) (enum.GitspaceInstanceStateType, error)
|
|
||||||
|
|
||||||
// GetGitspaceLogs fetches gitspace's start/stop logs.
|
|
||||||
GetGitspaceLogs(ctx context.Context, gitspaceConfig types.GitspaceConfig) (string, error)
|
|
||||||
}
|
|
@ -26,6 +26,7 @@ import (
|
|||||||
"github.com/harness/gitness/app/gitspace/orchestrator/container"
|
"github.com/harness/gitness/app/gitspace/orchestrator/container"
|
||||||
"github.com/harness/gitness/app/gitspace/secret"
|
"github.com/harness/gitness/app/gitspace/secret"
|
||||||
secretenum "github.com/harness/gitness/app/gitspace/secret/enum"
|
secretenum "github.com/harness/gitness/app/gitspace/secret/enum"
|
||||||
|
gitspaceTypes "github.com/harness/gitness/app/gitspace/types"
|
||||||
"github.com/harness/gitness/app/paths"
|
"github.com/harness/gitness/app/paths"
|
||||||
"github.com/harness/gitness/types"
|
"github.com/harness/gitness/types"
|
||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
@ -34,7 +35,8 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (o orchestrator) ResumeStartGitspace(
|
// ResumeStartGitspace saves the provisioned infra, resolves the code repo details & creates the Gitspace container.
|
||||||
|
func (o Orchestrator) ResumeStartGitspace(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
provisionedInfra types.Infrastructure,
|
provisionedInfra types.Infrastructure,
|
||||||
@ -217,7 +219,7 @@ func generateIDEURL(
|
|||||||
case enum.IDETypeVSCode:
|
case enum.IDETypeVSCode:
|
||||||
// TODO: the following userID is hard coded and should be changed.
|
// TODO: the following userID is hard coded and should be changed.
|
||||||
ideURL = url.URL{
|
ideURL = url.URL{
|
||||||
Scheme: vscodeURLScheme,
|
Scheme: gitspaceTypes.VSCodeURLScheme,
|
||||||
Host: "", // Empty since we include the host and port in the path
|
Host: "", // Empty since we include the host and port in the path
|
||||||
Path: fmt.Sprintf(
|
Path: fmt.Sprintf(
|
||||||
"ssh-remote+%s@%s:%s",
|
"ssh-remote+%s@%s:%s",
|
||||||
@ -229,7 +231,7 @@ func generateIDEURL(
|
|||||||
case enum.IDETypeIntellij:
|
case enum.IDETypeIntellij:
|
||||||
idePath := relativeRepoPath + "/.cache"
|
idePath := relativeRepoPath + "/.cache"
|
||||||
ideURL = url.URL{
|
ideURL = url.URL{
|
||||||
Scheme: intellijURLScheme,
|
Scheme: gitspaceTypes.IntellijURLScheme,
|
||||||
Host: "", // Empty since we include the host and port in the path
|
Host: "", // Empty since we include the host and port in the path
|
||||||
Path: "connect",
|
Path: "connect",
|
||||||
Fragment: fmt.Sprintf("idePath=%s&projectPath=%s&host=%s&port=%s&user=%s&type=%s&deploy=%s",
|
Fragment: fmt.Sprintf("idePath=%s&projectPath=%s&host=%s&port=%s&user=%s&type=%s&deploy=%s",
|
||||||
@ -248,7 +250,7 @@ func generateIDEURL(
|
|||||||
return ideURLString
|
return ideURLString
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o orchestrator) getSecretResolver(accessType enum.GitspaceAccessType) (secret.Resolver, error) {
|
func (o Orchestrator) getSecretResolver(accessType enum.GitspaceAccessType) (secret.Resolver, error) {
|
||||||
secretType := secretenum.PasswordSecretType
|
secretType := secretenum.PasswordSecretType
|
||||||
switch accessType {
|
switch accessType {
|
||||||
case enum.GitspaceAccessTypeUserCredentials:
|
case enum.GitspaceAccessTypeUserCredentials:
|
||||||
@ -261,7 +263,8 @@ func (o orchestrator) getSecretResolver(accessType enum.GitspaceAccessType) (sec
|
|||||||
return o.secretResolverFactory.GetSecretResolver(secretType)
|
return o.secretResolverFactory.GetSecretResolver(secretType)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o orchestrator) ResumeStopGitspace(
|
// ResumeStopGitspace saves the deprovisioned infra details.
|
||||||
|
func (o Orchestrator) ResumeStopGitspace(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
stoppedInfra types.Infrastructure,
|
stoppedInfra types.Infrastructure,
|
||||||
@ -302,7 +305,8 @@ func (o orchestrator) ResumeStopGitspace(
|
|||||||
return instanceState, nil
|
return instanceState, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o orchestrator) ResumeDeleteGitspace(
|
// ResumeDeleteGitspace saves the deprovisioned infra details.
|
||||||
|
func (o Orchestrator) ResumeDeleteGitspace(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
deprovisionedInfra types.Infrastructure,
|
deprovisionedInfra types.Infrastructure,
|
||||||
@ -334,7 +338,8 @@ func (o orchestrator) ResumeDeleteGitspace(
|
|||||||
return instanceState, nil
|
return instanceState, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o orchestrator) ResumeCleanupInstanceResources(
|
// ResumeCleanupInstanceResources saves the cleaned up infra details.
|
||||||
|
func (o Orchestrator) ResumeCleanupInstanceResources(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
cleanedUpInfra types.Infrastructure,
|
cleanedUpInfra types.Infrastructure,
|
||||||
|
@ -26,7 +26,6 @@ import (
|
|||||||
"github.com/harness/gitness/app/gitspace/platformconnector"
|
"github.com/harness/gitness/app/gitspace/platformconnector"
|
||||||
"github.com/harness/gitness/app/gitspace/scm"
|
"github.com/harness/gitness/app/gitspace/scm"
|
||||||
"github.com/harness/gitness/app/gitspace/secret"
|
"github.com/harness/gitness/app/gitspace/secret"
|
||||||
"github.com/harness/gitness/app/store"
|
|
||||||
"github.com/harness/gitness/types"
|
"github.com/harness/gitness/types"
|
||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
|
|
||||||
@ -41,24 +40,20 @@ type Config struct {
|
|||||||
DefaultBaseImage string
|
DefaultBaseImage string
|
||||||
}
|
}
|
||||||
|
|
||||||
type orchestrator struct {
|
type Orchestrator struct {
|
||||||
scm *scm.SCM
|
scm *scm.SCM
|
||||||
platformConnector platformconnector.PlatformConnector
|
platformConnector platformconnector.PlatformConnector
|
||||||
infraProviderResourceStore store.InfraProviderResourceStore
|
infraProvisioner infrastructure.InfraProvisioner
|
||||||
infraProvisioner infrastructure.InfraProvisioner
|
containerOrchestrator container.Orchestrator
|
||||||
containerOrchestrator container.Orchestrator
|
eventReporter *events.Reporter
|
||||||
eventReporter *events.Reporter
|
config *Config
|
||||||
config *Config
|
ideFactory ide.Factory
|
||||||
ideFactory ide.Factory
|
secretResolverFactory *secret.ResolverFactory
|
||||||
secretResolverFactory *secret.ResolverFactory
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Orchestrator = (*orchestrator)(nil)
|
|
||||||
|
|
||||||
func NewOrchestrator(
|
func NewOrchestrator(
|
||||||
scm *scm.SCM,
|
scm *scm.SCM,
|
||||||
platformConnector platformconnector.PlatformConnector,
|
platformConnector platformconnector.PlatformConnector,
|
||||||
infraProviderResourceStore store.InfraProviderResourceStore,
|
|
||||||
infraProvisioner infrastructure.InfraProvisioner,
|
infraProvisioner infrastructure.InfraProvisioner,
|
||||||
containerOrchestrator container.Orchestrator,
|
containerOrchestrator container.Orchestrator,
|
||||||
eventReporter *events.Reporter,
|
eventReporter *events.Reporter,
|
||||||
@ -66,20 +61,20 @@ func NewOrchestrator(
|
|||||||
ideFactory ide.Factory,
|
ideFactory ide.Factory,
|
||||||
secretResolverFactory *secret.ResolverFactory,
|
secretResolverFactory *secret.ResolverFactory,
|
||||||
) Orchestrator {
|
) Orchestrator {
|
||||||
return orchestrator{
|
return Orchestrator{
|
||||||
scm: scm,
|
scm: scm,
|
||||||
platformConnector: platformConnector,
|
platformConnector: platformConnector,
|
||||||
infraProviderResourceStore: infraProviderResourceStore,
|
infraProvisioner: infraProvisioner,
|
||||||
infraProvisioner: infraProvisioner,
|
containerOrchestrator: containerOrchestrator,
|
||||||
containerOrchestrator: containerOrchestrator,
|
eventReporter: eventReporter,
|
||||||
eventReporter: eventReporter,
|
config: config,
|
||||||
config: config,
|
ideFactory: ideFactory,
|
||||||
ideFactory: ideFactory,
|
secretResolverFactory: secretResolverFactory,
|
||||||
secretResolverFactory: secretResolverFactory,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o orchestrator) TriggerStartGitspace(
|
// TriggerStartGitspace fetches the infra resources configured for the gitspace and triggers the infra provisioning.
|
||||||
|
func (o Orchestrator) TriggerStartGitspace(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
) *types.GitspaceError {
|
) *types.GitspaceError {
|
||||||
@ -142,7 +137,9 @@ func (o orchestrator) TriggerStartGitspace(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o orchestrator) TriggerStopGitspace(
|
// TriggerStopGitspace stops the Gitspace container and triggers infra deprovisioning to deprovision
|
||||||
|
// all the infra resources which are not required to restart the Gitspace.
|
||||||
|
func (o Orchestrator) TriggerStopGitspace(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
) *types.GitspaceError {
|
) *types.GitspaceError {
|
||||||
@ -183,7 +180,7 @@ func (o orchestrator) TriggerStopGitspace(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o orchestrator) stopGitspaceContainer(
|
func (o Orchestrator) stopGitspaceContainer(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
infra types.Infrastructure,
|
infra types.Infrastructure,
|
||||||
@ -215,7 +212,7 @@ func (o orchestrator) stopGitspaceContainer(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o orchestrator) stopAndRemoveGitspaceContainer(
|
func (o Orchestrator) stopAndRemoveGitspaceContainer(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
infra types.Infrastructure,
|
infra types.Infrastructure,
|
||||||
@ -246,7 +243,8 @@ func (o orchestrator) stopAndRemoveGitspaceContainer(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o orchestrator) TriggerCleanupInstanceResources(ctx context.Context, gitspaceConfig types.GitspaceConfig) error {
|
// TriggerCleanupInstanceResources cleans up all the resources exclusive to gitspace instance.
|
||||||
|
func (o Orchestrator) TriggerCleanupInstanceResources(ctx context.Context, gitspaceConfig types.GitspaceConfig) error {
|
||||||
infra, err := o.getProvisionedInfra(ctx, gitspaceConfig,
|
infra, err := o.getProvisionedInfra(ctx, gitspaceConfig,
|
||||||
[]enum.InfraStatus{
|
[]enum.InfraStatus{
|
||||||
enum.InfraStatusProvisioned,
|
enum.InfraStatusProvisioned,
|
||||||
@ -281,7 +279,11 @@ func (o orchestrator) TriggerCleanupInstanceResources(ctx context.Context, gitsp
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o orchestrator) TriggerDeleteGitspace(
|
// TriggerDeleteGitspace removes the Gitspace container and triggers infra deprovisioning to deprovision
|
||||||
|
// the infra resources.
|
||||||
|
// canDeleteUserData = false -> trigger deprovision of all resources except storage associated to user data.
|
||||||
|
// canDeleteUserData = true -> trigger deprovision of all resources.
|
||||||
|
func (o Orchestrator) TriggerDeleteGitspace(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
canDeleteUserData bool,
|
canDeleteUserData bool,
|
||||||
@ -324,7 +326,7 @@ func (o orchestrator) TriggerDeleteGitspace(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o orchestrator) emitGitspaceEvent(
|
func (o Orchestrator) emitGitspaceEvent(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
config types.GitspaceConfig,
|
config types.GitspaceConfig,
|
||||||
eventType enum.GitspaceEventType,
|
eventType enum.GitspaceEventType,
|
||||||
@ -341,7 +343,7 @@ func (o orchestrator) emitGitspaceEvent(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o orchestrator) getPortsRequiredForGitspace(
|
func (o Orchestrator) getPortsRequiredForGitspace(
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
devcontainerConfig types.DevcontainerConfig,
|
devcontainerConfig types.DevcontainerConfig,
|
||||||
) ([]types.GitspacePort, error) {
|
) ([]types.GitspacePort, error) {
|
||||||
@ -363,7 +365,8 @@ func (o orchestrator) getPortsRequiredForGitspace(
|
|||||||
return gitspacePorts, nil
|
return gitspacePorts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o orchestrator) GetGitspaceLogs(ctx context.Context, gitspaceConfig types.GitspaceConfig) (string, error) {
|
// GetGitspaceLogs fetches gitspace's start/stop logs.
|
||||||
|
func (o Orchestrator) GetGitspaceLogs(ctx context.Context, gitspaceConfig types.GitspaceConfig) (string, error) {
|
||||||
if gitspaceConfig.GitspaceInstance == nil {
|
if gitspaceConfig.GitspaceInstance == nil {
|
||||||
return "", fmt.Errorf("gitspace %s is not setup yet, please try later", gitspaceConfig.Identifier)
|
return "", fmt.Errorf("gitspace %s is not setup yet, please try later", gitspaceConfig.Identifier)
|
||||||
}
|
}
|
||||||
@ -384,7 +387,7 @@ func (o orchestrator) GetGitspaceLogs(ctx context.Context, gitspaceConfig types.
|
|||||||
return logs, nil
|
return logs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o orchestrator) getProvisionedInfra(
|
func (o Orchestrator) getProvisionedInfra(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
expectedStatus []enum.InfraStatus,
|
expectedStatus []enum.InfraStatus,
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
// 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"
|
|
||||||
"github.com/harness/gitness/app/gitspace/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Service interface {
|
|
||||||
// Manage manager the linux user in the container.
|
|
||||||
Manage(ctx context.Context, exec *devcontainer.Exec, gitspaceLogger types.GitspaceLogger) error
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
// 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()
|
|
||||||
}
|
|
89
app/gitspace/orchestrator/utils/environment.go
Normal file
89
app/gitspace/orchestrator/utils/environment.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// 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 utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
||||||
|
"github.com/harness/gitness/app/gitspace/types"
|
||||||
|
|
||||||
|
_ "embed"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
templateSupportedOSDistribution = "supported_os_distribution.sh"
|
||||||
|
templateVsCodeWebToolsInstallation = "install_tools_vs_code_web.sh"
|
||||||
|
templateVsCodeToolsInstallation = "install_tools_vs_code.sh"
|
||||||
|
templateSetEnv = "set_env.sh"
|
||||||
|
templateGitInstallScript string = "install_git.sh"
|
||||||
|
templateSetupGitCredentials = "setup_git_credentials.sh" // nolint:gosec
|
||||||
|
templateCloneCode = "clone_code.sh"
|
||||||
|
templateManagerUser = "manage_user.sh"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed script/os_info.sh
|
||||||
|
var osDetectScript string
|
||||||
|
|
||||||
|
func GetOSInfoScript() (script string) {
|
||||||
|
return osDetectScript
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateSupportedOS(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
gitspaceLogger types.GitspaceLogger,
|
||||||
|
) error {
|
||||||
|
// TODO: Currently not supporting arch, freebsd and alpine.
|
||||||
|
// For alpine wee need to install multiple things from
|
||||||
|
// https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites
|
||||||
|
script, err := GenerateScriptFromTemplate(
|
||||||
|
templateSupportedOSDistribution, &types.SupportedOSDistributionPayload{
|
||||||
|
OSInfoScript: osDetectScript,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to generate scipt to validate supported os distribution from template %s: %w",
|
||||||
|
templateSupportedOSDistribution, err)
|
||||||
|
}
|
||||||
|
gitspaceLogger.Info("Validate supported OSes...")
|
||||||
|
err = exec.ExecuteCommandInHomeDirAndLog(ctx, script, true, gitspaceLogger, false)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error while detecting os distribution: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetEnv(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
gitspaceLogger types.GitspaceLogger,
|
||||||
|
environment []string,
|
||||||
|
) error {
|
||||||
|
script, err := GenerateScriptFromTemplate(
|
||||||
|
templateSetEnv, &types.SetEnvPayload{
|
||||||
|
EnvVariables: environment,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to generate scipt to set env from template %s: %w",
|
||||||
|
templateSetEnv, err)
|
||||||
|
}
|
||||||
|
gitspaceLogger.Info("Setting env...")
|
||||||
|
err = exec.ExecuteCommandInHomeDirAndLog(ctx, script, true, gitspaceLogger, true)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error while setting env vars: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -12,41 +12,26 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package git
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/common"
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/template"
|
|
||||||
"github.com/harness/gitness/app/gitspace/scm"
|
"github.com/harness/gitness/app/gitspace/scm"
|
||||||
"github.com/harness/gitness/app/gitspace/types"
|
"github.com/harness/gitness/app/gitspace/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Service = (*ServiceImpl)(nil)
|
func InstallGit(
|
||||||
|
|
||||||
const templateGitInstallScript string = "install_git.sh"
|
|
||||||
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,
|
ctx context.Context,
|
||||||
exec *devcontainer.Exec,
|
exec *devcontainer.Exec,
|
||||||
gitspaceLogger types.GitspaceLogger,
|
gitspaceLogger types.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
script, err := template.GenerateScriptFromTemplate(
|
script, err := GenerateScriptFromTemplate(
|
||||||
templateGitInstallScript, &template.SetupGitInstallPayload{
|
templateGitInstallScript, &types.SetupGitInstallPayload{
|
||||||
OSInfoScript: common.GetOSInfoScript(),
|
OSInfoScript: GetOSInfoScript(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
@ -54,7 +39,7 @@ func (g *ServiceImpl) Install(
|
|||||||
}
|
}
|
||||||
gitspaceLogger.Info("Install git output...")
|
gitspaceLogger.Info("Install git output...")
|
||||||
gitspaceLogger.Info("Setting up git inside container")
|
gitspaceLogger.Info("Setting up git inside container")
|
||||||
err = common.ExecuteCommandInHomeDirAndLog(ctx, exec, script, true, gitspaceLogger, false)
|
err = exec.ExecuteCommandInHomeDirAndLog(ctx, script, true, gitspaceLogger, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to setup git: %w", err)
|
return fmt.Errorf("failed to setup git: %w", err)
|
||||||
}
|
}
|
||||||
@ -63,14 +48,14 @@ func (g *ServiceImpl) Install(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *ServiceImpl) SetupCredentials(
|
func SetupGitCredentials(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
exec *devcontainer.Exec,
|
exec *devcontainer.Exec,
|
||||||
resolvedRepoDetails scm.ResolvedDetails,
|
resolvedRepoDetails scm.ResolvedDetails,
|
||||||
gitspaceLogger types.GitspaceLogger,
|
gitspaceLogger types.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
script, err := template.GenerateScriptFromTemplate(
|
script, err := GenerateScriptFromTemplate(
|
||||||
templateSetupGitCredentials, &template.SetupGitCredentialsPayload{
|
templateSetupGitCredentials, &types.SetupGitCredentialsPayload{
|
||||||
CloneURLWithCreds: resolvedRepoDetails.CloneURL.Value(),
|
CloneURLWithCreds: resolvedRepoDetails.CloneURL.Value(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -79,7 +64,7 @@ func (g *ServiceImpl) SetupCredentials(
|
|||||||
}
|
}
|
||||||
gitspaceLogger.Info("Setting up git credentials output...")
|
gitspaceLogger.Info("Setting up git credentials output...")
|
||||||
gitspaceLogger.Info("Setting up git credentials inside container")
|
gitspaceLogger.Info("Setting up git credentials inside container")
|
||||||
err = common.ExecuteCommandInHomeDirAndLog(ctx, exec, script, false, gitspaceLogger, true)
|
err = exec.ExecuteCommandInHomeDirAndLog(ctx, script, false, gitspaceLogger, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to setup git credentials: %w", err)
|
return fmt.Errorf("failed to setup git credentials: %w", err)
|
||||||
}
|
}
|
||||||
@ -87,7 +72,7 @@ func (g *ServiceImpl) SetupCredentials(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *ServiceImpl) CloneCode(
|
func CloneCode(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
exec *devcontainer.Exec,
|
exec *devcontainer.Exec,
|
||||||
resolvedRepoDetails scm.ResolvedDetails,
|
resolvedRepoDetails scm.ResolvedDetails,
|
||||||
@ -100,7 +85,7 @@ func (g *ServiceImpl) CloneCode(
|
|||||||
"failed to parse clone url %s: %w", resolvedRepoDetails.CloneURL, err)
|
"failed to parse clone url %s: %w", resolvedRepoDetails.CloneURL, err)
|
||||||
}
|
}
|
||||||
cloneURL.User = nil
|
cloneURL.User = nil
|
||||||
data := &template.CloneCodePayload{
|
data := &types.CloneCodePayload{
|
||||||
RepoURL: cloneURL.String(),
|
RepoURL: cloneURL.String(),
|
||||||
Image: defaultBaseImage,
|
Image: defaultBaseImage,
|
||||||
Branch: resolvedRepoDetails.Branch,
|
Branch: resolvedRepoDetails.Branch,
|
||||||
@ -110,14 +95,14 @@ func (g *ServiceImpl) CloneCode(
|
|||||||
data.Email = resolvedRepoDetails.Credentials.Email
|
data.Email = resolvedRepoDetails.Credentials.Email
|
||||||
data.Name = resolvedRepoDetails.Credentials.Name.Value()
|
data.Name = resolvedRepoDetails.Credentials.Name.Value()
|
||||||
}
|
}
|
||||||
script, err := template.GenerateScriptFromTemplate(
|
script, err := GenerateScriptFromTemplate(
|
||||||
templateCloneCode, data)
|
templateCloneCode, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"failed to generate scipt to clone code from template %s: %w", templateCloneCode, err)
|
"failed to generate scipt to clone code from template %s: %w", templateCloneCode, err)
|
||||||
}
|
}
|
||||||
gitspaceLogger.Info("Cloning code inside container")
|
gitspaceLogger.Info("Cloning code inside container")
|
||||||
err = common.ExecuteCommandInHomeDirAndLog(ctx, exec, script, false, gitspaceLogger, true)
|
err = exec.ExecuteCommandInHomeDirAndLog(ctx, script, false, gitspaceLogger, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to clone code: %w", err)
|
return fmt.Errorf("failed to clone code: %w", err)
|
||||||
}
|
}
|
@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package template
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -21,8 +21,6 @@ import (
|
|||||||
"io/fs"
|
"io/fs"
|
||||||
"path"
|
"path"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/harness/gitness/types/enum"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -35,68 +33,6 @@ var (
|
|||||||
scriptTemplates map[string]*template.Template
|
scriptTemplates map[string]*template.Template
|
||||||
)
|
)
|
||||||
|
|
||||||
type CloneCodePayload struct {
|
|
||||||
RepoURL string
|
|
||||||
Image string
|
|
||||||
Branch string
|
|
||||||
RepoName string
|
|
||||||
Name string
|
|
||||||
Email string
|
|
||||||
}
|
|
||||||
|
|
||||||
type SetupGitInstallPayload struct {
|
|
||||||
OSInfoScript string
|
|
||||||
}
|
|
||||||
|
|
||||||
type SetupGitCredentialsPayload struct {
|
|
||||||
CloneURLWithCreds string
|
|
||||||
}
|
|
||||||
|
|
||||||
type RunVSCodeWebPayload struct {
|
|
||||||
Port string
|
|
||||||
Arguments string
|
|
||||||
ProxyURI string
|
|
||||||
}
|
|
||||||
|
|
||||||
type SetupVSCodeWebPayload struct {
|
|
||||||
Extensions []string
|
|
||||||
}
|
|
||||||
|
|
||||||
type SetupUserPayload struct {
|
|
||||||
Username string
|
|
||||||
AccessKey string
|
|
||||||
AccessType enum.GitspaceAccessType
|
|
||||||
HomeDir string
|
|
||||||
}
|
|
||||||
|
|
||||||
type SetupSSHServerPayload struct {
|
|
||||||
Username string
|
|
||||||
AccessType enum.GitspaceAccessType
|
|
||||||
OSInfoScript string
|
|
||||||
}
|
|
||||||
|
|
||||||
type SetupVSCodeExtensionsPayload struct {
|
|
||||||
Username string
|
|
||||||
Extensions string
|
|
||||||
RepoName string
|
|
||||||
}
|
|
||||||
|
|
||||||
type RunSSHServerPayload struct {
|
|
||||||
Port string
|
|
||||||
}
|
|
||||||
|
|
||||||
type InstallToolsPayload struct {
|
|
||||||
OSInfoScript string
|
|
||||||
}
|
|
||||||
|
|
||||||
type SupportedOSDistributionPayload struct {
|
|
||||||
OSInfoScript string
|
|
||||||
}
|
|
||||||
|
|
||||||
type SetEnvPayload struct {
|
|
||||||
EnvVariables []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
err := LoadTemplates()
|
err := LoadTemplates()
|
||||||
if err != nil {
|
if err != nil {
|
99
app/gitspace/orchestrator/utils/tools.go
Normal file
99
app/gitspace/orchestrator/utils/tools.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// 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 utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
||||||
|
"github.com/harness/gitness/app/gitspace/types"
|
||||||
|
"github.com/harness/gitness/types/enum"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InstallTools(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
ideType enum.IDEType,
|
||||||
|
gitspaceLogger types.GitspaceLogger,
|
||||||
|
) error {
|
||||||
|
switch ideType {
|
||||||
|
case enum.IDETypeVSCodeWeb:
|
||||||
|
err := InstallToolsForVsCodeWeb(ctx, exec, gitspaceLogger)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case enum.IDETypeVSCode:
|
||||||
|
err := InstallToolsForVsCode(ctx, exec, gitspaceLogger)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case enum.IDETypeIntellij:
|
||||||
|
// not installing any tools for intellij
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func InstallToolsForVsCodeWeb(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
gitspaceLogger types.GitspaceLogger,
|
||||||
|
) error {
|
||||||
|
script, err := GenerateScriptFromTemplate(
|
||||||
|
templateVsCodeWebToolsInstallation, &types.InstallToolsPayload{
|
||||||
|
OSInfoScript: osDetectScript,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"failed to generate scipt to install tools for vs code web from template %s: %w",
|
||||||
|
templateVsCodeWebToolsInstallation, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gitspaceLogger.Info("Installing tools for vs code web inside container")
|
||||||
|
gitspaceLogger.Info("Tools installation output...")
|
||||||
|
err = exec.ExecuteCommandInHomeDirAndLog(ctx, script, true, gitspaceLogger, false)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to install tools for vs code web: %w", err)
|
||||||
|
}
|
||||||
|
gitspaceLogger.Info("Successfully installed tools for vs code web")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func InstallToolsForVsCode(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
gitspaceLogger types.GitspaceLogger,
|
||||||
|
) error {
|
||||||
|
script, err := GenerateScriptFromTemplate(
|
||||||
|
templateVsCodeToolsInstallation, &types.InstallToolsPayload{
|
||||||
|
OSInfoScript: osDetectScript,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"failed to generate scipt to install tools for vs code from template %s: %w",
|
||||||
|
templateVsCodeToolsInstallation, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gitspaceLogger.Info("Installing tools for vs code in container")
|
||||||
|
err = exec.ExecuteCommandInHomeDirAndLog(ctx, script, true, gitspaceLogger, false)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to install tools for vs code: %w", err)
|
||||||
|
}
|
||||||
|
gitspaceLogger.Info("Successfully installed tools for vs code")
|
||||||
|
return nil
|
||||||
|
}
|
@ -12,36 +12,23 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package user
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/common"
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/template"
|
"github.com/harness/gitness/app/gitspace/types"
|
||||||
gitspaceTypes "github.com/harness/gitness/app/gitspace/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Service = (*ServiceImpl)(nil)
|
func ManageUser(
|
||||||
|
|
||||||
const templateManagerUser = "manage_user.sh"
|
|
||||||
|
|
||||||
type ServiceImpl struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewUserServiceImpl() Service {
|
|
||||||
return &ServiceImpl{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *ServiceImpl) Manage(
|
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
exec *devcontainer.Exec,
|
exec *devcontainer.Exec,
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger types.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
script, err := template.GenerateScriptFromTemplate(
|
script, err := GenerateScriptFromTemplate(
|
||||||
templateManagerUser, &template.SetupUserPayload{
|
templateManagerUser, &types.SetupUserPayload{
|
||||||
Username: exec.RemoteUser,
|
Username: exec.RemoteUser,
|
||||||
AccessKey: exec.AccessKey,
|
AccessKey: exec.AccessKey,
|
||||||
AccessType: exec.AccessType,
|
AccessType: exec.AccessType,
|
||||||
@ -53,7 +40,7 @@ func (u *ServiceImpl) Manage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
gitspaceLogger.Info("Configuring user directory and credentials inside container")
|
gitspaceLogger.Info("Configuring user directory and credentials inside container")
|
||||||
err = common.ExecuteCommandInHomeDirAndLog(ctx, exec, script, true, gitspaceLogger, true)
|
err = exec.ExecuteCommandInHomeDirAndLog(ctx, script, true, gitspaceLogger, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to setup user: %w", err)
|
return fmt.Errorf("failed to setup user: %w", err)
|
||||||
}
|
}
|
@ -22,7 +22,6 @@ import (
|
|||||||
"github.com/harness/gitness/app/gitspace/platformconnector"
|
"github.com/harness/gitness/app/gitspace/platformconnector"
|
||||||
"github.com/harness/gitness/app/gitspace/scm"
|
"github.com/harness/gitness/app/gitspace/scm"
|
||||||
"github.com/harness/gitness/app/gitspace/secret"
|
"github.com/harness/gitness/app/gitspace/secret"
|
||||||
"github.com/harness/gitness/app/store"
|
|
||||||
|
|
||||||
"github.com/google/wire"
|
"github.com/google/wire"
|
||||||
)
|
)
|
||||||
@ -35,7 +34,6 @@ var WireSet = wire.NewSet(
|
|||||||
func ProvideOrchestrator(
|
func ProvideOrchestrator(
|
||||||
scm *scm.SCM,
|
scm *scm.SCM,
|
||||||
platformConnector platformconnector.PlatformConnector,
|
platformConnector platformconnector.PlatformConnector,
|
||||||
infraProviderResourceStore store.InfraProviderResourceStore,
|
|
||||||
infraProvisioner infrastructure.InfraProvisioner,
|
infraProvisioner infrastructure.InfraProvisioner,
|
||||||
containerOrchestrator container.Orchestrator,
|
containerOrchestrator container.Orchestrator,
|
||||||
reporter *events.Reporter,
|
reporter *events.Reporter,
|
||||||
@ -46,7 +44,6 @@ func ProvideOrchestrator(
|
|||||||
return NewOrchestrator(
|
return NewOrchestrator(
|
||||||
scm,
|
scm,
|
||||||
platformConnector,
|
platformConnector,
|
||||||
infraProviderResourceStore,
|
|
||||||
infraProvisioner,
|
infraProvisioner,
|
||||||
containerOrchestrator,
|
containerOrchestrator,
|
||||||
reporter,
|
reporter,
|
||||||
|
79
app/gitspace/types/script_template_payload.go
Normal file
79
app/gitspace/types/script_template_payload.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// 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 types
|
||||||
|
|
||||||
|
import "github.com/harness/gitness/types/enum"
|
||||||
|
|
||||||
|
type CloneCodePayload struct {
|
||||||
|
RepoURL string
|
||||||
|
Image string
|
||||||
|
Branch string
|
||||||
|
RepoName string
|
||||||
|
Name string
|
||||||
|
Email string
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetupGitInstallPayload struct {
|
||||||
|
OSInfoScript string
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetupGitCredentialsPayload struct {
|
||||||
|
CloneURLWithCreds string
|
||||||
|
}
|
||||||
|
|
||||||
|
type RunVSCodeWebPayload struct {
|
||||||
|
Port string
|
||||||
|
Arguments string
|
||||||
|
ProxyURI string
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetupVSCodeWebPayload struct {
|
||||||
|
Extensions []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetupUserPayload struct {
|
||||||
|
Username string
|
||||||
|
AccessKey string
|
||||||
|
AccessType enum.GitspaceAccessType
|
||||||
|
HomeDir string
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetupSSHServerPayload struct {
|
||||||
|
Username string
|
||||||
|
AccessType enum.GitspaceAccessType
|
||||||
|
OSInfoScript string
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetupVSCodeExtensionsPayload struct {
|
||||||
|
Username string
|
||||||
|
Extensions string
|
||||||
|
RepoName string
|
||||||
|
}
|
||||||
|
|
||||||
|
type RunSSHServerPayload struct {
|
||||||
|
Port string
|
||||||
|
}
|
||||||
|
|
||||||
|
type InstallToolsPayload struct {
|
||||||
|
OSInfoScript string
|
||||||
|
}
|
||||||
|
|
||||||
|
type SupportedOSDistributionPayload struct {
|
||||||
|
OSInfoScript string
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetEnvPayload struct {
|
||||||
|
EnvVariables []string
|
||||||
|
}
|
@ -15,9 +15,6 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
|
||||||
"github.com/harness/gitness/types"
|
"github.com/harness/gitness/types"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
@ -29,6 +26,8 @@ const (
|
|||||||
VSCodeCustomizationArg IDEArg = "VSCODE_CUSTOMIZATION"
|
VSCodeCustomizationArg IDEArg = "VSCODE_CUSTOMIZATION"
|
||||||
VSCodeProxyURIArg IDEArg = "VSCODE_PROXY_URI"
|
VSCodeProxyURIArg IDEArg = "VSCODE_PROXY_URI"
|
||||||
IDERepoNameArg IDEArg = "IDE_REPO_NAME"
|
IDERepoNameArg IDEArg = "IDE_REPO_NAME"
|
||||||
|
VSCodeURLScheme = "vscode-remote"
|
||||||
|
IntellijURLScheme = "jetbrains-gateway"
|
||||||
)
|
)
|
||||||
|
|
||||||
type GitspaceLogger interface {
|
type GitspaceLogger interface {
|
||||||
@ -38,13 +37,6 @@ type GitspaceLogger interface {
|
|||||||
Error(msg string, err error)
|
Error(msg string, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step represents a single setup action.
|
|
||||||
type Step struct {
|
|
||||||
Name string
|
|
||||||
Execute func(ctx context.Context, exec *devcontainer.Exec, gitspaceLogger GitspaceLogger) error
|
|
||||||
StopOnFailure bool // Flag to control whether execution should stop on failure
|
|
||||||
}
|
|
||||||
|
|
||||||
type ZerologAdapter struct {
|
type ZerologAdapter struct {
|
||||||
logger *zerolog.Logger
|
logger *zerolog.Logger
|
||||||
}
|
}
|
||||||
|
@ -64,10 +64,8 @@ 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"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/runarg"
|
"github.com/harness/gitness/app/gitspace/orchestrator/runarg"
|
||||||
containerUser "github.com/harness/gitness/app/gitspace/orchestrator/user"
|
|
||||||
"github.com/harness/gitness/app/gitspace/platformconnector"
|
"github.com/harness/gitness/app/gitspace/platformconnector"
|
||||||
"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"
|
||||||
@ -282,8 +280,6 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
|
|||||||
capabilitiesservice.WireSet,
|
capabilitiesservice.WireSet,
|
||||||
docker.ProvideReporter,
|
docker.ProvideReporter,
|
||||||
secretservice.WireSet,
|
secretservice.WireSet,
|
||||||
containerGit.WireSet,
|
|
||||||
containerUser.WireSet,
|
|
||||||
messagingservice.WireSet,
|
messagingservice.WireSet,
|
||||||
runarg.WireSet,
|
runarg.WireSet,
|
||||||
usage.WireSet,
|
usage.WireSet,
|
||||||
|
@ -53,10 +53,8 @@ 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"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/runarg"
|
"github.com/harness/gitness/app/gitspace/orchestrator/runarg"
|
||||||
user2 "github.com/harness/gitness/app/gitspace/orchestrator/user"
|
|
||||||
"github.com/harness/gitness/app/gitspace/platformconnector"
|
"github.com/harness/gitness/app/gitspace/platformconnector"
|
||||||
"github.com/harness/gitness/app/gitspace/scm"
|
"github.com/harness/gitness/app/gitspace/scm"
|
||||||
"github.com/harness/gitness/app/gitspace/secret"
|
"github.com/harness/gitness/app/gitspace/secret"
|
||||||
@ -321,8 +319,6 @@ 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)
|
||||||
gitService := git2.ProvideGitServiceImpl()
|
|
||||||
userService := user2.ProvideUserServiceImpl()
|
|
||||||
runargResolver, err := runarg.ProvideResolver()
|
runargResolver, err := runarg.ProvideResolver()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -331,7 +327,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
containerOrchestrator := container.ProvideEmbeddedDockerOrchestrator(dockerClientFactory, statefulLogger, gitService, userService, runargProvider)
|
containerOrchestrator := container.ProvideEmbeddedDockerOrchestrator(dockerClientFactory, statefulLogger, runargProvider)
|
||||||
orchestratorConfig := server.ProvideGitspaceOrchestratorConfig(config)
|
orchestratorConfig := server.ProvideGitspaceOrchestratorConfig(config)
|
||||||
vsCodeConfig := server.ProvideIDEVSCodeConfig(config)
|
vsCodeConfig := server.ProvideIDEVSCodeConfig(config)
|
||||||
vsCode := ide.ProvideVSCodeService(vsCodeConfig)
|
vsCode := ide.ProvideVSCodeService(vsCodeConfig)
|
||||||
@ -340,7 +336,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
|||||||
ideFactory := ide.ProvideIDEFactory(vsCode, vsCodeWeb)
|
ideFactory := ide.ProvideIDEFactory(vsCode, vsCodeWeb)
|
||||||
passwordResolver := secret.ProvidePasswordResolver()
|
passwordResolver := secret.ProvidePasswordResolver()
|
||||||
resolverFactory := secret.ProvideResolverFactory(passwordResolver)
|
resolverFactory := secret.ProvideResolverFactory(passwordResolver)
|
||||||
orchestratorOrchestrator := orchestrator.ProvideOrchestrator(scmSCM, platformConnector, infraProviderResourceStore, infraProvisioner, containerOrchestrator, eventsReporter, orchestratorConfig, ideFactory, resolverFactory)
|
orchestratorOrchestrator := orchestrator.ProvideOrchestrator(scmSCM, platformConnector, infraProvisioner, containerOrchestrator, eventsReporter, orchestratorConfig, ideFactory, resolverFactory)
|
||||||
gitspaceService := gitspace.ProvideGitspace(transactor, gitspaceConfigStore, gitspaceInstanceStore, eventsReporter, gitspaceEventStore, spaceStore, infraproviderService, orchestratorOrchestrator, scmSCM, config)
|
gitspaceService := gitspace.ProvideGitspace(transactor, gitspaceConfigStore, gitspaceInstanceStore, eventsReporter, gitspaceEventStore, spaceStore, infraproviderService, orchestratorOrchestrator, scmSCM, config)
|
||||||
usageMetricStore := database.ProvideUsageMetricStore(db)
|
usageMetricStore := database.ProvideUsageMetricStore(db)
|
||||||
spaceController := space.ProvideController(config, transactor, provider, streamer, spaceIdentifier, authorizer, spacePathStore, pipelineStore, secretStore, connectorStore, templateStore, spaceStore, repoStore, principalStore, repoController, membershipStore, listService, spaceCache, repository, exporterRepository, resourceLimiter, publicaccessService, auditService, gitspaceService, labelService, instrumentService, executionStore, rulesService, usageMetricStore)
|
spaceController := space.ProvideController(config, transactor, provider, streamer, spaceIdentifier, authorizer, spacePathStore, pipelineStore, secretStore, connectorStore, templateStore, spaceStore, repoStore, principalStore, repoController, membershipStore, listService, spaceCache, repository, exporterRepository, resourceLimiter, publicaccessService, auditService, gitspaceService, labelService, instrumentService, executionStore, rulesService, usageMetricStore)
|
||||||
|
Loading…
Reference in New Issue
Block a user