diff --git a/apis/apps/v1alpha1/cluster_types.go b/apis/apps/v1alpha1/cluster_types.go index 33fdaad0356..985dd6e483d 100644 --- a/apis/apps/v1alpha1/cluster_types.go +++ b/apis/apps/v1alpha1/cluster_types.go @@ -414,10 +414,12 @@ type ClusterComponentVolumeClaimTemplate struct { } func (r *ClusterComponentVolumeClaimTemplate) toVolumeClaimTemplate() corev1.PersistentVolumeClaimTemplate { - t := corev1.PersistentVolumeClaimTemplate{} - t.ObjectMeta.Name = r.Name - t.Spec = r.Spec.ToV1PersistentVolumeClaimSpec() - return t + return corev1.PersistentVolumeClaimTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Name: r.Name, + }, + Spec: r.Spec.ToV1PersistentVolumeClaimSpec(), + } } type PersistentVolumeClaimSpec struct { @@ -438,12 +440,9 @@ type PersistentVolumeClaimSpec struct { // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1. // +optional StorageClassName *string `json:"storageClassName,omitempty" protobuf:"bytes,5,opt,name=storageClassName"` - // TODO: - // // preferStorageClassNames added support specifying storageclasses.storage.k8s.io names, in order - // // to adapt multi-cloud deployment, where storageclasses are all distinctly different among clouds. - // // +listType=set - // // +optional - // PreferSCNames []string `json:"preferStorageClassNames,omitempty"` + // volumeMode defines what type of volume is required by the claim. + // +optional + VolumeMode *corev1.PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,6,opt,name=volumeMode,casttype=PersistentVolumeMode"` } // ToV1PersistentVolumeClaimSpec converts to corev1.PersistentVolumeClaimSpec. @@ -451,21 +450,21 @@ func (r *PersistentVolumeClaimSpec) ToV1PersistentVolumeClaimSpec() corev1.Persi return corev1.PersistentVolumeClaimSpec{ AccessModes: r.AccessModes, Resources: r.Resources, - StorageClassName: r.GetStorageClassName(viper.GetString(constant.CfgKeyDefaultStorageClass)), + StorageClassName: r.getStorageClassName(viper.GetString(constant.CfgKeyDefaultStorageClass)), + VolumeMode: r.VolumeMode, } } -// GetStorageClassName returns PersistentVolumeClaimSpec.StorageClassName if a value is assigned; otherwise, +// getStorageClassName returns PersistentVolumeClaimSpec.StorageClassName if a value is assigned; otherwise, // it returns preferSC argument. -func (r *PersistentVolumeClaimSpec) GetStorageClassName(preferSC string) *string { +func (r *PersistentVolumeClaimSpec) getStorageClassName(preferSC string) *string { if r.StorageClassName != nil && *r.StorageClassName != "" { return r.StorageClassName } - - if preferSC == "" { - return nil + if preferSC != "" { + return &preferSC } - return &preferSC + return nil } type Affinity struct { diff --git a/apis/apps/v1alpha1/cluster_types_test.go b/apis/apps/v1alpha1/cluster_types_test.go index 0f991b0883c..205dd990f51 100644 --- a/apis/apps/v1alpha1/cluster_types_test.go +++ b/apis/apps/v1alpha1/cluster_types_test.go @@ -24,6 +24,7 @@ import ( . "github.com/onsi/gomega" "github.com/spf13/viper" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/yaml" @@ -31,7 +32,6 @@ import ( ) var _ = Describe("", func() { - It("test GetMinAvailable", func() { prefer := intstr.IntOrString{} clusterCompSpec := &ClusterComponentSpec{} @@ -56,7 +56,8 @@ var _ = Describe("", func() { pvcSpec := r.ToV1PersistentVolumeClaimSpec() Expect(pvcSpec.AccessModes).Should(BeEquivalentTo(r.AccessModes)) Expect(pvcSpec.Resources).Should(BeEquivalentTo(r.Resources)) - Expect(pvcSpec.StorageClassName).Should(BeEquivalentTo(r.GetStorageClassName(viper.GetString(constant.CfgKeyDefaultStorageClass)))) + Expect(pvcSpec.StorageClassName).Should(BeEquivalentTo(r.getStorageClassName(viper.GetString(constant.CfgKeyDefaultStorageClass)))) + Expect(pvcSpec.VolumeMode).Should(BeEquivalentTo(r.VolumeMode)) }) It("test ToV1PersistentVolumeClaimSpec with default storage class", func() { @@ -68,14 +69,24 @@ var _ = Describe("", func() { viper.Set(constant.CfgKeyDefaultStorageClass, "") }) - It("test GetStorageClassName", func() { + It("test ToV1PersistentVolumeClaimSpec with volume mode", func() { + for _, mode := range []corev1.PersistentVolumeMode{corev1.PersistentVolumeBlock, corev1.PersistentVolumeFilesystem} { + r := PersistentVolumeClaimSpec{ + VolumeMode: &mode, + } + pvcSpec := r.ToV1PersistentVolumeClaimSpec() + Expect(pvcSpec.VolumeMode).Should(BeEquivalentTo(r.VolumeMode)) + } + }) + + It("test getStorageClassName", func() { preferSC := "prefer-sc" r := PersistentVolumeClaimSpec{} r.StorageClassName = nil - Expect(r.GetStorageClassName(preferSC)).Should(BeEquivalentTo(&preferSC)) + Expect(r.getStorageClassName(preferSC)).Should(BeEquivalentTo(&preferSC)) scName := "test-sc" r.StorageClassName = &scName - Expect(r.GetStorageClassName(preferSC)).Should(BeEquivalentTo(&scName)) + Expect(r.getStorageClassName(preferSC)).Should(BeEquivalentTo(&scName)) }) It("test IsDeleting", func() { diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index 7a22043804f..feda2d5696f 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -2695,6 +2695,11 @@ func (in *PersistentVolumeClaimSpec) DeepCopyInto(out *PersistentVolumeClaimSpec *out = new(string) **out = **in } + if in.VolumeMode != nil { + in, out := &in.VolumeMode, &out.VolumeMode + *out = new(v1.PersistentVolumeMode) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersistentVolumeClaimSpec. diff --git a/config/crd/bases/apps.kubeblocks.io_clusters.yaml b/config/crd/bases/apps.kubeblocks.io_clusters.yaml index 449998a3cf7..5fb5188f913 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusters.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusters.yaml @@ -562,6 +562,10 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1.' type: string + volumeMode: + description: volumeMode defines what type of volume + is required by the claim. + type: string type: object required: - name diff --git a/controllers/apps/components/base_stateful.go b/controllers/apps/components/base_stateful.go index c21a1de0add..97b27b8608a 100644 --- a/controllers/apps/components/base_stateful.go +++ b/controllers/apps/components/base_stateful.go @@ -220,9 +220,9 @@ func (c *statefulComponentBase) Restart(reqCtx intctrlutil.RequestCtx, cli clien func (c *statefulComponentBase) ExpandVolume(reqCtx intctrlutil.RequestCtx, cli client.Client) error { for _, vct := range c.runningWorkload.Spec.VolumeClaimTemplates { var proto *corev1.PersistentVolumeClaimTemplate - for _, v := range c.Component.VolumeClaimTemplates { + for i, v := range c.Component.VolumeClaimTemplates { if v.Name == vct.Name { - proto = &v + proto = &c.Component.VolumeClaimTemplates[i] break } } diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml index 449998a3cf7..5fb5188f913 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml @@ -562,6 +562,10 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1.' type: string + volumeMode: + description: volumeMode defines what type of volume + is required by the claim. + type: string type: object required: - name