drone/app/gitspace/orchestrator/container/runarg_utils.go

542 lines
15 KiB
Go

// 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
}