github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/controllerutil/volume_util_test.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  This file is part of KubeBlocks project
     5  
     6  This program is free software: you can redistribute it and/or modify
     7  it under the terms of the GNU Affero General Public License as published by
     8  the Free Software Foundation, either version 3 of the License, or
     9  (at your option) any later version.
    10  
    11  This program is distributed in the hope that it will be useful
    12  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  GNU Affero General Public License for more details.
    15  
    16  You should have received a copy of the GNU Affero General Public License
    17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18  */
    19  
    20  package controllerutil
    21  
    22  import (
    23  	. "github.com/onsi/ginkgo/v2"
    24  	. "github.com/onsi/gomega"
    25  
    26  	appsv1 "k8s.io/api/apps/v1"
    27  	corev1 "k8s.io/api/core/v1"
    28  
    29  	appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1"
    30  )
    31  
    32  var _ = Describe("lifecycle_utils", func() {
    33  
    34  	Context("has the checkAndUpdatePodVolumes function which generates Pod Volumes for mounting ConfigMap objects", func() {
    35  		var sts appsv1.StatefulSet
    36  		var volumes map[string]appsv1alpha1.ComponentTemplateSpec
    37  		BeforeEach(func() {
    38  			sts = appsv1.StatefulSet{
    39  				Spec: appsv1.StatefulSetSpec{
    40  					Template: corev1.PodTemplateSpec{
    41  						Spec: corev1.PodSpec{
    42  							Volumes: []corev1.Volume{
    43  								{
    44  									Name: "data",
    45  									VolumeSource: corev1.VolumeSource{
    46  										EmptyDir: &corev1.EmptyDirVolumeSource{},
    47  									},
    48  								},
    49  							},
    50  							Containers: []corev1.Container{
    51  								{
    52  									Name:            "mysql",
    53  									Image:           "docker.io/apecloud/apecloud-mysql-server:latest",
    54  									ImagePullPolicy: "IfNotPresent",
    55  									VolumeMounts: []corev1.VolumeMount{
    56  										{
    57  											Name:      "data",
    58  											MountPath: "/data",
    59  										},
    60  									},
    61  								},
    62  							},
    63  						},
    64  					},
    65  				},
    66  			}
    67  			volumes = make(map[string]appsv1alpha1.ComponentTemplateSpec)
    68  
    69  		})
    70  
    71  		It("should succeed in corner case where input volumes is nil, which means no volume is added", func() {
    72  			ps := &sts.Spec.Template.Spec
    73  			err := CreateOrUpdatePodVolumes(ps, volumes)
    74  			Expect(err).Should(BeNil())
    75  			Expect(len(ps.Volumes)).To(Equal(1))
    76  		})
    77  
    78  		It("should succeed in normal test case, where one volume is added", func() {
    79  			volumes["my_config"] = appsv1alpha1.ComponentTemplateSpec{
    80  				Name:        "myConfig",
    81  				TemplateRef: "myConfig",
    82  				VolumeName:  "myConfigVolume",
    83  			}
    84  			ps := &sts.Spec.Template.Spec
    85  			err := CreateOrUpdatePodVolumes(ps, volumes)
    86  			Expect(err).Should(BeNil())
    87  			Expect(len(ps.Volumes)).To(Equal(2))
    88  		})
    89  
    90  		It("should succeed in normal test case, where two volumes are added", func() {
    91  			volumes["my_config"] = appsv1alpha1.ComponentTemplateSpec{
    92  				Name:        "myConfig",
    93  				TemplateRef: "myConfig",
    94  				VolumeName:  "myConfigVolume",
    95  			}
    96  			volumes["my_config1"] = appsv1alpha1.ComponentTemplateSpec{
    97  				Name:        "myConfig",
    98  				TemplateRef: "myConfig",
    99  				VolumeName:  "myConfigVolume2",
   100  			}
   101  			ps := &sts.Spec.Template.Spec
   102  			err := CreateOrUpdatePodVolumes(ps, volumes)
   103  			Expect(err).Should(BeNil())
   104  			Expect(len(ps.Volumes)).To(Equal(3))
   105  		})
   106  
   107  		It("should fail if updated volume doesn't contain ConfigMap", func() {
   108  			const (
   109  				cmName            = "my_config_for_test"
   110  				replicaVolumeName = "mytest-cm-volume_for_test"
   111  			)
   112  			sts.Spec.Template.Spec.Volumes = append(sts.Spec.Template.Spec.Volumes,
   113  				corev1.Volume{
   114  					Name: replicaVolumeName,
   115  					VolumeSource: corev1.VolumeSource{
   116  						EmptyDir: &corev1.EmptyDirVolumeSource{},
   117  					},
   118  				})
   119  			volumes[cmName] = appsv1alpha1.ComponentTemplateSpec{
   120  				Name:        "configTplName",
   121  				TemplateRef: "configTplName",
   122  				VolumeName:  replicaVolumeName,
   123  			}
   124  			ps := &sts.Spec.Template.Spec
   125  			Expect(CreateOrUpdatePodVolumes(ps, volumes)).ShouldNot(Succeed())
   126  		})
   127  
   128  		It("should succeed if updated volume contains ConfigMap", func() {
   129  			const (
   130  				cmName            = "my_config_for_isv"
   131  				replicaVolumeName = "mytest-cm-volume_for_isv"
   132  			)
   133  
   134  			// mock clusterdefinition has volume
   135  			sts.Spec.Template.Spec.Volumes = append(sts.Spec.Template.Spec.Volumes,
   136  				corev1.Volume{
   137  					Name: replicaVolumeName,
   138  					VolumeSource: corev1.VolumeSource{
   139  						ConfigMap: &corev1.ConfigMapVolumeSource{
   140  							LocalObjectReference: corev1.LocalObjectReference{Name: "anything"},
   141  						},
   142  					},
   143  				})
   144  
   145  			volumes[cmName] = appsv1alpha1.ComponentTemplateSpec{
   146  				Name:        "configTplName",
   147  				TemplateRef: "configTplName",
   148  				VolumeName:  replicaVolumeName,
   149  			}
   150  			ps := &sts.Spec.Template.Spec
   151  			err := CreateOrUpdatePodVolumes(ps, volumes)
   152  			Expect(err).Should(BeNil())
   153  			Expect(len(sts.Spec.Template.Spec.Volumes)).To(Equal(2))
   154  			volume := GetVolumeMountName(sts.Spec.Template.Spec.Volumes, cmName)
   155  			Expect(volume).ShouldNot(BeNil())
   156  			Expect(volume.ConfigMap).ShouldNot(BeNil())
   157  			Expect(volume.ConfigMap.Name).Should(BeEquivalentTo(cmName))
   158  			Expect(volume.Name).Should(BeEquivalentTo(replicaVolumeName))
   159  		})
   160  
   161  	})
   162  })