From a00b17e2d9f4820e58c07aac2af569523004cd74 Mon Sep 17 00:00:00 2001 From: sophon Date: Fri, 13 Oct 2023 11:50:28 +0800 Subject: [PATCH 1/6] feat: add UserResourceRefs for cluster.spec.ComponentSpecs api --- apis/apps/v1alpha1/cluster_types.go | 55 +++++++++++ apis/apps/v1alpha1/zz_generated.deepcopy.go | 54 ++++++++++ .../bases/apps.kubeblocks.io_clusters.yaml | 98 +++++++++++++++++++ .../crds/apps.kubeblocks.io_clusters.yaml | 98 +++++++++++++++++++ 4 files changed, 305 insertions(+) diff --git a/apis/apps/v1alpha1/cluster_types.go b/apis/apps/v1alpha1/cluster_types.go index dec68f06800..cdacedb1fe2 100644 --- a/apis/apps/v1alpha1/cluster_types.go +++ b/apis/apps/v1alpha1/cluster_types.go @@ -177,6 +177,57 @@ type ClusterStorage struct { Size resource.Quantity `json:"size,omitempty"` } +type ResourceRefMount struct { + // name is the name of the referenced the Configmap/Secret object. + // +kubebuilder:validation:Required + // +kubebuilder:validation:MaxLength=63 + // +kubebuilder:validation:Pattern:=`^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$` + Name string `json:"name"` + + // TODO support different namespace of the referenced ConfigMap/Secret object and cluster. + // Specify the namespace of the referenced the ConfigMap/Secret object. + // An empty namespace is equivalent to the same namespace with cluster. + // +kubebuilder:validation:MaxLength=63 + // +kubebuilder:validation:Pattern:=`^/[-\w/]+$` + // +kubebuilder:default="default" + // +optional + Namespace string `json:"namespace,omitempty"` + + // mountPath is the path at which to mount the volume. + // +kubebuilder:validation:Required + // +kubebuilder:validation:MaxLength=256 + // +kubebuilder:validation:Pattern:=`^/[a-z]([a-z0-9\-]*[a-z0-9])?$` + MountPoint string `json:"mountPoint"` + + // defaultMode is optional: mode bits used to set permissions on created files by default. + // Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + // YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + // Defaults to 0644. + // Directories within the path are not affected by this setting. + // This might be in conflict with other options that affect the file + // mode, like fsGroup, and the result can be other mode bits set. + // +optional + DefaultMode *int32 `json:"defaultMode,omitempty" protobuf:"varint,3,opt,name=defaultMode"` +} + +type UserResourceRefs struct { + // secrets defines the user-defined secrets. + // +patchMergeKey=name + // +patchStrategy=merge,retainKeys + // +listType=map + // +listMapKey=name + // +optional + Secrets []ResourceRefMount `json:"secrets,omitempty"` + + // secrets defines the user-defined configmaps. + // +patchMergeKey=name + // +patchStrategy=merge,retainKeys + // +listType=map + // +listMapKey=name + // +optional + ConfigMaps []ResourceRefMount `json:"configMaps,omitempty"` +} + // ClusterStatus defines the observed state of Cluster. type ClusterStatus struct { // observedGeneration is the most recent generation observed for this @@ -312,6 +363,10 @@ type ClusterComponentSpec struct { // +kubebuilder:default=false // +optional NoCreatePDB bool `json:"noCreatePDB,omitempty"` + + // userVolumes defines the user-defined volumes. + // +optional + UserResourceRefs *UserResourceRefs `json:"userResourceRefs,omitempty"` } // GetMinAvailable wraps the 'prefer' value return. As for component replicaCount <= 1, it will return 0, diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index b6a7d7636ae..1fc42ee1e6a 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -552,6 +552,11 @@ func (in *ClusterComponentSpec) DeepCopyInto(out *ClusterComponentSpec) { *out = new(Issuer) (*in).DeepCopyInto(*out) } + if in.UserResourceRefs != nil { + in, out := &in.UserResourceRefs, &out.UserResourceRefs + *out = new(UserResourceRefs) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterComponentSpec. @@ -3306,6 +3311,26 @@ func (in *ResourceConstraintRule) DeepCopy() *ResourceConstraintRule { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceRefMount) DeepCopyInto(out *ResourceRefMount) { + *out = *in + if in.DefaultMode != nil { + in, out := &in.DefaultMode, &out.DefaultMode + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRefMount. +func (in *ResourceRefMount) DeepCopy() *ResourceRefMount { + if in == nil { + return nil + } + out := new(ResourceRefMount) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RestoreFromSpec) DeepCopyInto(out *RestoreFromSpec) { *out = *in @@ -4054,6 +4079,35 @@ func (in *Upgrade) DeepCopy() *Upgrade { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UserResourceRefs) DeepCopyInto(out *UserResourceRefs) { + *out = *in + if in.Secrets != nil { + in, out := &in.Secrets, &out.Secrets + *out = make([]ResourceRefMount, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ConfigMaps != nil { + in, out := &in.ConfigMaps, &out.ConfigMaps + *out = make([]ResourceRefMount, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserResourceRefs. +func (in *UserResourceRefs) DeepCopy() *UserResourceRefs { + if in == nil { + return nil + } + out := new(UserResourceRefs) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ValueFrom) DeepCopyInto(out *ValueFrom) { *out = *in diff --git a/config/crd/bases/apps.kubeblocks.io_clusters.yaml b/config/crd/bases/apps.kubeblocks.io_clusters.yaml index af998c8e481..734251855fe 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusters.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusters.yaml @@ -549,6 +549,104 @@ spec: type: object type: array x-kubernetes-preserve-unknown-fields: true + userResourceRefs: + description: userVolumes defines the user-defined volumes. + properties: + configMaps: + description: secrets defines the user-defined configmaps. + items: + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + mountPoint: + description: mountPath is the path at which to mount + the volume. + maxLength: 256 + pattern: ^/[a-z]([a-z0-9\-]*[a-z0-9])?$ + type: string + name: + description: name is the name of the referenced the + Configmap/Secret object. + maxLength: 63 + pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ + type: string + namespace: + default: default + description: TODO support different namespace of the + referenced ConfigMap/Secret object and cluster. + Specify the namespace of the referenced the ConfigMap/Secret + object. An empty namespace is equivalent to the + same namespace with cluster. + maxLength: 63 + pattern: ^/[-\w/]+$ + type: string + required: + - mountPoint + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + secrets: + description: secrets defines the user-defined secrets. + items: + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + mountPoint: + description: mountPath is the path at which to mount + the volume. + maxLength: 256 + pattern: ^/[a-z]([a-z0-9\-]*[a-z0-9])?$ + type: string + name: + description: name is the name of the referenced the + Configmap/Secret object. + maxLength: 63 + pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ + type: string + namespace: + default: default + description: TODO support different namespace of the + referenced ConfigMap/Secret object and cluster. + Specify the namespace of the referenced the ConfigMap/Secret + object. An empty namespace is equivalent to the + same namespace with cluster. + maxLength: 63 + pattern: ^/[-\w/]+$ + type: string + required: + - mountPoint + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object volumeClaimTemplates: description: volumeClaimTemplates information for statefulset.spec.volumeClaimTemplates. items: diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml index af998c8e481..734251855fe 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml @@ -549,6 +549,104 @@ spec: type: object type: array x-kubernetes-preserve-unknown-fields: true + userResourceRefs: + description: userVolumes defines the user-defined volumes. + properties: + configMaps: + description: secrets defines the user-defined configmaps. + items: + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + mountPoint: + description: mountPath is the path at which to mount + the volume. + maxLength: 256 + pattern: ^/[a-z]([a-z0-9\-]*[a-z0-9])?$ + type: string + name: + description: name is the name of the referenced the + Configmap/Secret object. + maxLength: 63 + pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ + type: string + namespace: + default: default + description: TODO support different namespace of the + referenced ConfigMap/Secret object and cluster. + Specify the namespace of the referenced the ConfigMap/Secret + object. An empty namespace is equivalent to the + same namespace with cluster. + maxLength: 63 + pattern: ^/[-\w/]+$ + type: string + required: + - mountPoint + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + secrets: + description: secrets defines the user-defined secrets. + items: + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + mountPoint: + description: mountPath is the path at which to mount + the volume. + maxLength: 256 + pattern: ^/[a-z]([a-z0-9\-]*[a-z0-9])?$ + type: string + name: + description: name is the name of the referenced the + Configmap/Secret object. + maxLength: 63 + pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ + type: string + namespace: + default: default + description: TODO support different namespace of the + referenced ConfigMap/Secret object and cluster. + Specify the namespace of the referenced the ConfigMap/Secret + object. An empty namespace is equivalent to the + same namespace with cluster. + maxLength: 63 + pattern: ^/[-\w/]+$ + type: string + required: + - mountPoint + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object volumeClaimTemplates: description: volumeClaimTemplates information for statefulset.spec.volumeClaimTemplates. items: From 3259e083b124b6f6142d017d94d17f1226c25827 Mon Sep 17 00:00:00 2001 From: sophon Date: Fri, 13 Oct 2023 16:07:03 +0800 Subject: [PATCH 2/6] feat: support custom configmap/secret for cluster --- apis/apps/v1alpha1/cluster_types.go | 40 +++--- apis/apps/v1alpha1/zz_generated.deepcopy.go | 54 +++++-- .../bases/apps.kubeblocks.io_clusters.yaml | 133 +++++++++++++++--- controllers/apps/components/component.go | 1 + controllers/apps/components/component_test.go | 2 + .../components/component_workload_builder.go | 63 +++++++++ .../crds/apps.kubeblocks.io_clusters.yaml | 133 +++++++++++++++--- pkg/testutil/apps/cluster_factory.go | 50 +++++++ 8 files changed, 408 insertions(+), 68 deletions(-) diff --git a/apis/apps/v1alpha1/cluster_types.go b/apis/apps/v1alpha1/cluster_types.go index cdacedb1fe2..b8fd17eb011 100644 --- a/apis/apps/v1alpha1/cluster_types.go +++ b/apis/apps/v1alpha1/cluster_types.go @@ -177,37 +177,37 @@ type ClusterStorage struct { Size resource.Quantity `json:"size,omitempty"` } -type ResourceRefMount struct { +type ResourceMeta struct { // name is the name of the referenced the Configmap/Secret object. // +kubebuilder:validation:Required // +kubebuilder:validation:MaxLength=63 // +kubebuilder:validation:Pattern:=`^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$` Name string `json:"name"` - // TODO support different namespace of the referenced ConfigMap/Secret object and cluster. - // Specify the namespace of the referenced the ConfigMap/Secret object. - // An empty namespace is equivalent to the same namespace with cluster. - // +kubebuilder:validation:MaxLength=63 - // +kubebuilder:validation:Pattern:=`^/[-\w/]+$` - // +kubebuilder:default="default" - // +optional - Namespace string `json:"namespace,omitempty"` - // mountPath is the path at which to mount the volume. // +kubebuilder:validation:Required // +kubebuilder:validation:MaxLength=256 // +kubebuilder:validation:Pattern:=`^/[a-z]([a-z0-9\-]*[a-z0-9])?$` MountPoint string `json:"mountPoint"` - // defaultMode is optional: mode bits used to set permissions on created files by default. - // Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - // YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - // Defaults to 0644. - // Directories within the path are not affected by this setting. - // This might be in conflict with other options that affect the file - // mode, like fsGroup, and the result can be other mode bits set. + // + // +optional + SubPath string `json:"subPath,omitempty"` + + // asVolumeFrom is optional: the list of containers will be injected into volumeMounts. + // +listType=set // +optional - DefaultMode *int32 `json:"defaultMode,omitempty" protobuf:"varint,3,opt,name=defaultMode"` + AsVolumeFrom []string `json:"asVolumeFrom,omitempty"` +} + +type SecretRef struct { + ResourceMeta `json:",inline"` + corev1.SecretVolumeSource `json:",inline"` +} + +type ConfigMapRef struct { + ResourceMeta `json:",inline"` + corev1.ConfigMapVolumeSource `json:",inline"` } type UserResourceRefs struct { @@ -217,7 +217,7 @@ type UserResourceRefs struct { // +listType=map // +listMapKey=name // +optional - Secrets []ResourceRefMount `json:"secrets,omitempty"` + Secrets []SecretRef `json:"secrets,omitempty"` // secrets defines the user-defined configmaps. // +patchMergeKey=name @@ -225,7 +225,7 @@ type UserResourceRefs struct { // +listType=map // +listMapKey=name // +optional - ConfigMaps []ResourceRefMount `json:"configMaps,omitempty"` + ConfigMaps []ConfigMapRef `json:"configMaps,omitempty"` } // ClusterStatus defines the observed state of Cluster. diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index 1fc42ee1e6a..760c92d4247 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -1827,6 +1827,23 @@ func (in *ConfigConstraintStatus) DeepCopy() *ConfigConstraintStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigMapRef) DeepCopyInto(out *ConfigMapRef) { + *out = *in + in.ResourceMeta.DeepCopyInto(&out.ResourceMeta) + in.ConfigMapVolumeSource.DeepCopyInto(&out.ConfigMapVolumeSource) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapRef. +func (in *ConfigMapRef) DeepCopy() *ConfigMapRef { + if in == nil { + return nil + } + out := new(ConfigMapRef) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConfigParams) DeepCopyInto(out *ConfigParams) { *out = *in @@ -3312,21 +3329,21 @@ func (in *ResourceConstraintRule) DeepCopy() *ResourceConstraintRule { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ResourceRefMount) DeepCopyInto(out *ResourceRefMount) { +func (in *ResourceMeta) DeepCopyInto(out *ResourceMeta) { *out = *in - if in.DefaultMode != nil { - in, out := &in.DefaultMode, &out.DefaultMode - *out = new(int32) - **out = **in + if in.AsVolumeFrom != nil { + in, out := &in.AsVolumeFrom, &out.AsVolumeFrom + *out = make([]string, len(*in)) + copy(*out, *in) } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRefMount. -func (in *ResourceRefMount) DeepCopy() *ResourceRefMount { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceMeta. +func (in *ResourceMeta) DeepCopy() *ResourceMeta { if in == nil { return nil } - out := new(ResourceRefMount) + out := new(ResourceMeta) in.DeepCopyInto(out) return out } @@ -3486,6 +3503,23 @@ func (in *ScriptSpecSelector) DeepCopy() *ScriptSpecSelector { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretRef) DeepCopyInto(out *SecretRef) { + *out = *in + in.ResourceMeta.DeepCopyInto(&out.ResourceMeta) + in.SecretVolumeSource.DeepCopyInto(&out.SecretVolumeSource) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretRef. +func (in *SecretRef) DeepCopy() *SecretRef { + if in == nil { + return nil + } + out := new(SecretRef) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceDescriptor) DeepCopyInto(out *ServiceDescriptor) { *out = *in @@ -4084,14 +4118,14 @@ func (in *UserResourceRefs) DeepCopyInto(out *UserResourceRefs) { *out = *in if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets - *out = make([]ResourceRefMount, len(*in)) + *out = make([]SecretRef, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps - *out = make([]ResourceRefMount, len(*in)) + *out = make([]ConfigMapRef, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } diff --git a/config/crd/bases/apps.kubeblocks.io_clusters.yaml b/config/crd/bases/apps.kubeblocks.io_clusters.yaml index 734251855fe..644c9fbfdd0 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusters.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusters.yaml @@ -556,6 +556,13 @@ spec: description: secrets defines the user-defined configmaps. items: properties: + asVolumeFrom: + description: 'asVolumeFrom is optional: the list of + containers will be injected into volumeMounts.' + items: + type: string + type: array + x-kubernetes-list-type: set defaultMode: description: 'defaultMode is optional: mode bits used to set permissions on created files by default. @@ -569,6 +576,48 @@ spec: can be other mode bits set.' format: int32 type: integer + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. If + a key is specified which is not present in the ConfigMap, + the volume setup will error unless it is marked + optional. Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires decimal + values for mode bits. If not specified, the + volume defaultMode will be used. This might + be in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the + file to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array mountPoint: description: mountPath is the path at which to mount the volume. @@ -581,20 +630,17 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string - namespace: - default: default - description: TODO support different namespace of the - referenced ConfigMap/Secret object and cluster. - Specify the namespace of the referenced the ConfigMap/Secret - object. An empty namespace is equivalent to the - same namespace with cluster. - maxLength: 63 - pattern: ^/[-\w/]+$ + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + subPath: type: string required: - mountPoint - name type: object + x-kubernetes-map-type: atomic type: array x-kubernetes-list-map-keys: - name @@ -603,8 +649,15 @@ spec: description: secrets defines the user-defined secrets. items: properties: + asVolumeFrom: + description: 'asVolumeFrom is optional: the list of + containers will be injected into volumeMounts.' + items: + type: string + type: array + x-kubernetes-list-type: set defaultMode: - description: 'defaultMode is optional: mode bits used + description: 'defaultMode is Optional: mode bits used to set permissions on created files by default. Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. YAML accepts @@ -616,6 +669,48 @@ spec: can be other mode bits set.' format: int32 type: integer + items: + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. If + a key is specified which is not present in the Secret, + the volume setup will error unless it is marked + optional. Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires decimal + values for mode bits. If not specified, the + volume defaultMode will be used. This might + be in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the + file to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array mountPoint: description: mountPath is the path at which to mount the volume. @@ -628,15 +723,15 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string - namespace: - default: default - description: TODO support different namespace of the - referenced ConfigMap/Secret object and cluster. - Specify the namespace of the referenced the ConfigMap/Secret - object. An empty namespace is equivalent to the - same namespace with cluster. - maxLength: 63 - pattern: ^/[-\w/]+$ + optional: + description: optional field specify whether the Secret + or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + subPath: type: string required: - mountPoint diff --git a/controllers/apps/components/component.go b/controllers/apps/components/component.go index 16e46ab1090..93287d337b7 100644 --- a/controllers/apps/components/component.go +++ b/controllers/apps/components/component.go @@ -187,6 +187,7 @@ func (c *rsmComponent) init(reqCtx intctrlutil.RequestCtx, cli client.Client, bu if err = builder.BuildEnv(). BuildWorkload(). BuildPDB(). + BuildCustomVolumes(). BuildConfig(). BuildTLSVolume(). BuildVolumeMount(). diff --git a/controllers/apps/components/component_test.go b/controllers/apps/components/component_test.go index f548b6c65e5..2bc06be3da4 100644 --- a/controllers/apps/components/component_test.go +++ b/controllers/apps/components/component_test.go @@ -115,6 +115,8 @@ var _ = Describe("Component", func() { SetReplicas(int32(defaultReplicas)). AddVolumeClaimTemplate(testapps.LogVolumeName, testapps.NewPVCSpec(defaultVolumeSize)). AddVolumeClaimTemplate(testapps.DataVolumeName, testapps.NewPVCSpec(defaultVolumeSize)). + AddUserSecretVolume("secret_volumes", "/opt/secrets", "secret_name", "mysql"). + AddUserConfigmapVolume("configmap_volumes", "/opt/scripts", "user_config_name", "mysql"). GetObject() reqCtx = intctrlutil.RequestCtx{Ctx: ctx, Log: logger, Recorder: recorder} diff --git a/controllers/apps/components/component_workload_builder.go b/controllers/apps/components/component_workload_builder.go index cd3ffa32169..f6d8d1c3578 100644 --- a/controllers/apps/components/component_workload_builder.go +++ b/controllers/apps/components/component_workload_builder.go @@ -22,6 +22,7 @@ package components import ( "fmt" + "golang.org/x/exp/slices" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -44,6 +45,7 @@ type componentWorkloadBuilder interface { BuildVolumeMount() componentWorkloadBuilder BuildTLSCert() componentWorkloadBuilder BuildTLSVolume() componentWorkloadBuilder + BuildCustomVolumes() componentWorkloadBuilder Complete() error } @@ -71,6 +73,12 @@ func (b *rsmComponentWorkloadBuilder) BuildEnv() componentWorkloadBuilder { return b.BuildWrapper(buildfn) } +func (b *rsmComponentWorkloadBuilder) BuildCustomVolumes() componentWorkloadBuilder { + return b.BuildWrapper(func() ([]client.Object, error) { + return nil, doBuildCustomVolumes(b.getRuntime(), b.comp.GetCluster(), b.comp.GetName(), b.comp.GetNamespace()) + }) +} + func (b *rsmComponentWorkloadBuilder) BuildConfig() componentWorkloadBuilder { buildfn := func() ([]client.Object, error) { if b.workload == nil { @@ -319,3 +327,58 @@ func composeTLSVolumeMount() corev1.VolumeMount { ReadOnly: true, } } + +func newSourceFromResource(name string, source any) corev1.Volume { + volume := corev1.Volume{ + Name: name, + } + switch t := source.(type) { + default: + panic(fmt.Sprintf("unknown volume source type: %T", t)) + case *corev1.ConfigMapVolumeSource: + volume.VolumeSource.ConfigMap = t + case *corev1.SecretVolumeSource: + volume.VolumeSource.Secret = t + } + return volume +} + +func doBuildCustomVolumes(podSpec *corev1.PodSpec, cluster *appsv1alpha1.Cluster, componentName string, namespace string) error { + comp := cluster.Spec.GetComponentByName(componentName) + if comp == nil || comp.UserResourceRefs == nil { + return nil + } + + volumes := podSpec.Volumes + for _, configMap := range comp.UserResourceRefs.ConfigMaps { + volumes = append(volumes, newSourceFromResource(configMap.Name, configMap.ConfigMapVolumeSource.DeepCopy())) + } + for _, secret := range comp.UserResourceRefs.Secrets { + volumes = append(volumes, newSourceFromResource(secret.Name, secret.SecretVolumeSource.DeepCopy())) + } + podSpec.Volumes = volumes + buildVolumeMountForContainers(podSpec, *comp.UserResourceRefs) + return nil +} + +func buildVolumeMountForContainers(podSpec *corev1.PodSpec, resourceRefs appsv1alpha1.UserResourceRefs) { + for _, configMap := range resourceRefs.ConfigMaps { + newVolumeMount(podSpec, configMap.ResourceMeta) + } + for _, secret := range resourceRefs.Secrets { + newVolumeMount(podSpec, secret.ResourceMeta) + } +} + +func newVolumeMount(podSpec *corev1.PodSpec, res appsv1alpha1.ResourceMeta) { + for i := range podSpec.Containers { + container := &podSpec.Containers[i] + if slices.Contains(res.AsVolumeFrom, container.Name) { + container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{ + Name: res.Name, + MountPath: res.MountPoint, + SubPath: res.SubPath, + }) + } + } +} diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml index 734251855fe..644c9fbfdd0 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml @@ -556,6 +556,13 @@ spec: description: secrets defines the user-defined configmaps. items: properties: + asVolumeFrom: + description: 'asVolumeFrom is optional: the list of + containers will be injected into volumeMounts.' + items: + type: string + type: array + x-kubernetes-list-type: set defaultMode: description: 'defaultMode is optional: mode bits used to set permissions on created files by default. @@ -569,6 +576,48 @@ spec: can be other mode bits set.' format: int32 type: integer + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. If + a key is specified which is not present in the ConfigMap, + the volume setup will error unless it is marked + optional. Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires decimal + values for mode bits. If not specified, the + volume defaultMode will be used. This might + be in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the + file to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array mountPoint: description: mountPath is the path at which to mount the volume. @@ -581,20 +630,17 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string - namespace: - default: default - description: TODO support different namespace of the - referenced ConfigMap/Secret object and cluster. - Specify the namespace of the referenced the ConfigMap/Secret - object. An empty namespace is equivalent to the - same namespace with cluster. - maxLength: 63 - pattern: ^/[-\w/]+$ + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + subPath: type: string required: - mountPoint - name type: object + x-kubernetes-map-type: atomic type: array x-kubernetes-list-map-keys: - name @@ -603,8 +649,15 @@ spec: description: secrets defines the user-defined secrets. items: properties: + asVolumeFrom: + description: 'asVolumeFrom is optional: the list of + containers will be injected into volumeMounts.' + items: + type: string + type: array + x-kubernetes-list-type: set defaultMode: - description: 'defaultMode is optional: mode bits used + description: 'defaultMode is Optional: mode bits used to set permissions on created files by default. Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. YAML accepts @@ -616,6 +669,48 @@ spec: can be other mode bits set.' format: int32 type: integer + items: + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. If + a key is specified which is not present in the Secret, + the volume setup will error unless it is marked + optional. Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires decimal + values for mode bits. If not specified, the + volume defaultMode will be used. This might + be in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the + file to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array mountPoint: description: mountPath is the path at which to mount the volume. @@ -628,15 +723,15 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string - namespace: - default: default - description: TODO support different namespace of the - referenced ConfigMap/Secret object and cluster. - Specify the namespace of the referenced the ConfigMap/Secret - object. An empty namespace is equivalent to the - same namespace with cluster. - maxLength: 63 - pattern: ^/[-\w/]+$ + optional: + description: optional field specify whether the Secret + or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + subPath: type: string required: - mountPoint diff --git a/pkg/testutil/apps/cluster_factory.go b/pkg/testutil/apps/cluster_factory.go index 417f5267aa0..a3e63daefe5 100644 --- a/pkg/testutil/apps/cluster_factory.go +++ b/pkg/testutil/apps/cluster_factory.go @@ -180,3 +180,53 @@ func (factory *MockClusterFactory) SetServiceRefs(serviceRefs []appsv1alpha1.Ser comp.ServiceRefs = serviceRefs }) } + +func (factory *MockClusterFactory) AddUserSecretVolume(name, mountPoint, resName, containerName string) *MockClusterFactory { + secretResource := appsv1alpha1.SecretRef{ + ResourceMeta: appsv1alpha1.ResourceMeta{ + Name: name, + MountPoint: mountPoint, + AsVolumeFrom: []string{containerName}, + }, + SecretVolumeSource: corev1.SecretVolumeSource{ + SecretName: resName, + }, + } + comps := factory.Get().Spec.ComponentSpecs + if len(comps) > 0 { + userResourcesRefs := comps[len(comps)-1].UserResourceRefs + if userResourcesRefs == nil { + userResourcesRefs = &appsv1alpha1.UserResourceRefs{} + comps[len(comps)-1].UserResourceRefs = userResourcesRefs + } + userResourcesRefs.Secrets = append(userResourcesRefs.Secrets, secretResource) + } + factory.Get().Spec.ComponentSpecs = comps + return factory +} + +func (factory *MockClusterFactory) AddUserConfigmapVolume(name, mountPoint, resName, containerName string) *MockClusterFactory { + cmResource := appsv1alpha1.ConfigMapRef{ + ResourceMeta: appsv1alpha1.ResourceMeta{ + Name: name, + MountPoint: mountPoint, + AsVolumeFrom: []string{containerName}, + }, + ConfigMapVolumeSource: corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: resName, + }, + }, + } + comps := factory.Get().Spec.ComponentSpecs + if len(comps) > 0 { + userResourcesRefs := comps[len(comps)-1].UserResourceRefs + if userResourcesRefs == nil { + userResourcesRefs = &appsv1alpha1.UserResourceRefs{} + comps[len(comps)-1].UserResourceRefs = userResourcesRefs + } + userResourcesRefs.ConfigMaps = append(userResourcesRefs.ConfigMaps, cmResource) + } + factory.Get().Spec.ComponentSpecs = comps + return factory +} From bb6075461bd5c377e01eeeb3262bce0e6539b50c Mon Sep 17 00:00:00 2001 From: sophon Date: Fri, 13 Oct 2023 16:57:10 +0800 Subject: [PATCH 3/6] chore: minor adjust --- apis/apps/v1alpha1/cluster_types.go | 2 +- config/crd/bases/apps.kubeblocks.io_clusters.yaml | 4 ++++ deploy/helm/crds/apps.kubeblocks.io_clusters.yaml | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/apis/apps/v1alpha1/cluster_types.go b/apis/apps/v1alpha1/cluster_types.go index b8fd17eb011..f6ae87422c8 100644 --- a/apis/apps/v1alpha1/cluster_types.go +++ b/apis/apps/v1alpha1/cluster_types.go @@ -190,7 +190,7 @@ type ResourceMeta struct { // +kubebuilder:validation:Pattern:=`^/[a-z]([a-z0-9\-]*[a-z0-9])?$` MountPoint string `json:"mountPoint"` - // + // subPath is a relative file path within the volume to mount. // +optional SubPath string `json:"subPath,omitempty"` diff --git a/config/crd/bases/apps.kubeblocks.io_clusters.yaml b/config/crd/bases/apps.kubeblocks.io_clusters.yaml index 644c9fbfdd0..7e041c16f37 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusters.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusters.yaml @@ -635,6 +635,8 @@ spec: or its keys must be defined type: boolean subPath: + description: subPath is a relative file path within + the volume to mount. type: string required: - mountPoint @@ -732,6 +734,8 @@ spec: in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string subPath: + description: subPath is a relative file path within + the volume to mount. type: string required: - mountPoint diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml index 644c9fbfdd0..7e041c16f37 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml @@ -635,6 +635,8 @@ spec: or its keys must be defined type: boolean subPath: + description: subPath is a relative file path within + the volume to mount. type: string required: - mountPoint @@ -732,6 +734,8 @@ spec: in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string subPath: + description: subPath is a relative file path within + the volume to mount. type: string required: - mountPoint From 81a868d07c572b1ad4e9105cf721b6b2b30b2e76 Mon Sep 17 00:00:00 2001 From: sophon Date: Fri, 13 Oct 2023 17:22:17 +0800 Subject: [PATCH 4/6] chore: update api --- apis/apps/v1alpha1/cluster_types.go | 24 +- apis/apps/v1alpha1/zz_generated.deepcopy.go | 12 +- .../bases/apps.kubeblocks.io_clusters.yaml | 287 ++++++++++-------- .../components/component_workload_builder.go | 12 +- .../crds/apps.kubeblocks.io_clusters.yaml | 287 ++++++++++-------- pkg/testutil/apps/cluster_factory.go | 8 +- 6 files changed, 343 insertions(+), 287 deletions(-) diff --git a/apis/apps/v1alpha1/cluster_types.go b/apis/apps/v1alpha1/cluster_types.go index f6ae87422c8..9dea6795854 100644 --- a/apis/apps/v1alpha1/cluster_types.go +++ b/apis/apps/v1alpha1/cluster_types.go @@ -194,38 +194,44 @@ type ResourceMeta struct { // +optional SubPath string `json:"subPath,omitempty"` - // asVolumeFrom is optional: the list of containers will be injected into volumeMounts. + // asVolumeFrom defines the list of containers will be injected into volumeMounts. // +listType=set // +optional AsVolumeFrom []string `json:"asVolumeFrom,omitempty"` } type SecretRef struct { - ResourceMeta `json:",inline"` - corev1.SecretVolumeSource `json:",inline"` + ResourceMeta `json:",inline"` + + // secret defines the secret volume source. + // +kubebuilder:validation:Required + Secret corev1.SecretVolumeSource `json:"secret"` } type ConfigMapRef struct { - ResourceMeta `json:",inline"` - corev1.ConfigMapVolumeSource `json:",inline"` + ResourceMeta `json:",inline"` + + // configMap defines the configmap volume source. + // +kubebuilder:validation:Required + ConfigMap corev1.ConfigMapVolumeSource `json:"configMap"` } type UserResourceRefs struct { - // secrets defines the user-defined secrets. + // secretRefs defines the user-defined secrets. // +patchMergeKey=name // +patchStrategy=merge,retainKeys // +listType=map // +listMapKey=name // +optional - Secrets []SecretRef `json:"secrets,omitempty"` + SecretRefs []SecretRef `json:"secretRefs,omitempty"` - // secrets defines the user-defined configmaps. + // configMapRefs defines the user-defined configmaps. // +patchMergeKey=name // +patchStrategy=merge,retainKeys // +listType=map // +listMapKey=name // +optional - ConfigMaps []ConfigMapRef `json:"configMaps,omitempty"` + ConfigMapRefs []ConfigMapRef `json:"configMapRefs,omitempty"` } // ClusterStatus defines the observed state of Cluster. diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index 760c92d4247..e395d1901b3 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -1831,7 +1831,7 @@ func (in *ConfigConstraintStatus) DeepCopy() *ConfigConstraintStatus { func (in *ConfigMapRef) DeepCopyInto(out *ConfigMapRef) { *out = *in in.ResourceMeta.DeepCopyInto(&out.ResourceMeta) - in.ConfigMapVolumeSource.DeepCopyInto(&out.ConfigMapVolumeSource) + in.ConfigMap.DeepCopyInto(&out.ConfigMap) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapRef. @@ -3507,7 +3507,7 @@ func (in *ScriptSpecSelector) DeepCopy() *ScriptSpecSelector { func (in *SecretRef) DeepCopyInto(out *SecretRef) { *out = *in in.ResourceMeta.DeepCopyInto(&out.ResourceMeta) - in.SecretVolumeSource.DeepCopyInto(&out.SecretVolumeSource) + in.Secret.DeepCopyInto(&out.Secret) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretRef. @@ -4116,15 +4116,15 @@ func (in *Upgrade) DeepCopy() *Upgrade { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UserResourceRefs) DeepCopyInto(out *UserResourceRefs) { *out = *in - if in.Secrets != nil { - in, out := &in.Secrets, &out.Secrets + if in.SecretRefs != nil { + in, out := &in.SecretRefs, &out.SecretRefs *out = make([]SecretRef, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.ConfigMaps != nil { - in, out := &in.ConfigMaps, &out.ConfigMaps + if in.ConfigMapRefs != nil { + in, out := &in.ConfigMapRefs, &out.ConfigMapRefs *out = make([]ConfigMapRef, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) diff --git a/config/crd/bases/apps.kubeblocks.io_clusters.yaml b/config/crd/bases/apps.kubeblocks.io_clusters.yaml index 7e041c16f37..052e7a4a67b 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusters.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusters.yaml @@ -552,72 +552,92 @@ spec: userResourceRefs: description: userVolumes defines the user-defined volumes. properties: - configMaps: - description: secrets defines the user-defined configmaps. + configMapRefs: + description: configMapRefs defines the user-defined configmaps. items: properties: asVolumeFrom: - description: 'asVolumeFrom is optional: the list of - containers will be injected into volumeMounts.' + description: asVolumeFrom defines the list of containers + will be injected into volumeMounts. items: type: string type: array x-kubernetes-list-type: set - defaultMode: - description: 'defaultMode is optional: mode bits used - to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or - a decimal value between 0 and 511. YAML accepts - both octal and decimal values, JSON requires decimal - values for mode bits. Defaults to 0644. Directories - within the path are not affected by this setting. - This might be in conflict with other options that - affect the file mode, like fsGroup, and the result - can be other mode bits set.' - format: int32 - type: integer - items: - description: items if unspecified, each key-value - pair in the Data field of the referenced ConfigMap - will be projected into the volume as a file whose - name is the key and content is the value. If specified, - the listed keys will be projected into the specified - paths, and unlisted keys will not be present. If - a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked - optional. Paths must be relative and may not contain - the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: 'mode is Optional: mode bits used - to set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires decimal - values for mode bits. If not specified, the - volume defaultMode will be used. This might - be in conflict with other options that affect - the file mode, like fsGroup, and the result - can be other mode bits set.' - format: int32 - type: integer - path: - description: path is the relative path of the - file to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array + configMap: + description: configMap defines the configmap volume + source. + properties: + defaultMode: + description: 'defaultMode is optional: mode bits + used to set permissions on created files by + default. Must be an octal value between 0000 + and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. + Defaults to 0644. Directories within the path + are not affected by this setting. This might + be in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified which + is not present in the ConfigMap, the volume + setup will error unless it is marked optional. + Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 and + 0777 or a decimal value between 0 and + 511. YAML accepts both octal and decimal + values, JSON requires decimal values for + mode bits. If not specified, the volume + defaultMode will be used. This might be + in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be + an absolute path. May not contain the + path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic mountPoint: description: mountPath is the path at which to mount the volume. @@ -630,89 +650,30 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string - optional: - description: optional specify whether the ConfigMap - or its keys must be defined - type: boolean subPath: description: subPath is a relative file path within the volume to mount. type: string required: + - configMap - mountPoint - name type: object - x-kubernetes-map-type: atomic type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map - secrets: - description: secrets defines the user-defined secrets. + secretRefs: + description: secretRefs defines the user-defined secrets. items: properties: asVolumeFrom: - description: 'asVolumeFrom is optional: the list of - containers will be injected into volumeMounts.' + description: asVolumeFrom defines the list of containers + will be injected into volumeMounts. items: type: string type: array x-kubernetes-list-type: set - defaultMode: - description: 'defaultMode is Optional: mode bits used - to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or - a decimal value between 0 and 511. YAML accepts - both octal and decimal values, JSON requires decimal - values for mode bits. Defaults to 0644. Directories - within the path are not affected by this setting. - This might be in conflict with other options that - affect the file mode, like fsGroup, and the result - can be other mode bits set.' - format: int32 - type: integer - items: - description: items If unspecified, each key-value - pair in the Data field of the referenced Secret - will be projected into the volume as a file whose - name is the key and content is the value. If specified, - the listed keys will be projected into the specified - paths, and unlisted keys will not be present. If - a key is specified which is not present in the Secret, - the volume setup will error unless it is marked - optional. Paths must be relative and may not contain - the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: 'mode is Optional: mode bits used - to set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires decimal - values for mode bits. If not specified, the - volume defaultMode will be used. This might - be in conflict with other options that affect - the file mode, like fsGroup, and the result - can be other mode bits set.' - format: int32 - type: integer - path: - description: path is the relative path of the - file to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array mountPoint: description: mountPath is the path at which to mount the volume. @@ -725,14 +686,77 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string - optional: - description: optional field specify whether the Secret - or its keys must be defined - type: boolean - secretName: - description: 'secretName is the name of the secret - in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' - type: string + secret: + description: secret defines the secret volume source. + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by + default. Must be an octal value between 0000 + and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. + Defaults to 0644. Directories within the path + are not affected by this setting. This might + be in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified which + is not present in the Secret, the volume setup + will error unless it is marked optional. Paths + must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 and + 0777 or a decimal value between 0 and + 511. YAML accepts both octal and decimal + values, JSON requires decimal values for + mode bits. If not specified, the volume + defaultMode will be used. This might be + in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be + an absolute path. May not contain the + path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the + Secret or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object subPath: description: subPath is a relative file path within the volume to mount. @@ -740,6 +764,7 @@ spec: required: - mountPoint - name + - secret type: object type: array x-kubernetes-list-map-keys: diff --git a/controllers/apps/components/component_workload_builder.go b/controllers/apps/components/component_workload_builder.go index f6d8d1c3578..e10702300b5 100644 --- a/controllers/apps/components/component_workload_builder.go +++ b/controllers/apps/components/component_workload_builder.go @@ -350,11 +350,11 @@ func doBuildCustomVolumes(podSpec *corev1.PodSpec, cluster *appsv1alpha1.Cluster } volumes := podSpec.Volumes - for _, configMap := range comp.UserResourceRefs.ConfigMaps { - volumes = append(volumes, newSourceFromResource(configMap.Name, configMap.ConfigMapVolumeSource.DeepCopy())) + for _, configMap := range comp.UserResourceRefs.ConfigMapRefs { + volumes = append(volumes, newSourceFromResource(configMap.Name, configMap.ConfigMap.DeepCopy())) } - for _, secret := range comp.UserResourceRefs.Secrets { - volumes = append(volumes, newSourceFromResource(secret.Name, secret.SecretVolumeSource.DeepCopy())) + for _, secret := range comp.UserResourceRefs.SecretRefs { + volumes = append(volumes, newSourceFromResource(secret.Name, secret.Secret.DeepCopy())) } podSpec.Volumes = volumes buildVolumeMountForContainers(podSpec, *comp.UserResourceRefs) @@ -362,10 +362,10 @@ func doBuildCustomVolumes(podSpec *corev1.PodSpec, cluster *appsv1alpha1.Cluster } func buildVolumeMountForContainers(podSpec *corev1.PodSpec, resourceRefs appsv1alpha1.UserResourceRefs) { - for _, configMap := range resourceRefs.ConfigMaps { + for _, configMap := range resourceRefs.ConfigMapRefs { newVolumeMount(podSpec, configMap.ResourceMeta) } - for _, secret := range resourceRefs.Secrets { + for _, secret := range resourceRefs.SecretRefs { newVolumeMount(podSpec, secret.ResourceMeta) } } diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml index 7e041c16f37..052e7a4a67b 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml @@ -552,72 +552,92 @@ spec: userResourceRefs: description: userVolumes defines the user-defined volumes. properties: - configMaps: - description: secrets defines the user-defined configmaps. + configMapRefs: + description: configMapRefs defines the user-defined configmaps. items: properties: asVolumeFrom: - description: 'asVolumeFrom is optional: the list of - containers will be injected into volumeMounts.' + description: asVolumeFrom defines the list of containers + will be injected into volumeMounts. items: type: string type: array x-kubernetes-list-type: set - defaultMode: - description: 'defaultMode is optional: mode bits used - to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or - a decimal value between 0 and 511. YAML accepts - both octal and decimal values, JSON requires decimal - values for mode bits. Defaults to 0644. Directories - within the path are not affected by this setting. - This might be in conflict with other options that - affect the file mode, like fsGroup, and the result - can be other mode bits set.' - format: int32 - type: integer - items: - description: items if unspecified, each key-value - pair in the Data field of the referenced ConfigMap - will be projected into the volume as a file whose - name is the key and content is the value. If specified, - the listed keys will be projected into the specified - paths, and unlisted keys will not be present. If - a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked - optional. Paths must be relative and may not contain - the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: 'mode is Optional: mode bits used - to set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires decimal - values for mode bits. If not specified, the - volume defaultMode will be used. This might - be in conflict with other options that affect - the file mode, like fsGroup, and the result - can be other mode bits set.' - format: int32 - type: integer - path: - description: path is the relative path of the - file to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array + configMap: + description: configMap defines the configmap volume + source. + properties: + defaultMode: + description: 'defaultMode is optional: mode bits + used to set permissions on created files by + default. Must be an octal value between 0000 + and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. + Defaults to 0644. Directories within the path + are not affected by this setting. This might + be in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified which + is not present in the ConfigMap, the volume + setup will error unless it is marked optional. + Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 and + 0777 or a decimal value between 0 and + 511. YAML accepts both octal and decimal + values, JSON requires decimal values for + mode bits. If not specified, the volume + defaultMode will be used. This might be + in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be + an absolute path. May not contain the + path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic mountPoint: description: mountPath is the path at which to mount the volume. @@ -630,89 +650,30 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string - optional: - description: optional specify whether the ConfigMap - or its keys must be defined - type: boolean subPath: description: subPath is a relative file path within the volume to mount. type: string required: + - configMap - mountPoint - name type: object - x-kubernetes-map-type: atomic type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map - secrets: - description: secrets defines the user-defined secrets. + secretRefs: + description: secretRefs defines the user-defined secrets. items: properties: asVolumeFrom: - description: 'asVolumeFrom is optional: the list of - containers will be injected into volumeMounts.' + description: asVolumeFrom defines the list of containers + will be injected into volumeMounts. items: type: string type: array x-kubernetes-list-type: set - defaultMode: - description: 'defaultMode is Optional: mode bits used - to set permissions on created files by default. - Must be an octal value between 0000 and 0777 or - a decimal value between 0 and 511. YAML accepts - both octal and decimal values, JSON requires decimal - values for mode bits. Defaults to 0644. Directories - within the path are not affected by this setting. - This might be in conflict with other options that - affect the file mode, like fsGroup, and the result - can be other mode bits set.' - format: int32 - type: integer - items: - description: items If unspecified, each key-value - pair in the Data field of the referenced Secret - will be projected into the volume as a file whose - name is the key and content is the value. If specified, - the listed keys will be projected into the specified - paths, and unlisted keys will not be present. If - a key is specified which is not present in the Secret, - the volume setup will error unless it is marked - optional. Paths must be relative and may not contain - the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: 'mode is Optional: mode bits used - to set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires decimal - values for mode bits. If not specified, the - volume defaultMode will be used. This might - be in conflict with other options that affect - the file mode, like fsGroup, and the result - can be other mode bits set.' - format: int32 - type: integer - path: - description: path is the relative path of the - file to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array mountPoint: description: mountPath is the path at which to mount the volume. @@ -725,14 +686,77 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$ type: string - optional: - description: optional field specify whether the Secret - or its keys must be defined - type: boolean - secretName: - description: 'secretName is the name of the secret - in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' - type: string + secret: + description: secret defines the secret volume source. + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by + default. Must be an octal value between 0000 + and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, + JSON requires decimal values for mode bits. + Defaults to 0644. Directories within the path + are not affected by this setting. This might + be in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified which + is not present in the Secret, the volume setup + will error unless it is marked optional. Paths + must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 and + 0777 or a decimal value between 0 and + 511. YAML accepts both octal and decimal + values, JSON requires decimal values for + mode bits. If not specified, the volume + defaultMode will be used. This might be + in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be + an absolute path. May not contain the + path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the + Secret or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object subPath: description: subPath is a relative file path within the volume to mount. @@ -740,6 +764,7 @@ spec: required: - mountPoint - name + - secret type: object type: array x-kubernetes-list-map-keys: diff --git a/pkg/testutil/apps/cluster_factory.go b/pkg/testutil/apps/cluster_factory.go index a3e63daefe5..7b49c6ec2f9 100644 --- a/pkg/testutil/apps/cluster_factory.go +++ b/pkg/testutil/apps/cluster_factory.go @@ -188,7 +188,7 @@ func (factory *MockClusterFactory) AddUserSecretVolume(name, mountPoint, resName MountPoint: mountPoint, AsVolumeFrom: []string{containerName}, }, - SecretVolumeSource: corev1.SecretVolumeSource{ + Secret: corev1.SecretVolumeSource{ SecretName: resName, }, } @@ -199,7 +199,7 @@ func (factory *MockClusterFactory) AddUserSecretVolume(name, mountPoint, resName userResourcesRefs = &appsv1alpha1.UserResourceRefs{} comps[len(comps)-1].UserResourceRefs = userResourcesRefs } - userResourcesRefs.Secrets = append(userResourcesRefs.Secrets, secretResource) + userResourcesRefs.SecretRefs = append(userResourcesRefs.SecretRefs, secretResource) } factory.Get().Spec.ComponentSpecs = comps return factory @@ -212,7 +212,7 @@ func (factory *MockClusterFactory) AddUserConfigmapVolume(name, mountPoint, resN MountPoint: mountPoint, AsVolumeFrom: []string{containerName}, }, - ConfigMapVolumeSource: corev1.ConfigMapVolumeSource{ + ConfigMap: corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ Name: resName, }, @@ -225,7 +225,7 @@ func (factory *MockClusterFactory) AddUserConfigmapVolume(name, mountPoint, resN userResourcesRefs = &appsv1alpha1.UserResourceRefs{} comps[len(comps)-1].UserResourceRefs = userResourcesRefs } - userResourcesRefs.ConfigMaps = append(userResourcesRefs.ConfigMaps, cmResource) + userResourcesRefs.ConfigMapRefs = append(userResourcesRefs.ConfigMapRefs, cmResource) } factory.Get().Spec.ComponentSpecs = comps return factory From bc132fa1d8049c4f1730665e3b54ee98e4eaa080 Mon Sep 17 00:00:00 2001 From: sophon Date: Sun, 15 Oct 2023 00:24:54 +0800 Subject: [PATCH 5/6] chore: rebase main --- pkg/testutil/apps/cluster_factory.go | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/pkg/testutil/apps/cluster_factory.go b/pkg/testutil/apps/cluster_factory.go index 7b49c6ec2f9..1f7b153d4d2 100644 --- a/pkg/testutil/apps/cluster_factory.go +++ b/pkg/testutil/apps/cluster_factory.go @@ -192,17 +192,14 @@ func (factory *MockClusterFactory) AddUserSecretVolume(name, mountPoint, resName SecretName: resName, }, } - comps := factory.Get().Spec.ComponentSpecs - if len(comps) > 0 { - userResourcesRefs := comps[len(comps)-1].UserResourceRefs + return factory.lastComponentRef(func(comp *appsv1alpha1.ClusterComponentSpec) { + userResourcesRefs := comp.UserResourceRefs if userResourcesRefs == nil { userResourcesRefs = &appsv1alpha1.UserResourceRefs{} - comps[len(comps)-1].UserResourceRefs = userResourcesRefs + comp.UserResourceRefs = userResourcesRefs } userResourcesRefs.SecretRefs = append(userResourcesRefs.SecretRefs, secretResource) - } - factory.Get().Spec.ComponentSpecs = comps - return factory + }) } func (factory *MockClusterFactory) AddUserConfigmapVolume(name, mountPoint, resName, containerName string) *MockClusterFactory { @@ -218,15 +215,12 @@ func (factory *MockClusterFactory) AddUserConfigmapVolume(name, mountPoint, resN }, }, } - comps := factory.Get().Spec.ComponentSpecs - if len(comps) > 0 { - userResourcesRefs := comps[len(comps)-1].UserResourceRefs + return factory.lastComponentRef(func(comp *appsv1alpha1.ClusterComponentSpec) { + userResourcesRefs := comp.UserResourceRefs if userResourcesRefs == nil { userResourcesRefs = &appsv1alpha1.UserResourceRefs{} - comps[len(comps)-1].UserResourceRefs = userResourcesRefs + comp.UserResourceRefs = userResourcesRefs } userResourcesRefs.ConfigMapRefs = append(userResourcesRefs.ConfigMapRefs, cmResource) - } - factory.Get().Spec.ComponentSpecs = comps - return factory + }) } From 15186b470c253275c4b407fb486948a4b5d45338 Mon Sep 17 00:00:00 2001 From: sophon Date: Mon, 23 Oct 2023 14:31:57 +0800 Subject: [PATCH 6/6] chore: adjust typo as recommended by code review --- apis/apps/v1alpha1/cluster_types.go | 4 ++-- config/crd/bases/apps.kubeblocks.io_clusters.yaml | 6 +++--- deploy/helm/crds/apps.kubeblocks.io_clusters.yaml | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apis/apps/v1alpha1/cluster_types.go b/apis/apps/v1alpha1/cluster_types.go index 9dea6795854..8ee63e1a03b 100644 --- a/apis/apps/v1alpha1/cluster_types.go +++ b/apis/apps/v1alpha1/cluster_types.go @@ -194,7 +194,7 @@ type ResourceMeta struct { // +optional SubPath string `json:"subPath,omitempty"` - // asVolumeFrom defines the list of containers will be injected into volumeMounts. + // asVolumeFrom defines the list of containers where volumeMounts will be injected into. // +listType=set // +optional AsVolumeFrom []string `json:"asVolumeFrom,omitempty"` @@ -370,7 +370,7 @@ type ClusterComponentSpec struct { // +optional NoCreatePDB bool `json:"noCreatePDB,omitempty"` - // userVolumes defines the user-defined volumes. + // userResourceRefs defines the user-defined volumes. // +optional UserResourceRefs *UserResourceRefs `json:"userResourceRefs,omitempty"` } diff --git a/config/crd/bases/apps.kubeblocks.io_clusters.yaml b/config/crd/bases/apps.kubeblocks.io_clusters.yaml index 052e7a4a67b..4fb79fa1c0d 100644 --- a/config/crd/bases/apps.kubeblocks.io_clusters.yaml +++ b/config/crd/bases/apps.kubeblocks.io_clusters.yaml @@ -550,7 +550,7 @@ spec: type: array x-kubernetes-preserve-unknown-fields: true userResourceRefs: - description: userVolumes defines the user-defined volumes. + description: userResourceRefs defines the user-defined volumes. properties: configMapRefs: description: configMapRefs defines the user-defined configmaps. @@ -558,7 +558,7 @@ spec: properties: asVolumeFrom: description: asVolumeFrom defines the list of containers - will be injected into volumeMounts. + where volumeMounts will be injected into. items: type: string type: array @@ -669,7 +669,7 @@ spec: properties: asVolumeFrom: description: asVolumeFrom defines the list of containers - will be injected into volumeMounts. + where volumeMounts will be injected into. items: type: string type: array diff --git a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml index 052e7a4a67b..4fb79fa1c0d 100644 --- a/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml +++ b/deploy/helm/crds/apps.kubeblocks.io_clusters.yaml @@ -550,7 +550,7 @@ spec: type: array x-kubernetes-preserve-unknown-fields: true userResourceRefs: - description: userVolumes defines the user-defined volumes. + description: userResourceRefs defines the user-defined volumes. properties: configMapRefs: description: configMapRefs defines the user-defined configmaps. @@ -558,7 +558,7 @@ spec: properties: asVolumeFrom: description: asVolumeFrom defines the list of containers - will be injected into volumeMounts. + where volumeMounts will be injected into. items: type: string type: array @@ -669,7 +669,7 @@ spec: properties: asVolumeFrom: description: asVolumeFrom defines the list of containers - will be injected into volumeMounts. + where volumeMounts will be injected into. items: type: string type: array