woodpecker/pipeline/backend/kubernetes/pod.go
Anbraten 3b0263442a
Adding initial version of Kubernetes backend (#552)
Co-authored-by: laszlocph <laszlo@laszlo.cloud>
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: Rynoxx <rynoxx@grid-servers.net>
2022-09-05 06:01:14 +02:00

137 lines
3.4 KiB
Go

package kubernetes
import (
"strings"
"github.com/woodpecker-ci/woodpecker/pipeline/backend/types"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func Pod(namespace string, step *types.Step) *v1.Pod {
var vols []v1.Volume
var volMounts []v1.VolumeMount
if step.WorkingDir != "" {
for _, vol := range step.Volumes {
vols = append(vols, v1.Volume{
Name: volumeName(vol),
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: volumeName(vol),
ReadOnly: false,
},
},
})
volMounts = append(volMounts, v1.VolumeMount{
Name: volumeName(vol),
MountPath: volumeMountPath(vol),
})
}
}
pullPolicy := v1.PullIfNotPresent
if step.Pull {
pullPolicy = v1.PullAlways
}
command := step.Entrypoint
args := step.Command
envs := mapToEnvVars(step.Environment)
if _, hasScript := step.Environment["CI_SCRIPT"]; !strings.HasSuffix(step.Name, "_clone") && hasScript {
command = []string{"/bin/sh", "-c"}
args = []string{"echo $CI_SCRIPT | base64 -d | /bin/sh -e"}
}
hostAliases := []v1.HostAlias{}
for _, extraHost := range step.ExtraHosts {
host := strings.Split(extraHost, ":")
hostAliases = append(hostAliases, v1.HostAlias{IP: host[1], Hostnames: []string{host[0]}})
}
// TODO: add support for resource limits
// if step.Resources.CPULimit == "" {
// step.Resources.CPULimit = "2"
// }
// if step.Resources.MemoryLimit == "" {
// step.Resources.MemoryLimit = "2G"
// }
// memoryLimit := resource.MustParse(step.Resources.MemoryLimit)
// CPULimit := resource.MustParse(step.Resources.CPULimit)
memoryLimit := resource.MustParse("2G")
CPULimit := resource.MustParse("2")
memoryLimitValue, _ := memoryLimit.AsInt64()
CPULimitValue, _ := CPULimit.AsInt64()
loadfactor := 0.5
memoryRequest := resource.NewQuantity(int64(float64(memoryLimitValue)*loadfactor), resource.DecimalSI)
CPURequest := resource.NewQuantity(int64(float64(CPULimitValue)*loadfactor), resource.DecimalSI)
resources := v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceMemory: *memoryRequest,
v1.ResourceCPU: *CPURequest,
},
Limits: v1.ResourceList{
v1.ResourceMemory: memoryLimit,
v1.ResourceCPU: CPULimit,
},
}
return &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: podName(step),
Namespace: namespace,
Labels: map[string]string{
"step": podName(step),
},
},
Spec: v1.PodSpec{
RestartPolicy: v1.RestartPolicyNever,
HostAliases: hostAliases,
Containers: []v1.Container{{
Name: podName(step),
Image: step.Image,
ImagePullPolicy: pullPolicy,
Command: command,
Args: args,
WorkingDir: step.WorkingDir,
Env: envs,
VolumeMounts: volMounts,
Resources: resources,
SecurityContext: &v1.SecurityContext{
Privileged: &step.Privileged,
},
}},
ImagePullSecrets: []v1.LocalObjectReference{{Name: "regcred"}},
Volumes: vols,
},
}
}
func podName(s *types.Step) string {
return dnsName(s.Name)
}
func mapToEnvVars(m map[string]string) []v1.EnvVar {
var ev []v1.EnvVar
for k, v := range m {
ev = append(ev, v1.EnvVar{
Name: k,
Value: v,
})
}
return ev
}
func volumeMountPath(i string) string {
s := strings.Split(i, ":")
if len(s) > 1 {
return s[1]
}
return s[0]
}