Skip to content

Commit d42f801

Browse files
committed
feat: add support for volumes and volumeMounts in Image resource, update conversion logic, and enable custom build pod PVCs for kpack builds
1 parent 5105ae3 commit d42f801

5 files changed

Lines changed: 82 additions & 10 deletions

File tree

pkg/apis/build/v1alpha1/image_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ type ImageBuild struct {
6363
// +listType
6464
Env []corev1.EnvVar `json:"env,omitempty"`
6565
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
66+
// +listType
67+
Volumes []corev1.Volume `json:"volumes,omitempty"`
68+
// +listType
69+
VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"`
6670
}
6771

6872
// +k8s:openapi-gen=true

pkg/apis/build/v1alpha2/build_pod_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2458,6 +2458,51 @@ func testBuildPod(t *testing.T, when spec.G, it spec.S) {
24582458
)
24592459
})
24602460
})
2461+
2462+
when("custom volumes and mounts", func() {
2463+
it("attaches user-supplied volumes and mounts to all init containers", func() {
2464+
build.Spec.Volumes = []corev1.Volume{
2465+
{
2466+
Name: "sqlite-pvc",
2467+
VolumeSource: corev1.VolumeSource{
2468+
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
2469+
ClaimName: "my-sqlite-pvc",
2470+
},
2471+
},
2472+
},
2473+
}
2474+
build.Spec.VolumeMounts = []corev1.VolumeMount{
2475+
{
2476+
Name: "sqlite-pvc",
2477+
MountPath: "/workspace/sqlite",
2478+
ReadOnly: false,
2479+
},
2480+
}
2481+
2482+
pod, err := build.BuildPod(config, buildContext)
2483+
require.NoError(t, err)
2484+
2485+
// Check that the volume is present in the pod spec
2486+
found := false
2487+
for _, v := range pod.Spec.Volumes {
2488+
if v.Name == "sqlite-pvc" && v.VolumeSource.PersistentVolumeClaim != nil && v.VolumeSource.PersistentVolumeClaim.ClaimName == "my-sqlite-pvc" {
2489+
found = true
2490+
}
2491+
}
2492+
assert.True(t, found, "sqlite-pvc volume should be present in pod spec")
2493+
2494+
// Check that the mount is present in all init containers
2495+
for _, c := range pod.Spec.InitContainers {
2496+
foundMount := false
2497+
for _, m := range c.VolumeMounts {
2498+
if m.Name == "sqlite-pvc" && m.MountPath == "/workspace/sqlite" {
2499+
foundMount = true
2500+
}
2501+
}
2502+
assert.True(t, foundMount, "sqlite-pvc mount should be present in init container %s", c.Name)
2503+
}
2504+
})
2505+
})
24612506
})
24622507
}
24632508

pkg/apis/build/v1alpha2/build_validation.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func (b *Build) Validate(ctx context.Context) *apis.FieldError {
2525
}
2626

2727
func (bs *BuildSpec) Validate(ctx context.Context) *apis.FieldError {
28-
return validate.ListNotEmpty(bs.Tags, "tags").
28+
err := validate.ListNotEmpty(bs.Tags, "tags").
2929
Also(validate.Tags(bs.Tags, "tags")).
3030
Also(bs.Cache.Validate(ctx).ViaField("cache")).
3131
Also(bs.Builder.Validate(ctx).ViaField("builder")).
@@ -36,6 +36,25 @@ func (bs *BuildSpec) Validate(ctx context.Context) *apis.FieldError {
3636
Also(validateCnbBindings(ctx, bs.CNBBindings).ViaField("cnbBindings")).
3737
Also(bs.validateNodeSelector(ctx)).
3838
Also(validateNotary(ctx, bs.Notary).ViaField("notary"))
39+
40+
// Validate that all volumeMounts refer to a defined volume
41+
volumeNames := make(map[string]struct{})
42+
for _, v := range bs.Volumes {
43+
if _, exists := volumeNames[v.Name]; exists {
44+
err = err.Also(apis.ErrGeneric("duplicate volume name", "volumes", v.Name))
45+
}
46+
volumeNames[v.Name] = struct{}{}
47+
}
48+
for i, m := range bs.VolumeMounts {
49+
if m.Name == "" {
50+
err = err.Also(apis.ErrMissingField("name").ViaField("volumeMounts").ViaIndex(i))
51+
continue
52+
}
53+
if _, ok := volumeNames[m.Name]; !ok {
54+
err = err.Also(apis.ErrInvalidValue(m.Name, "volumeMounts").ViaIndex(i).Also(apis.ErrGeneric("volumeMount refers to undefined volume", "volumeMounts", m.Name)))
55+
}
56+
}
57+
return err
3958
}
4059

4160
func resourceCreatedByKpackController(info *authv1.UserInfo) bool {

pkg/apis/build/v1alpha2/image_conversion.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ func (is *ImageSpec) convertTo(to *v1alpha1.ImageSpec) {
7676
to.Build.Env = is.Build.Env
7777
to.Build.Resources = is.Build.Resources
7878
to.Build.Bindings = is.Build.CNBBindings
79+
to.Build.VolumeMounts = is.Build.VolumeMounts
80+
to.Build.Volumes = is.Build.Volumes
7981
}
8082
}
8183

@@ -283,6 +285,8 @@ func (is *ImageSpec) convertFrom(from *v1alpha1.ImageSpec) {
283285
is.Build.Env = from.Build.Env
284286
is.Build.Resources = from.Build.Resources
285287
is.Build.CNBBindings = from.Build.Bindings
288+
is.Build.VolumeMounts = from.Build.VolumeMounts
289+
is.Build.Volumes = from.Build.Volumes
286290
}
287291
}
288292

pkg/apis/build/v1alpha2/image_types.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,15 @@ type ImageBuild struct {
7272
Env []corev1.EnvVar `json:"env,omitempty"`
7373
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
7474
// +listType
75-
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
76-
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
77-
Affinity *corev1.Affinity `json:"affinity,omitempty"`
78-
RuntimeClassName *string `json:"runtimeClassName,omitempty"`
79-
SchedulerName string `json:"schedulerName,omitempty"`
80-
BuildTimeout *int64 `json:"buildTimeout,omitempty"`
81-
CreationTime string `json:"creationTime,omitempty"`
82-
VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"`
83-
Volumes []corev1.Volume `json:"volumes,omitempty"`
75+
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
76+
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
77+
Affinity *corev1.Affinity `json:"affinity,omitempty"`
78+
RuntimeClassName *string `json:"runtimeClassName,omitempty"`
79+
SchedulerName string `json:"schedulerName,omitempty"`
80+
BuildTimeout *int64 `json:"buildTimeout,omitempty"`
81+
CreationTime string `json:"creationTime,omitempty"`
82+
VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"`
83+
Volumes []corev1.Volume `json:"volumes,omitempty"`
8484
}
8585

8686
// +k8s:openapi-gen=true

0 commit comments

Comments
 (0)