mirror of https://github.com/harness/drone.git
feat: [CDE-475]: Adding support for runArgs. (#3031)
* Rebasing * feat: [CDE-475]: Adding support for runArgs. * WIP * WIPpull/3597/head
parent
1299db775e
commit
7c358528ef
|
@ -7,7 +7,7 @@ GITNESS_METRIC_ENABLED=false
|
||||||
GITNESS_HTTP_HOST=localhost
|
GITNESS_HTTP_HOST=localhost
|
||||||
GITNESS_GITSPACE_ENABLE=true
|
GITNESS_GITSPACE_ENABLE=true
|
||||||
GITNESS_DEBUG=true
|
GITNESS_DEBUG=true
|
||||||
GITNESS_DOCKER_API_VERSION=1.41
|
GITNESS_DOCKER_API_VERSION=1.45
|
||||||
GITNESS_SSH_ENABLE=true
|
GITNESS_SSH_ENABLE=true
|
||||||
GITNESS_SSH_HOST=localhost
|
GITNESS_SSH_HOST=localhost
|
||||||
GITNESS_SSH_PORT=2222
|
GITNESS_SSH_PORT=2222
|
||||||
|
|
|
@ -0,0 +1,167 @@
|
||||||
|
// 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 container
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/app/gitspace/orchestrator/runarg"
|
||||||
|
"github.com/harness/gitness/types"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExtractRunArgs(
|
||||||
|
ctx context.Context,
|
||||||
|
spaceID int64,
|
||||||
|
runArgProvider runarg.Provider,
|
||||||
|
runArgsRaw []string,
|
||||||
|
) (map[types.RunArg]*types.RunArgValue, error) {
|
||||||
|
supportedRunArgsMap, err := runArgProvider.ProvideSupportedRunArgs(ctx, spaceID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var runArgsMap = make(map[types.RunArg]*types.RunArgValue)
|
||||||
|
primaryLoopCounter := 0
|
||||||
|
for primaryLoopCounter < len(runArgsRaw) {
|
||||||
|
currentArg := runArgsRaw[primaryLoopCounter]
|
||||||
|
if currentArg == "" || !isArg(currentArg) {
|
||||||
|
primaryLoopCounter++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
argParts := strings.SplitN(currentArg, "=", 2)
|
||||||
|
argKey := argParts[0]
|
||||||
|
|
||||||
|
currentRunArgDefinition, isSupportedArg := supportedRunArgsMap[types.RunArg(argKey)]
|
||||||
|
if !isSupportedArg {
|
||||||
|
primaryLoopCounter++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
updatedPrimaryLoopCounter, allowedValues, isAnyValueBlocked := getValues(runArgsRaw, argParts,
|
||||||
|
primaryLoopCounter, currentRunArgDefinition)
|
||||||
|
|
||||||
|
primaryLoopCounter = updatedPrimaryLoopCounter
|
||||||
|
|
||||||
|
if isAnyValueBlocked && len(allowedValues) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
currentRunArgValue := types.RunArgValue{
|
||||||
|
Name: currentRunArgDefinition.Name,
|
||||||
|
Values: allowedValues,
|
||||||
|
}
|
||||||
|
|
||||||
|
existingRunArgValue, isAlreadyPresent := runArgsMap[currentRunArgDefinition.Name]
|
||||||
|
if isAlreadyPresent && currentRunArgDefinition.AllowMultipleOccurences {
|
||||||
|
existingRunArgValue.Values = append(existingRunArgValue.Values, currentRunArgValue.Values...)
|
||||||
|
} else {
|
||||||
|
runArgsMap[currentRunArgDefinition.Name] = ¤tRunArgValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return runArgsMap, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getValues(
|
||||||
|
runArgs []string,
|
||||||
|
argParts []string,
|
||||||
|
primaryLoopCounter int,
|
||||||
|
currentRunArgDefinition types.RunArgDefinition,
|
||||||
|
) (int, []string, bool) {
|
||||||
|
values := make([]string, 0)
|
||||||
|
if len(argParts) > 1 {
|
||||||
|
values = append(values, argParts[1])
|
||||||
|
primaryLoopCounter++
|
||||||
|
} else {
|
||||||
|
var secondaryLoopCounter = primaryLoopCounter + 1
|
||||||
|
for secondaryLoopCounter < len(runArgs) {
|
||||||
|
currentValue := runArgs[secondaryLoopCounter]
|
||||||
|
if isArg(currentValue) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
values = append(values, currentValue)
|
||||||
|
secondaryLoopCounter++
|
||||||
|
}
|
||||||
|
primaryLoopCounter = secondaryLoopCounter
|
||||||
|
}
|
||||||
|
allowedValues, isAnyValueBlocked := filterAllowedValues(values, currentRunArgDefinition)
|
||||||
|
return primaryLoopCounter, allowedValues, isAnyValueBlocked
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterAllowedValues(values []string, currentRunArgDefinition types.RunArgDefinition) ([]string, bool) {
|
||||||
|
isAnyValueBlocked := false
|
||||||
|
allowedValues := make([]string, 0)
|
||||||
|
for _, v := range values {
|
||||||
|
switch {
|
||||||
|
case len(currentRunArgDefinition.AllowedValues) > 0:
|
||||||
|
if _, ok := currentRunArgDefinition.AllowedValues[v]; ok {
|
||||||
|
allowedValues = append(allowedValues, v)
|
||||||
|
} else {
|
||||||
|
isAnyValueBlocked = true
|
||||||
|
}
|
||||||
|
case len(currentRunArgDefinition.BlockedValues) > 0:
|
||||||
|
if _, ok := currentRunArgDefinition.BlockedValues[v]; !ok {
|
||||||
|
allowedValues = append(allowedValues, v)
|
||||||
|
} else {
|
||||||
|
isAnyValueBlocked = true
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
allowedValues = append(allowedValues, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allowedValues, isAnyValueBlocked
|
||||||
|
}
|
||||||
|
|
||||||
|
func isArg(str string) bool {
|
||||||
|
return strings.HasPrefix(str, "--") || strings.HasPrefix(str, "-")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExtractEnv(devcontainerConfig types.DevcontainerConfig, runArgsMap map[types.RunArg]*types.RunArgValue) []string {
|
||||||
|
var env []string
|
||||||
|
for key, value := range devcontainerConfig.ContainerEnv {
|
||||||
|
env = append(env, fmt.Sprintf("%s=%s", key, value))
|
||||||
|
}
|
||||||
|
envFromRunArgs := getEnv(runArgsMap)
|
||||||
|
env = append(env, envFromRunArgs...)
|
||||||
|
return env
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExtractForwardPorts(devcontainerConfig types.DevcontainerConfig) []int {
|
||||||
|
var ports []int
|
||||||
|
for _, strPort := range devcontainerConfig.ForwardPorts {
|
||||||
|
portAsInt, err := strPort.Int64() // Using Atoi to convert string to int
|
||||||
|
if err != nil {
|
||||||
|
log.Warn().Msgf("Error converting port string '%s' to int: %v", strPort, err)
|
||||||
|
continue // Skip the invalid port
|
||||||
|
}
|
||||||
|
ports = append(ports, int(portAsInt))
|
||||||
|
}
|
||||||
|
return ports
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExtractLifecycleCommands(actionType PostAction, devcontainerConfig types.DevcontainerConfig) []string {
|
||||||
|
switch actionType {
|
||||||
|
case PostCreateAction:
|
||||||
|
return devcontainerConfig.PostCreateCommand.ToCommandArray()
|
||||||
|
case PostStartAction:
|
||||||
|
return devcontainerConfig.PostStartCommand.ToCommandArray()
|
||||||
|
default:
|
||||||
|
return []string{} // Return empty string if actionType is not recognized
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/app/gitspace/orchestrator/runarg"
|
||||||
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"
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ import (
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/image"
|
"github.com/docker/docker/api/types/image"
|
||||||
"github.com/docker/docker/api/types/mount"
|
"github.com/docker/docker/api/types/mount"
|
||||||
|
"github.com/docker/docker/api/types/strslice"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
@ -131,22 +133,50 @@ func CreateContainer(
|
||||||
mountType mount.Type,
|
mountType mount.Type,
|
||||||
portMappings map[int]*types.PortMapping,
|
portMappings map[int]*types.PortMapping,
|
||||||
env []string,
|
env []string,
|
||||||
|
runArgsMap map[types.RunArg]*types.RunArgValue,
|
||||||
) error {
|
) error {
|
||||||
exposedPorts, portBindings := applyPortMappings(portMappings)
|
exposedPorts, portBindings := applyPortMappings(portMappings)
|
||||||
|
|
||||||
gitspaceLogger.Info("Creating container: " + containerName)
|
gitspaceLogger.Info("Creating container: " + containerName)
|
||||||
|
|
||||||
hostConfig := prepareHostConfig(bindMountSource, bindMountTarget, mountType, portBindings)
|
hostConfig, err := prepareHostConfig(bindMountSource, bindMountTarget, mountType, portBindings, runArgsMap)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
healthCheckConfig, err := getHealthCheckConfig(runArgsMap)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stopTimeout, err := getStopTimeout(runArgsMap)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
entrypoint := getEntrypoint(runArgsMap)
|
||||||
|
var cmd strslice.StrSlice
|
||||||
|
if len(entrypoint) == 0 {
|
||||||
|
entrypoint = []string{"/bin/sh"}
|
||||||
|
cmd = []string{"-c", "trap 'exit 0' 15; sleep infinity & wait $!"}
|
||||||
|
}
|
||||||
|
|
||||||
// Create the container
|
// Create the container
|
||||||
containerConfig := &container.Config{
|
containerConfig := &container.Config{
|
||||||
|
Hostname: getHostname(runArgsMap),
|
||||||
|
Domainname: getDomainname(runArgsMap),
|
||||||
Image: imageName,
|
Image: imageName,
|
||||||
Env: env,
|
Env: env,
|
||||||
Entrypoint: []string{"/bin/sh"},
|
Entrypoint: entrypoint,
|
||||||
Cmd: []string{"-c", "trap 'exit 0' 15; sleep infinity & wait $!"},
|
Cmd: cmd,
|
||||||
ExposedPorts: exposedPorts,
|
ExposedPorts: exposedPorts,
|
||||||
|
Labels: getLabels(runArgsMap),
|
||||||
|
Healthcheck: healthCheckConfig,
|
||||||
|
MacAddress: getMACAddress(runArgsMap),
|
||||||
|
StopSignal: getStopSignal(runArgsMap),
|
||||||
|
StopTimeout: stopTimeout,
|
||||||
|
User: getUser(runArgsMap),
|
||||||
}
|
}
|
||||||
_, err := dockerClient.ContainerCreate(ctx, containerConfig, hostConfig, nil, nil, containerName)
|
|
||||||
|
_, err = dockerClient.ContainerCreate(ctx, containerConfig, hostConfig, nil, nil, containerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logStreamWrapError(gitspaceLogger, "Error while creating container", err)
|
return logStreamWrapError(gitspaceLogger, "Error while creating container", err)
|
||||||
}
|
}
|
||||||
|
@ -178,7 +208,33 @@ func prepareHostConfig(
|
||||||
bindMountTarget string,
|
bindMountTarget string,
|
||||||
mountType mount.Type,
|
mountType mount.Type,
|
||||||
portBindings nat.PortMap,
|
portBindings nat.PortMap,
|
||||||
) *container.HostConfig {
|
runArgsMap map[types.RunArg]*types.RunArgValue,
|
||||||
|
) (*container.HostConfig, error) {
|
||||||
|
hostResources, err := getHostResources(runArgsMap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
extraHosts := getExtraHosts(runArgsMap)
|
||||||
|
if goruntime.GOOS == "linux" {
|
||||||
|
extraHosts = append(extraHosts, "host.docker.internal:host-gateway")
|
||||||
|
}
|
||||||
|
|
||||||
|
restartPolicy, err := getRestartPolicy(runArgsMap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
oomScoreAdj, err := getOomScoreAdj(runArgsMap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
shmSize, err := getSHMSize(runArgsMap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
hostConfig := &container.HostConfig{
|
hostConfig := &container.HostConfig{
|
||||||
PortBindings: portBindings,
|
PortBindings: portBindings,
|
||||||
Mounts: []mount.Mount{
|
Mounts: []mount.Mount{
|
||||||
|
@ -188,14 +244,33 @@ func prepareHostConfig(
|
||||||
Target: bindMountTarget,
|
Target: bindMountTarget,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Resources: hostResources,
|
||||||
|
Annotations: getAnnotations(runArgsMap),
|
||||||
|
ExtraHosts: extraHosts,
|
||||||
|
NetworkMode: getNetworkMode(runArgsMap),
|
||||||
|
RestartPolicy: restartPolicy,
|
||||||
|
AutoRemove: getAutoRemove(runArgsMap),
|
||||||
|
CapDrop: getCapDrop(runArgsMap),
|
||||||
|
CgroupnsMode: getCgroupNSMode(runArgsMap),
|
||||||
|
DNS: getDNS(runArgsMap),
|
||||||
|
DNSOptions: getDNSOptions(runArgsMap),
|
||||||
|
DNSSearch: getDNSSearch(runArgsMap),
|
||||||
|
IpcMode: getIPCMode(runArgsMap),
|
||||||
|
Isolation: getIsolation(runArgsMap),
|
||||||
|
Init: getInit(runArgsMap),
|
||||||
|
Links: getLinks(runArgsMap),
|
||||||
|
OomScoreAdj: oomScoreAdj,
|
||||||
|
PidMode: getPIDMode(runArgsMap),
|
||||||
|
Runtime: getRuntime(runArgsMap),
|
||||||
|
SecurityOpt: getSecurityOpt(runArgsMap),
|
||||||
|
StorageOpt: getStorageOpt(runArgsMap),
|
||||||
|
ShmSize: shmSize,
|
||||||
|
Sysctls: getSysctls(runArgsMap),
|
||||||
}
|
}
|
||||||
|
|
||||||
if goruntime.GOOS == "linux" {
|
return hostConfig, nil
|
||||||
hostConfig.ExtraHosts = []string{"host.docker.internal:host-gateway"}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hostConfig
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetContainerInfo(
|
func GetContainerInfo(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
containerName string,
|
containerName string,
|
||||||
|
@ -227,10 +302,46 @@ func PullImage(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
imageName string,
|
imageName string,
|
||||||
dockerClient *client.Client,
|
dockerClient *client.Client,
|
||||||
|
runArgsMap map[types.RunArg]*types.RunArgValue,
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
) error {
|
) error {
|
||||||
|
imagePullRunArg := getImagePullPolicy(runArgsMap)
|
||||||
|
gitspaceLogger.Info("Image pull policy is: " + imagePullRunArg)
|
||||||
|
if imagePullRunArg == "never" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if imagePullRunArg == "missing" {
|
||||||
|
gitspaceLogger.Info("Checking if image " + imageName + " is present locally")
|
||||||
|
|
||||||
|
filterArgs := filters.NewArgs()
|
||||||
|
filterArgs.Add("reference", imageName)
|
||||||
|
|
||||||
|
images, err := dockerClient.ImageList(ctx, image.ListOptions{Filters: filterArgs})
|
||||||
|
if err != nil {
|
||||||
|
gitspaceLogger.Error("Error listing images locally", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(images) > 0 {
|
||||||
|
gitspaceLogger.Info("Image " + imageName + " is present locally")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
gitspaceLogger.Info("Image " + imageName + " is not present locally")
|
||||||
|
}
|
||||||
|
|
||||||
gitspaceLogger.Info("Pulling image: " + imageName)
|
gitspaceLogger.Info("Pulling image: " + imageName)
|
||||||
pullResponse, err := dockerClient.ImagePull(ctx, imageName, image.PullOptions{})
|
|
||||||
|
pullResponse, err := dockerClient.ImagePull(ctx, imageName, image.PullOptions{Platform: getPlatform(runArgsMap)})
|
||||||
|
defer func() {
|
||||||
|
if pullResponse == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
closingErr := pullResponse.Close()
|
||||||
|
if closingErr != nil {
|
||||||
|
log.Warn().Err(closingErr).Msg("failed to close image pull response")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logStreamWrapError(gitspaceLogger, "Error while pulling image", err)
|
return logStreamWrapError(gitspaceLogger, "Error while pulling image", err)
|
||||||
}
|
}
|
||||||
|
@ -271,6 +382,28 @@ func PullImage(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExtractRunArgsWithLogging(
|
||||||
|
ctx context.Context,
|
||||||
|
spaceID int64,
|
||||||
|
runArgProvider runarg.Provider,
|
||||||
|
runArgsRaw []string,
|
||||||
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
|
) (map[types.RunArg]*types.RunArgValue, error) {
|
||||||
|
gitspaceLogger.Info("Extracting runsArgs")
|
||||||
|
runArgsMap, err := ExtractRunArgs(ctx, spaceID, runArgProvider, runArgsRaw)
|
||||||
|
if err != nil {
|
||||||
|
return nil, logStreamWrapError(gitspaceLogger, "Error while extracting runArgs", err)
|
||||||
|
}
|
||||||
|
if len(runArgsMap) > 0 {
|
||||||
|
st := ""
|
||||||
|
for key, value := range runArgsMap {
|
||||||
|
st = fmt.Sprintf("%s%s: %s\n", st, key, value)
|
||||||
|
}
|
||||||
|
gitspaceLogger.Info(fmt.Sprintf("Extracted following runArgs\n%v", st))
|
||||||
|
}
|
||||||
|
return runArgsMap, nil
|
||||||
|
}
|
||||||
|
|
||||||
// getContainerResponse retrieves container information and prepares the start response.
|
// getContainerResponse retrieves container information and prepares the start response.
|
||||||
func GetContainerResponse(
|
func GetContainerResponse(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
|
@ -17,7 +17,6 @@ package container
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/common"
|
"github.com/harness/gitness/app/gitspace/orchestrator/common"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
||||||
|
@ -26,178 +25,9 @@ import (
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/user"
|
"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/types"
|
|
||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
)
|
)
|
||||||
|
|
||||||
// buildSetupSteps constructs the steps to be executed in the setup process.
|
|
||||||
func (e *EmbeddedDockerOrchestrator) buildSetupSteps(
|
|
||||||
_ context.Context,
|
|
||||||
ideService ide.IDE,
|
|
||||||
gitspaceConfig types.GitspaceConfig,
|
|
||||||
resolvedRepoDetails scm.ResolvedDetails,
|
|
||||||
defaultBaseImage string,
|
|
||||||
environment []string,
|
|
||||||
devcontainerConfig types.DevcontainerConfig,
|
|
||||||
codeRepoDir string,
|
|
||||||
) []gitspaceTypes.Step {
|
|
||||||
return []gitspaceTypes.Step{
|
|
||||||
{
|
|
||||||
Name: "Validate Supported OS",
|
|
||||||
Execute: ValidateSupportedOS,
|
|
||||||
StopOnFailure: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Manage User",
|
|
||||||
Execute: func(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
return ManageUser(ctx, exec, e.userService, gitspaceLogger)
|
|
||||||
},
|
|
||||||
StopOnFailure: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Set environment",
|
|
||||||
Execute: func(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
return SetEnv(ctx, exec, gitspaceLogger, environment)
|
|
||||||
},
|
|
||||||
StopOnFailure: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Install Tools",
|
|
||||||
Execute: func(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
return InstallTools(ctx, exec, gitspaceLogger, gitspaceConfig.IDE)
|
|
||||||
},
|
|
||||||
StopOnFailure: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Setup IDE",
|
|
||||||
Execute: func(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
return SetupIDE(ctx, exec, ideService, gitspaceLogger)
|
|
||||||
},
|
|
||||||
StopOnFailure: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Run IDE",
|
|
||||||
Execute: func(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
return RunIDE(ctx, exec, ideService, gitspaceLogger)
|
|
||||||
},
|
|
||||||
StopOnFailure: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Install Git",
|
|
||||||
Execute: func(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
return InstallGit(ctx, exec, e.gitService, gitspaceLogger)
|
|
||||||
},
|
|
||||||
StopOnFailure: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Setup Git Credentials",
|
|
||||||
Execute: func(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
if resolvedRepoDetails.ResolvedCredentials.Credentials != nil {
|
|
||||||
return SetupGitCredentials(ctx, exec, resolvedRepoDetails, e.gitService, gitspaceLogger)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
StopOnFailure: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Clone Code",
|
|
||||||
Execute: func(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
return CloneCode(ctx, exec, defaultBaseImage, resolvedRepoDetails, e.gitService, gitspaceLogger)
|
|
||||||
},
|
|
||||||
StopOnFailure: true,
|
|
||||||
},
|
|
||||||
// Post-create and Post-start steps
|
|
||||||
{
|
|
||||||
Name: "Execute PostCreate Command",
|
|
||||||
Execute: func(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
command := ExtractLifecycleCommands(PostCreateAction, devcontainerConfig)
|
|
||||||
return ExecuteCommands(ctx, exec, codeRepoDir, gitspaceLogger, command, PostCreateAction)
|
|
||||||
},
|
|
||||||
StopOnFailure: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Execute PostStart Command",
|
|
||||||
Execute: func(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
|
||||||
) error {
|
|
||||||
command := ExtractLifecycleCommands(PostStartAction, devcontainerConfig)
|
|
||||||
return ExecuteCommands(ctx, exec, codeRepoDir, gitspaceLogger, command, PostStartAction)
|
|
||||||
},
|
|
||||||
StopOnFailure: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupGitspaceAndIDE initializes Gitspace and IDE by registering and executing the setup steps.
|
|
||||||
func (e *EmbeddedDockerOrchestrator) setupGitspaceAndIDE(
|
|
||||||
ctx context.Context,
|
|
||||||
exec *devcontainer.Exec,
|
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
|
||||||
ideService ide.IDE,
|
|
||||||
gitspaceConfig types.GitspaceConfig,
|
|
||||||
resolvedRepoDetails scm.ResolvedDetails,
|
|
||||||
defaultBaseImage string,
|
|
||||||
environment []string,
|
|
||||||
) error {
|
|
||||||
homeDir := GetUserHomeDir(gitspaceConfig.GitspaceUser.Identifier)
|
|
||||||
devcontainerConfig := resolvedRepoDetails.DevcontainerConfig
|
|
||||||
codeRepoDir := filepath.Join(homeDir, resolvedRepoDetails.RepoName)
|
|
||||||
|
|
||||||
steps := e.buildSetupSteps(
|
|
||||||
ctx,
|
|
||||||
ideService,
|
|
||||||
gitspaceConfig,
|
|
||||||
resolvedRepoDetails,
|
|
||||||
defaultBaseImage,
|
|
||||||
environment,
|
|
||||||
devcontainerConfig,
|
|
||||||
codeRepoDir)
|
|
||||||
|
|
||||||
// Execute the registered steps
|
|
||||||
if err := e.ExecuteSteps(ctx, exec, gitspaceLogger, steps); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func InstallTools(
|
func InstallTools(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
exec *devcontainer.Exec,
|
exec *devcontainer.Exec,
|
|
@ -13,43 +13,3 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/harness/gitness/types"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExtractEnv(devcontainerConfig types.DevcontainerConfig) []string {
|
|
||||||
var env []string
|
|
||||||
for key, value := range devcontainerConfig.ContainerEnv {
|
|
||||||
env = append(env, fmt.Sprintf("%s=%s", key, value))
|
|
||||||
}
|
|
||||||
return env
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExtractForwardPorts(devcontainerConfig types.DevcontainerConfig) []int {
|
|
||||||
var ports []int
|
|
||||||
for _, strPort := range devcontainerConfig.ForwardPorts {
|
|
||||||
portAsInt, err := strPort.Int64() // Using Atoi to convert string to int
|
|
||||||
if err != nil {
|
|
||||||
log.Warn().Msgf("Error converting port string '%s' to int: %v", strPort, err)
|
|
||||||
continue // Skip the invalid port
|
|
||||||
}
|
|
||||||
ports = append(ports, int(portAsInt))
|
|
||||||
}
|
|
||||||
return ports
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExtractLifecycleCommands(actionType PostAction, devcontainerConfig types.DevcontainerConfig) []string {
|
|
||||||
switch actionType {
|
|
||||||
case PostCreateAction:
|
|
||||||
return devcontainerConfig.PostCreateCommand.ToCommandArray()
|
|
||||||
case PostStartAction:
|
|
||||||
return devcontainerConfig.PostStartCommand.ToCommandArray()
|
|
||||||
default:
|
|
||||||
return []string{} // Return empty string if actionType is not recognized
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"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/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/user"
|
"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"
|
||||||
|
@ -45,6 +46,7 @@ type EmbeddedDockerOrchestrator struct {
|
||||||
statefulLogger *logutil.StatefulLogger
|
statefulLogger *logutil.StatefulLogger
|
||||||
gitService git.Service
|
gitService git.Service
|
||||||
userService user.Service
|
userService user.Service
|
||||||
|
runArgProvider runarg.Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecuteSteps executes all registered steps in sequence, respecting stopOnFailure flag.
|
// ExecuteSteps executes all registered steps in sequence, respecting stopOnFailure flag.
|
||||||
|
@ -73,12 +75,14 @@ func NewEmbeddedDockerOrchestrator(
|
||||||
statefulLogger *logutil.StatefulLogger,
|
statefulLogger *logutil.StatefulLogger,
|
||||||
gitService git.Service,
|
gitService git.Service,
|
||||||
userService user.Service,
|
userService user.Service,
|
||||||
|
runArgProvider runarg.Provider,
|
||||||
) Orchestrator {
|
) Orchestrator {
|
||||||
return &EmbeddedDockerOrchestrator{
|
return &EmbeddedDockerOrchestrator{
|
||||||
dockerClientFactory: dockerClientFactory,
|
dockerClientFactory: dockerClientFactory,
|
||||||
statefulLogger: statefulLogger,
|
statefulLogger: statefulLogger,
|
||||||
gitService: gitService,
|
gitService: gitService,
|
||||||
userService: userService,
|
userService: userService,
|
||||||
|
runArgProvider: runArgProvider,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,8 +379,14 @@ func (e *EmbeddedDockerOrchestrator) runGitspaceSetupSteps(
|
||||||
imageName = defaultBaseImage
|
imageName = defaultBaseImage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runArgsMap, err := ExtractRunArgsWithLogging(ctx, gitspaceConfig.SpaceID, e.runArgProvider,
|
||||||
|
devcontainerConfig.RunArgs, gitspaceLogger)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Pull the required image
|
// Pull the required image
|
||||||
if err := PullImage(ctx, imageName, dockerClient, gitspaceLogger); err != nil {
|
if err := PullImage(ctx, imageName, dockerClient, runArgsMap, gitspaceLogger); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
portMappings := infrastructure.GitspacePortMappings
|
portMappings := infrastructure.GitspacePortMappings
|
||||||
|
@ -392,12 +402,12 @@ func (e *EmbeddedDockerOrchestrator) runGitspaceSetupSteps(
|
||||||
}
|
}
|
||||||
|
|
||||||
storage := infrastructure.Storage
|
storage := infrastructure.Storage
|
||||||
environment := ExtractEnv(devcontainerConfig)
|
environment := ExtractEnv(devcontainerConfig, runArgsMap)
|
||||||
if len(environment) > 0 {
|
if len(environment) > 0 {
|
||||||
gitspaceLogger.Info(fmt.Sprintf("Setting Environment : %v", environment))
|
gitspaceLogger.Info(fmt.Sprintf("Setting Environment : %v", environment))
|
||||||
}
|
}
|
||||||
// Create the container
|
// Create the container
|
||||||
err := CreateContainer(
|
err = CreateContainer(
|
||||||
ctx,
|
ctx,
|
||||||
dockerClient,
|
dockerClient,
|
||||||
imageName,
|
imageName,
|
||||||
|
@ -408,6 +418,7 @@ func (e *EmbeddedDockerOrchestrator) runGitspaceSetupSteps(
|
||||||
mount.TypeVolume,
|
mount.TypeVolume,
|
||||||
portMappings,
|
portMappings,
|
||||||
environment,
|
environment,
|
||||||
|
runArgsMap,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -444,6 +455,174 @@ func (e *EmbeddedDockerOrchestrator) runGitspaceSetupSteps(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// buildSetupSteps constructs the steps to be executed in the setup process.
|
||||||
|
func (e *EmbeddedDockerOrchestrator) buildSetupSteps(
|
||||||
|
_ context.Context,
|
||||||
|
ideService ide.IDE,
|
||||||
|
gitspaceConfig types.GitspaceConfig,
|
||||||
|
resolvedRepoDetails scm.ResolvedDetails,
|
||||||
|
defaultBaseImage string,
|
||||||
|
environment []string,
|
||||||
|
devcontainerConfig types.DevcontainerConfig,
|
||||||
|
codeRepoDir string,
|
||||||
|
) []gitspaceTypes.Step {
|
||||||
|
return []gitspaceTypes.Step{
|
||||||
|
{
|
||||||
|
Name: "Validate Supported OS",
|
||||||
|
Execute: ValidateSupportedOS,
|
||||||
|
StopOnFailure: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Manage User",
|
||||||
|
Execute: func(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
|
) error {
|
||||||
|
return ManageUser(ctx, exec, e.userService, gitspaceLogger)
|
||||||
|
},
|
||||||
|
StopOnFailure: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Set environment",
|
||||||
|
Execute: func(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
|
) error {
|
||||||
|
return SetEnv(ctx, exec, gitspaceLogger, environment)
|
||||||
|
},
|
||||||
|
StopOnFailure: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Install Tools",
|
||||||
|
Execute: func(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
|
) error {
|
||||||
|
return InstallTools(ctx, exec, gitspaceLogger, gitspaceConfig.IDE)
|
||||||
|
},
|
||||||
|
StopOnFailure: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Setup IDE",
|
||||||
|
Execute: func(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
|
) error {
|
||||||
|
return SetupIDE(ctx, exec, ideService, gitspaceLogger)
|
||||||
|
},
|
||||||
|
StopOnFailure: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Run IDE",
|
||||||
|
Execute: func(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
|
) error {
|
||||||
|
return RunIDE(ctx, exec, ideService, gitspaceLogger)
|
||||||
|
},
|
||||||
|
StopOnFailure: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Install Git",
|
||||||
|
Execute: func(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
|
) error {
|
||||||
|
return InstallGit(ctx, exec, e.gitService, gitspaceLogger)
|
||||||
|
},
|
||||||
|
StopOnFailure: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Setup Git Credentials",
|
||||||
|
Execute: func(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
|
) error {
|
||||||
|
if resolvedRepoDetails.ResolvedCredentials.Credentials != nil {
|
||||||
|
return SetupGitCredentials(ctx, exec, resolvedRepoDetails, e.gitService, gitspaceLogger)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
StopOnFailure: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Clone Code",
|
||||||
|
Execute: func(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
|
) error {
|
||||||
|
return CloneCode(ctx, exec, defaultBaseImage, resolvedRepoDetails, e.gitService, gitspaceLogger)
|
||||||
|
},
|
||||||
|
StopOnFailure: true,
|
||||||
|
},
|
||||||
|
// Post-create and Post-start steps
|
||||||
|
{
|
||||||
|
Name: "Execute PostCreate Command",
|
||||||
|
Execute: func(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
|
) error {
|
||||||
|
command := ExtractLifecycleCommands(PostCreateAction, devcontainerConfig)
|
||||||
|
return ExecuteCommands(ctx, exec, codeRepoDir, gitspaceLogger, command, PostCreateAction)
|
||||||
|
},
|
||||||
|
StopOnFailure: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Execute PostStart Command",
|
||||||
|
Execute: func(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
|
) error {
|
||||||
|
command := ExtractLifecycleCommands(PostStartAction, devcontainerConfig)
|
||||||
|
return ExecuteCommands(ctx, exec, codeRepoDir, gitspaceLogger, command, PostStartAction)
|
||||||
|
},
|
||||||
|
StopOnFailure: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// setupGitspaceAndIDE initializes Gitspace and IDE by registering and executing the setup steps.
|
||||||
|
func (e *EmbeddedDockerOrchestrator) setupGitspaceAndIDE(
|
||||||
|
ctx context.Context,
|
||||||
|
exec *devcontainer.Exec,
|
||||||
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
|
ideService ide.IDE,
|
||||||
|
gitspaceConfig types.GitspaceConfig,
|
||||||
|
resolvedRepoDetails scm.ResolvedDetails,
|
||||||
|
defaultBaseImage string,
|
||||||
|
environment []string,
|
||||||
|
) error {
|
||||||
|
homeDir := GetUserHomeDir(gitspaceConfig.GitspaceUser.Identifier)
|
||||||
|
devcontainerConfig := resolvedRepoDetails.DevcontainerConfig
|
||||||
|
codeRepoDir := filepath.Join(homeDir, resolvedRepoDetails.RepoName)
|
||||||
|
|
||||||
|
steps := e.buildSetupSteps(
|
||||||
|
ctx,
|
||||||
|
ideService,
|
||||||
|
gitspaceConfig,
|
||||||
|
resolvedRepoDetails,
|
||||||
|
defaultBaseImage,
|
||||||
|
environment,
|
||||||
|
devcontainerConfig,
|
||||||
|
codeRepoDir)
|
||||||
|
|
||||||
|
// Execute the registered steps
|
||||||
|
if err := e.ExecuteSteps(ctx, exec, gitspaceLogger, steps); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// getDockerClient creates and returns a new Docker client using the factory.
|
// getDockerClient creates and returns a new Docker client using the factory.
|
||||||
func (e *EmbeddedDockerOrchestrator) getDockerClient(
|
func (e *EmbeddedDockerOrchestrator) getDockerClient(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
|
@ -0,0 +1,541 @@
|
||||||
|
// 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 container
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/types"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api/types/container"
|
||||||
|
"github.com/docker/docker/api/types/strslice"
|
||||||
|
"github.com/docker/go-units"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getHostResources(runArgsMap map[types.RunArg]*types.RunArgValue) (container.Resources, error) { // nolint: gocognit
|
||||||
|
var resources = container.Resources{}
|
||||||
|
blkioWeight, err := getArgValueUint16(runArgsMap, types.RunArgBlkioWeight)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.BlkioWeight = blkioWeight
|
||||||
|
|
||||||
|
cpuShares, err := getArgValueInt64(runArgsMap, types.RunArgCPUShares)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.CPUShares = cpuShares
|
||||||
|
|
||||||
|
memory, err := getArgValueMemoryBytes(runArgsMap, types.RunArgMemory)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.Memory = memory
|
||||||
|
|
||||||
|
cpus, err := getCPUs(runArgsMap, types.RunArgCpus)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.NanoCPUs = cpus
|
||||||
|
|
||||||
|
resources.CgroupParent = getArgValueString(runArgsMap, types.RunArgCgroupParent)
|
||||||
|
|
||||||
|
cpuPeriod, err := getArgValueInt64(runArgsMap, types.RunArgCPUPeriod)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.CPUPeriod = cpuPeriod
|
||||||
|
|
||||||
|
cpuQuota, err := getArgValueInt64(runArgsMap, types.RunArgCPUQuota)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.CPUQuota = cpuQuota
|
||||||
|
|
||||||
|
cpuRTPeriod, err := getArgValueInt64(runArgsMap, types.RunArgCPURtPeriod)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.CPURealtimePeriod = cpuRTPeriod
|
||||||
|
|
||||||
|
cpuRTRuntime, err := getArgValueInt64(runArgsMap, types.RunArgCPURtRuntime)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.CPURealtimeRuntime = cpuRTRuntime
|
||||||
|
|
||||||
|
resources.CpusetCpus = getArgValueString(runArgsMap, types.RunArgCpusetCpus)
|
||||||
|
|
||||||
|
resources.CpusetMems = getArgValueString(runArgsMap, types.RunArgCpusetMems)
|
||||||
|
|
||||||
|
cpuCount, err := getArgValueInt64(runArgsMap, types.RunArgCPUCount)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.CPUCount = cpuCount
|
||||||
|
|
||||||
|
cpuPercent, err := getArgValueInt64(runArgsMap, types.RunArgCPUPercent)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.CPUPercent = cpuPercent
|
||||||
|
|
||||||
|
kernelMemory, err := getArgValueMemoryBytes(runArgsMap, types.RunArgKernelMemory)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.KernelMemory = kernelMemory
|
||||||
|
|
||||||
|
memoryReservation, err := getArgValueMemoryBytes(runArgsMap, types.RunArgMemoryReservation)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.MemoryReservation = memoryReservation
|
||||||
|
|
||||||
|
memorySwappiness, err := getArgValueInt64Ptr(runArgsMap, types.RunArgMemorySwappiness)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.MemorySwappiness = memorySwappiness
|
||||||
|
|
||||||
|
memorySwap, err := getArgValueMemorySwapBytes(runArgsMap, types.RunArgMemorySwap)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.MemorySwap = memorySwap
|
||||||
|
|
||||||
|
resources.OomKillDisable = getArgValueBoolPtr(runArgsMap, types.RunArgOomKillDisable)
|
||||||
|
|
||||||
|
pidsLimit, err := getArgValueInt64Ptr(runArgsMap, types.RunArgPidsLimit)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.PidsLimit = pidsLimit
|
||||||
|
|
||||||
|
ioMaxiops, err := getArgValueUint64(runArgsMap, types.RunArgIoMaxiops)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.IOMaximumIOps = ioMaxiops
|
||||||
|
|
||||||
|
ioMaxbandwidth, err := getArgValueMemoryBytes(runArgsMap, types.RunArgIoMaxbandwidth)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
resources.IOMaximumBandwidth = uint64(ioMaxbandwidth)
|
||||||
|
|
||||||
|
if arg, ok := runArgsMap[types.RunArgUlimit]; ok {
|
||||||
|
ulimits := []*container.Ulimit{}
|
||||||
|
for _, v := range arg.Values {
|
||||||
|
ulimit, err := units.ParseUlimit(v)
|
||||||
|
if err != nil {
|
||||||
|
return resources, err
|
||||||
|
}
|
||||||
|
ulimits = append(ulimits, ulimit)
|
||||||
|
}
|
||||||
|
resources.Ulimits = ulimits
|
||||||
|
}
|
||||||
|
return resources, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNetworkMode(runArgsMap map[types.RunArg]*types.RunArgValue) container.NetworkMode {
|
||||||
|
return container.NetworkMode(getArgValueString(runArgsMap, types.RunArgNetwork))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCapDrop(runArgsMap map[types.RunArg]*types.RunArgValue) strslice.StrSlice {
|
||||||
|
return getArgValueStringSlice(runArgsMap, types.RunArgCapDrop)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSHMSize(runArgsMap map[types.RunArg]*types.RunArgValue) (int64, error) {
|
||||||
|
return getArgValueMemoryBytes(runArgsMap, types.RunArgShmSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArgValueMemorySwapBytes(runArgsMap map[types.RunArg]*types.RunArgValue, argName types.RunArg) (int64, error) {
|
||||||
|
value := getArgValueString(runArgsMap, argName)
|
||||||
|
if value == "" {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
if value == "-1" {
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
memorySwapBytes, err := units.RAMInBytes(value)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return memorySwapBytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSysctls(runArgsMap map[types.RunArg]*types.RunArgValue) map[string]string {
|
||||||
|
values := getArgValueStringSlice(runArgsMap, types.RunArgSysctl)
|
||||||
|
var opt = map[string]string{}
|
||||||
|
for _, value := range values {
|
||||||
|
parts := strings.SplitN(value, "=", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
parts = append(parts, "")
|
||||||
|
}
|
||||||
|
opt[parts[0]] = parts[1]
|
||||||
|
}
|
||||||
|
return opt
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDNS(runArgsMap map[types.RunArg]*types.RunArgValue) []string {
|
||||||
|
return getArgValueStringSlice(runArgsMap, types.RunArgDNS)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDNSOptions(runArgsMap map[types.RunArg]*types.RunArgValue) []string {
|
||||||
|
return getArgValueStringSlice(runArgsMap, types.RunArgDNSOption)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDNSSearch(runArgsMap map[types.RunArg]*types.RunArgValue) []string {
|
||||||
|
return getArgValueStringSlice(runArgsMap, types.RunArgDNSSearch)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCgroupNSMode(runArgsMap map[types.RunArg]*types.RunArgValue) container.CgroupnsMode {
|
||||||
|
value := getArgValueString(runArgsMap, types.RunArgCgroupns)
|
||||||
|
return container.CgroupnsMode(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIPCMode(runArgsMap map[types.RunArg]*types.RunArgValue) container.IpcMode {
|
||||||
|
return container.IpcMode(getArgValueString(runArgsMap, types.RunArgIpc))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIsolation(runArgsMap map[types.RunArg]*types.RunArgValue) container.Isolation {
|
||||||
|
return container.Isolation(getArgValueString(runArgsMap, types.RunArgIsolation))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRuntime(runArgsMap map[types.RunArg]*types.RunArgValue) string {
|
||||||
|
return getArgValueString(runArgsMap, types.RunArgRuntime)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPlatform(runArgsMap map[types.RunArg]*types.RunArgValue) string {
|
||||||
|
return getArgValueString(runArgsMap, types.RunArgPlatform)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPIDMode(runArgsMap map[types.RunArg]*types.RunArgValue) container.PidMode {
|
||||||
|
return container.PidMode(getArgValueString(runArgsMap, types.RunArgPid))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSecurityOpt(runArgsMap map[types.RunArg]*types.RunArgValue) []string {
|
||||||
|
return getArgValueStringSlice(runArgsMap, types.RunArgSecurityOpt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStorageOpt(runArgsMap map[types.RunArg]*types.RunArgValue) map[string]string {
|
||||||
|
values := getArgValueStringSlice(runArgsMap, types.RunArgStorageOpt)
|
||||||
|
var opt = map[string]string{}
|
||||||
|
for _, value := range values {
|
||||||
|
parts := strings.SplitN(value, "=", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
parts = append(parts, "")
|
||||||
|
}
|
||||||
|
opt[parts[0]] = parts[1]
|
||||||
|
}
|
||||||
|
return opt
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAutoRemove(runArgsMap map[types.RunArg]*types.RunArgValue) bool {
|
||||||
|
return getArgValueBool(runArgsMap, types.RunArgRm)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getInit(runArgsMap map[types.RunArg]*types.RunArgValue) *bool {
|
||||||
|
return getArgValueBoolPtr(runArgsMap, types.RunArgInit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEnv(runArgsMap map[types.RunArg]*types.RunArgValue) []string {
|
||||||
|
return getArgValueStringSlice(runArgsMap, types.RunArgEnv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLinks(runArgsMap map[types.RunArg]*types.RunArgValue) []string {
|
||||||
|
return getArgValueStringSlice(runArgsMap, types.RunArgLink)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getOomScoreAdj(runArgsMap map[types.RunArg]*types.RunArgValue) (int, error) {
|
||||||
|
return getArgValueInt(runArgsMap, types.RunArgOomScoreAdj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRestartPolicy(runArgsMap map[types.RunArg]*types.RunArgValue) (container.RestartPolicy, error) {
|
||||||
|
value := getArgValueString(runArgsMap, types.RunArgRestart)
|
||||||
|
if len(value) == 0 {
|
||||||
|
return container.RestartPolicy{}, nil
|
||||||
|
}
|
||||||
|
parts := strings.SplitN(value, ":", 2)
|
||||||
|
maxCount := 0
|
||||||
|
if container.RestartPolicyMode(parts[0]) == container.RestartPolicyOnFailure && len(parts) == 2 {
|
||||||
|
count, err := strconv.Atoi(parts[1])
|
||||||
|
if err != nil {
|
||||||
|
return container.RestartPolicy{}, err
|
||||||
|
}
|
||||||
|
maxCount = count
|
||||||
|
}
|
||||||
|
return container.RestartPolicy{
|
||||||
|
Name: container.RestartPolicyMode(parts[0]),
|
||||||
|
MaximumRetryCount: maxCount,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getExtraHosts(runArgsMap map[types.RunArg]*types.RunArgValue) []string {
|
||||||
|
return getArgValueStringSlice(runArgsMap, types.RunArgAddHost)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getHostname(runArgsMap map[types.RunArg]*types.RunArgValue) string {
|
||||||
|
return getArgValueString(runArgsMap, types.RunArgHostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDomainname(runArgsMap map[types.RunArg]*types.RunArgValue) string {
|
||||||
|
return getArgValueString(runArgsMap, types.RunArgDomainname)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMACAddress(runArgsMap map[types.RunArg]*types.RunArgValue) string {
|
||||||
|
return getArgValueString(runArgsMap, types.RunArgMacAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStopSignal(runArgsMap map[types.RunArg]*types.RunArgValue) string {
|
||||||
|
return getArgValueString(runArgsMap, types.RunArgStopSignal)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStopTimeout(runArgsMap map[types.RunArg]*types.RunArgValue) (*int, error) {
|
||||||
|
return getArgValueIntPtr(runArgsMap, types.RunArgStopTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getImagePullPolicy(runArgsMap map[types.RunArg]*types.RunArgValue) string {
|
||||||
|
policy := getArgValueString(runArgsMap, types.RunArgPull)
|
||||||
|
if policy == "" {
|
||||||
|
policy = "missing"
|
||||||
|
}
|
||||||
|
return policy
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUser(runArgsMap map[types.RunArg]*types.RunArgValue) string {
|
||||||
|
return getArgValueString(runArgsMap, types.RunArgUser)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEntrypoint(runArgsMap map[types.RunArg]*types.RunArgValue) []string {
|
||||||
|
return getArgValueStringSlice(runArgsMap, types.RunArgEntrypoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getHealthCheckConfig(runArgsMap map[types.RunArg]*types.RunArgValue) (*container.HealthConfig, error) {
|
||||||
|
var healthConfig = &container.HealthConfig{}
|
||||||
|
|
||||||
|
retries, err := getArgValueInt(runArgsMap, types.RunArgHealthRetries)
|
||||||
|
if err != nil {
|
||||||
|
return healthConfig, err
|
||||||
|
}
|
||||||
|
healthConfig.Retries = retries
|
||||||
|
|
||||||
|
interval, err := getArgValueDuration(runArgsMap, types.RunArgHealthInterval)
|
||||||
|
if err != nil {
|
||||||
|
return healthConfig, err
|
||||||
|
}
|
||||||
|
healthConfig.Interval = interval
|
||||||
|
|
||||||
|
timeout, err := getArgValueDuration(runArgsMap, types.RunArgHealthTimeout)
|
||||||
|
if err != nil {
|
||||||
|
return healthConfig, err
|
||||||
|
}
|
||||||
|
healthConfig.Timeout = timeout
|
||||||
|
|
||||||
|
startPeriod, err := getArgValueDuration(runArgsMap, types.RunArgHealthStartPeriod)
|
||||||
|
if err != nil {
|
||||||
|
return healthConfig, err
|
||||||
|
}
|
||||||
|
healthConfig.StartPeriod = startPeriod
|
||||||
|
|
||||||
|
startInterval, err := getArgValueDuration(runArgsMap, types.RunArgHealthStartInterval)
|
||||||
|
if err != nil {
|
||||||
|
return healthConfig, err
|
||||||
|
}
|
||||||
|
healthConfig.StartInterval = startInterval
|
||||||
|
|
||||||
|
if _, ok := runArgsMap[types.RunArgNoHealthcheck]; ok {
|
||||||
|
healthConfig.Test = []string{"NONE"}
|
||||||
|
} else if arg, healthCmdOK := runArgsMap[types.RunArgHealthCmd]; healthCmdOK {
|
||||||
|
healthConfig.Test = arg.Values
|
||||||
|
}
|
||||||
|
|
||||||
|
return healthConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLabels(runArgsMap map[types.RunArg]*types.RunArgValue) map[string]string {
|
||||||
|
arg, ok := runArgsMap[types.RunArgLabel]
|
||||||
|
labelsMap := make(map[string]string)
|
||||||
|
if ok {
|
||||||
|
labels := arg.Values
|
||||||
|
for _, v := range labels {
|
||||||
|
parts := strings.SplitN(v, "=", 2)
|
||||||
|
if len(parts) < 2 {
|
||||||
|
labelsMap[parts[0]] = ""
|
||||||
|
} else {
|
||||||
|
labelsMap[parts[0]] = parts[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return labelsMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAnnotations(runArgsMap map[types.RunArg]*types.RunArgValue) map[string]string {
|
||||||
|
arg, ok := runArgsMap[types.RunArgAnnotation]
|
||||||
|
annotationsMap := make(map[string]string)
|
||||||
|
if ok {
|
||||||
|
annotations := arg.Values
|
||||||
|
for _, v := range annotations {
|
||||||
|
annotationParts := strings.SplitN(v, "=", 2)
|
||||||
|
if len(annotationParts) != 2 {
|
||||||
|
log.Warn().Msgf("invalid annotation: %s", v)
|
||||||
|
} else {
|
||||||
|
annotationsMap[annotationParts[0]] = annotationParts[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return annotationsMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArgValueMemoryBytes(runArgsMap map[types.RunArg]*types.RunArgValue, argName types.RunArg) (int64, error) {
|
||||||
|
value := getArgValueString(runArgsMap, argName)
|
||||||
|
if value == "" {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
memoryBytes, err := units.RAMInBytes(value)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return memoryBytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArgValueString(runArgsMap map[types.RunArg]*types.RunArgValue, argName types.RunArg) string {
|
||||||
|
if arg, ok := runArgsMap[argName]; ok {
|
||||||
|
return arg.Values[0]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArgValueStringSlice(runArgsMap map[types.RunArg]*types.RunArgValue, argName types.RunArg) []string {
|
||||||
|
if arg, ok := runArgsMap[argName]; ok {
|
||||||
|
return arg.Values
|
||||||
|
}
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArgValueInt(runArgsMap map[types.RunArg]*types.RunArgValue, argName types.RunArg) (int, error) {
|
||||||
|
value, err := getArgValueIntPtr(runArgsMap, argName)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if value == nil {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
return *value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArgValueIntPtr(runArgsMap map[types.RunArg]*types.RunArgValue, argName types.RunArg) (*int, error) {
|
||||||
|
if arg, ok := runArgsMap[argName]; ok {
|
||||||
|
value, err := strconv.Atoi(arg.Values[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &value, nil
|
||||||
|
}
|
||||||
|
return nil, nil // nolint: nilnil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArgValueUint16(runArgsMap map[types.RunArg]*types.RunArgValue, argName types.RunArg) (uint16, error) {
|
||||||
|
if arg, ok := runArgsMap[argName]; ok {
|
||||||
|
value, err := strconv.ParseUint(arg.Values[0], 10, 16)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return uint16(value), nil
|
||||||
|
}
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArgValueUint64(runArgsMap map[types.RunArg]*types.RunArgValue, argName types.RunArg) (uint64, error) {
|
||||||
|
if arg, ok := runArgsMap[argName]; ok {
|
||||||
|
value, err := strconv.ParseUint(arg.Values[0], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCPUs(runArgsMap map[types.RunArg]*types.RunArgValue, argName types.RunArg) (int64, error) {
|
||||||
|
if arg, ok := runArgsMap[argName]; ok {
|
||||||
|
value := arg.Values[0]
|
||||||
|
cpu, ok1 := new(big.Rat).SetString(value) // nolint: gosec
|
||||||
|
if !ok1 {
|
||||||
|
return 0, fmt.Errorf("failed to parse %v as a rational number", value)
|
||||||
|
}
|
||||||
|
nano := cpu.Mul(cpu, big.NewRat(1e9, 1))
|
||||||
|
if !nano.IsInt() {
|
||||||
|
return 0, fmt.Errorf("value is too precise")
|
||||||
|
}
|
||||||
|
return nano.Num().Int64(), nil
|
||||||
|
}
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArgValueInt64(runArgsMap map[types.RunArg]*types.RunArgValue, argName types.RunArg) (int64, error) {
|
||||||
|
value, err := getArgValueInt64Ptr(runArgsMap, argName)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if value == nil {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
return *value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArgValueInt64Ptr(runArgsMap map[types.RunArg]*types.RunArgValue, argName types.RunArg) (*int64, error) {
|
||||||
|
if arg, ok := runArgsMap[argName]; ok {
|
||||||
|
value, err := strconv.ParseInt(arg.Values[0], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &value, nil
|
||||||
|
}
|
||||||
|
return nil, nil // nolint: nilnil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArgValueDuration(runArgsMap map[types.RunArg]*types.RunArgValue, argName types.RunArg) (time.Duration, error) {
|
||||||
|
defaultDur := time.Second * 0
|
||||||
|
if arg, ok := runArgsMap[argName]; ok {
|
||||||
|
dur, err := time.ParseDuration(arg.Values[0])
|
||||||
|
if err != nil {
|
||||||
|
return defaultDur, err
|
||||||
|
}
|
||||||
|
return dur, nil
|
||||||
|
}
|
||||||
|
return defaultDur, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArgValueBool(runArgsMap map[types.RunArg]*types.RunArgValue, argName types.RunArg) bool {
|
||||||
|
value := getArgValueBoolPtr(runArgsMap, argName)
|
||||||
|
if value == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return *value
|
||||||
|
}
|
||||||
|
func getArgValueBoolPtr(runArgsMap map[types.RunArg]*types.RunArgValue, argName types.RunArg) *bool {
|
||||||
|
_, ok := runArgsMap[argName]
|
||||||
|
if ok {
|
||||||
|
return &ok
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -17,6 +17,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/git"
|
||||||
|
"github.com/harness/gitness/app/gitspace/orchestrator/runarg"
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/user"
|
"github.com/harness/gitness/app/gitspace/orchestrator/user"
|
||||||
"github.com/harness/gitness/infraprovider"
|
"github.com/harness/gitness/infraprovider"
|
||||||
|
|
||||||
|
@ -32,11 +33,13 @@ func ProvideEmbeddedDockerOrchestrator(
|
||||||
statefulLogger *logutil.StatefulLogger,
|
statefulLogger *logutil.StatefulLogger,
|
||||||
gitService git.Service,
|
gitService git.Service,
|
||||||
userService user.Service,
|
userService user.Service,
|
||||||
|
runArgProvdier runarg.Provider,
|
||||||
) Orchestrator {
|
) Orchestrator {
|
||||||
return NewEmbeddedDockerOrchestrator(
|
return NewEmbeddedDockerOrchestrator(
|
||||||
dockerClientFactory,
|
dockerClientFactory,
|
||||||
statefulLogger,
|
statefulLogger,
|
||||||
gitService,
|
gitService,
|
||||||
userService,
|
userService,
|
||||||
|
runArgProvdier,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package runarg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Provider interface {
|
||||||
|
// ProvideSupportedRunArgs returns a map of the run arg definitions for all the supported arg applicable for the
|
||||||
|
// given gitspace spaceID.
|
||||||
|
ProvideSupportedRunArgs(ctx context.Context, spaceID int64) (map[types.RunArg]types.RunArgDefinition, error)
|
||||||
|
}
|
|
@ -0,0 +1,727 @@
|
||||||
|
---
|
||||||
|
- name: --add-host
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: {}
|
||||||
|
allowed_values: {}
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --annotation
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: {}
|
||||||
|
allowed_values: {}
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --attach
|
||||||
|
short_hand: -a
|
||||||
|
supported: false
|
||||||
|
blocked_values: {}
|
||||||
|
allowed_values: {}
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --blkio-weight
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: {}
|
||||||
|
allowed_values: {}
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --blkio-weight-device
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: {}
|
||||||
|
allowed_values: {}
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --cap-add
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --cap-drop
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --cgroup-parent
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --cgroupns
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --cidfile
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --cpu-count
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --cpu-percent
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --cpu-period
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --cpu-quota
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --cpu-rt-period
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --cpu-rt-runtime
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --cpu-shares
|
||||||
|
short_hand: -c
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --cpus
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --cpuset-cpus
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --cpuset-mems
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --detach
|
||||||
|
short_hand: -d
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --detach-keys
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --device
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --device-cgroup-rule
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --device-read-bps
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --device-read-iops
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --device-write-bps
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --device-write-iops
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --disable-content-trust
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --dns
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --dns-option
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --dns-search
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --domainname
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --entrypoint
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --env
|
||||||
|
short_hand: -e
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --env-file
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --expose
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --gpus
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --group-add
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --health-cmd
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --health-interval
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --health-retries
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --health-start-interval
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --health-start-period
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --health-timeout
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --help
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --hostname
|
||||||
|
short_hand: -h
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --init
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --interactive
|
||||||
|
short_hand: -i
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --io-maxbandwidth
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --io-maxiops
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --ip
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --ip6
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --ipc
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --isolation
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --kernel-memory
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --label
|
||||||
|
short_hand: -l
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --label-file
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: {}
|
||||||
|
allowed_values: {}
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --link
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --link-local-ip
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --log-driver
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --log-opt
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --mac-address
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --memory
|
||||||
|
short_hand: -m
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --memory-reservation
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --memory-swap
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --memory-swappiness
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --mount
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --name
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --network
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values:
|
||||||
|
host: true
|
||||||
|
none: true
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --network-alias
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --no-healthcheck
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --oom-kill-disable
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --oom-score-adj
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --pid
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --pids-limit
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --platform
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --privileged
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --publish
|
||||||
|
short_hand: -p
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --publish-all
|
||||||
|
short_hand: -P
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --pull
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --quiet
|
||||||
|
short_hand: -q
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --read-only
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --restart
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --rm
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
|
||||||
|
- name: --runtime
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --security-opt
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --shm-size
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --sig-proxy
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --stop-signal
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --stop-timeout
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
- name: --storage-opt
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --sysctl
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --tmpfs
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --tty
|
||||||
|
short_hand: -t
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --ulimit
|
||||||
|
short_hand:
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
|
||||||
|
- name: --user
|
||||||
|
short_hand: -u
|
||||||
|
supported: true
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: false
|
||||||
|
|
||||||
|
|
||||||
|
- name: --userns
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
|
||||||
|
- name: --uts
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --volume
|
||||||
|
short_hand: -v
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --volume-driver
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --volumes-from
|
||||||
|
short_hand:
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
||||||
|
|
||||||
|
- name: --workdir
|
||||||
|
short_hand: -w
|
||||||
|
supported: false
|
||||||
|
blocked_values: { }
|
||||||
|
allowed_values: { }
|
||||||
|
allow_multiple_occurrences: true
|
|
@ -0,0 +1,61 @@
|
||||||
|
// 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 runarg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/types"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
_ "embed"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ Provider = (*StaticProvider)(nil)
|
||||||
|
|
||||||
|
//go:embed runArgs.yaml
|
||||||
|
var supportedRunArgsRaw []byte
|
||||||
|
|
||||||
|
type StaticProvider struct {
|
||||||
|
supportedRunArgsMap map[types.RunArg]types.RunArgDefinition
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStaticProvider() (Provider, error) {
|
||||||
|
allRunArgs := make([]types.RunArgDefinition, 0)
|
||||||
|
err := yaml.Unmarshal(supportedRunArgsRaw, &allRunArgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to unmarshal runArgs.yaml: %w", err)
|
||||||
|
}
|
||||||
|
argsMap := make(map[types.RunArg]types.RunArgDefinition)
|
||||||
|
for _, arg := range allRunArgs {
|
||||||
|
if arg.Supported {
|
||||||
|
argsMap[arg.Name] = arg
|
||||||
|
if arg.ShortHand != "" {
|
||||||
|
argsMap[arg.ShortHand] = arg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &StaticProvider{supportedRunArgsMap: argsMap}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProvideSupportedRunArgs provides a static map of supported run args.
|
||||||
|
func (s *StaticProvider) ProvideSupportedRunArgs(
|
||||||
|
_ context.Context,
|
||||||
|
_ int64,
|
||||||
|
) (map[types.RunArg]types.RunArgDefinition, error) {
|
||||||
|
return s.supportedRunArgsMap, nil
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright 2023 Harness, Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package runarg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/wire"
|
||||||
|
)
|
||||||
|
|
||||||
|
var WireSet = wire.NewSet(
|
||||||
|
ProvideStaticProvider,
|
||||||
|
)
|
||||||
|
|
||||||
|
func ProvideStaticProvider() (Provider, error) {
|
||||||
|
return NewStaticProvider()
|
||||||
|
}
|
|
@ -66,6 +66,7 @@ import (
|
||||||
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"
|
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"
|
||||||
containerUser "github.com/harness/gitness/app/gitspace/orchestrator/user"
|
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"
|
||||||
|
@ -281,6 +282,7 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
|
||||||
containerGit.WireSet,
|
containerGit.WireSet,
|
||||||
containerUser.WireSet,
|
containerUser.WireSet,
|
||||||
messagingservice.WireSet,
|
messagingservice.WireSet,
|
||||||
|
runarg.WireSet,
|
||||||
)
|
)
|
||||||
return &cliserver.System{}, nil
|
return &cliserver.System{}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ import (
|
||||||
"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"
|
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"
|
||||||
user2 "github.com/harness/gitness/app/gitspace/orchestrator/user"
|
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"
|
||||||
|
@ -318,7 +319,11 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
||||||
statefulLogger := logutil.ProvideStatefulLogger(logStream)
|
statefulLogger := logutil.ProvideStatefulLogger(logStream)
|
||||||
gitService := git2.ProvideGitServiceImpl()
|
gitService := git2.ProvideGitServiceImpl()
|
||||||
userService := user2.ProvideUserServiceImpl()
|
userService := user2.ProvideUserServiceImpl()
|
||||||
containerOrchestrator := container.ProvideEmbeddedDockerOrchestrator(dockerClientFactory, statefulLogger, gitService, userService)
|
runargProvider, err := runarg.ProvideStaticProvider()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
containerOrchestrator := container.ProvideEmbeddedDockerOrchestrator(dockerClientFactory, statefulLogger, gitService, userService, 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)
|
||||||
|
|
|
@ -27,6 +27,7 @@ type DevcontainerConfig struct {
|
||||||
ForwardPorts []json.Number `json:"forwardPorts"` //nolint:tagliatelle
|
ForwardPorts []json.Number `json:"forwardPorts"` //nolint:tagliatelle
|
||||||
ContainerEnv map[string]string `json:"containerEnv"` //nolint:tagliatelle
|
ContainerEnv map[string]string `json:"containerEnv"` //nolint:tagliatelle
|
||||||
Customizations DevContainerConfigCustomizations `json:"customizations"`
|
Customizations DevContainerConfigCustomizations `json:"customizations"`
|
||||||
|
RunArgs []string `json:"runArgs"` //nolint:tagliatelle
|
||||||
}
|
}
|
||||||
|
|
||||||
// LifecycleCommand supports multiple formats for lifecycle commands.
|
// LifecycleCommand supports multiple formats for lifecycle commands.
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
// 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 (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RunArg string
|
||||||
|
|
||||||
|
const (
|
||||||
|
RunArgAddHost = RunArg("--add-host")
|
||||||
|
RunArgAnnotation = RunArg("--annotation")
|
||||||
|
RunArgBlkioWeight = RunArg("--blkio-weight")
|
||||||
|
RunArgCapDrop = RunArg("--cap-drop")
|
||||||
|
RunArgCgroupParent = RunArg("--cgroup-parent")
|
||||||
|
RunArgCgroupns = RunArg("--cgroupns")
|
||||||
|
RunArgCPUCount = RunArg("--cpu-count")
|
||||||
|
RunArgCPUPercent = RunArg("--cpu-percent")
|
||||||
|
RunArgCPUPeriod = RunArg("--cpu-period")
|
||||||
|
RunArgCPUQuota = RunArg("--cpu-quota")
|
||||||
|
RunArgCPURtPeriod = RunArg("--cpu-rt-period")
|
||||||
|
RunArgCPURtRuntime = RunArg("--cpu-rt-runtime")
|
||||||
|
RunArgCPUShares = RunArg("--cpu-shares")
|
||||||
|
RunArgCpus = RunArg("--cpus")
|
||||||
|
RunArgCpusetCpus = RunArg("--cpuset-cpus")
|
||||||
|
RunArgCpusetMems = RunArg("--cpuset-mems")
|
||||||
|
RunArgDNS = RunArg("--dns")
|
||||||
|
RunArgDNSOption = RunArg("--dns-option")
|
||||||
|
RunArgDNSSearch = RunArg("--dns-search")
|
||||||
|
RunArgDomainname = RunArg("--domainname")
|
||||||
|
RunArgEntrypoint = RunArg("--entrypoint")
|
||||||
|
RunArgEnv = RunArg("--env")
|
||||||
|
RunArgHealthCmd = RunArg("--health-cmd")
|
||||||
|
RunArgHealthInterval = RunArg("--health-interval")
|
||||||
|
RunArgHealthRetries = RunArg("--health-retries")
|
||||||
|
RunArgHealthStartInterval = RunArg("--health-start-interval")
|
||||||
|
RunArgHealthStartPeriod = RunArg("--health-start-period")
|
||||||
|
RunArgHealthTimeout = RunArg("--health-timeout")
|
||||||
|
RunArgHostname = RunArg("--hostname")
|
||||||
|
RunArgInit = RunArg("--init")
|
||||||
|
RunArgIoMaxbandwidth = RunArg("--io-maxbandwidth")
|
||||||
|
RunArgIoMaxiops = RunArg("--io-maxiops")
|
||||||
|
RunArgIpc = RunArg("--ipc")
|
||||||
|
RunArgIsolation = RunArg("--isolation")
|
||||||
|
RunArgKernelMemory = RunArg("--kernel-memory")
|
||||||
|
RunArgLabel = RunArg("--label")
|
||||||
|
RunArgLink = RunArg("--link")
|
||||||
|
RunArgMacAddress = RunArg("--mac-address")
|
||||||
|
RunArgMemory = RunArg("--memory")
|
||||||
|
RunArgMemoryReservation = RunArg("--memory-reservation")
|
||||||
|
RunArgMemorySwap = RunArg("--memory-swap")
|
||||||
|
RunArgMemorySwappiness = RunArg("--memory-swappiness")
|
||||||
|
RunArgNetwork = RunArg("--network")
|
||||||
|
RunArgNoHealthcheck = RunArg("--no-healthcheck")
|
||||||
|
RunArgOomKillDisable = RunArg("--oom-kill-disable")
|
||||||
|
RunArgOomScoreAdj = RunArg("--oom-score-adj")
|
||||||
|
RunArgPid = RunArg("--pid")
|
||||||
|
RunArgPidsLimit = RunArg("--pids-limit")
|
||||||
|
RunArgPlatform = RunArg("--platform")
|
||||||
|
RunArgPull = RunArg("--pull")
|
||||||
|
RunArgRestart = RunArg("--restart")
|
||||||
|
RunArgRm = RunArg("--rm")
|
||||||
|
RunArgRuntime = RunArg("--runtime")
|
||||||
|
RunArgSecurityOpt = RunArg("--security-opt")
|
||||||
|
RunArgShmSize = RunArg("--shm-size")
|
||||||
|
RunArgStopSignal = RunArg("--stop-signal")
|
||||||
|
RunArgStopTimeout = RunArg("--stop-timeout")
|
||||||
|
RunArgStorageOpt = RunArg("--storage-opt")
|
||||||
|
RunArgSysctl = RunArg("--sysctl")
|
||||||
|
RunArgUlimit = RunArg("--ulimit")
|
||||||
|
RunArgUser = RunArg("--user")
|
||||||
|
)
|
||||||
|
|
||||||
|
type RunArgDefinition struct {
|
||||||
|
Name RunArg `yaml:"name"`
|
||||||
|
ShortHand RunArg `yaml:"short_hand"`
|
||||||
|
Supported bool `yaml:"supported"`
|
||||||
|
BlockedValues map[string]bool `yaml:"blocked_values"`
|
||||||
|
AllowedValues map[string]bool `yaml:"allowed_values"`
|
||||||
|
AllowMultipleOccurences bool `yaml:"allow_multiple_occurrences"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RunArgValue struct {
|
||||||
|
Name RunArg
|
||||||
|
Values []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RunArgValue) String() string {
|
||||||
|
return strings.Join(c.Values, ", ")
|
||||||
|
}
|
Loading…
Reference in New Issue