Skip to content

Commit 630ad3a

Browse files
authored
Merge pull request #534 from buildkite/SUP-3228-default-extra-volume-mounts
SUP-3228: Allow `extraVolumeMounts` for default params
2 parents 3df18ee + bcc6a9c commit 630ad3a

File tree

10 files changed

+284
-5
lines changed

10 files changed

+284
-5
lines changed

README.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,10 +676,139 @@ config:
676676
677677
### Extra volume mounts
678678
679+
#### All containers
680+
679681
In some situations, for example if you want to use [git mirrors](https://buildkite.com/docs/agent/v3#promoted-experiments-git-mirrors) you may want to attach extra volume mounts (in addition to the `/workspace` one) in all the pod containers.
680682
681683
See [this example](internal/integration/fixtures/extra-volume-mounts.yaml), that will declare a new volume in the `podSpec` and mount it in all the containers. The benefit, is to have the same mounted path in all containers, including the `checkout` container.
682684
685+
#### `checkout` containers
686+
687+
In order to attach extra volumes to your `checkout` containers, define `config.default-checkout-params.extraVolumeMounts` in your configuration. Example:
688+
```yaml
689+
# values.yaml
690+
config:
691+
default-checkout-params:
692+
gitCredentialsSecret:
693+
secretName: my-git-credentials
694+
extraVolumeMounts:
695+
- name: checkout-extra-dir
696+
mountPath: /extra-checkout
697+
pod-spec-patch:
698+
containers:
699+
- name: checkout
700+
image: "buildkite/agent:latest"
701+
volumes:
702+
- name: checkout-extra-dir
703+
hostPath:
704+
path: /my/extra/dir/checkout
705+
type: DirectoryOrCreate
706+
```
707+
708+
Or `checkout.extraVolumeMounts` in the `kubernetes` plugin. Example:
709+
```yaml
710+
# pipeline.yml
711+
...
712+
kubernetes:
713+
checkout:
714+
extraVolumeMounts:
715+
- name: checkout-extra-dir
716+
mountPath: /extra-checkout
717+
podSpecPatch:
718+
containers:
719+
- name: checkout
720+
image: "buildkite/agent:latest"
721+
volumes:
722+
- name: checkout-extra-dir
723+
hostPath:
724+
path: /my/extra/dir/checkout
725+
type: DirectoryOrCreate
726+
```
727+
728+
#### `command` containers
729+
730+
In order to attach extra volumes to your `container-#` (`command`) containers, define `config.default-command-params.extraVolumeMounts` in your configuration. Example:
731+
```yaml
732+
# values.yaml
733+
config:
734+
default-command-params:
735+
extraVolumeMounts:
736+
- name: command-extra-dir
737+
mountPath: /extra-command
738+
pod-spec-patch:
739+
containers:
740+
- name: container-0
741+
image: "buildkite/agent:latest"
742+
volumes:
743+
- name: command-extra-dir
744+
hostPath:
745+
path: /my/extra/dir/command
746+
type: DirectoryOrCreate
747+
```
748+
749+
Or `commandParams.extraVolumeMounts` in the `kubernetes` plugin. Example:
750+
```yaml
751+
# pipeline.yml
752+
...
753+
kubernetes:
754+
commandParams:
755+
extraVolumeMounts:
756+
- name: command-extra-dir
757+
mountPath: /extra-command
758+
podSpecPatch:
759+
containers:
760+
- name: container-0
761+
image: "buildkite/agent:latest"
762+
volumes:
763+
- name: command-extra-dir
764+
hostPath:
765+
path: /my/extra/dir/command
766+
type: DirectoryOrCreate
767+
```
768+
769+
#### `sidecar` containers
770+
771+
In order to attach extra volumes to your `sidecar` containers, define `config.default-sidecar-params.extraVolumeMounts` in your configuration. Example:
772+
```yaml
773+
# values.yaml
774+
config:
775+
default-sidecar-params:
776+
extraVolumeMounts:
777+
- name: sidecar-extra-dir
778+
mountPath: /extra-sidecar
779+
pod-spec-patch:
780+
containers:
781+
- name: checkout
782+
image: "buildkite/agent:latest"
783+
volumes:
784+
- name: sidecar-extra-dir
785+
hostPath:
786+
path: /my/extra/dir/sidecar
787+
type: DirectoryOrCreate
788+
```
789+
790+
Or `sidecarParams.extraVolumeMounts` in the `kubernetes` plugin. Example:
791+
```yaml
792+
# pipeline.yml
793+
...
794+
kubernetes:
795+
sidecars:
796+
- image: nginx:latest
797+
sidecarParams:
798+
extraVolumeMounts:
799+
- name: sidecar-extra-dir
800+
mountPath: /extra-sidecar
801+
podSpecPatch:
802+
containers:
803+
- name: checkout
804+
image: "buildkite/agent:latest"
805+
volumes:
806+
- name: sidecar-extra-dir
807+
hostPath:
808+
path: /my/extra/dir/sidecar
809+
type: DirectoryOrCreate
810+
```
811+
683812
### Skipping checkout (v0.13.0 and later)
684813
685814
For some steps, you may wish to avoid checkout (cloning a source repository).

charts/agent-stack-k8s/values.schema.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,14 @@
481481
"items": {
482482
"$ref": "https://kubernetesjsonschema.dev/master/_definitions.json#/definitions/io.k8s.api.core.v1.EnvFromSource"
483483
}
484+
},
485+
"extraVolumeMounts": {
486+
"type": "array",
487+
"default": [],
488+
"title": "extra volumes to mount to all checkout containers",
489+
"items": {
490+
"$ref": "https://kubernetesjsonschema.dev/master/_definitions.json#/definitions/io.k8s.api.core.v1.VolumeMount"
491+
}
484492
}
485493
}
486494
},
@@ -502,6 +510,14 @@
502510
"items": {
503511
"$ref": "https://kubernetesjsonschema.dev/master/_definitions.json#/definitions/io.k8s.api.core.v1.EnvFromSource"
504512
}
513+
},
514+
"extraVolumeMounts": {
515+
"type": "array",
516+
"default": [],
517+
"title": "extra volumes to mount to all command containers",
518+
"items": {
519+
"$ref": "https://kubernetesjsonschema.dev/master/_definitions.json#/definitions/io.k8s.api.core.v1.VolumeMount"
520+
}
505521
}
506522
}
507523
},
@@ -517,6 +533,14 @@
517533
"items": {
518534
"$ref": "https://kubernetesjsonschema.dev/master/_definitions.json#/definitions/io.k8s.api.core.v1.EnvFromSource"
519535
}
536+
},
537+
"extraVolumeMounts": {
538+
"type": "array",
539+
"default": [],
540+
"title": "extra volumes to mount to all sidecar containers",
541+
"items": {
542+
"$ref": "https://kubernetesjsonschema.dev/master/_definitions.json#/definitions/io.k8s.api.core.v1.VolumeMount"
543+
}
520544
}
521545
}
522546
},

