Skip to content

Commit bb2697e

Browse files
committed
Add tests for using ImageVolumeSource in AdditionalVolume feature.
1 parent 5bd40b2 commit bb2697e

File tree

3 files changed

+214
-0
lines changed

3 files changed

+214
-0
lines changed

internal/testing/validation/postgrescluster_test.go

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import (
99
"testing"
1010

1111
"gotest.tools/v3/assert"
12+
apierrors "k8s.io/apimachinery/pkg/api/errors"
13+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1214
"sigs.k8s.io/controller-runtime/pkg/client"
15+
"sigs.k8s.io/yaml"
1316

1417
"github.com/crunchydata/postgres-operator/internal/testing/require"
1518
v1 "github.com/crunchydata/postgres-operator/pkg/apis/postgres-operator.crunchydata.com/v1"
@@ -103,3 +106,141 @@ func TestPostgresUserInterfaceAcrossVersions(t *testing.T) {
103106
"userInterface not available in v1")
104107
})
105108
}
109+
110+
func TestAdditionalVolumes(t *testing.T) {
111+
ctx := context.Background()
112+
cc := require.KubernetesAtLeast(t, "1.30")
113+
t.Parallel()
114+
115+
namespace := require.Namespace(t, cc)
116+
base := v1beta1.NewPostgresCluster()
117+
118+
base.Namespace = namespace.Name
119+
base.Name = "image-volume-source-test"
120+
// required fields
121+
require.UnmarshalInto(t, &base.Spec, `{
122+
postgresVersion: 16,
123+
instances: [{
124+
dataVolumeClaimSpec: {
125+
accessModes: [ReadWriteOnce],
126+
resources: { requests: { storage: 1Mi } },
127+
},
128+
}],
129+
}`)
130+
131+
assert.NilError(t, cc.Create(ctx, base.DeepCopy(), client.DryRunAll),
132+
"expected this base to be valid")
133+
134+
var unstructuredBase unstructured.Unstructured
135+
require.UnmarshalInto(t, &unstructuredBase, require.Value(yaml.Marshal(base)))
136+
137+
t.Run("Cannot set both image and claimName", func(t *testing.T) {
138+
tmp := unstructuredBase.DeepCopy()
139+
140+
require.UnmarshalIntoField(t, tmp, `[{
141+
dataVolumeClaimSpec: {
142+
accessModes: [ReadWriteOnce],
143+
resources: { requests: { storage: 1Mi } },
144+
},
145+
volumes: {
146+
additional: [{
147+
name: "test",
148+
claimName: "pvc-claim",
149+
image: {
150+
reference: "test-image",
151+
pullPolicy: Always
152+
},
153+
readOnly: true
154+
}]
155+
}
156+
}]`, "spec", "instances")
157+
err := cc.Create(ctx, tmp.DeepCopy(), client.DryRunAll)
158+
assert.Assert(t, apierrors.IsInvalid(err))
159+
assert.ErrorContains(t, err, "you must set only one of image or claimName")
160+
})
161+
162+
t.Run("Cannot set readOnly to false when using image volume", func(t *testing.T) {
163+
tmp := unstructuredBase.DeepCopy()
164+
165+
require.UnmarshalIntoField(t, tmp, `[{
166+
dataVolumeClaimSpec: {
167+
accessModes: [ReadWriteOnce],
168+
resources: { requests: { storage: 1Mi } },
169+
},
170+
volumes: {
171+
additional: [{
172+
name: "test",
173+
image: {
174+
reference: "test-image",
175+
pullPolicy: Always
176+
},
177+
readOnly: false
178+
}]
179+
}
180+
}]`, "spec", "instances")
181+
err := cc.Create(ctx, tmp.DeepCopy(), client.DryRunAll)
182+
assert.Assert(t, apierrors.IsInvalid(err))
183+
assert.ErrorContains(t, err, "readOnly cannot be set false when using an ImageVolumeSource")
184+
})
185+
186+
t.Run("Reference must be set when using image volume", func(t *testing.T) {
187+
tmp := unstructuredBase.DeepCopy()
188+
189+
require.UnmarshalIntoField(t, tmp, `[{
190+
dataVolumeClaimSpec: {
191+
accessModes: [ReadWriteOnce],
192+
resources: { requests: { storage: 1Mi } },
193+
},
194+
volumes: {
195+
additional: [{
196+
name: "test",
197+
image: {
198+
pullPolicy: Always
199+
},
200+
readOnly: true
201+
}]
202+
}
203+
}]`, "spec", "instances")
204+
err := cc.Create(ctx, tmp.DeepCopy(), client.DryRunAll)
205+
assert.Assert(t, apierrors.IsInvalid(err))
206+
assert.ErrorContains(t, err, "if using an ImageVolumeSource, you must set a reference")
207+
})
208+
209+
t.Run("ReadOnly can be omitted or set true when using image volume", func(t *testing.T) {
210+
tmp := unstructuredBase.DeepCopy()
211+
212+
require.UnmarshalIntoField(t, tmp, `[{
213+
name: "test-instance",
214+
dataVolumeClaimSpec: {
215+
accessModes: [ReadWriteOnce],
216+
resources: { requests: { storage: 1Mi } },
217+
},
218+
volumes: {
219+
additional: [{
220+
name: "test",
221+
image: {
222+
reference: "test-image",
223+
pullPolicy: Always
224+
},
225+
}]
226+
}
227+
}, {
228+
name: "another-instance",
229+
dataVolumeClaimSpec: {
230+
accessModes: [ReadWriteOnce],
231+
resources: { requests: { storage: 1Mi } },
232+
},
233+
volumes: {
234+
additional: [{
235+
name: "another",
236+
image: {
237+
reference: "another-image",
238+
pullPolicy: Always
239+
},
240+
readOnly: true
241+
}]
242+
}
243+
}]`, "spec", "instances")
244+
assert.NilError(t, cc.Create(ctx, tmp.DeepCopy(), client.DryRunAll))
245+
})
246+
}

