2023-12-19 03:53:52 +00:00
|
|
|
// Copyright 2023 Woodpecker Authors
|
|
|
|
//
|
|
|
|
// 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 kubernetes
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/kinbiko/jsonassert"
|
|
|
|
"github.com/stretchr/testify/assert"
|
2024-01-14 17:22:06 +00:00
|
|
|
|
2023-12-19 03:53:52 +00:00
|
|
|
"go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestPodName(t *testing.T) {
|
2024-01-11 15:32:37 +00:00
|
|
|
name, err := podName(&types.Step{UUID: "01he8bebctabr3kgk0qj36d2me-0"})
|
2023-12-19 03:53:52 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, "wp-01he8bebctabr3kgk0qj36d2me-0", name)
|
|
|
|
|
2024-01-11 15:32:37 +00:00
|
|
|
_, err = podName(&types.Step{UUID: "01he8bebctabr3kgk0qj36d2me\\0a"})
|
|
|
|
assert.ErrorIs(t, err, ErrDNSPatternInvalid)
|
2023-12-19 03:53:52 +00:00
|
|
|
|
2024-01-11 15:32:37 +00:00
|
|
|
_, err = podName(&types.Step{UUID: "01he8bebctabr3kgk0qj36d2me-0-services-0..woodpecker-runtime.svc.cluster.local"})
|
2023-12-19 03:53:52 +00:00
|
|
|
assert.ErrorIs(t, err, ErrDNSPatternInvalid)
|
|
|
|
}
|
|
|
|
|
2024-01-11 15:32:37 +00:00
|
|
|
func TestStepToPodName(t *testing.T) {
|
|
|
|
name, err := stepToPodName(&types.Step{UUID: "01he8bebctabr3kg", Name: "clone", Type: types.StepTypeClone})
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.EqualValues(t, "wp-01he8bebctabr3kg", name)
|
2024-01-26 12:42:21 +00:00
|
|
|
name, err = stepToPodName(&types.Step{UUID: "01he8bebctabr3kg", Name: "cache", Type: types.StepTypeCache})
|
2024-01-11 15:32:37 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.EqualValues(t, "wp-01he8bebctabr3kg", name)
|
2024-01-26 12:42:21 +00:00
|
|
|
name, err = stepToPodName(&types.Step{UUID: "01he8bebctabr3kg", Name: "release", Type: types.StepTypePlugin})
|
2024-01-11 15:32:37 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.EqualValues(t, "wp-01he8bebctabr3kg", name)
|
2024-01-26 12:42:21 +00:00
|
|
|
name, err = stepToPodName(&types.Step{UUID: "01he8bebctabr3kg", Name: "prepare-env", Type: types.StepTypeCommands})
|
2024-01-11 15:32:37 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.EqualValues(t, "wp-01he8bebctabr3kg", name)
|
2024-01-26 12:42:21 +00:00
|
|
|
name, err = stepToPodName(&types.Step{UUID: "01he8bebctabr3kg", Name: "postgres", Type: types.StepTypeService})
|
2024-01-11 15:32:37 +00:00
|
|
|
assert.NoError(t, err)
|
2024-01-26 12:42:21 +00:00
|
|
|
assert.EqualValues(t, "postgres", name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStepLabel(t *testing.T) {
|
|
|
|
name, err := stepLabel(&types.Step{Name: "Build image"})
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.EqualValues(t, "build-image", name)
|
|
|
|
|
|
|
|
_, err = stepLabel(&types.Step{Name: ".build.image"})
|
|
|
|
assert.ErrorIs(t, err, ErrDNSPatternInvalid)
|
2024-01-11 15:32:37 +00:00
|
|
|
}
|
|
|
|
|
2023-12-19 03:53:52 +00:00
|
|
|
func TestTinyPod(t *testing.T) {
|
|
|
|
expected := `
|
|
|
|
{
|
|
|
|
"metadata": {
|
|
|
|
"name": "wp-01he8bebctabr3kgk0qj36d2me-0",
|
|
|
|
"namespace": "woodpecker",
|
|
|
|
"creationTimestamp": null,
|
|
|
|
"labels": {
|
2024-01-11 15:32:37 +00:00
|
|
|
"step": "build-via-gradle"
|
2023-12-19 03:53:52 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
"spec": {
|
|
|
|
"volumes": [
|
|
|
|
{
|
|
|
|
"name": "workspace",
|
|
|
|
"persistentVolumeClaim": {
|
|
|
|
"claimName": "workspace"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"containers": [
|
|
|
|
{
|
|
|
|
"name": "wp-01he8bebctabr3kgk0qj36d2me-0",
|
|
|
|
"image": "gradle:8.4.0-jdk21",
|
|
|
|
"command": [
|
|
|
|
"/bin/sh",
|
|
|
|
"-c"
|
|
|
|
],
|
|
|
|
"args": [
|
|
|
|
"echo $CI_SCRIPT | base64 -d | /bin/sh -e"
|
|
|
|
],
|
|
|
|
"workingDir": "/woodpecker/src",
|
|
|
|
"env": [
|
|
|
|
"<<UNORDERED>>",
|
|
|
|
{
|
|
|
|
"name": "CI",
|
|
|
|
"value": "woodpecker"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "HOME",
|
|
|
|
"value": "/root"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "SHELL",
|
|
|
|
"value": "/bin/sh"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "CI_SCRIPT",
|
|
|
|
"value": "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVAoKZWNobyArICdncmFkbGUgYnVpbGQnCmdyYWRsZSBidWlsZAo="
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"resources": {},
|
|
|
|
"volumeMounts": [
|
|
|
|
{
|
|
|
|
"name": "workspace",
|
|
|
|
"mountPath": "/woodpecker/src"
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
],
|
2024-01-05 07:33:56 +00:00
|
|
|
"restartPolicy": "Never"
|
2023-12-19 03:53:52 +00:00
|
|
|
},
|
|
|
|
"status": {}
|
|
|
|
}`
|
|
|
|
|
2024-01-11 15:32:37 +00:00
|
|
|
pod, err := mkPod(&types.Step{
|
|
|
|
Name: "build-via-gradle",
|
|
|
|
Image: "gradle:8.4.0-jdk21",
|
|
|
|
WorkingDir: "/woodpecker/src",
|
|
|
|
Pull: false,
|
|
|
|
Privileged: false,
|
|
|
|
Commands: []string{"gradle build"},
|
|
|
|
Volumes: []string{"workspace:/woodpecker/src"},
|
|
|
|
Environment: map[string]string{"CI": "woodpecker"},
|
|
|
|
}, &config{
|
|
|
|
Namespace: "woodpecker",
|
2024-02-08 17:39:32 +00:00
|
|
|
}, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{})
|
2023-12-19 03:53:52 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2024-01-26 12:42:21 +00:00
|
|
|
podJSON, err := json.Marshal(pod)
|
2023-12-19 03:53:52 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ja := jsonassert.New(t)
|
2024-01-26 12:42:21 +00:00
|
|
|
ja.Assertf(string(podJSON), expected)
|
2023-12-19 03:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestFullPod(t *testing.T) {
|
|
|
|
expected := `
|
|
|
|
{
|
|
|
|
"metadata": {
|
|
|
|
"name": "wp-01he8bebctabr3kgk0qj36d2me-0",
|
|
|
|
"namespace": "woodpecker",
|
|
|
|
"creationTimestamp": null,
|
|
|
|
"labels": {
|
|
|
|
"app": "test",
|
2024-01-11 15:32:37 +00:00
|
|
|
"step": "go-test"
|
2023-12-19 03:53:52 +00:00
|
|
|
},
|
|
|
|
"annotations": {
|
2024-01-12 22:32:24 +00:00
|
|
|
"apps.kubernetes.io/pod-index": "0",
|
|
|
|
"container.apparmor.security.beta.kubernetes.io/wp-01he8bebctabr3kgk0qj36d2me-0": "localhost/k8s-apparmor-example-deny-write"
|
2023-12-19 03:53:52 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
"spec": {
|
|
|
|
"volumes": [
|
|
|
|
{
|
|
|
|
"name": "woodpecker-cache",
|
|
|
|
"persistentVolumeClaim": {
|
|
|
|
"claimName": "woodpecker-cache"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"containers": [
|
|
|
|
{
|
|
|
|
"name": "wp-01he8bebctabr3kgk0qj36d2me-0",
|
|
|
|
"image": "meltwater/drone-cache",
|
|
|
|
"command": [
|
|
|
|
"/bin/sh",
|
|
|
|
"-c"
|
|
|
|
],
|
|
|
|
"args": [
|
|
|
|
"echo $CI_SCRIPT | base64 -d | /bin/sh -e"
|
|
|
|
],
|
|
|
|
"workingDir": "/woodpecker/src",
|
2024-01-12 22:57:24 +00:00
|
|
|
"ports": [
|
|
|
|
{
|
|
|
|
"containerPort": 1234
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"containerPort": 2345,
|
|
|
|
"protocol": "TCP"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"containerPort": 3456,
|
|
|
|
"protocol": "UDP"
|
|
|
|
}
|
|
|
|
],
|
2023-12-19 03:53:52 +00:00
|
|
|
"env": [
|
|
|
|
"<<UNORDERED>>",
|
|
|
|
{
|
|
|
|
"name": "CGO",
|
|
|
|
"value": "0"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "CI_SCRIPT",
|
|
|
|
"value": "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVAoKZWNobyArICdnbyBnZXQnCmdvIGdldAoKZWNobyArICdnbyB0ZXN0JwpnbyB0ZXN0Cg=="
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "HOME",
|
|
|
|
"value": "/root"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "SHELL",
|
|
|
|
"value": "/bin/sh"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"resources": {
|
|
|
|
"limits": {
|
|
|
|
"cpu": "2",
|
|
|
|
"memory": "256Mi"
|
|
|
|
},
|
|
|
|
"requests": {
|
|
|
|
"cpu": "1",
|
|
|
|
"memory": "128Mi"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"volumeMounts": [
|
|
|
|
{
|
|
|
|
"name": "woodpecker-cache",
|
|
|
|
"mountPath": "/woodpecker/src/cache"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"imagePullPolicy": "Always",
|
|
|
|
"securityContext": {
|
|
|
|
"privileged": true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"restartPolicy": "Never",
|
|
|
|
"nodeSelector": {
|
|
|
|
"storage": "ssd"
|
|
|
|
},
|
|
|
|
"serviceAccountName": "wp-svc-acc",
|
|
|
|
"securityContext": {
|
|
|
|
"runAsUser": 101,
|
|
|
|
"runAsGroup": 101,
|
|
|
|
"runAsNonRoot": true,
|
2024-01-12 22:32:24 +00:00
|
|
|
"fsGroup": 101,
|
|
|
|
"seccompProfile": {
|
|
|
|
"type": "Localhost",
|
|
|
|
"localhostProfile": "profiles/audit.json"
|
|
|
|
}
|
2023-12-19 03:53:52 +00:00
|
|
|
},
|
|
|
|
"imagePullSecrets": [
|
|
|
|
{
|
|
|
|
"name": "regcred"
|
2024-01-05 07:33:56 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "another-pull-secret"
|
2023-12-19 03:53:52 +00:00
|
|
|
}
|
|
|
|
],
|
|
|
|
"tolerations": [
|
|
|
|
{
|
|
|
|
"key": "net-port",
|
|
|
|
"value": "100Mbit",
|
|
|
|
"effect": "NoSchedule"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"hostAliases": [
|
|
|
|
{
|
|
|
|
"ip": "1.1.1.1",
|
|
|
|
"hostnames": [
|
|
|
|
"cloudflare"
|
|
|
|
]
|
2023-12-22 23:42:30 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"ip": "2606:4700:4700::64",
|
|
|
|
"hostnames": [
|
|
|
|
"cf.v6"
|
|
|
|
]
|
2023-12-19 03:53:52 +00:00
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
"status": {}
|
|
|
|
}`
|
|
|
|
|
2023-12-22 23:42:30 +00:00
|
|
|
hostAliases := []types.HostAlias{
|
|
|
|
{Name: "cloudflare", IP: "1.1.1.1"},
|
|
|
|
{Name: "cf.v6", IP: "2606:4700:4700::64"},
|
|
|
|
}
|
2024-01-12 22:57:24 +00:00
|
|
|
ports := []types.Port{
|
|
|
|
{Number: 1234},
|
|
|
|
{Number: 2345, Protocol: "tcp"},
|
|
|
|
{Number: 3456, Protocol: "udp"},
|
|
|
|
}
|
2024-02-08 17:39:32 +00:00
|
|
|
secCtx := SecurityContext{
|
2024-01-12 22:32:24 +00:00
|
|
|
Privileged: newBool(true),
|
|
|
|
RunAsNonRoot: newBool(true),
|
|
|
|
RunAsUser: newInt64(101),
|
|
|
|
RunAsGroup: newInt64(101),
|
|
|
|
FSGroup: newInt64(101),
|
2024-02-08 17:39:32 +00:00
|
|
|
SeccompProfile: &SecProfile{
|
2024-01-12 22:32:24 +00:00
|
|
|
Type: "Localhost",
|
|
|
|
LocalhostProfile: "profiles/audit.json",
|
|
|
|
},
|
2024-02-08 17:39:32 +00:00
|
|
|
ApparmorProfile: &SecProfile{
|
2024-01-12 22:32:24 +00:00
|
|
|
Type: "Localhost",
|
|
|
|
LocalhostProfile: "k8s-apparmor-example-deny-write",
|
|
|
|
},
|
|
|
|
}
|
2024-01-11 15:32:37 +00:00
|
|
|
pod, err := mkPod(&types.Step{
|
|
|
|
Name: "go-test",
|
|
|
|
Image: "meltwater/drone-cache",
|
|
|
|
WorkingDir: "/woodpecker/src",
|
|
|
|
Pull: true,
|
|
|
|
Privileged: true,
|
|
|
|
Commands: []string{"go get", "go test"},
|
2024-01-19 04:34:02 +00:00
|
|
|
Entrypoint: []string{"/bin/sh", "-c"},
|
2024-01-11 15:32:37 +00:00
|
|
|
Volumes: []string{"woodpecker-cache:/woodpecker/src/cache"},
|
|
|
|
Environment: map[string]string{"CGO": "0"},
|
|
|
|
ExtraHosts: hostAliases,
|
2024-01-12 22:57:24 +00:00
|
|
|
Ports: ports,
|
2024-01-11 15:32:37 +00:00
|
|
|
}, &config{
|
|
|
|
Namespace: "woodpecker",
|
|
|
|
ImagePullSecretNames: []string{"regcred", "another-pull-secret"},
|
|
|
|
PodLabels: map[string]string{"app": "test"},
|
2024-01-12 22:32:24 +00:00
|
|
|
PodAnnotations: map[string]string{"apps.kubernetes.io/pod-index": "0"},
|
2024-01-11 15:32:37 +00:00
|
|
|
SecurityContext: SecurityContextConfig{RunAsNonRoot: false},
|
2024-02-08 17:39:32 +00:00
|
|
|
}, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{
|
|
|
|
NodeSelector: map[string]string{"storage": "ssd"},
|
|
|
|
ServiceAccountName: "wp-svc-acc",
|
|
|
|
Tolerations: []Toleration{{Key: "net-port", Value: "100Mbit", Effect: TaintEffectNoSchedule}},
|
|
|
|
Resources: Resources{
|
|
|
|
Requests: map[string]string{"memory": "128Mi", "cpu": "1000m"},
|
|
|
|
Limits: map[string]string{"memory": "256Mi", "cpu": "2"},
|
|
|
|
},
|
|
|
|
SecurityContext: &secCtx,
|
|
|
|
})
|
2023-12-19 03:53:52 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
2024-01-26 12:42:21 +00:00
|
|
|
podJSON, err := json.Marshal(pod)
|
2023-12-19 03:53:52 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
ja := jsonassert.New(t)
|
2024-01-26 12:42:21 +00:00
|
|
|
ja.Assertf(string(podJSON), expected)
|
2023-12-19 03:53:52 +00:00
|
|
|
}
|