@@ -16,7 +16,9 @@ import (
1616 . "github.com/onsi/ginkgo/v2"
1717 . "github.com/onsi/gomega"
1818 corev1 "k8s.io/api/core/v1"
19+ storagev1 "k8s.io/api/storage/v1"
1920 "k8s.io/apimachinery/pkg/api/meta"
21+ "k8s.io/apimachinery/pkg/api/resource"
2022 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2123 "k8s.io/apimachinery/pkg/labels"
2224 "k8s.io/apimachinery/pkg/runtime"
@@ -254,6 +256,91 @@ var _ = Describe("ClickHouse controller", Label("clickhouse"), func() {
254256 ClickHouseRWChecks (ctx , & cr , new (0 ))
255257 })
256258
259+ It ("should resize PVCs on every replica" , func (ctx context.Context ) {
260+ By ("creating an expandable StorageClass" )
261+
262+ sc := & storagev1.StorageClass {
263+ ObjectMeta : metav1.ObjectMeta {
264+ Name : fmt .Sprintf ("expandable-%d" , rand .Uint32 ()), //nolint:gosec
265+ },
266+ Provisioner : "rancher.io/local-path" ,
267+ VolumeBindingMode : new (storagev1.VolumeBindingWaitForFirstConsumer ),
268+ AllowVolumeExpansion : new (true ),
269+ ReclaimPolicy : new (corev1.PersistentVolumeReclaimDelete ),
270+ }
271+ Expect (k8sClient .Create (ctx , sc )).To (Succeed ())
272+ DeferCleanup (func (ctx context.Context ) {
273+ Expect (client .IgnoreNotFound (k8sClient .Delete (ctx , sc ))).To (Succeed ())
274+ })
275+
276+ cr := v1.ClickHouseCluster {
277+ ObjectMeta : metav1.ObjectMeta {
278+ Namespace : ns ,
279+ Name : fmt .Sprintf ("pvc-resize-%d" , rand .Uint32 ()), //nolint:gosec
280+ },
281+ Spec : v1.ClickHouseClusterSpec {
282+ Replicas : new (int32 (3 )),
283+ ContainerTemplate : v1.ContainerTemplateSpec {
284+ Image : v1.ContainerImage {Tag : BaseVersion },
285+ },
286+ KeeperClusterRef : v1.KeeperClusterReference {
287+ Name : keeper .Name ,
288+ },
289+ DataVolumeClaimSpec : & corev1.PersistentVolumeClaimSpec {
290+ AccessModes : []corev1.PersistentVolumeAccessMode {corev1 .ReadWriteOnce },
291+ StorageClassName : & sc .Name ,
292+ Resources : corev1.VolumeResourceRequirements {
293+ Requests : corev1.ResourceList {
294+ corev1 .ResourceStorage : resource .MustParse ("1Gi" ),
295+ },
296+ },
297+ },
298+ },
299+ }
300+
301+ By ("creating cluster CR with 3 replicas" )
302+ Expect (k8sClient .Create (ctx , & cr )).To (Succeed ())
303+ DeferCleanup (func (ctx context.Context ) {
304+ By ("deleting cluster CR" )
305+ Expect (k8sClient .Delete (ctx , & cr )).To (Succeed ())
306+ })
307+
308+ WaitClickHouseUpdatedAndReady (ctx , & cr , 3 * time .Minute , false )
309+
310+ By ("recording initial PVC sizes" )
311+
312+ listOpts := []client.ListOption {
313+ client .InNamespace (ns ),
314+ client.MatchingLabels {controllerutil .LabelAppKey : cr .SpecificName ()},
315+ }
316+
317+ var pvcs corev1.PersistentVolumeClaimList
318+ Expect (k8sClient .List (ctx , & pvcs , listOpts ... )).To (Succeed ())
319+ Expect (pvcs .Items ).To (HaveLen (int (cr .Replicas ())), "expected one PVC per replica" )
320+
321+ for _ , pvc := range pvcs .Items {
322+ Expect (pvc .Spec .Resources .Requests .Storage ().Cmp (
323+ * cr .Spec .DataVolumeClaimSpec .Resources .Requests .Storage ())).To (Equal (0 ),
324+ "actual: %v, spec: %v" , pvc .Spec .Resources , cr .Spec .DataVolumeClaimSpec .Resources )
325+ }
326+
327+ By ("upgrading storage request from 1Gi to 2Gi" )
328+
329+ Expect (k8sClient .Get (ctx , cr .NamespacedName (), & cr )).To (Succeed ())
330+ cr .Spec .DataVolumeClaimSpec .Resources .Requests [corev1 .ResourceStorage ] = resource .MustParse ("2Gi" )
331+ Expect (k8sClient .Update (ctx , & cr )).To (Succeed ())
332+ WaitClickHouseUpdatedAndReady (ctx , & cr , 3 * time .Minute , false )
333+
334+ Expect (k8sClient .List (ctx , & pvcs , listOpts ... )).To (Succeed ())
335+ Expect (pvcs .Items ).To (HaveLen (int (cr .Replicas ())), "expected one PVC per replica" )
336+
337+ for _ , pvc := range pvcs .Items {
338+ Expect (pvc .Spec .Resources .Requests .Storage ().Cmp (
339+ * cr .Spec .DataVolumeClaimSpec .Resources .Requests .Storage ())).To (Equal (0 ),
340+ "actual: %v, spec: %v" , pvc .Spec .Resources , cr .Spec .DataVolumeClaimSpec .Resources )
341+ }
342+ })
343+
257344 It ("should correctly configure access" , func (ctx context.Context ) {
258345 var (
259346 password = fmt .Sprintf ("test-password-%d" , rand .Uint32 ()) //nolint:gosec
0 commit comments