internal/util/volumes_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,60 @@ func TestAddAdditionalVolumesAndMounts(t *testing.T) {
207207
claimName: required
208208
readOnly: true`,
209209
expectedMissing: []string{},
210+
}, {
211+
tcName: "image volumes - readOnly overridden true",
212+
additionalVolumes: []v1beta1.AdditionalVolume{{
213+
Containers: []string{"database"},
214+
Image: &corev1.ImageVolumeSource{
215+
Reference: "some-image-name",
216+
PullPolicy: corev1.PullAlways,
217+
},
218+
Name: "required",
219+
ReadOnly: true,
220+
}, {
221+
Image: &corev1.ImageVolumeSource{
222+
Reference: "another-image-name",
223+
PullPolicy: corev1.PullAlways,
224+
},
225+
Name: "other",
226+
ReadOnly: false,
227+
}},
228+
expectedContainers: `- name: database
229+
resources: {}
230+
volumeMounts:
231+
- mountPath: /volumes/required
232+
name: volumes-required
233+
readOnly: true
234+
- mountPath: /volumes/other
235+
name: volumes-other
236+
readOnly: true
237+
- name: other
238+
resources: {}
239+
volumeMounts:
240+
- mountPath: /volumes/other
241+
name: volumes-other
242+
readOnly: true`,
243+
expectedInitContainers: `- name: startup
244+
resources: {}
245+
volumeMounts:
246+
- mountPath: /volumes/other
247+
name: volumes-other
248+
readOnly: true
249+
- name: config
250+
resources: {}
251+
volumeMounts:
252+
- mountPath: /volumes/other
253+
name: volumes-other
254+
readOnly: true`,
255+
expectedVolumes: `- image:
256+
pullPolicy: Always
257+
reference: some-image-name
258+
name: volumes-required
259+
- image:
260+
pullPolicy: Always
261+
reference: another-image-name
262+
name: volumes-other`,
263+
expectedMissing: []string{},
210264
}}
211265

212266
for _, tc := range testCases {

pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,25 @@ func TestAdditionalVolumeAsVolume(t *testing.T) {
4545
assert.DeepEqual(t, out, expected)
4646
})
4747
})
48+
49+
t.Run("Image", func(t *testing.T) {
50+
in := v1beta1.AdditionalVolume{Image: &corev1.ImageVolumeSource{
51+
Reference: "jkl;",
52+
PullPolicy: corev1.PullAlways,
53+
}}
54+
out := in.AsVolume("asdf")
55+
56+
var expected corev1.Volume
57+
assert.NilError(t, yaml.Unmarshal([]byte(`{
58+
name: asdf,
59+
image: {
60+
reference: jkl;,
61+
pullPolicy: Always,
62+
},
63+
}`), &expected))
64+
65+
assert.DeepEqual(t, out, expected)
66+
})
4867
}
4968

5069
func TestDurationAsDuration(t *testing.T) {

0 commit comments

Comments
 (0)