1
0
mirror of https://github.com/woodpecker-ci/woodpecker.git synced 2026-06-03 16:35:37 +02:00

Allow disabling service workspace volumes in k8s (#6644)

This commit is contained in:
Julien Vincent
2026-05-26 17:43:46 +01:00
committed by GitHub
parent fd916365f8
commit b6880141e2
5 changed files with 80 additions and 2 deletions
@@ -81,6 +81,22 @@ steps:
To give steps access to the Kubernetes API via service account, take a look at [RBAC Authorization](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)
### Workspace volume
`workspaceVolume` controls whether the default workspace volume is mounted into a service Pod. It only affects service
containers and does not disable explicitly configured service volumes.
If unset, the default workspace volume is mounted.
```yaml
services:
postgres:
image: postgres:16
backend_options:
kubernetes:
workspaceVolume: false
```
### Node selector
`nodeSelector` specifies the labels which are used to select the node on which the step will be executed.
@@ -33,6 +33,7 @@ type BackendOptions struct {
Affinity *kube_core_v1.Affinity `mapstructure:"affinity"`
SecurityContext *SecurityContext `mapstructure:"securityContext"`
Secrets []SecretRef `mapstructure:"secrets"`
WorkspaceVolume *bool `mapstructure:"workspaceVolume"`
}
// Resources defines two maps for kubernetes resource definitions.
@@ -48,6 +48,7 @@ func Test_parseBackendOptions(t *testing.T) {
"kubernetes": map[string]any{
"nodeSelector": map[string]string{"storage": "ssd"},
"serviceAccountName": "wp-svc-acc",
"workspaceVolume": false,
"labels": map[string]string{"app": "test"},
"annotations": map[string]string{"apps.kubernetes.io/pod-index": "0"},
"tolerations": []map[string]any{
@@ -107,6 +108,7 @@ func Test_parseBackendOptions(t *testing.T) {
want: BackendOptions{
NodeSelector: map[string]string{"storage": "ssd"},
ServiceAccountName: "wp-svc-acc",
WorkspaceVolume: newBool(false),
Labels: map[string]string{"app": "test"},
Annotations: map[string]string{"apps.kubernetes.io/pod-index": "0"},
Tolerations: []Toleration{{Key: "net-port", Value: "100Mbit", Effect: TaintEffectNoSchedule}},
+23 -2
View File
@@ -206,7 +206,7 @@ func podSpec(step *types.Step, config *config, options BackendOptions, nsp nativ
spec.Tolerations = tolerations(config.PodTolerations)
}
spec.Volumes, err = pvcVolumes(step.Volumes)
spec.Volumes, err = pvcVolumes(podVolumes(step, options))
if err != nil {
return spec, err
}
@@ -278,7 +278,7 @@ func podContainer(step *types.Step, podName, goos string, options BackendOptions
return container, err
}
container.VolumeMounts, err = volumeMounts(step.Volumes)
container.VolumeMounts, err = volumeMounts(podVolumes(step, options))
if err != nil {
return container, err
}
@@ -388,6 +388,27 @@ func pvcVolumes(volumes []string) ([]kube_core_v1.Volume, error) {
return vols, nil
}
func podVolumes(step *types.Step, options BackendOptions) []string {
if !isService(step) || useWorkspaceVolume(options) {
return step.Volumes
}
volumes := make([]string, 0, len(step.Volumes))
for _, volume := range step.Volumes {
if volumeMountPath(volume) != step.WorkspaceBase {
volumes = append(volumes, volume)
}
}
return volumes
}
func useWorkspaceVolume(options BackendOptions) bool {
if options.WorkspaceVolume != nil {
return *options.WorkspaceVolume
}
return true
}
func pvcVolume(name string) kube_core_v1.Volume {
pvcSource := kube_core_v1.PersistentVolumeClaimVolumeSource{
ClaimName: name,
+38
View File
@@ -220,6 +220,44 @@ func TestTinyPod(t *testing.T) {
ja.Assertf(string(podJSON), expected)
}
func TestServiceWorkspaceVolume(t *testing.T) {
useWorkspaceVolume := true
disableWorkspaceVolume := false
step := &types.Step{
Name: "postgres",
Image: "postgres:16",
UUID: "01he8bebctabr3kgk0qj36d2me-0",
Type: types.StepTypeService,
WorkingDir: "/woodpecker/src",
WorkspaceBase: "/woodpecker",
Environment: map[string]string{},
Volumes: []string{"workspace:/woodpecker", "cache:/cache"},
}
pod, err := mkPod(step, &config{Namespace: "woodpecker"}, "wp-svc-postgres", "linux/amd64", BackendOptions{}, taskUUID)
assert.NoError(t, err)
assert.Len(t, pod.Spec.Volumes, 2)
assert.Equal(t, "workspace", pod.Spec.Volumes[0].Name)
assert.Equal(t, "/woodpecker", pod.Spec.Containers[0].VolumeMounts[0].MountPath)
assert.Equal(t, "cache", pod.Spec.Volumes[1].Name)
assert.Equal(t, "/cache", pod.Spec.Containers[0].VolumeMounts[1].MountPath)
pod, err = mkPod(step, &config{Namespace: "woodpecker"}, "wp-svc-postgres", "linux/amd64", BackendOptions{WorkspaceVolume: &disableWorkspaceVolume}, taskUUID)
assert.NoError(t, err)
assert.Len(t, pod.Spec.Volumes, 1)
assert.Equal(t, "cache", pod.Spec.Volumes[0].Name)
assert.Len(t, pod.Spec.Containers[0].VolumeMounts, 1)
assert.Equal(t, "/cache", pod.Spec.Containers[0].VolumeMounts[0].MountPath)
pod, err = mkPod(step, &config{Namespace: "woodpecker"}, "wp-svc-postgres", "linux/amd64", BackendOptions{WorkspaceVolume: &useWorkspaceVolume}, taskUUID)
assert.NoError(t, err)
assert.Len(t, pod.Spec.Volumes, 2)
assert.Equal(t, "workspace", pod.Spec.Volumes[0].Name)
assert.Equal(t, "/woodpecker", pod.Spec.Containers[0].VolumeMounts[0].MountPath)
assert.Equal(t, "cache", pod.Spec.Volumes[1].Name)
assert.Equal(t, "/cache", pod.Spec.Containers[0].VolumeMounts[1].MountPath)
}
func TestFullPod(t *testing.T) {
const expected = `
{