mirror of https://github.com/harness/drone.git
542 lines
15 KiB
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
|
|
}
|