internal/controller/config/checkout_params.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type CheckoutParams struct {
1818
GitMirrors *GitMirrorsParams `json:"gitMirrors,omitempty"`
1919
GitCredentialsSecret *corev1.SecretVolumeSource `json:"gitCredentialsSecret,omitempty"`
2020
EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"`
21+
ExtraVolumeMounts []corev1.VolumeMount `json:"extraVolumeMounts,omitempty"`
2122
}
2223

2324
func (co *CheckoutParams) ApplyTo(podSpec *corev1.PodSpec, ctr *corev1.Container) {
@@ -31,6 +32,7 @@ func (co *CheckoutParams) ApplyTo(podSpec *corev1.PodSpec, ctr *corev1.Container
3132
appendCommaSepToEnv(ctr, "BUILDKITE_GIT_SUBMODULE_CLONE_CONFIG", co.SubmoduleCloneConfig)
3233
co.GitMirrors.ApplyTo(podSpec, ctr)
3334
ctr.EnvFrom = append(ctr.EnvFrom, co.EnvFrom...)
35+
ctr.VolumeMounts = append(ctr.VolumeMounts, co.ExtraVolumeMounts...)
3436
}
3537

3638
func (co *CheckoutParams) GitCredsSecret() *corev1.SecretVolumeSource {

internal/controller/config/command_params.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,17 @@ import (
1313
// CommandParams contains parameters that provide additional control over all
1414
// command container(s).
1515
type CommandParams struct {
16-
Interposer Interposer `json:"interposer,omitempty"`
17-
EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"`
16+
Interposer Interposer `json:"interposer,omitempty"`
17+
EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"`
18+
ExtraVolumeMounts []corev1.VolumeMount `json:"extraVolumeMounts,omitempty"`
1819
}
1920

2021
func (cmd *CommandParams) ApplyTo(ctr *corev1.Container) {
2122
if cmd == nil || ctr == nil {
2223
return
2324
}
2425
ctr.EnvFrom = append(ctr.EnvFrom, cmd.EnvFrom...)
26+
ctr.VolumeMounts = append(ctr.VolumeMounts, cmd.ExtraVolumeMounts...)
2527
}
2628

2729
// Command interprets the command and args fields of the container into a

internal/controller/config/sidecar_params.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import corev1 "k8s.io/api/core/v1"
55
// SidecarParams contains parameters that provide additional control over all sidecar
66
// container(s).
77
type SidecarParams struct {
8-
EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"`
8+
EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"`
9+
ExtraVolumeMounts []corev1.VolumeMount `json:"extraVolumeMounts,omitempty"`
910
}
1011

1112
func (sc *SidecarParams) ApplyTo(ctr *corev1.Container) {
1213
if sc == nil || ctr == nil {
1314
return
1415
}
1516
ctr.EnvFrom = append(ctr.EnvFrom, sc.EnvFrom...)
17+
ctr.VolumeMounts = append(ctr.VolumeMounts, sc.ExtraVolumeMounts...)
1618
}

internal/controller/scheduler/scheduler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,8 +498,8 @@ func (w *worker) Build(podSpec *corev1.PodSpec, skipCheckout bool, inputs buildI
498498
if c.Name == "" {
499499
c.Name = fmt.Sprintf("%s-%d", "sidecar", i)
500500
}
501-
c.VolumeMounts = append(c.VolumeMounts, volumeMounts...)
502501
w.cfg.DefaultSidecarParams.ApplyTo(&c)
502+
c.VolumeMounts = append(c.VolumeMounts, volumeMounts...)
503503
inputs.k8sPlugin.SidecarParams.ApplyTo(&c)
504504
c.EnvFrom = append(c.EnvFrom, inputs.k8sPlugin.GitEnvFrom...)
505505
podSpec.Containers = append(podSpec.Containers, c)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
agents:
2+
queue: "{{.queue}}"
3+
steps:
4+
- label: ":k8s: Write file to extraVolumeMount on command containers"
5+
key: write-file-to-extra-volume-mount-command
6+
plugins:
7+
- kubernetes:
8+
podSpec:
9+
containers:
10+
- image: alpine:latest
11+
command: ["sh"]
12+
args:
13+
- "-c"
14+
- "touch /tmp/extra-volume-mount-command/foo-$${BUILDKITE_JOB_ID}.txt"
15+
- image: alpine:latest
16+
command:
17+
- |-
18+
COUNT=0
19+
until [[ $$((COUNT++)) == 15 ]]; do
20+
[[ -f "/tmp/extra-volume-mount-command/foo-$${BUILDKITE_JOB_ID}.txt" ]] && break
21+
echo "⚠️ Waiting for /tmp/extra-volume-mount-command/foo-$${BUILDKITE_JOB_ID}.txt to be written..."
22+
sleep 1
23+
done
24+
25+
if ! [[ -f "/tmp/extra-volume-mount-command/foo-$${BUILDKITE_JOB_ID}.txt" ]]; then
26+
echo "⛔ /tmp/extra-volume-mount-command/foo-$${BUILDKITE_JOB_ID}.txt has not been written"
27+
exit 1
28+
fi
29+
30+
echo "✅ /tmp/extra-volume-mount-command/foo-$${BUILDKITE_JOB_ID}.txt has been written"
31+
rm -f "/tmp/extra-volume-mount-command/foo-$${BUILDKITE_JOB_ID}.txt"
32+
volumes:
33+
- name: host-volume
34+
hostPath:
35+
path: "/tmp/volumes/{{.queue}}"
36+
type: DirectoryOrCreate
37+
commandParams:
38+
extraVolumeMounts:
39+
- name: host-volume
40+
mountPath: /tmp/extra-volume-mount-command
41+
subPath: extra-volume-mount-command
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
agents:
2+
queue: "{{.queue}}"
3+
steps:
4+
- label: ":k8s: Write file to extraVolumeMount on sidecar containers"
5+
key: write-file-to-extra-volume-mount-sidecar
6+
plugins:
7+
- kubernetes:
8+
sidecars:
9+
- image: alpine:latest
10+
command: ["sh"]
11+
args:
12+
- "-c"
13+
- |-
14+
touch /tmp/extra-volume-mount-sidecar/pass-the-parcel
15+
rm -f "/tmp/extra-volume-mount/pass-the-parcel"
16+
mv /tmp/extra-volume-mount-sidecar/pass-the-parcel /tmp/extra-volume-mount/pass-the-parcel
17+
ls -lah /tmp/extra-volume-mount-sidecar
18+
ls -lah /tmp/extra-volume-mount
19+
podSpec:
20+
containers:
21+
- image: alpine:latest
22+
command:
23+
- |-
24+
COUNT=0
25+
until [[ $$((COUNT++)) == 15 ]]; do
26+
[[ -f "/tmp/extra-volume-mount/pass-the-parcel" ]] && break
27+
echo "⚠️ Waiting for my package to be delivered..."
28+
sleep 1
29+
done
30+
31+
if ! [[ -f "/tmp/extra-volume-mount/pass-the-parcel" ]]; then
32+
echo "⛔ My package has not been delivered!"
33+
exit 1
34+
fi
35+
36+
echo "✅ My package has been delivered!"
37+
rm -f "/tmp/extra-volume-mount/pass-the-parcel"
38+
volumes:
39+
- name: host-volume
40+
hostPath:
41+
path: "/tmp/volumes/{{.queue}}"
42+
type: DirectoryOrCreate
43+
sidecarParams:
44+
extraVolumeMounts:
45+
- name: host-volume
46+
mountPath: /tmp/extra-volume-mount-sidecar
47+
subPath: extra-volume-mount-sidecar
48+
extraVolumeMounts:
49+
- name: host-volume
50+
mountPath: /tmp/extra-volume-mount
51+
subPath: extra-volume-mount

internal/integration/integration_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,34 @@ func TestExtraVolumeMounts(t *testing.T) {
373373
tc.AssertSuccess(ctx, build)
374374
}
375375

376+
func TestExtraVolumeMountsCommandContainers(t *testing.T) {
377+
tc := testcase{
378+
T: t,
379+
Fixture: "extra-volume-mounts-command.yaml",
380+
Repo: repoHTTP,
381+
GraphQL: api.NewClient(cfg.BuildkiteToken, cfg.GraphQLEndpoint),
382+
}.Init()
383+
ctx := context.Background()
384+
pipelineID := tc.PrepareQueueAndPipelineWithCleanup(ctx)
385+
tc.StartController(ctx, cfg)
386+
build := tc.TriggerBuild(ctx, pipelineID)
387+
tc.AssertSuccess(ctx, build)
388+
}
389+
390+
func TestExtraVolumeMountsSidecars(t *testing.T) {
391+
tc := testcase{
392+
T: t,
393+
Fixture: "extra-volume-mounts-sidecar.yaml",
394+
Repo: repoHTTP,
395+
GraphQL: api.NewClient(cfg.BuildkiteToken, cfg.GraphQLEndpoint),
396+
}.Init()
397+
ctx := context.Background()
398+
pipelineID := tc.PrepareQueueAndPipelineWithCleanup(ctx)
399+
tc.StartController(ctx, cfg)
400+
build := tc.TriggerBuild(ctx, pipelineID)
401+
tc.AssertSuccess(ctx, build)
402+
}
403+
376404
func TestInvalidPodSpec(t *testing.T) {
377405
tc := testcase{
378406
T: t,

internal/integration/testcase_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ type testcase struct {
4242
// k8s labels are limited to length 63, we use the pipeline name as a label.
4343
// So we sometimes need to limit the length of the pipeline name too.
4444
func (t *testcase) ShortPipelineName() string {
45-
return t.PipelineName[:min(len(t.PipelineName), 63)]
45+
return strings.Trim(t.PipelineName[:min(len(t.PipelineName), 63)], "-")
4646
}
4747

4848
func (t testcase) Init() testcase {

0 commit comments

Comments
 (0)