2022-09-05 04:01:14 +00:00
|
|
|
package kubernetes
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
|
2022-10-30 23:26:49 +00:00
|
|
|
"github.com/woodpecker-ci/woodpecker/pipeline/backend/common"
|
2022-09-05 04:01:14 +00:00
|
|
|
"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"
|
|
|
|
)
|
|
|
|
|
2023-03-21 19:00:45 +00:00
|
|
|
func Pod(namespace string, step *types.Step, labels, annotations map[string]string) (*v1.Pod, error) {
|
2022-10-30 23:26:49 +00:00
|
|
|
var (
|
|
|
|
vols []v1.Volume
|
|
|
|
volMounts []v1.VolumeMount
|
|
|
|
entrypoint []string
|
|
|
|
args []string
|
|
|
|
)
|
|
|
|
|
2022-09-05 04:01:14 +00:00
|
|
|
if step.WorkingDir != "" {
|
|
|
|
for _, vol := range step.Volumes {
|
2023-03-21 19:00:45 +00:00
|
|
|
volumeName, err := dnsName(strings.Split(vol, ":")[0])
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-09-05 04:01:14 +00:00
|
|
|
vols = append(vols, v1.Volume{
|
2023-03-21 19:00:45 +00:00
|
|
|
Name: volumeName,
|
2022-09-05 04:01:14 +00:00
|
|
|
VolumeSource: v1.VolumeSource{
|
|
|
|
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
|
2023-03-21 19:00:45 +00:00
|
|
|
ClaimName: volumeName,
|
2022-09-05 04:01:14 +00:00
|
|
|
ReadOnly: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
volMounts = append(volMounts, v1.VolumeMount{
|
2023-03-21 19:00:45 +00:00
|
|
|
Name: volumeName,
|
2022-09-05 04:01:14 +00:00
|
|
|
MountPath: volumeMountPath(vol),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pullPolicy := v1.PullIfNotPresent
|
|
|
|
if step.Pull {
|
|
|
|
pullPolicy = v1.PullAlways
|
|
|
|
}
|
|
|
|
|
2022-10-30 23:26:49 +00:00
|
|
|
if len(step.Commands) != 0 {
|
|
|
|
scriptEnv, entry, cmds := common.GenerateContainerConf(step.Commands)
|
|
|
|
for k, v := range scriptEnv {
|
|
|
|
step.Environment[k] = v
|
|
|
|
}
|
|
|
|
entrypoint = entry
|
|
|
|
args = cmds
|
2022-09-05 04:01:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2023-03-21 19:00:45 +00:00
|
|
|
podName, err := dnsName(step.Name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
labels["step"] = podName
|
2022-12-31 00:37:09 +00:00
|
|
|
|
2023-03-21 19:00:45 +00:00
|
|
|
pod := &v1.Pod{
|
2022-09-05 04:01:14 +00:00
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
2023-03-21 19:00:45 +00:00
|
|
|
Name: podName,
|
2022-12-31 00:37:09 +00:00
|
|
|
Namespace: namespace,
|
|
|
|
Labels: labels,
|
|
|
|
Annotations: annotations,
|
2022-09-05 04:01:14 +00:00
|
|
|
},
|
|
|
|
Spec: v1.PodSpec{
|
|
|
|
RestartPolicy: v1.RestartPolicyNever,
|
|
|
|
HostAliases: hostAliases,
|
|
|
|
Containers: []v1.Container{{
|
2023-03-21 19:00:45 +00:00
|
|
|
Name: podName,
|
2022-09-05 04:01:14 +00:00
|
|
|
Image: step.Image,
|
|
|
|
ImagePullPolicy: pullPolicy,
|
2022-10-30 23:26:49 +00:00
|
|
|
Command: entrypoint,
|
2022-09-05 04:01:14 +00:00
|
|
|
Args: args,
|
|
|
|
WorkingDir: step.WorkingDir,
|
2022-10-30 23:26:49 +00:00
|
|
|
Env: mapToEnvVars(step.Environment),
|
2022-09-05 04:01:14 +00:00
|
|
|
VolumeMounts: volMounts,
|
|
|
|
Resources: resources,
|
|
|
|
SecurityContext: &v1.SecurityContext{
|
|
|
|
Privileged: &step.Privileged,
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
ImagePullSecrets: []v1.LocalObjectReference{{Name: "regcred"}},
|
|
|
|
Volumes: vols,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2023-03-21 19:00:45 +00:00
|
|
|
return pod, nil
|
2022-09-05 04:01:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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]
|
|
|
|
}
|