diff --git a/apis/apps/v1alpha1/cluster_types.go b/apis/apps/v1alpha1/cluster_types.go
index 9fbecdfe6ea..7ca245b1575 100644
--- a/apis/apps/v1alpha1/cluster_types.go
+++ b/apis/apps/v1alpha1/cluster_types.go
@@ -475,7 +475,7 @@ type InstanceTemplate struct {
// Defines VolumeClaimTemplates to override.
// Add new or override existing volume claim templates.
// +optional
- VolumeClaimTemplates []corev1.PersistentVolumeClaim `json:"volumeClaimTemplates,omitempty"`
+ VolumeClaimTemplates []ClusterComponentVolumeClaimTemplate `json:"volumeClaimTemplates,omitempty"`
}
// ClusterStatus defines the observed state of Cluster.
@@ -804,6 +804,10 @@ type ClusterComponentSpec struct {
// Any remaining replicas will be generated using the default template and will follow the default naming rules.
//
// +optional
+ // +patchMergeKey=name
+ // +patchStrategy=merge,retainKeys
+ // +listType=map
+ // +listMapKey=name
Instances []InstanceTemplate `json:"instances,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"name"`
// Specifies the names of instances to be transitioned to offline status.
@@ -1420,6 +1424,15 @@ func (r ClusterSpec) GetComponentByName(componentName string) *ClusterComponentS
return nil
}
+func (r ClusterSpec) GetShardingByName(shardingName string) *ShardingSpec {
+ for _, v := range r.ShardingSpecs {
+ if v.Name == shardingName {
+ return &v
+ }
+ }
+ return nil
+}
+
// GetComponentDefRefName gets the name of referenced component definition.
func (r ClusterSpec) GetComponentDefRefName(componentName string) string {
for _, component := range r.ComponentSpecs {
diff --git a/apis/apps/v1alpha1/opsrequest_types.go b/apis/apps/v1alpha1/opsrequest_types.go
index e4771d4339e..afb7d5c95ba 100644
--- a/apis/apps/v1alpha1/opsrequest_types.go
+++ b/apis/apps/v1alpha1/opsrequest_types.go
@@ -61,71 +61,42 @@ type OpsRequestSpec struct {
// Defines what component need to horizontal scale the specified replicas.
// +optional
- // +patchMergeKey=componentName
- // +patchStrategy=merge,retainKeys
- // +listType=map
- // +listMapKey=componentName
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.horizontalScaling"
- HorizontalScalingList []HorizontalScaling `json:"horizontalScaling,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"componentName"`
+ HorizontalScalingList []HorizontalScaling `json:"horizontalScaling,omitempty"`
// Note: Quantity struct can not do immutable check by CEL.
// Defines what component and volumeClaimTemplate need to expand the specified storage.
// +optional
- // +patchMergeKey=componentName
- // +patchStrategy=merge,retainKeys
- // +listType=map
- // +listMapKey=componentName
- VolumeExpansionList []VolumeExpansion `json:"volumeExpansion,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"componentName"`
+ VolumeExpansionList []VolumeExpansion `json:"volumeExpansion,omitempty"`
// Restarts the specified components.
// +optional
- // +patchMergeKey=componentName
- // +patchStrategy=merge,retainKeys
- // +listType=map
- // +listMapKey=componentName
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.restart"
- RestartList []ComponentOps `json:"restart,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"componentName"`
+ RestartList []ComponentOps `json:"restart,omitempty"`
// Switches over the specified components.
// +optional
- // +patchMergeKey=componentName
- // +patchStrategy=merge,retainKeys
- // +listType=map
- // +listMapKey=componentName
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.switchover"
- SwitchoverList []Switchover `json:"switchover,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"componentName"`
+ SwitchoverList []Switchover `json:"switchover,omitempty"`
// Note: Quantity struct can not do immutable check by CEL.
// Defines what component need to vertical scale the specified compute resources.
// +optional
- // +patchMergeKey=componentName
- // +patchStrategy=merge,retainKeys
- // +listType=map
- // +listMapKey=componentName
- VerticalScalingList []VerticalScaling `json:"verticalScaling,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"componentName"`
+ VerticalScalingList []VerticalScaling `json:"verticalScaling,omitempty"`
// Deprecated: replace by reconfigures.
// Defines the variables that need to input when updating configuration.
// +optional
- // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.reconfigure"
- // +kubebuilder:validation:XValidation:rule="self.configurations.size() > 0", message="Value can not be empty"
Reconfigure *Reconfigure `json:"reconfigure,omitempty"`
// Defines the variables that need to input when updating configuration.
+ // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.reconfigure"
// +optional
- // +patchMergeKey=componentName
- // +patchStrategy=merge,retainKeys
- // +listType=map
- // +listMapKey=componentName
Reconfigures []Reconfigure `json:"reconfigures,omitempty"`
// Defines services the component needs to expose.
// +optional
- // +patchMergeKey=componentName
- // +patchStrategy=merge,retainKeys
- // +listType=map
- // +listMapKey=componentName
- ExposeList []Expose `json:"expose,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"componentName"`
+ ExposeList []Expose `json:"expose,omitempty"`
// Cluster RestoreFrom backup or point in time.
// +optional
@@ -152,24 +123,23 @@ type OpsRequestSpec struct {
RestoreSpec *RestoreSpec `json:"restoreSpec,omitempty"`
// Specifies the instances that require re-creation.
- // +patchMergeKey=componentName
- // +patchStrategy=merge,retainKeys
- // +listType=map
- // +listMapKey=componentName
// +optional
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="forbidden to update spec.rebuildFrom"
- RebuildFrom []RebuildInstance `json:"rebuildFrom,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"componentName"`
+ RebuildFrom []RebuildInstance `json:"rebuildFrom,omitempty"`
// Specifies a custom operation as defined by OpsDefinition.
// +optional
CustomSpec *CustomOpsSpec `json:"customSpec,omitempty"`
}
-// ComponentOps represents the common variables required for operations within the scope of a component.
+// ComponentOps represents the common variables required for operations within the scope of a normal component/shard component.
+// +kubebuilder:validation:XValidation:rule="(has(self.componentName) && !has(self.shardingName)) || (has(self.shardingName) && !has(self.componentName))",message="either componentName or shardingName"
type ComponentOps struct {
// Specifies the name of the cluster component.
- // +kubebuilder:validation:Required
- ComponentName string `json:"componentName"`
+ ComponentName string `json:"componentName,omitempty"`
+
+ // Specifies the name of the cluster sharding component.
+ ShardingName string `json:"shardingName,omitempty"`
}
type RebuildInstance struct {
@@ -240,6 +210,27 @@ type VerticalScaling struct {
// Defines the computational resource size for vertical scaling.
// +kubebuilder:pruning:PreserveUnknownFields
corev1.ResourceRequirements `json:",inline"`
+
+ // Specifies the instance template that need to vertical scale.
+ Instances []PartInstanceTemplate `json:"instances,omitempty"`
+}
+
+type PartInstanceTemplate struct {
+ // Refer to the instance template name of the component or sharding.
+ // +kubebuilder:validation:Required
+ Name string `json:"name"`
+
+ // Defines the computational resource size for vertical scaling.
+ // +kubebuilder:pruning:PreserveUnknownFields
+ corev1.ResourceRequirements `json:",inline"`
+
+ // volumeClaimTemplates specifies the storage size and volumeClaimTemplate name.
+ // +kubebuilder:validation:Required
+ // +patchMergeKey=name
+ // +patchStrategy=merge,retainKeys
+ // +listType=map
+ // +listMapKey=name
+ VolumeClaimTemplates []OpsRequestVolumeClaimTemplate `json:"volumeClaimTemplates" patchStrategy:"merge,retainKeys" patchMergeKey:"name"`
}
// VolumeExpansion encapsulates the parameters required for a volume expansion operation.
@@ -253,6 +244,9 @@ type VolumeExpansion struct {
// +listType=map
// +listMapKey=name
VolumeClaimTemplates []OpsRequestVolumeClaimTemplate `json:"volumeClaimTemplates" patchStrategy:"merge,retainKeys" patchMergeKey:"name"`
+
+ // Specifies the instance template that need to volume expand.
+ Instances []PartInstanceTemplate `json:"instances,omitempty"`
}
type OpsRequestVolumeClaimTemplate struct {
@@ -355,20 +349,14 @@ type CustomOpsSpec struct {
Parallelism intstr.IntOrString `json:"parallelism,omitempty"`
// Defines which components need to perform the actions defined by this OpsDefinition.
- // At least one component is required. The components are identified by their name and can be merged or retained.
+ // At least one component/shardComponent is required. The components are identified by their name and can be merged or retained.
// +kubebuilder:validation:Required
// +kubebuilder:validation:MinItems=1
- // +patchMergeKey=name
- // +patchStrategy=merge,retainKeys
- // +listType=map
- // +listMapKey=name
- CustomOpsComponents []CustomOpsComponent `json:"components" patchStrategy:"merge,retainKeys" patchMergeKey:"name"`
+ CustomOpsItems []CustomOpsItem `json:"items"`
}
-type CustomOpsComponent struct {
- // Specifies the unique identifier of the cluster component
- // +kubebuilder:validation:Required
- ComponentName string `json:"name"`
+type CustomOpsItem struct {
+ ComponentOps `json:",inline"`
// Represents the parameters for this operation as declared in the opsDefinition.spec.parametersSchema.
// +patchMergeKey=name
@@ -428,7 +416,8 @@ const (
)
type Expose struct {
- ComponentOps `json:",inline"`
+ // Specifies the name of the cluster component.
+ ComponentName string `json:"componentName,omitempty"`
// Controls the expose operation.
// If set to Enable, the corresponding service will be exposed. Conversely, if set to Disable, the service will be removed.
@@ -437,7 +426,7 @@ type Expose struct {
Switch ExposeSwitch `json:"switch"`
// A list of services that are to be exposed or removed.
- // If componentNamem is not specified, each `OpsService` in the list must specify ports and selectors.
+ // If componentName is not specified, each `OpsService` in the list must specify ports and selectors.
//
// +kubebuilder:validation:Required
// +kubebuilder:validation:Minitems=0
@@ -696,7 +685,7 @@ type OpsRequestStatus struct {
// +optional
LastConfiguration LastConfiguration `json:"lastConfiguration,omitempty"`
- // Records the status information of components changed due to the operation request.
+ // Records the status information of components, including the sharding component, that have changed due to the operation request.
// +optional
Components map[string]OpsRequestComponentStatus `json:"components,omitempty"`
@@ -733,7 +722,7 @@ type OpsRequestStatus struct {
Conditions []metav1.Condition `json:"conditions,omitempty"`
}
-// +kubebuilder:validation:XValidation:rule="has(self.objectKey) || has(self.actionName)", message="either objectKey and actionName."
+// +kubebuilder:validation:XValidation:rule="has(self.objectKey) || has(self.actionName)", message="at least one objectKey or actionName."
type ProgressStatusDetail struct {
// Specifies the group to which the current object belongs.
@@ -819,11 +808,11 @@ type LastComponentConfiguration struct {
// Records the last instances of the component.
// +optional
- Instances *[]InstanceTemplate `json:"instances,omitempty"`
+ Instances []InstanceTemplate `json:"instances,omitempty"`
// Records the last offline instances of the component.
// +optional
- OfflineInstances *[]string `json:"offlineInstances,omitempty"`
+ OfflineInstances []string `json:"offlineInstances,omitempty"`
}
type LastConfiguration struct {
@@ -998,83 +987,12 @@ func init() {
SchemeBuilder.Register(&OpsRequest{}, &OpsRequestList{})
}
-// GetRestartComponentNameSet gets the component name map with restart operation.
-func (r OpsRequestSpec) GetRestartComponentNameSet() ComponentNameSet {
- set := make(ComponentNameSet)
- for _, v := range r.RestartList {
- set[v.ComponentName] = struct{}{}
- }
- return set
-}
-
-// GetSwitchoverComponentNameSet gets the component name map with switchover operation.
-func (r OpsRequestSpec) GetSwitchoverComponentNameSet() ComponentNameSet {
- set := make(ComponentNameSet)
- for _, v := range r.SwitchoverList {
- set[v.ComponentName] = struct{}{}
- }
- return set
-}
-
-// GetVerticalScalingComponentNameSet gets the component name map with vertical scaling operation.
-func (r OpsRequestSpec) GetVerticalScalingComponentNameSet() ComponentNameSet {
- set := make(ComponentNameSet)
- for _, v := range r.VerticalScalingList {
- set[v.ComponentName] = struct{}{}
- }
- return set
-}
-
-// ToVerticalScalingListToMap converts OpsRequest.spec.verticalScaling list to map
-func (r OpsRequestSpec) ToVerticalScalingListToMap() map[string]VerticalScaling {
- verticalScalingMap := make(map[string]VerticalScaling)
- for _, v := range r.VerticalScalingList {
- verticalScalingMap[v.ComponentName] = v
- }
- return verticalScalingMap
-}
-
-// GetHorizontalScalingComponentNameSet gets the component name map with horizontal scaling operation.
-func (r OpsRequestSpec) GetHorizontalScalingComponentNameSet() ComponentNameSet {
- set := make(ComponentNameSet)
- for _, v := range r.HorizontalScalingList {
- set[v.ComponentName] = struct{}{}
- }
- return set
-}
-
-// ToHorizontalScalingListToMap converts OpsRequest.spec.horizontalScaling list to map
-func (r OpsRequestSpec) ToHorizontalScalingListToMap() map[string]HorizontalScaling {
- verticalScalingMap := make(map[string]HorizontalScaling)
- for _, v := range r.HorizontalScalingList {
- verticalScalingMap[v.ComponentName] = v
- }
- return verticalScalingMap
-}
-
-// GetVolumeExpansionComponentNameSet gets the component name map with volume expansion operation.
-func (r OpsRequestSpec) GetVolumeExpansionComponentNameSet() ComponentNameSet {
- set := make(ComponentNameSet)
- for _, v := range r.VolumeExpansionList {
- set[v.ComponentName] = struct{}{}
- }
- return set
-}
-
-// GetDataScriptComponentNameSet gets the component name map with switchover operation.
-func (r OpsRequestSpec) GetDataScriptComponentNameSet() ComponentNameSet {
- set := make(ComponentNameSet)
- set[r.ScriptSpec.ComponentName] = struct{}{}
- return set
+func (c ComponentOps) GetComponentName() string {
+ return c.ComponentName
}
-// ToVolumeExpansionListToMap converts volumeExpansionList to map
-func (r OpsRequestSpec) ToVolumeExpansionListToMap() map[string]VolumeExpansion {
- volumeExpansionMap := make(map[string]VolumeExpansion)
- for _, v := range r.VolumeExpansionList {
- volumeExpansionMap[v.ComponentName] = v
- }
- return volumeExpansionMap
+func (c ComponentOps) GetShardingName() string {
+ return c.ShardingName
}
// ToExposeListToMap build expose map
@@ -1086,62 +1004,6 @@ func (r OpsRequestSpec) ToExposeListToMap() map[string]Expose {
return exposeMap
}
-// GetReconfiguringComponentNameSet gets the component name map with reconfiguring operation.
-func (r OpsRequestSpec) GetReconfiguringComponentNameSet() ComponentNameSet {
- if r.Reconfigure == nil {
- return nil
- }
- return ComponentNameSet{
- r.Reconfigure.ComponentName: {},
- }
-}
-
-func (r OpsRequestSpec) GetExposeComponentNameSet() ComponentNameSet {
- set := make(ComponentNameSet)
- for _, v := range r.ExposeList {
- set[v.ComponentName] = struct{}{}
- }
- return set
-}
-
-// GetUpgradeComponentNameSet gets the component name map with upgrade operation.
-func (r *OpsRequest) GetUpgradeComponentNameSet() ComponentNameSet {
- if r == nil || r.Spec.Upgrade == nil {
- return nil
- }
- set := make(ComponentNameSet)
- for k := range r.Status.Components {
- set[k] = struct{}{}
- }
- return set
-}
-
-// GetComponentNameSet if the operations are within the scope of component, this function should be implemented
-func (r *OpsRequest) GetComponentNameSet() ComponentNameSet {
- switch r.Spec.Type {
- case RestartType:
- return r.Spec.GetRestartComponentNameSet()
- case VerticalScalingType:
- return r.Spec.GetVerticalScalingComponentNameSet()
- case HorizontalScalingType:
- return r.Spec.GetHorizontalScalingComponentNameSet()
- case VolumeExpansionType:
- return r.Spec.GetVolumeExpansionComponentNameSet()
- case UpgradeType:
- return r.GetUpgradeComponentNameSet()
- case ReconfiguringType:
- return r.Spec.GetReconfiguringComponentNameSet()
- case ExposeType:
- return r.Spec.GetExposeComponentNameSet()
- case SwitchoverType:
- return r.Spec.GetSwitchoverComponentNameSet()
- case DataScriptType:
- return r.Spec.GetDataScriptComponentNameSet()
- default:
- return nil
- }
-}
-
func (p *ProgressStatusDetail) SetStatusAndMessage(status ProgressStatus, message string) {
p.Message = message
p.Status = status
diff --git a/apis/apps/v1alpha1/opsrequest_types_test.go b/apis/apps/v1alpha1/opsrequest_types_test.go
index 86e731f117d..c9635b8e702 100644
--- a/apis/apps/v1alpha1/opsrequest_types_test.go
+++ b/apis/apps/v1alpha1/opsrequest_types_test.go
@@ -22,158 +22,12 @@ import (
var componentName = "mysql"
-func mockRestartOps() *OpsRequest {
- ops := &OpsRequest{}
- ops.Spec.Type = RestartType
- ops.Spec.RestartList = []ComponentOps{
- {
- ComponentName: componentName,
- },
- }
- return ops
-}
-
-func TestGetRestartComponentNameSet(t *testing.T) {
- ops := mockRestartOps()
- componentNameSet := ops.Spec.GetRestartComponentNameSet()
- checkComponentMap(t, componentNameSet, len(ops.Spec.RestartList), componentName)
- componentNameSet1 := ops.GetComponentNameSet()
- checkComponentMap(t, componentNameSet1, len(ops.Spec.RestartList), componentName)
-}
-
-func mockVerticalScalingOps() *OpsRequest {
- ops := &OpsRequest{}
- ops.Spec.Type = VerticalScalingType
- ops.Spec.VerticalScalingList = []VerticalScaling{
- {
- ComponentOps: ComponentOps{
- ComponentName: componentName,
- },
- },
- }
- return ops
-}
-
-func TestGetVerticalScalingComponentNameSet(t *testing.T) {
- ops := mockVerticalScalingOps()
- componentNameSet := ops.Spec.GetVerticalScalingComponentNameSet()
- checkComponentMap(t, componentNameSet, len(ops.Spec.VerticalScalingList), componentName)
- componentNameSet1 := ops.GetComponentNameSet()
- checkComponentMap(t, componentNameSet1, len(ops.Spec.VerticalScalingList), componentName)
-}
-
-func mockHorizontalScalingOps() *OpsRequest {
- ops := &OpsRequest{}
- ops.Spec.Type = HorizontalScalingType
- ops.Spec.HorizontalScalingList = []HorizontalScaling{
- {
- ComponentOps: ComponentOps{
- ComponentName: componentName,
- },
- },
- }
- return ops
-}
-
-func TestGetHorizontalScalingComponentNameSet(t *testing.T) {
- ops := mockHorizontalScalingOps()
- componentNameSet := ops.Spec.GetHorizontalScalingComponentNameSet()
- checkComponentMap(t, componentNameSet, len(ops.Spec.HorizontalScalingList), componentName)
- componentNameSet1 := ops.GetComponentNameSet()
- checkComponentMap(t, componentNameSet1, len(ops.Spec.HorizontalScalingList), componentName)
-}
-
-func mockVolumeExpansionOps() *OpsRequest {
- ops := &OpsRequest{}
- ops.Spec.Type = VolumeExpansionType
- ops.Spec.VolumeExpansionList = []VolumeExpansion{
- {
- ComponentOps: ComponentOps{
- ComponentName: componentName,
- },
- },
- }
- return ops
-}
-
-func TestVolumeExpansioncomponentNameSet(t *testing.T) {
- ops := mockVolumeExpansionOps()
- componentNameSet := ops.Spec.GetVolumeExpansionComponentNameSet()
- checkComponentMap(t, componentNameSet, len(ops.Spec.VolumeExpansionList), componentName)
- componentNameSet1 := ops.GetComponentNameSet()
- checkComponentMap(t, componentNameSet1, len(ops.Spec.VolumeExpansionList), componentName)
-}
-
-func checkComponentMap(t *testing.T, componentNameSet map[string]struct{}, expectLen int, expectName string) {
- if len(componentNameSet) != expectLen {
- t.Error(`Expected component name map length equals list length`)
- }
- if _, ok := componentNameSet[expectName]; !ok {
- t.Error(`Expected component name map exists the key of "mysql"`)
- }
-}
-
-func TestToVerticalScalingListToMap(t *testing.T) {
- ops := mockVerticalScalingOps()
- verticalScalingMap := ops.Spec.ToVerticalScalingListToMap()
- if len(verticalScalingMap) != len(ops.Spec.VerticalScalingList) {
- t.Error(`Expected vertical scaling map length equals list length`)
- }
- if _, ok := verticalScalingMap[componentName]; !ok {
- t.Error(`Expected component name map exists the key of "mysql"`)
- }
-}
-
-func TestConvertVolumeExpansionListToMap(t *testing.T) {
- ops := mockVolumeExpansionOps()
- volumeExpansionMap := ops.Spec.ToVolumeExpansionListToMap()
- if len(volumeExpansionMap) != len(ops.Spec.VolumeExpansionList) {
- t.Error(`Expected volume expansion map length equals list length`)
- }
- if _, ok := volumeExpansionMap[componentName]; !ok {
- t.Error(`Expected component name map exists the key of "mysql"`)
- }
-}
-
-func TestToHorizontalScalingListToMap(t *testing.T) {
- ops := mockHorizontalScalingOps()
- horizontalScalingMap := ops.Spec.ToHorizontalScalingListToMap()
- if len(horizontalScalingMap) != len(ops.Spec.HorizontalScalingList) {
- t.Error(`Expected horizontal scaling map length equals list length`)
- }
- if _, ok := horizontalScalingMap[componentName]; !ok {
- t.Error(`Expected component name map exists the key of "mysql"`)
- }
-}
-
-func TestGetUpgradeComponentNameSet(t *testing.T) {
- ops := &OpsRequest{}
- ops.Spec.Type = UpgradeType
- componentNameSet := ops.GetUpgradeComponentNameSet()
- if componentNameSet != nil {
- t.Error(`Expected component name map of upgrade ops is nil`)
- }
- ops.Spec.Upgrade = &Upgrade{
- ClusterVersionRef: "test-version",
- }
- ops.Status.Components = map[string]OpsRequestComponentStatus{
- componentName: {},
- }
-
- componentNameSet = ops.GetUpgradeComponentNameSet()
- checkComponentMap(t, componentNameSet, len(ops.Status.Components), componentName)
- componentNameSet1 := ops.GetComponentNameSet()
- checkComponentMap(t, componentNameSet1, len(ops.Status.Components), componentName)
-}
-
func mockExposeOps() *OpsRequest {
ops := &OpsRequest{}
ops.Spec.Type = ExposeType
ops.Spec.ExposeList = []Expose{
{
- ComponentOps: ComponentOps{
- ComponentName: componentName,
- },
+ ComponentName: componentName,
},
}
return ops
@@ -190,25 +44,6 @@ func TestToExposeListToMap(t *testing.T) {
}
}
-func TestGetExposeComponentNameSet(t *testing.T) {
- ops := mockExposeOps()
- componentNameSet := ops.Spec.GetExposeComponentNameSet()
- checkComponentMap(t, componentNameSet, len(ops.Spec.ExposeList), componentName)
- componentNameSet1 := ops.GetComponentNameSet()
- checkComponentMap(t, componentNameSet1, len(ops.Spec.ExposeList), componentName)
-}
-
-func TestGetReconfiguringComponentNameSet(t *testing.T) {
- ops := &OpsRequest{}
- ops.Spec.Type = ReconfiguringType
- ops.Spec.Reconfigure = &Reconfigure{
- ComponentOps: ComponentOps{
- ComponentName: componentName,
- },
- }
- ops.Spec.GetReconfiguringComponentNameSet()
-}
-
func TestSetStatusAndMessage(t *testing.T) {
p := ProgressStatusDetail{}
message := "handle successfully"
diff --git a/apis/apps/v1alpha1/opsrequest_webhook.go b/apis/apps/v1alpha1/opsrequest_webhook.go
index 40bff05aa35..af542208456 100644
--- a/apis/apps/v1alpha1/opsrequest_webhook.go
+++ b/apis/apps/v1alpha1/opsrequest_webhook.go
@@ -31,6 +31,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
+ "k8s.io/apimachinery/pkg/util/sets"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
logf "sigs.k8s.io/controller-runtime/pkg/log"
@@ -240,12 +241,11 @@ func (r *OpsRequest) validateExpose(_ context.Context, cluster *Cluster) error {
return notEmptyError("spec.expose")
}
- // compNames := make([]string, len(exposeList))
- var componentNames []string
+ var compOpsList []ComponentOps
counter := 0
for _, v := range exposeList {
if len(v.ComponentName) > 0 {
- componentNames = append(componentNames, v.ComponentName)
+ compOpsList = append(compOpsList, ComponentOps{ComponentName: v.ComponentName})
continue
} else {
counter++
@@ -261,7 +261,7 @@ func (r *OpsRequest) validateExpose(_ context.Context, cluster *Cluster) error {
}
}
}
- return r.checkComponentExistence(cluster, componentNames)
+ return r.checkComponentExistence(cluster, compOpsList)
}
// validateUpgrade validates spec.restart
@@ -271,11 +271,7 @@ func (r *OpsRequest) validateRestart(cluster *Cluster) error {
return notEmptyError("spec.restart")
}
- compNames := make([]string, len(restartList))
- for i, v := range restartList {
- compNames[i] = v.ComponentName
- }
- return r.checkComponentExistence(cluster, compNames)
+ return r.checkComponentExistence(cluster, restartList)
}
// validateUpgrade validates spec.clusterOps.upgrade
@@ -301,10 +297,12 @@ func (r *OpsRequest) validateVerticalScaling(cluster *Cluster) error {
}
// validate resources is legal and get component name slice
- componentNames := make([]string, len(verticalScalingList))
+ compOpsList := make([]ComponentOps, len(verticalScalingList))
for i, v := range verticalScalingList {
- componentNames[i] = v.ComponentName
-
+ compOpsList[i] = v.ComponentOps
+ if err := r.checkInstanceTemplate(cluster, v.ComponentOps, v.Instances); err != nil {
+ return err
+ }
if invalidValue, err := validateVerticalResourceList(v.Requests); err != nil {
return invalidValueError(invalidValue, err.Error())
}
@@ -315,7 +313,7 @@ func (r *OpsRequest) validateVerticalScaling(cluster *Cluster) error {
return invalidValueError(invalidValue, err.Error())
}
}
- return r.checkComponentExistence(cluster, componentNames)
+ return r.checkComponentExistence(cluster, compOpsList)
}
// validateVerticalScaling validate api is legal when spec.type is VerticalScaling
@@ -391,11 +389,11 @@ func (r *OpsRequest) validateHorizontalScaling(_ context.Context, _ client.Clien
return notEmptyError("spec.horizontalScaling")
}
- componentNames := make([]string, len(horizontalScalingList))
+ compOpsList := make([]ComponentOps, len(horizontalScalingList))
for i, v := range horizontalScalingList {
- componentNames[i] = v.ComponentName
+ compOpsList[i] = v.ComponentOps
}
- return r.checkComponentExistence(cluster, componentNames)
+ return r.checkComponentExistence(cluster, compOpsList)
}
// validateVolumeExpansion validates volumeExpansion api when spec.type is VolumeExpansion
@@ -405,11 +403,15 @@ func (r *OpsRequest) validateVolumeExpansion(ctx context.Context, cli client.Cli
return notEmptyError("spec.volumeExpansion")
}
- componentNames := make([]string, len(volumeExpansionList))
+ compOpsList := make([]ComponentOps, len(volumeExpansionList))
for i, v := range volumeExpansionList {
- componentNames[i] = v.ComponentName
+ // TODO: check instances
+ compOpsList[i] = v.ComponentOps
+ if err := r.checkInstanceTemplate(cluster, v.ComponentOps, v.Instances); err != nil {
+ return err
+ }
}
- if err := r.checkComponentExistence(cluster, componentNames); err != nil {
+ if err := r.checkComponentExistence(cluster, compOpsList); err != nil {
return err
}
return r.checkVolumesAllowExpansion(ctx, cli, cluster)
@@ -421,34 +423,86 @@ func (r *OpsRequest) validateSwitchover(ctx context.Context, cli client.Client,
if len(switchoverList) == 0 {
return notEmptyError("spec.switchover")
}
- componentNames := make([]string, len(switchoverList))
+ compOpsList := make([]ComponentOps, len(switchoverList))
for i, v := range switchoverList {
- componentNames[i] = v.ComponentName
+ compOpsList[i] = v.ComponentOps
}
- if err := r.checkComponentExistence(cluster, componentNames); err != nil {
+ if err := r.checkComponentExistence(cluster, compOpsList); err != nil {
return err
}
return validateSwitchoverResourceList(ctx, cli, cluster, switchoverList)
}
+func (r *OpsRequest) checkInstanceTemplate(cluster *Cluster, componentOps ComponentOps, inputInstances []PartInstanceTemplate) error {
+ instanceNameMap := make(map[string]sets.Empty)
+ setInstanceMap := func(instances []InstanceTemplate) {
+ for i := range instances {
+ instanceNameMap[instances[i].Name] = sets.Empty{}
+ }
+ }
+ if componentOps.ShardingName != "" {
+ for _, shardingSpec := range cluster.Spec.ShardingSpecs {
+ if shardingSpec.Name != componentOps.ShardingName {
+ continue
+ }
+ setInstanceMap(shardingSpec.Template.Instances)
+ }
+ } else {
+ for _, compSpec := range cluster.Spec.ComponentSpecs {
+ if compSpec.Name != componentOps.ComponentName {
+ continue
+ }
+ setInstanceMap(compSpec.Instances)
+ }
+ }
+ var notFoundInstanceNames []string
+ for _, v := range inputInstances {
+ if _, ok := instanceNameMap[v.Name]; !ok {
+ notFoundInstanceNames = append(notFoundInstanceNames, v.Name)
+ }
+ }
+ if len(notFoundInstanceNames) > 0 {
+ return fmt.Errorf("instance: %v not found in cluster: %s", notFoundInstanceNames, r.Spec.ClusterRef)
+ }
+ return nil
+}
+
// checkComponentExistence checks whether components to be operated exist in cluster spec.
-func (r *OpsRequest) checkComponentExistence(cluster *Cluster, compNames []string) error {
- compSpecNameMap := make(map[string]bool)
+func (r *OpsRequest) checkComponentExistence(cluster *Cluster, compOpsList []ComponentOps) error {
+ compSpecNameMap := make(map[string]sets.Empty)
+ shardingMap := make(map[string]sets.Empty)
for _, compSpec := range cluster.Spec.ComponentSpecs {
- compSpecNameMap[compSpec.Name] = true
+ compSpecNameMap[compSpec.Name] = sets.Empty{}
}
-
- var notFoundCompNames []string
- for _, compName := range compNames {
- if _, ok := compSpecNameMap[compName]; !ok {
- notFoundCompNames = append(notFoundCompNames, compName)
+ for _, shardingSpec := range cluster.Spec.ShardingSpecs {
+ shardingMap[shardingSpec.Name] = sets.Empty{}
+ }
+ var (
+ notFoundCompNames []string
+ notFoundShardingNames []string
+ )
+ for _, compOps := range compOpsList {
+ if compOps.ComponentName != "" {
+ if _, ok := compSpecNameMap[compOps.ComponentName]; !ok {
+ notFoundCompNames = append(notFoundCompNames, compOps.ComponentName)
+ }
+ continue
}
+ if compOps.ShardingName != "" {
+ if _, ok := shardingMap[compOps.ShardingName]; !ok {
+ notFoundShardingNames = append(notFoundShardingNames, compOps.ShardingName)
+ }
+ continue
+ }
+ return fmt.Errorf("shardingName or componentName can not be empty")
}
if len(notFoundCompNames) > 0 {
- return fmt.Errorf("components: %v not found, you can view the components by command: "+
- "kbcli cluster describe %s -n %s", notFoundCompNames, cluster.Name, r.Namespace)
+ return fmt.Errorf("components: %v not found, in cluster.spec.componentSpecs", notFoundCompNames)
+ }
+ if len(notFoundShardingNames) > 0 {
+ return fmt.Errorf("shardings: %v not found in cluster.spec.shardingSpecs", notFoundShardingNames)
}
return nil
}
@@ -461,41 +515,75 @@ func (r *OpsRequest) checkVolumesAllowExpansion(ctx context.Context, cli client.
requestStorage resource.Quantity
}
- // component name -> vct name -> entity
vols := make(map[string]map[string]Entity)
- for _, comp := range r.Spec.VolumeExpansionList {
- for _, vct := range comp.VolumeClaimTemplates {
- if _, ok := vols[comp.ComponentName]; !ok {
- vols[comp.ComponentName] = make(map[string]Entity)
+ // component name/ sharding name -> vct name -> entity
+ getKey := func(compName, shardingName, templateName string) string {
+ templateKey := ""
+ if templateName != "" {
+ templateKey = "." + templateName
+ }
+ if compName != "" {
+ return fmt.Sprintf("component.%s%s", compName, templateKey)
+ }
+ return fmt.Sprintf("sharding.%s%s", shardingName, templateKey)
+ }
+ setVols := func(vcts []OpsRequestVolumeClaimTemplate, compOps ComponentOps, templateName string) {
+ for _, vct := range vcts {
+ key := getKey(compOps.ComponentName, compOps.ShardingName, templateName)
+ if _, ok := vols[key]; !ok {
+ vols[key] = make(map[string]Entity)
}
- vols[comp.ComponentName][vct.Name] = Entity{false, nil, false, vct.Storage}
+ vols[key][vct.Name] = Entity{false, nil, false, vct.Storage}
}
}
- // traverse the spec to update volumes
- for _, comp := range cluster.Spec.ComponentSpecs {
- if _, ok := vols[comp.Name]; !ok {
- continue // ignore not-exist component
+
+ for _, comp := range r.Spec.VolumeExpansionList {
+ setVols(comp.VolumeClaimTemplates, comp.ComponentOps, "")
+ for _, ins := range comp.Instances {
+ setVols(ins.VolumeClaimTemplates, comp.ComponentOps, ins.Name)
}
- for _, vct := range comp.VolumeClaimTemplates {
- e, ok := vols[comp.Name][vct.Name]
- if !ok {
- continue
+ }
+ fillVol := func(vct ClusterComponentVolumeClaimTemplate, key string) {
+ e, ok := vols[key][vct.Name]
+ if !ok {
+ return
+ }
+ e.existInSpec = true
+ e.storageClassName = vct.Spec.StorageClassName
+ vols[key][vct.Name] = e
+ }
+ fillCompVols := func(compSpec ClusterComponentSpec, compName, shardingName string) {
+ key := getKey(compName, shardingName, "")
+ if _, ok := vols[key]; !ok {
+ return // ignore not-exist component
+ }
+ for _, vct := range compSpec.VolumeClaimTemplates {
+ fillVol(vct, key)
+ }
+ for _, ins := range compSpec.Instances {
+ key = getKey(compName, shardingName, ins.Name)
+ for _, vct := range ins.VolumeClaimTemplates {
+ fillVol(vct, key)
}
- e.existInSpec = true
- e.storageClassName = vct.Spec.StorageClassName
- vols[comp.Name][vct.Name] = e
}
}
+ // traverse the spec to update volumes
+ for _, comp := range cluster.Spec.ComponentSpecs {
+ fillCompVols(comp, comp.Name, "")
+ }
+ for _, sharding := range cluster.Spec.ShardingSpecs {
+ fillCompVols(sharding.Template, "", sharding.Name)
+ }
// check all used storage classes
var err error
- for cname, compVols := range vols {
+ for key, compVols := range vols {
for vname := range compVols {
- e := vols[cname][vname]
+ e := vols[key][vname]
if !e.existInSpec {
continue
}
- e.storageClassName, err = r.getSCNameByPvcAndCheckStorageSize(ctx, cli, cname, vname, e.requestStorage)
+ e.storageClassName, err = r.getSCNameByPvcAndCheckStorageSize(ctx, cli, key, vname, e.requestStorage)
if err != nil {
return err
}
@@ -504,11 +592,11 @@ func (r *OpsRequest) checkVolumesAllowExpansion(ctx context.Context, cli client.
continue // ignore the error and take it as not-supported
}
e.allowExpansion = allowExpansion
- vols[cname][vname] = e
+ vols[key][vname] = e
}
}
- for cname, compVols := range vols {
+ for key, compVols := range vols {
var (
notFound []string
notSupport []string
@@ -525,17 +613,18 @@ func (r *OpsRequest) checkVolumesAllowExpansion(ctx context.Context, cli client.
}
}
}
+ keyStrs := strings.Split(key, ".")
if len(notFound) > 0 {
- return fmt.Errorf("volumeClaimTemplates: %v not found in component: %s, you can view infos by command: "+
- "kbcli cluster describe %s -n %s", notFound, cname, cluster.Name, r.Namespace)
+ return fmt.Errorf("volumeClaimTemplates: %v not found in %s: %s, you can view infos by command: "+
+ "kubectl get cluster %s -n %s", notFound, keyStrs[0], keyStrs[1], cluster.Name, r.Namespace)
}
if len(notSupport) > 0 {
var notSupportScString string
if len(notSupportSc) > 0 {
notSupportScString = fmt.Sprintf("storageClass: %v of ", notSupportSc)
}
- return fmt.Errorf(notSupportScString+"volumeClaimTemplate: %s not support volume expansion in component: %s, you can view infos by command: "+
- "kubectl get sc", notSupport, cname)
+ return fmt.Errorf(notSupportScString+"volumeClaimTemplate: %v not support volume expansion in %s: %s, you can view infos by command: "+
+ "kubectl get sc", notSupport, keyStrs[0], keyStrs[1])
}
}
return nil
@@ -562,31 +651,27 @@ func (r *OpsRequest) checkStorageClassAllowExpansion(ctx context.Context,
// getSCNameByPvcAndCheckStorageSize gets the storageClassName by pvc and checks if the storage size is valid.
func (r *OpsRequest) getSCNameByPvcAndCheckStorageSize(ctx context.Context,
cli client.Client,
- compName,
+ key,
vctName string,
requestStorage resource.Quantity) (*string, error) {
+ keyStrs := strings.Split(key, ".")
+ matchingLabels := client.MatchingLabels{
+ constant.AppInstanceLabelKey: r.Spec.ClusterRef,
+ constant.VolumeClaimTemplateNameLabelKey: vctName,
+ }
+ if keyStrs[0] == "component" {
+ matchingLabels[constant.KBAppComponentLabelKey] = keyStrs[1]
+ } else {
+ matchingLabels[constant.KBAppShardingNameLabelKey] = keyStrs[1]
+ }
pvcList := &corev1.PersistentVolumeClaimList{}
- if err := cli.List(ctx, pvcList, client.InNamespace(r.Namespace), client.MatchingLabels{
- constant.AppInstanceLabelKey: r.Spec.ClusterRef,
- constant.KBAppComponentLabelKey: compName,
- }); err != nil {
+ if err := cli.List(ctx, pvcList, client.InNamespace(r.Namespace), matchingLabels); err != nil {
return nil, err
}
if len(pvcList.Items) == 0 {
return nil, nil
}
- var pvc *corev1.PersistentVolumeClaim
- for _, v := range pvcList.Items {
- // VolumeClaimTemplateNameLabelKeyForLegacy is deprecated: only compatible with version 0.5, will be removed in 0.7?
- if v.Labels[constant.VolumeClaimTemplateNameLabelKey] == vctName ||
- v.Labels[constant.VolumeClaimTemplateNameLabelKeyForLegacy] == vctName {
- pvc = &v
- break
- }
- }
- if pvc == nil {
- return nil, nil
- }
+ pvc := pvcList.Items[0]
previousValue := *pvc.Status.Capacity.Storage()
if requestStorage.Cmp(previousValue) < 0 {
return nil, fmt.Errorf(`requested storage size of volumeClaimTemplate "%s" can not less than status.capacity.storage "%s" `,
@@ -626,7 +711,7 @@ func (r *OpsRequest) validateDataScript(ctx context.Context, cli client.Client,
return notEmptyError("spec.scriptSpec")
}
- if err := r.checkComponentExistence(cluster, []string{scriptSpec.ComponentName}); err != nil {
+ if err := r.checkComponentExistence(cluster, []ComponentOps{scriptSpec.ComponentOps}); err != nil {
return err
}
diff --git a/apis/apps/v1alpha1/type.go b/apis/apps/v1alpha1/type.go
index 6aecaae1c5d..341a5ad6d85 100644
--- a/apis/apps/v1alpha1/type.go
+++ b/apis/apps/v1alpha1/type.go
@@ -792,8 +792,6 @@ func RegisterWebhookManager(mgr manager.Manager) {
webhookMgr = &webhookManager{mgr.GetClient()}
}
-type ComponentNameSet map[string]struct{}
-
var (
ErrWorkloadTypeIsUnknown = errors.New("workloadType is unknown")
ErrWorkloadTypeIsStateless = errors.New("workloadType should not be stateless")
diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go
index 158f1516479..a41cfb30499 100644
--- a/apis/apps/v1alpha1/zz_generated.deepcopy.go
+++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go
@@ -1847,27 +1847,6 @@ func (in ComponentMessageMap) DeepCopy() ComponentMessageMap {
return *out
}
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in ComponentNameSet) DeepCopyInto(out *ComponentNameSet) {
- {
- in := &in
- *out = make(ComponentNameSet, len(*in))
- for key, val := range *in {
- (*out)[key] = val
- }
- }
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentNameSet.
-func (in ComponentNameSet) DeepCopy() ComponentNameSet {
- if in == nil {
- return nil
- }
- out := new(ComponentNameSet)
- in.DeepCopyInto(out)
- return *out
-}
-
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ComponentOps) DeepCopyInto(out *ComponentOps) {
*out = *in
@@ -2936,8 +2915,9 @@ func (in *CustomLabelSpec) DeepCopy() *CustomLabelSpec {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *CustomOpsComponent) DeepCopyInto(out *CustomOpsComponent) {
+func (in *CustomOpsItem) DeepCopyInto(out *CustomOpsItem) {
*out = *in
+ out.ComponentOps = in.ComponentOps
if in.Parameters != nil {
in, out := &in.Parameters, &out.Parameters
*out = make([]Parameter, len(*in))
@@ -2945,12 +2925,12 @@ func (in *CustomOpsComponent) DeepCopyInto(out *CustomOpsComponent) {
}
}
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomOpsComponent.
-func (in *CustomOpsComponent) DeepCopy() *CustomOpsComponent {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomOpsItem.
+func (in *CustomOpsItem) DeepCopy() *CustomOpsItem {
if in == nil {
return nil
}
- out := new(CustomOpsComponent)
+ out := new(CustomOpsItem)
in.DeepCopyInto(out)
return out
}
@@ -2964,9 +2944,9 @@ func (in *CustomOpsSpec) DeepCopyInto(out *CustomOpsSpec) {
**out = **in
}
out.Parallelism = in.Parallelism
- if in.CustomOpsComponents != nil {
- in, out := &in.CustomOpsComponents, &out.CustomOpsComponents
- *out = make([]CustomOpsComponent, len(*in))
+ if in.CustomOpsItems != nil {
+ in, out := &in.CustomOpsItems, &out.CustomOpsItems
+ *out = make([]CustomOpsItem, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
@@ -3081,7 +3061,6 @@ func (in *ExecAction) DeepCopy() *ExecAction {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Expose) DeepCopyInto(out *Expose) {
*out = *in
- out.ComponentOps = in.ComponentOps
if in.Services != nil {
in, out := &in.Services, &out.Services
*out = make([]OpsService, len(*in))
@@ -3318,7 +3297,7 @@ func (in *InstanceTemplate) DeepCopyInto(out *InstanceTemplate) {
}
if in.VolumeClaimTemplates != nil {
in, out := &in.VolumeClaimTemplates, &out.VolumeClaimTemplates
- *out = make([]v1.PersistentVolumeClaim, len(*in))
+ *out = make([]ClusterComponentVolumeClaimTemplate, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
@@ -3410,23 +3389,15 @@ func (in *LastComponentConfiguration) DeepCopyInto(out *LastComponentConfigurati
}
if in.Instances != nil {
in, out := &in.Instances, &out.Instances
- *out = new([]InstanceTemplate)
- if **in != nil {
- in, out := *in, *out
- *out = make([]InstanceTemplate, len(*in))
- for i := range *in {
- (*in)[i].DeepCopyInto(&(*out)[i])
- }
+ *out = make([]InstanceTemplate, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.OfflineInstances != nil {
in, out := &in.OfflineInstances, &out.OfflineInstances
- *out = new([]string)
- if **in != nil {
- in, out := *in, *out
- *out = make([]string, len(*in))
- copy(*out, *in)
- }
+ *out = make([]string, len(*in))
+ copy(*out, *in)
}
}
@@ -4340,6 +4311,29 @@ func (in *ParametersSchema) DeepCopy() *ParametersSchema {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PartInstanceTemplate) DeepCopyInto(out *PartInstanceTemplate) {
+ *out = *in
+ in.ResourceRequirements.DeepCopyInto(&out.ResourceRequirements)
+ if in.VolumeClaimTemplates != nil {
+ in, out := &in.VolumeClaimTemplates, &out.VolumeClaimTemplates
+ *out = make([]OpsRequestVolumeClaimTemplate, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PartInstanceTemplate.
+func (in *PartInstanceTemplate) DeepCopy() *PartInstanceTemplate {
+ if in == nil {
+ return nil
+ }
+ out := new(PartInstanceTemplate)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PasswordConfig) DeepCopyInto(out *PasswordConfig) {
*out = *in
@@ -6111,6 +6105,13 @@ func (in *VerticalScaling) DeepCopyInto(out *VerticalScaling) {
*out = *in
out.ComponentOps = in.ComponentOps
in.ResourceRequirements.DeepCopyInto(&out.ResourceRequirements)
+ if in.Instances != nil {
+ in, out := &in.Instances, &out.Instances
+ *out = make([]PartInstanceTemplate, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerticalScaling.
@@ -6134,6 +6135,13 @@ func (in *VolumeExpansion) DeepCopyInto(out *VolumeExpansion) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
+ if in.Instances != nil {
+ in, out := &in.Instances, &out.Instances
+ *out = make([]PartInstanceTemplate, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeExpansion.
diff --git a/apis/workloads/v1alpha1/instanceset_types.go b/apis/workloads/v1alpha1/instanceset_types.go
index dcf12512aec..1bc31586928 100644
--- a/apis/workloads/v1alpha1/instanceset_types.go
+++ b/apis/workloads/v1alpha1/instanceset_types.go
@@ -183,6 +183,10 @@ type InstanceSetSpec struct {
// Any remaining replicas will be generated using the default template and will follow the default naming rules.
//
// +optional
+ // +patchMergeKey=name
+ // +patchStrategy=merge,retainKeys
+ // +listType=map
+ // +listMapKey=name
Instances []InstanceTemplate `json:"instances,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"name"`
// Specifies the names of instances to be transitioned to offline status.
diff --git a/config/crd/bases/apps.kubeblocks.io_clusters.yaml b/config/crd/bases/apps.kubeblocks.io_clusters.yaml
index b94251418b9..c67d8222d14 100644
--- a/config/crd/bases/apps.kubeblocks.io_clusters.yaml
+++ b/config/crd/bases/apps.kubeblocks.io_clusters.yaml
@@ -675,166 +675,40 @@ spec:
description: Defines VolumeClaimTemplates to override.
Add new or override existing volume claim templates.
items:
- description: PersistentVolumeClaim is a user's request
- for and claim to a persistent volume
properties:
- apiVersion:
- description: 'APIVersion defines the versioned schema
- of this representation of an object. Servers should
- convert recognized schemas to the latest internal
- value, and may reject unrecognized values. More
- info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
- type: string
- kind:
- description: 'Kind is a string value representing
- the REST resource this object represents. Servers
- may infer this from the endpoint the client submits
- requests to. Cannot be updated. In CamelCase.
- More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ name:
+ description: "Refers to the name of a volumeMount
+ defined in either: \n - `componentDefinition.spec.runtime.containers[*].volumeMounts`
+ - `clusterDefinition.spec.componentDefs[*].podSpec.containers[*].volumeMounts`
+ (deprecated) \n The value of `name` must match
+ the `name` field of a volumeMount specified in
+ the corresponding `volumeMounts` array."
type: string
- metadata:
- description: 'Standard object''s metadata. More
- info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata'
- properties:
- annotations:
- additionalProperties:
- type: string
- type: object
- finalizers:
- items:
- type: string
- type: array
- labels:
- additionalProperties:
- type: string
- type: object
- name:
- type: string
- namespace:
- type: string
- type: object
spec:
- description: 'spec defines the desired characteristics
- of a volume requested by a pod author. More info:
- https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
+ description: "Defines the desired characteristics
+ of a PersistentVolumeClaim that will be created
+ for the volume with the mount name specified in
+ the `name` field. \n When a Pod is created for
+ this ClusterComponent, a new PVC will be created
+ based on the specification defined in the `spec`
+ field. The PVC will be associated with the volume
+ mount specified by the `name` field."
properties:
accessModes:
- description: 'accessModes contains the desired
- access modes the volume should have. More
- info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
+ description: 'Contains the desired access modes
+ the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1.'
items:
type: string
type: array
- dataSource:
- description: 'dataSource field can be used to
- specify either: * An existing VolumeSnapshot
- object (snapshot.storage.k8s.io/VolumeSnapshot)
- * An existing PVC (PersistentVolumeClaim)
- If the provisioner or an external controller
- can support the specified data source, it
- will create a new volume based on the contents
- of the specified data source. When the AnyVolumeDataSource
- feature gate is enabled, dataSource contents
- will be copied to dataSourceRef, and dataSourceRef
- contents will be copied to dataSource when
- dataSourceRef.namespace is not specified.
- If the namespace is specified, then dataSourceRef
- will not be copied to dataSource.'
- properties:
- apiGroup:
- description: APIGroup is the group for the
- resource being referenced. If APIGroup
- is not specified, the specified Kind must
- be in the core API group. For any other
- third-party types, APIGroup is required.
- type: string
- kind:
- description: Kind is the type of resource
- being referenced
- type: string
- name:
- description: Name is the name of resource
- being referenced
- type: string
- required:
- - kind
- - name
- type: object
- x-kubernetes-map-type: atomic
- dataSourceRef:
- description: 'dataSourceRef specifies the object
- from which to populate the volume with data,
- if a non-empty volume is desired. This may
- be any object from a non-empty API group (non
- core object) or a PersistentVolumeClaim object.
- When this field is specified, volume binding
- will only succeed if the type of the specified
- object matches some installed volume populator
- or dynamic provisioner. This field will replace
- the functionality of the dataSource field
- and as such if both fields are non-empty,
- they must have the same value. For backwards
- compatibility, when namespace isn''t specified
- in dataSourceRef, both fields (dataSource
- and dataSourceRef) will be set to the same
- value automatically if one of them is empty
- and the other is non-empty. When namespace
- is specified in dataSourceRef, dataSource
- isn''t set to the same value and must be empty.
- There are three important differences between
- dataSource and dataSourceRef: * While dataSource
- only allows two specific types of objects,
- dataSourceRef allows any non-core object,
- as well as PersistentVolumeClaim objects.
- * While dataSource ignores disallowed values
- (dropping them), dataSourceRef preserves all
- values, and generates an error if a disallowed
- value is specified. * While dataSource only
- allows local objects, dataSourceRef allows
- objects in any namespaces. (Beta) Using this
- field requires the AnyVolumeDataSource feature
- gate to be enabled. (Alpha) Using the namespace
- field of dataSourceRef requires the CrossNamespaceVolumeDataSource
- feature gate to be enabled.'
- properties:
- apiGroup:
- description: APIGroup is the group for the
- resource being referenced. If APIGroup
- is not specified, the specified Kind must
- be in the core API group. For any other
- third-party types, APIGroup is required.
- type: string
- kind:
- description: Kind is the type of resource
- being referenced
- type: string
- name:
- description: Name is the name of resource
- being referenced
- type: string
- namespace:
- description: Namespace is the namespace
- of resource being referenced Note that
- when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant
- object is required in the referent namespace
- to allow that namespace's owner to accept
- the reference. See the ReferenceGrant
- documentation for details. (Alpha) This
- field requires the CrossNamespaceVolumeDataSource
- feature gate to be enabled.
- type: string
- required:
- - kind
- - name
- type: object
+ x-kubernetes-preserve-unknown-fields: true
resources:
- description: 'resources represents the minimum
- resources the volume should have. If RecoverVolumeExpansionFailure
- feature is enabled users are allowed to specify
+ description: 'Represents the minimum resources
+ the volume should have. If the RecoverVolumeExpansionFailure
+ feature is enabled, users are allowed to specify
resource requirements that are lower than
- previous value but must still be higher than
- capacity recorded in the status field of the
- claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources'
+ the previous value but must still be higher
+ than the capacity recorded in the status field
+ of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources.'
properties:
claims:
description: "Claims lists the names of
@@ -889,235 +763,18 @@ spec:
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
type: object
type: object
- selector:
- description: selector is a label query over
- volumes to consider for binding.
- properties:
- matchExpressions:
- description: matchExpressions is a list
- of label selector requirements. The requirements
- are ANDed.
- items:
- description: A label selector requirement
- is a selector that contains values,
- a key, and an operator that relates
- the key and values.
- properties:
- key:
- description: key is the label key
- that the selector applies to.
- type: string
- operator:
- description: operator represents a
- key's relationship to a set of values.
- Valid operators are In, NotIn, Exists
- and DoesNotExist.
- type: string
- values:
- description: values is an array of
- string values. If the operator is
- In or NotIn, the values array must
- be non-empty. If the operator is
- Exists or DoesNotExist, the values
- array must be empty. This array
- is replaced during a strategic merge
- patch.
- items:
- type: string
- type: array
- required:
- - key
- - operator
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- description: matchLabels is a map of {key,value}
- pairs. A single {key,value} in the matchLabels
- map is equivalent to an element of matchExpressions,
- whose key field is "key", the operator
- is "In", and the values array contains
- only "value". The requirements are ANDed.
- type: object
- type: object
- x-kubernetes-map-type: atomic
+ x-kubernetes-preserve-unknown-fields: true
storageClassName:
- description: 'storageClassName is the name of
- the StorageClass required by the claim. More
- info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1'
+ description: '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. Value of
- Filesystem is implied when not included in
- claim spec.
- type: string
- volumeName:
- description: volumeName is the binding reference
- to the PersistentVolume backing this claim.
- type: string
- type: object
- status:
- description: 'status represents the current information/status
- of a persistent volume claim. Read-only. More
- info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
- properties:
- accessModes:
- description: 'accessModes contains the actual
- access modes the volume backing the PVC has.
- More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
- items:
- type: string
- type: array
- allocatedResourceStatuses:
- additionalProperties:
- description: When a controller receives persistentvolume
- claim update with ClaimResourceStatus for
- a resource that it does not recognizes,
- then it should ignore that update and let
- other controllers handle it.
- type: string
- description: "allocatedResourceStatuses stores
- status of resource being resized for the given
- PVC. Key names follow standard Kubernetes
- label syntax. Valid values are either: * Un-prefixed
- keys: - storage - the capacity of the volume.
- * Custom resources must use implementation-defined
- prefixed names such as \"example.com/my-custom-resource\"
- Apart from above values - keys that are unprefixed
- or have kubernetes.io prefix are considered
- reserved and hence may not be used. \n ClaimResourceStatus
- can be in any of following states: - ControllerResizeInProgress:
- State set when resize controller starts resizing
- the volume in control-plane. - ControllerResizeFailed:
- State set when resize has failed in resize
- controller with a terminal error. - NodeResizePending:
- State set when resize controller has finished
- resizing the volume but further resizing of
- volume is needed on the node. - NodeResizeInProgress:
- State set when kubelet starts resizing the
- volume. - NodeResizeFailed: State set when
- resizing has failed in kubelet with a terminal
- error. Transient errors don't set NodeResizeFailed.
- For example: if expanding a PVC for more capacity
- - this field can be one of the following states:
- - pvc.status.allocatedResourceStatus['storage']
- = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage']
- = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizeFailed\" When this field is
- not set, it means that no resize operation
- is in progress for the given PVC. \n A controller
- that receives PVC update with previously unknown
- resourceName or ClaimResourceStatus should
- ignore the update for the purpose it was designed.
- For example - a controller that only is responsible
- for resizing capacity of the volume, should
- ignore PVC updates that change other valid
- resources associated with PVC. \n This is
- an alpha field and requires enabling RecoverVolumeExpansionFailure
- feature."
- type: object
- x-kubernetes-map-type: granular
- allocatedResources:
- additionalProperties:
- anyOf:
- - type: integer
- - type: string
- pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
- x-kubernetes-int-or-string: true
- description: "allocatedResources tracks the
- resources allocated to a PVC including its
- capacity. Key names follow standard Kubernetes
- label syntax. Valid values are either: * Un-prefixed
- keys: - storage - the capacity of the volume.
- * Custom resources must use implementation-defined
- prefixed names such as \"example.com/my-custom-resource\"
- Apart from above values - keys that are unprefixed
- or have kubernetes.io prefix are considered
- reserved and hence may not be used. \n Capacity
- reported here may be larger than the actual
- capacity when a volume expansion operation
- is requested. For storage quota, the larger
- value from allocatedResources and PVC.spec.resources
- is used. If allocatedResources is not set,
- PVC.spec.resources alone is used for quota
- calculation. If a volume expansion capacity
- request is lowered, allocatedResources is
- only lowered if there are no expansion operations
- in progress and if the actual volume capacity
- is equal or lower than the requested capacity.
- \n A controller that receives PVC update with
- previously unknown resourceName should ignore
- the update for the purpose it was designed.
- For example - a controller that only is responsible
- for resizing capacity of the volume, should
- ignore PVC updates that change other valid
- resources associated with PVC. \n This is
- an alpha field and requires enabling RecoverVolumeExpansionFailure
- feature."
- type: object
- capacity:
- additionalProperties:
- anyOf:
- - type: integer
- - type: string
- pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
- x-kubernetes-int-or-string: true
- description: capacity represents the actual
- resources of the underlying volume.
- type: object
- conditions:
- description: conditions is the current Condition
- of persistent volume claim. If underlying
- persistent volume is being resized then the
- Condition will be set to 'ResizeStarted'.
- items:
- description: PersistentVolumeClaimCondition
- contains details about state of pvc
- properties:
- lastProbeTime:
- description: lastProbeTime is the time
- we probed the condition.
- format: date-time
- type: string
- lastTransitionTime:
- description: lastTransitionTime is the
- time the condition transitioned from
- one status to another.
- format: date-time
- type: string
- message:
- description: message is the human-readable
- message indicating details about last
- transition.
- type: string
- reason:
- description: reason is a unique, this
- should be a short, machine understandable
- string that gives the reason for condition's
- last transition. If it reports "ResizeStarted"
- that means the underlying persistent
- volume is being resized.
- type: string
- status:
- type: string
- type:
- description: PersistentVolumeClaimConditionType
- is a valid value of PersistentVolumeClaimCondition.Type
- type: string
- required:
- - status
- - type
- type: object
- type: array
- phase:
- description: phase represents the current phase
- of PersistentVolumeClaim.
+ description: Defines what type of volume is
+ required by the claim, either Block or Filesystem.
type: string
type: object
+ required:
+ - name
type: object
type: array
volumeMounts:
@@ -2967,6 +2624,9 @@ spec:
- name
type: object
type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
issuer:
description: Specifies the configuration for the TLS certificates
issuer. It allows defining the issuer name and the reference
@@ -7073,174 +6733,43 @@ spec:
description: Defines VolumeClaimTemplates to override.
Add new or override existing volume claim templates.
items:
- description: PersistentVolumeClaim is a user's request
- for and claim to a persistent volume
properties:
- apiVersion:
- description: 'APIVersion defines the versioned
- schema of this representation of an object.
- Servers should convert recognized schemas
- to the latest internal value, and may reject
- unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
- type: string
- kind:
- description: 'Kind is a string value representing
- the REST resource this object represents.
- Servers may infer this from the endpoint the
- client submits requests to. Cannot be updated.
- In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ name:
+ description: "Refers to the name of a volumeMount
+ defined in either: \n - `componentDefinition.spec.runtime.containers[*].volumeMounts`
+ - `clusterDefinition.spec.componentDefs[*].podSpec.containers[*].volumeMounts`
+ (deprecated) \n The value of `name` must match
+ the `name` field of a volumeMount specified
+ in the corresponding `volumeMounts` array."
type: string
- metadata:
- description: 'Standard object''s metadata. More
- info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata'
- properties:
- annotations:
- additionalProperties:
- type: string
- type: object
- finalizers:
- items:
- type: string
- type: array
- labels:
- additionalProperties:
- type: string
- type: object
- name:
- type: string
- namespace:
- type: string
- type: object
spec:
- description: 'spec defines the desired characteristics
- of a volume requested by a pod author. More
- info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
+ description: "Defines the desired characteristics
+ of a PersistentVolumeClaim that will be created
+ for the volume with the mount name specified
+ in the `name` field. \n When a Pod is created
+ for this ClusterComponent, a new PVC will
+ be created based on the specification defined
+ in the `spec` field. The PVC will be associated
+ with the volume mount specified by the `name`
+ field."
properties:
accessModes:
- description: 'accessModes contains the desired
- access modes the volume should have. More
- info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
+ description: 'Contains the desired access
+ modes the volume should have. More info:
+ https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1.'
items:
type: string
type: array
- dataSource:
- description: 'dataSource field can be used
- to specify either: * An existing VolumeSnapshot
- object (snapshot.storage.k8s.io/VolumeSnapshot)
- * An existing PVC (PersistentVolumeClaim)
- If the provisioner or an external controller
- can support the specified data source,
- it will create a new volume based on the
- contents of the specified data source.
- When the AnyVolumeDataSource feature gate
- is enabled, dataSource contents will be
- copied to dataSourceRef, and dataSourceRef
- contents will be copied to dataSource
- when dataSourceRef.namespace is not specified.
- If the namespace is specified, then dataSourceRef
- will not be copied to dataSource.'
- properties:
- apiGroup:
- description: APIGroup is the group for
- the resource being referenced. If
- APIGroup is not specified, the specified
- Kind must be in the core API group.
- For any other third-party types, APIGroup
- is required.
- type: string
- kind:
- description: Kind is the type of resource
- being referenced
- type: string
- name:
- description: Name is the name of resource
- being referenced
- type: string
- required:
- - kind
- - name
- type: object
- x-kubernetes-map-type: atomic
- dataSourceRef:
- description: 'dataSourceRef specifies the
- object from which to populate the volume
- with data, if a non-empty volume is desired.
- This may be any object from a non-empty
- API group (non core object) or a PersistentVolumeClaim
- object. When this field is specified,
- volume binding will only succeed if the
- type of the specified object matches some
- installed volume populator or dynamic
- provisioner. This field will replace the
- functionality of the dataSource field
- and as such if both fields are non-empty,
- they must have the same value. For backwards
- compatibility, when namespace isn''t specified
- in dataSourceRef, both fields (dataSource
- and dataSourceRef) will be set to the
- same value automatically if one of them
- is empty and the other is non-empty. When
- namespace is specified in dataSourceRef,
- dataSource isn''t set to the same value
- and must be empty. There are three important
- differences between dataSource and dataSourceRef:
- * While dataSource only allows two specific
- types of objects, dataSourceRef allows
- any non-core object, as well as PersistentVolumeClaim
- objects. * While dataSource ignores disallowed
- values (dropping them), dataSourceRef
- preserves all values, and generates an
- error if a disallowed value is specified.
- * While dataSource only allows local objects,
- dataSourceRef allows objects in any namespaces.
- (Beta) Using this field requires the AnyVolumeDataSource
- feature gate to be enabled. (Alpha) Using
- the namespace field of dataSourceRef requires
- the CrossNamespaceVolumeDataSource feature
- gate to be enabled.'
- properties:
- apiGroup:
- description: APIGroup is the group for
- the resource being referenced. If
- APIGroup is not specified, the specified
- Kind must be in the core API group.
- For any other third-party types, APIGroup
- is required.
- type: string
- kind:
- description: Kind is the type of resource
- being referenced
- type: string
- name:
- description: Name is the name of resource
- being referenced
- type: string
- namespace:
- description: Namespace is the namespace
- of resource being referenced Note
- that when a namespace is specified,
- a gateway.networking.k8s.io/ReferenceGrant
- object is required in the referent
- namespace to allow that namespace's
- owner to accept the reference. See
- the ReferenceGrant documentation for
- details. (Alpha) This field requires
- the CrossNamespaceVolumeDataSource
- feature gate to be enabled.
- type: string
- required:
- - kind
- - name
- type: object
+ x-kubernetes-preserve-unknown-fields: true
resources:
- description: 'resources represents the minimum
- resources the volume should have. If RecoverVolumeExpansionFailure
- feature is enabled users are allowed to
- specify resource requirements that are
- lower than previous value but must still
- be higher than capacity recorded in the
- status field of the claim. More info:
- https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources'
+ description: 'Represents the minimum resources
+ the volume should have. If the RecoverVolumeExpansionFailure
+ feature is enabled, users are allowed
+ to specify resource requirements that
+ are lower than the previous value but
+ must still be higher than the capacity
+ recorded in the status field of the claim.
+ More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources.'
properties:
claims:
description: "Claims lists the names
@@ -7296,248 +6825,19 @@ spec:
info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
type: object
type: object
- selector:
- description: selector is a label query over
- volumes to consider for binding.
- properties:
- matchExpressions:
- description: matchExpressions is a list
- of label selector requirements. The
- requirements are ANDed.
- items:
- description: A label selector requirement
- is a selector that contains values,
- a key, and an operator that relates
- the key and values.
- properties:
- key:
- description: key is the label
- key that the selector applies
- to.
- type: string
- operator:
- description: operator represents
- a key's relationship to a set
- of values. Valid operators are
- In, NotIn, Exists and DoesNotExist.
- type: string
- values:
- description: values is an array
- of string values. If the operator
- is In or NotIn, the values array
- must be non-empty. If the operator
- is Exists or DoesNotExist, the
- values array must be empty.
- This array is replaced during
- a strategic merge patch.
- items:
- type: string
- type: array
- required:
- - key
- - operator
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- description: matchLabels is a map of
- {key,value} pairs. A single {key,value}
- in the matchLabels map is equivalent
- to an element of matchExpressions,
- whose key field is "key", the operator
- is "In", and the values array contains
- only "value". The requirements are
- ANDed.
- type: object
- type: object
- x-kubernetes-map-type: atomic
+ x-kubernetes-preserve-unknown-fields: true
storageClassName:
- description: 'storageClassName is the name
- of the StorageClass required by the claim.
- More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1'
+ description: '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. Value
- of Filesystem is implied when not included
- in claim spec.
- type: string
- volumeName:
- description: volumeName is the binding reference
- to the PersistentVolume backing this claim.
- type: string
- type: object
- status:
- description: 'status represents the current
- information/status of a persistent volume
- claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
- properties:
- accessModes:
- description: 'accessModes contains the actual
- access modes the volume backing the PVC
- has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
- items:
- type: string
- type: array
- allocatedResourceStatuses:
- additionalProperties:
- description: When a controller receives
- persistentvolume claim update with ClaimResourceStatus
- for a resource that it does not recognizes,
- then it should ignore that update and
- let other controllers handle it.
- type: string
- description: "allocatedResourceStatuses
- stores status of resource being resized
- for the given PVC. Key names follow standard
- Kubernetes label syntax. Valid values
- are either: * Un-prefixed keys: - storage
- - the capacity of the volume. * Custom
- resources must use implementation-defined
- prefixed names such as \"example.com/my-custom-resource\"
- Apart from above values - keys that are
- unprefixed or have kubernetes.io prefix
- are considered reserved and hence may
- not be used. \n ClaimResourceStatus can
- be in any of following states: - ControllerResizeInProgress:
- State set when resize controller starts
- resizing the volume in control-plane.
- - ControllerResizeFailed: State set when
- resize has failed in resize controller
- with a terminal error. - NodeResizePending:
- State set when resize controller has finished
- resizing the volume but further resizing
- of volume is needed on the node. - NodeResizeInProgress:
- State set when kubelet starts resizing
- the volume. - NodeResizeFailed: State
- set when resizing has failed in kubelet
- with a terminal error. Transient errors
- don't set NodeResizeFailed. For example:
- if expanding a PVC for more capacity -
- this field can be one of the following
- states: - pvc.status.allocatedResourceStatus['storage']
- = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage']
- = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizeFailed\" When this field
- is not set, it means that no resize operation
- is in progress for the given PVC. \n A
- controller that receives PVC update with
- previously unknown resourceName or ClaimResourceStatus
- should ignore the update for the purpose
- it was designed. For example - a controller
- that only is responsible for resizing
- capacity of the volume, should ignore
- PVC updates that change other valid resources
- associated with PVC. \n This is an alpha
- field and requires enabling RecoverVolumeExpansionFailure
- feature."
- type: object
- x-kubernetes-map-type: granular
- allocatedResources:
- additionalProperties:
- anyOf:
- - type: integer
- - type: string
- pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
- x-kubernetes-int-or-string: true
- description: "allocatedResources tracks
- the resources allocated to a PVC including
- its capacity. Key names follow standard
- Kubernetes label syntax. Valid values
- are either: * Un-prefixed keys: - storage
- - the capacity of the volume. * Custom
- resources must use implementation-defined
- prefixed names such as \"example.com/my-custom-resource\"
- Apart from above values - keys that are
- unprefixed or have kubernetes.io prefix
- are considered reserved and hence may
- not be used. \n Capacity reported here
- may be larger than the actual capacity
- when a volume expansion operation is requested.
- For storage quota, the larger value from
- allocatedResources and PVC.spec.resources
- is used. If allocatedResources is not
- set, PVC.spec.resources alone is used
- for quota calculation. If a volume expansion
- capacity request is lowered, allocatedResources
- is only lowered if there are no expansion
- operations in progress and if the actual
- volume capacity is equal or lower than
- the requested capacity. \n A controller
- that receives PVC update with previously
- unknown resourceName should ignore the
- update for the purpose it was designed.
- For example - a controller that only is
- responsible for resizing capacity of the
- volume, should ignore PVC updates that
- change other valid resources associated
- with PVC. \n This is an alpha field and
- requires enabling RecoverVolumeExpansionFailure
- feature."
- type: object
- capacity:
- additionalProperties:
- anyOf:
- - type: integer
- - type: string
- pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
- x-kubernetes-int-or-string: true
- description: capacity represents the actual
- resources of the underlying volume.
- type: object
- conditions:
- description: conditions is the current Condition
- of persistent volume claim. If underlying
- persistent volume is being resized then
- the Condition will be set to 'ResizeStarted'.
- items:
- description: PersistentVolumeClaimCondition
- contains details about state of pvc
- properties:
- lastProbeTime:
- description: lastProbeTime is the
- time we probed the condition.
- format: date-time
- type: string
- lastTransitionTime:
- description: lastTransitionTime is
- the time the condition transitioned
- from one status to another.
- format: date-time
- type: string
- message:
- description: message is the human-readable
- message indicating details about
- last transition.
- type: string
- reason:
- description: reason is a unique, this
- should be a short, machine understandable
- string that gives the reason for
- condition's last transition. If
- it reports "ResizeStarted" that
- means the underlying persistent
- volume is being resized.
- type: string
- status:
- type: string
- type:
- description: PersistentVolumeClaimConditionType
- is a valid value of PersistentVolumeClaimCondition.Type
- type: string
- required:
- - status
- - type
- type: object
- type: array
- phase:
- description: phase represents the current
- phase of PersistentVolumeClaim.
+ description: Defines what type of volume
+ is required by the claim, either Block
+ or Filesystem.
type: string
type: object
+ required:
+ - name
type: object
type: array
volumeMounts:
@@ -9499,6 +8799,9 @@ spec:
- name
type: object
type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
issuer:
description: Specifies the configuration for the TLS certificates
issuer. It allows defining the issuer name and the reference
diff --git a/config/crd/bases/apps.kubeblocks.io_components.yaml b/config/crd/bases/apps.kubeblocks.io_components.yaml
index a9ec71bb4d7..747033a2eb1 100644
--- a/config/crd/bases/apps.kubeblocks.io_components.yaml
+++ b/config/crd/bases/apps.kubeblocks.io_components.yaml
@@ -618,154 +618,39 @@ spec:
description: Defines VolumeClaimTemplates to override. Add new
or override existing volume claim templates.
items:
- description: PersistentVolumeClaim is a user's request for
- and claim to a persistent volume
properties:
- apiVersion:
- description: 'APIVersion defines the versioned schema
- of this representation of an object. Servers should
- convert recognized schemas to the latest internal value,
- and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
- type: string
- kind:
- description: 'Kind is a string value representing the
- REST resource this object represents. Servers may infer
- this from the endpoint the client submits requests to.
- Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ name:
+ description: "Refers to the name of a volumeMount defined
+ in either: \n - `componentDefinition.spec.runtime.containers[*].volumeMounts`
+ - `clusterDefinition.spec.componentDefs[*].podSpec.containers[*].volumeMounts`
+ (deprecated) \n The value of `name` must match the `name`
+ field of a volumeMount specified in the corresponding
+ `volumeMounts` array."
type: string
- metadata:
- description: 'Standard object''s metadata. More info:
- https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata'
- properties:
- annotations:
- additionalProperties:
- type: string
- type: object
- finalizers:
- items:
- type: string
- type: array
- labels:
- additionalProperties:
- type: string
- type: object
- name:
- type: string
- namespace:
- type: string
- type: object
spec:
- description: 'spec defines the desired characteristics
- of a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
+ description: "Defines the desired characteristics of a
+ PersistentVolumeClaim that will be created for the volume
+ with the mount name specified in the `name` field. \n
+ When a Pod is created for this ClusterComponent, a new
+ PVC will be created based on the specification defined
+ in the `spec` field. The PVC will be associated with
+ the volume mount specified by the `name` field."
properties:
accessModes:
- description: 'accessModes contains the desired access
- modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
+ description: 'Contains the desired access modes the
+ volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1.'
items:
type: string
type: array
- dataSource:
- description: 'dataSource field can be used to specify
- either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot)
- * An existing PVC (PersistentVolumeClaim) If the
- provisioner or an external controller can support
- the specified data source, it will create a new
- volume based on the contents of the specified data
- source. When the AnyVolumeDataSource feature gate
- is enabled, dataSource contents will be copied to
- dataSourceRef, and dataSourceRef contents will be
- copied to dataSource when dataSourceRef.namespace
- is not specified. If the namespace is specified,
- then dataSourceRef will not be copied to dataSource.'
- properties:
- apiGroup:
- description: APIGroup is the group for the resource
- being referenced. If APIGroup is not specified,
- the specified Kind must be in the core API group.
- For any other third-party types, APIGroup is
- required.
- type: string
- kind:
- description: Kind is the type of resource being
- referenced
- type: string
- name:
- description: Name is the name of resource being
- referenced
- type: string
- required:
- - kind
- - name
- type: object
- x-kubernetes-map-type: atomic
- dataSourceRef:
- description: 'dataSourceRef specifies the object from
- which to populate the volume with data, if a non-empty
- volume is desired. This may be any object from a
- non-empty API group (non core object) or a PersistentVolumeClaim
- object. When this field is specified, volume binding
- will only succeed if the type of the specified object
- matches some installed volume populator or dynamic
- provisioner. This field will replace the functionality
- of the dataSource field and as such if both fields
- are non-empty, they must have the same value. For
- backwards compatibility, when namespace isn''t specified
- in dataSourceRef, both fields (dataSource and dataSourceRef)
- will be set to the same value automatically if one
- of them is empty and the other is non-empty. When
- namespace is specified in dataSourceRef, dataSource
- isn''t set to the same value and must be empty.
- There are three important differences between dataSource
- and dataSourceRef: * While dataSource only allows
- two specific types of objects, dataSourceRef allows
- any non-core object, as well as PersistentVolumeClaim
- objects. * While dataSource ignores disallowed values
- (dropping them), dataSourceRef preserves all values,
- and generates an error if a disallowed value is
- specified. * While dataSource only allows local
- objects, dataSourceRef allows objects in any namespaces.
- (Beta) Using this field requires the AnyVolumeDataSource
- feature gate to be enabled. (Alpha) Using the namespace
- field of dataSourceRef requires the CrossNamespaceVolumeDataSource
- feature gate to be enabled.'
- properties:
- apiGroup:
- description: APIGroup is the group for the resource
- being referenced. If APIGroup is not specified,
- the specified Kind must be in the core API group.
- For any other third-party types, APIGroup is
- required.
- type: string
- kind:
- description: Kind is the type of resource being
- referenced
- type: string
- name:
- description: Name is the name of resource being
- referenced
- type: string
- namespace:
- description: Namespace is the namespace of resource
- being referenced Note that when a namespace
- is specified, a gateway.networking.k8s.io/ReferenceGrant
- object is required in the referent namespace
- to allow that namespace's owner to accept the
- reference. See the ReferenceGrant documentation
- for details. (Alpha) This field requires the
- CrossNamespaceVolumeDataSource feature gate
- to be enabled.
- type: string
- required:
- - kind
- - name
- type: object
+ x-kubernetes-preserve-unknown-fields: true
resources:
- description: 'resources represents the minimum resources
- the volume should have. If RecoverVolumeExpansionFailure
- feature is enabled users are allowed to specify
- resource requirements that are lower than previous
- value but must still be higher than capacity recorded
- in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources'
+ description: 'Represents the minimum resources the
+ volume should have. If the RecoverVolumeExpansionFailure
+ feature is enabled, users are allowed to specify
+ resource requirements that are lower than the previous
+ value but must still be higher than the capacity
+ recorded in the status field of the claim. More
+ info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources.'
properties:
claims:
description: "Claims lists the names of resources,
@@ -816,222 +701,18 @@ spec:
exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
type: object
type: object
- selector:
- description: selector is a label query over volumes
- to consider for binding.
- properties:
- matchExpressions:
- description: matchExpressions is a list of label
- selector requirements. The requirements are
- ANDed.
- items:
- description: A label selector requirement is
- a selector that contains values, a key, and
- an operator that relates the key and values.
- properties:
- key:
- description: key is the label key that the
- selector applies to.
- type: string
- operator:
- description: operator represents a key's
- relationship to a set of values. Valid
- operators are In, NotIn, Exists and DoesNotExist.
- type: string
- values:
- description: values is an array of string
- values. If the operator is In or NotIn,
- the values array must be non-empty. If
- the operator is Exists or DoesNotExist,
- the values array must be empty. This array
- is replaced during a strategic merge patch.
- items:
- type: string
- type: array
- required:
- - key
- - operator
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- description: matchLabels is a map of {key,value}
- pairs. A single {key,value} in the matchLabels
- map is equivalent to an element of matchExpressions,
- whose key field is "key", the operator is "In",
- and the values array contains only "value".
- The requirements are ANDed.
- type: object
- type: object
- x-kubernetes-map-type: atomic
+ x-kubernetes-preserve-unknown-fields: true
storageClassName:
- description: 'storageClassName is the name of the
- StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1'
+ description: '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. Value of Filesystem is
- implied when not included in claim spec.
- type: string
- volumeName:
- description: volumeName is the binding reference to
- the PersistentVolume backing this claim.
- type: string
- type: object
- status:
- description: 'status represents the current information/status
- of a persistent volume claim. Read-only. More info:
- https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
- properties:
- accessModes:
- description: 'accessModes contains the actual access
- modes the volume backing the PVC has. More info:
- https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
- items:
- type: string
- type: array
- allocatedResourceStatuses:
- additionalProperties:
- description: When a controller receives persistentvolume
- claim update with ClaimResourceStatus for a resource
- that it does not recognizes, then it should ignore
- that update and let other controllers handle it.
- type: string
- description: "allocatedResourceStatuses stores status
- of resource being resized for the given PVC. Key
- names follow standard Kubernetes label syntax. Valid
- values are either: * Un-prefixed keys: - storage
- - the capacity of the volume. * Custom resources
- must use implementation-defined prefixed names such
- as \"example.com/my-custom-resource\" Apart from
- above values - keys that are unprefixed or have
- kubernetes.io prefix are considered reserved and
- hence may not be used. \n ClaimResourceStatus can
- be in any of following states: - ControllerResizeInProgress:
- State set when resize controller starts resizing
- the volume in control-plane. - ControllerResizeFailed:
- State set when resize has failed in resize controller
- with a terminal error. - NodeResizePending: State
- set when resize controller has finished resizing
- the volume but further resizing of volume is needed
- on the node. - NodeResizeInProgress: State set when
- kubelet starts resizing the volume. - NodeResizeFailed:
- State set when resizing has failed in kubelet with
- a terminal error. Transient errors don't set NodeResizeFailed.
- For example: if expanding a PVC for more capacity
- - this field can be one of the following states:
- - pvc.status.allocatedResourceStatus['storage']
- = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage']
- = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizeFailed\" When this field is not set,
- it means that no resize operation is in progress
- for the given PVC. \n A controller that receives
- PVC update with previously unknown resourceName
- or ClaimResourceStatus should ignore the update
- for the purpose it was designed. For example - a
- controller that only is responsible for resizing
- capacity of the volume, should ignore PVC updates
- that change other valid resources associated with
- PVC. \n This is an alpha field and requires enabling
- RecoverVolumeExpansionFailure feature."
- type: object
- x-kubernetes-map-type: granular
- allocatedResources:
- additionalProperties:
- anyOf:
- - type: integer
- - type: string
- pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
- x-kubernetes-int-or-string: true
- description: "allocatedResources tracks the resources
- allocated to a PVC including its capacity. Key names
- follow standard Kubernetes label syntax. Valid values
- are either: * Un-prefixed keys: - storage - the
- capacity of the volume. * Custom resources must
- use implementation-defined prefixed names such as
- \"example.com/my-custom-resource\" Apart from above
- values - keys that are unprefixed or have kubernetes.io
- prefix are considered reserved and hence may not
- be used. \n Capacity reported here may be larger
- than the actual capacity when a volume expansion
- operation is requested. For storage quota, the larger
- value from allocatedResources and PVC.spec.resources
- is used. If allocatedResources is not set, PVC.spec.resources
- alone is used for quota calculation. If a volume
- expansion capacity request is lowered, allocatedResources
- is only lowered if there are no expansion operations
- in progress and if the actual volume capacity is
- equal or lower than the requested capacity. \n A
- controller that receives PVC update with previously
- unknown resourceName should ignore the update for
- the purpose it was designed. For example - a controller
- that only is responsible for resizing capacity of
- the volume, should ignore PVC updates that change
- other valid resources associated with PVC. \n This
- is an alpha field and requires enabling RecoverVolumeExpansionFailure
- feature."
- type: object
- capacity:
- additionalProperties:
- anyOf:
- - type: integer
- - type: string
- pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
- x-kubernetes-int-or-string: true
- description: capacity represents the actual resources
- of the underlying volume.
- type: object
- conditions:
- description: conditions is the current Condition of
- persistent volume claim. If underlying persistent
- volume is being resized then the Condition will
- be set to 'ResizeStarted'.
- items:
- description: PersistentVolumeClaimCondition contains
- details about state of pvc
- properties:
- lastProbeTime:
- description: lastProbeTime is the time we probed
- the condition.
- format: date-time
- type: string
- lastTransitionTime:
- description: lastTransitionTime is the time
- the condition transitioned from one status
- to another.
- format: date-time
- type: string
- message:
- description: message is the human-readable message
- indicating details about last transition.
- type: string
- reason:
- description: reason is a unique, this should
- be a short, machine understandable string
- that gives the reason for condition's last
- transition. If it reports "ResizeStarted"
- that means the underlying persistent volume
- is being resized.
- type: string
- status:
- type: string
- type:
- description: PersistentVolumeClaimConditionType
- is a valid value of PersistentVolumeClaimCondition.Type
- type: string
- required:
- - status
- - type
- type: object
- type: array
- phase:
- description: phase represents the current phase of
- PersistentVolumeClaim.
+ description: Defines what type of volume is required
+ by the claim, either Block or Filesystem.
type: string
type: object
+ required:
+ - name
type: object
type: array
volumeMounts:
diff --git a/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml b/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml
index 4a13b824dd7..a689e1befb6 100644
--- a/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml
+++ b/config/crd/bases/apps.kubeblocks.io_opsrequests.yaml
@@ -114,16 +114,15 @@ spec:
customSpec:
description: Specifies a custom operation as defined by OpsDefinition.
properties:
- components:
+ items:
description: Defines which components need to perform the actions
- defined by this OpsDefinition. At least one component is required.
- The components are identified by their name and can be merged
- or retained.
+ defined by this OpsDefinition. At least one component/shardComponent
+ is required. The components are identified by their name and
+ can be merged or retained.
items:
properties:
- name:
- description: Specifies the unique identifier of the cluster
- component
+ componentName:
+ description: Specifies the name of the cluster component.
type: string
parameters:
description: Represents the parameters for this operation
@@ -147,14 +146,17 @@ spec:
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
- required:
- - name
+ shardingName:
+ description: Specifies the name of the cluster sharding
+ component.
+ type: string
type: object
+ x-kubernetes-validations:
+ - message: either componentName or shardingName
+ rule: (has(self.componentName) && !has(self.shardingName))
+ || (has(self.shardingName) && !has(self.componentName))
minItems: 1
type: array
- x-kubernetes-list-map-keys:
- - name
- x-kubernetes-list-type: map
opsDefinitionRef:
description: Is a reference to an OpsDefinition.
type: string
@@ -173,7 +175,7 @@ spec:
serviceAccountName:
type: string
required:
- - components
+ - items
- opsDefinitionRef
type: object
expose:
@@ -185,7 +187,7 @@ spec:
type: string
services:
description: A list of services that are to be exposed or removed.
- If componentNamem is not specified, each `OpsService` in the
+ If componentName is not specified, each `OpsService` in the
list must specify ports and selectors.
items:
properties:
@@ -365,14 +367,10 @@ spec:
- Disable
type: string
required:
- - componentName
- services
- switch
type: object
type: array
- x-kubernetes-list-map-keys:
- - componentName
- x-kubernetes-list-type: map
force:
description: Indicates if pre-checks should be bypassed, allowing
the opsRequest to execute immediately. If set to true, pre-checks
@@ -694,166 +692,40 @@ spec:
description: Defines VolumeClaimTemplates to override.
Add new or override existing volume claim templates.
items:
- description: PersistentVolumeClaim is a user's request
- for and claim to a persistent volume
properties:
- apiVersion:
- description: 'APIVersion defines the versioned schema
- of this representation of an object. Servers should
- convert recognized schemas to the latest internal
- value, and may reject unrecognized values. More
- info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
- type: string
- kind:
- description: 'Kind is a string value representing
- the REST resource this object represents. Servers
- may infer this from the endpoint the client submits
- requests to. Cannot be updated. In CamelCase.
- More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ name:
+ description: "Refers to the name of a volumeMount
+ defined in either: \n - `componentDefinition.spec.runtime.containers[*].volumeMounts`
+ - `clusterDefinition.spec.componentDefs[*].podSpec.containers[*].volumeMounts`
+ (deprecated) \n The value of `name` must match
+ the `name` field of a volumeMount specified in
+ the corresponding `volumeMounts` array."
type: string
- metadata:
- description: 'Standard object''s metadata. More
- info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata'
- properties:
- annotations:
- additionalProperties:
- type: string
- type: object
- finalizers:
- items:
- type: string
- type: array
- labels:
- additionalProperties:
- type: string
- type: object
- name:
- type: string
- namespace:
- type: string
- type: object
spec:
- description: 'spec defines the desired characteristics
- of a volume requested by a pod author. More info:
- https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
+ description: "Defines the desired characteristics
+ of a PersistentVolumeClaim that will be created
+ for the volume with the mount name specified in
+ the `name` field. \n When a Pod is created for
+ this ClusterComponent, a new PVC will be created
+ based on the specification defined in the `spec`
+ field. The PVC will be associated with the volume
+ mount specified by the `name` field."
properties:
accessModes:
- description: 'accessModes contains the desired
- access modes the volume should have. More
- info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
+ description: 'Contains the desired access modes
+ the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1.'
items:
type: string
type: array
- dataSource:
- description: 'dataSource field can be used to
- specify either: * An existing VolumeSnapshot
- object (snapshot.storage.k8s.io/VolumeSnapshot)
- * An existing PVC (PersistentVolumeClaim)
- If the provisioner or an external controller
- can support the specified data source, it
- will create a new volume based on the contents
- of the specified data source. When the AnyVolumeDataSource
- feature gate is enabled, dataSource contents
- will be copied to dataSourceRef, and dataSourceRef
- contents will be copied to dataSource when
- dataSourceRef.namespace is not specified.
- If the namespace is specified, then dataSourceRef
- will not be copied to dataSource.'
- properties:
- apiGroup:
- description: APIGroup is the group for the
- resource being referenced. If APIGroup
- is not specified, the specified Kind must
- be in the core API group. For any other
- third-party types, APIGroup is required.
- type: string
- kind:
- description: Kind is the type of resource
- being referenced
- type: string
- name:
- description: Name is the name of resource
- being referenced
- type: string
- required:
- - kind
- - name
- type: object
- x-kubernetes-map-type: atomic
- dataSourceRef:
- description: 'dataSourceRef specifies the object
- from which to populate the volume with data,
- if a non-empty volume is desired. This may
- be any object from a non-empty API group (non
- core object) or a PersistentVolumeClaim object.
- When this field is specified, volume binding
- will only succeed if the type of the specified
- object matches some installed volume populator
- or dynamic provisioner. This field will replace
- the functionality of the dataSource field
- and as such if both fields are non-empty,
- they must have the same value. For backwards
- compatibility, when namespace isn''t specified
- in dataSourceRef, both fields (dataSource
- and dataSourceRef) will be set to the same
- value automatically if one of them is empty
- and the other is non-empty. When namespace
- is specified in dataSourceRef, dataSource
- isn''t set to the same value and must be empty.
- There are three important differences between
- dataSource and dataSourceRef: * While dataSource
- only allows two specific types of objects,
- dataSourceRef allows any non-core object,
- as well as PersistentVolumeClaim objects.
- * While dataSource ignores disallowed values
- (dropping them), dataSourceRef preserves all
- values, and generates an error if a disallowed
- value is specified. * While dataSource only
- allows local objects, dataSourceRef allows
- objects in any namespaces. (Beta) Using this
- field requires the AnyVolumeDataSource feature
- gate to be enabled. (Alpha) Using the namespace
- field of dataSourceRef requires the CrossNamespaceVolumeDataSource
- feature gate to be enabled.'
- properties:
- apiGroup:
- description: APIGroup is the group for the
- resource being referenced. If APIGroup
- is not specified, the specified Kind must
- be in the core API group. For any other
- third-party types, APIGroup is required.
- type: string
- kind:
- description: Kind is the type of resource
- being referenced
- type: string
- name:
- description: Name is the name of resource
- being referenced
- type: string
- namespace:
- description: Namespace is the namespace
- of resource being referenced Note that
- when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant
- object is required in the referent namespace
- to allow that namespace's owner to accept
- the reference. See the ReferenceGrant
- documentation for details. (Alpha) This
- field requires the CrossNamespaceVolumeDataSource
- feature gate to be enabled.
- type: string
- required:
- - kind
- - name
- type: object
+ x-kubernetes-preserve-unknown-fields: true
resources:
- description: 'resources represents the minimum
- resources the volume should have. If RecoverVolumeExpansionFailure
- feature is enabled users are allowed to specify
+ description: 'Represents the minimum resources
+ the volume should have. If the RecoverVolumeExpansionFailure
+ feature is enabled, users are allowed to specify
resource requirements that are lower than
- previous value but must still be higher than
- capacity recorded in the status field of the
- claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources'
+ the previous value but must still be higher
+ than the capacity recorded in the status field
+ of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources.'
properties:
claims:
description: "Claims lists the names of
@@ -908,235 +780,18 @@ spec:
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
type: object
type: object
- selector:
- description: selector is a label query over
- volumes to consider for binding.
- properties:
- matchExpressions:
- description: matchExpressions is a list
- of label selector requirements. The requirements
- are ANDed.
- items:
- description: A label selector requirement
- is a selector that contains values,
- a key, and an operator that relates
- the key and values.
- properties:
- key:
- description: key is the label key
- that the selector applies to.
- type: string
- operator:
- description: operator represents a
- key's relationship to a set of values.
- Valid operators are In, NotIn, Exists
- and DoesNotExist.
- type: string
- values:
- description: values is an array of
- string values. If the operator is
- In or NotIn, the values array must
- be non-empty. If the operator is
- Exists or DoesNotExist, the values
- array must be empty. This array
- is replaced during a strategic merge
- patch.
- items:
- type: string
- type: array
- required:
- - key
- - operator
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- description: matchLabels is a map of {key,value}
- pairs. A single {key,value} in the matchLabels
- map is equivalent to an element of matchExpressions,
- whose key field is "key", the operator
- is "In", and the values array contains
- only "value". The requirements are ANDed.
- type: object
- type: object
- x-kubernetes-map-type: atomic
+ x-kubernetes-preserve-unknown-fields: true
storageClassName:
- description: 'storageClassName is the name of
- the StorageClass required by the claim. More
- info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1'
+ description: '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. Value of
- Filesystem is implied when not included in
- claim spec.
- type: string
- volumeName:
- description: volumeName is the binding reference
- to the PersistentVolume backing this claim.
- type: string
- type: object
- status:
- description: 'status represents the current information/status
- of a persistent volume claim. Read-only. More
- info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
- properties:
- accessModes:
- description: 'accessModes contains the actual
- access modes the volume backing the PVC has.
- More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
- items:
- type: string
- type: array
- allocatedResourceStatuses:
- additionalProperties:
- description: When a controller receives persistentvolume
- claim update with ClaimResourceStatus for
- a resource that it does not recognizes,
- then it should ignore that update and let
- other controllers handle it.
- type: string
- description: "allocatedResourceStatuses stores
- status of resource being resized for the given
- PVC. Key names follow standard Kubernetes
- label syntax. Valid values are either: * Un-prefixed
- keys: - storage - the capacity of the volume.
- * Custom resources must use implementation-defined
- prefixed names such as \"example.com/my-custom-resource\"
- Apart from above values - keys that are unprefixed
- or have kubernetes.io prefix are considered
- reserved and hence may not be used. \n ClaimResourceStatus
- can be in any of following states: - ControllerResizeInProgress:
- State set when resize controller starts resizing
- the volume in control-plane. - ControllerResizeFailed:
- State set when resize has failed in resize
- controller with a terminal error. - NodeResizePending:
- State set when resize controller has finished
- resizing the volume but further resizing of
- volume is needed on the node. - NodeResizeInProgress:
- State set when kubelet starts resizing the
- volume. - NodeResizeFailed: State set when
- resizing has failed in kubelet with a terminal
- error. Transient errors don't set NodeResizeFailed.
- For example: if expanding a PVC for more capacity
- - this field can be one of the following states:
- - pvc.status.allocatedResourceStatus['storage']
- = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage']
- = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizeFailed\" When this field is
- not set, it means that no resize operation
- is in progress for the given PVC. \n A controller
- that receives PVC update with previously unknown
- resourceName or ClaimResourceStatus should
- ignore the update for the purpose it was designed.
- For example - a controller that only is responsible
- for resizing capacity of the volume, should
- ignore PVC updates that change other valid
- resources associated with PVC. \n This is
- an alpha field and requires enabling RecoverVolumeExpansionFailure
- feature."
- type: object
- x-kubernetes-map-type: granular
- allocatedResources:
- additionalProperties:
- anyOf:
- - type: integer
- - type: string
- pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
- x-kubernetes-int-or-string: true
- description: "allocatedResources tracks the
- resources allocated to a PVC including its
- capacity. Key names follow standard Kubernetes
- label syntax. Valid values are either: * Un-prefixed
- keys: - storage - the capacity of the volume.
- * Custom resources must use implementation-defined
- prefixed names such as \"example.com/my-custom-resource\"
- Apart from above values - keys that are unprefixed
- or have kubernetes.io prefix are considered
- reserved and hence may not be used. \n Capacity
- reported here may be larger than the actual
- capacity when a volume expansion operation
- is requested. For storage quota, the larger
- value from allocatedResources and PVC.spec.resources
- is used. If allocatedResources is not set,
- PVC.spec.resources alone is used for quota
- calculation. If a volume expansion capacity
- request is lowered, allocatedResources is
- only lowered if there are no expansion operations
- in progress and if the actual volume capacity
- is equal or lower than the requested capacity.
- \n A controller that receives PVC update with
- previously unknown resourceName should ignore
- the update for the purpose it was designed.
- For example - a controller that only is responsible
- for resizing capacity of the volume, should
- ignore PVC updates that change other valid
- resources associated with PVC. \n This is
- an alpha field and requires enabling RecoverVolumeExpansionFailure
- feature."
- type: object
- capacity:
- additionalProperties:
- anyOf:
- - type: integer
- - type: string
- pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
- x-kubernetes-int-or-string: true
- description: capacity represents the actual
- resources of the underlying volume.
- type: object
- conditions:
- description: conditions is the current Condition
- of persistent volume claim. If underlying
- persistent volume is being resized then the
- Condition will be set to 'ResizeStarted'.
- items:
- description: PersistentVolumeClaimCondition
- contains details about state of pvc
- properties:
- lastProbeTime:
- description: lastProbeTime is the time
- we probed the condition.
- format: date-time
- type: string
- lastTransitionTime:
- description: lastTransitionTime is the
- time the condition transitioned from
- one status to another.
- format: date-time
- type: string
- message:
- description: message is the human-readable
- message indicating details about last
- transition.
- type: string
- reason:
- description: reason is a unique, this
- should be a short, machine understandable
- string that gives the reason for condition's
- last transition. If it reports "ResizeStarted"
- that means the underlying persistent
- volume is being resized.
- type: string
- status:
- type: string
- type:
- description: PersistentVolumeClaimConditionType
- is a valid value of PersistentVolumeClaimCondition.Type
- type: string
- required:
- - status
- - type
- type: object
- type: array
- phase:
- description: phase represents the current phase
- of PersistentVolumeClaim.
+ description: Defines what type of volume is
+ required by the claim, either Block or Filesystem.
type: string
type: object
+ required:
+ - name
type: object
type: array
volumeMounts:
@@ -2997,14 +2652,17 @@ spec:
format: int32
minimum: 0
type: integer
+ shardingName:
+ description: Specifies the name of the cluster sharding component.
+ type: string
required:
- - componentName
- replicas
type: object
+ x-kubernetes-validations:
+ - message: either componentName or shardingName
+ rule: (has(self.componentName) && !has(self.shardingName)) ||
+ (has(self.shardingName) && !has(self.componentName))
type: array
- x-kubernetes-list-map-keys:
- - componentName
- x-kubernetes-list-type: map
x-kubernetes-validations:
- message: forbidden to update spec.horizontalScaling
rule: self == oldSelf
@@ -3162,14 +2820,17 @@ spec:
- name
type: object
type: array
+ shardingName:
+ description: Specifies the name of the cluster sharding component.
+ type: string
required:
- - componentName
- instances
type: object
+ x-kubernetes-validations:
+ - message: either componentName or shardingName
+ rule: (has(self.componentName) && !has(self.shardingName)) ||
+ (has(self.shardingName) && !has(self.componentName))
type: array
- x-kubernetes-list-map-keys:
- - componentName
- x-kubernetes-list-type: map
x-kubernetes-validations:
- message: forbidden to update spec.rebuildFrom
rule: self == oldSelf
@@ -3252,15 +2913,16 @@ spec:
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
+ shardingName:
+ description: Specifies the name of the cluster sharding component.
+ type: string
required:
- - componentName
- configurations
type: object
x-kubernetes-validations:
- - message: forbidden to update spec.reconfigure
- rule: self == oldSelf
- - message: Value can not be empty
- rule: self.configurations.size() > 0
+ - message: either componentName or shardingName
+ rule: (has(self.componentName) && !has(self.shardingName)) || (has(self.shardingName)
+ && !has(self.componentName))
reconfigures:
description: Defines the variables that need to input when updating
configuration.
@@ -3345,30 +3007,38 @@ spec:
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
+ shardingName:
+ description: Specifies the name of the cluster sharding component.
+ type: string
required:
- - componentName
- configurations
type: object
+ x-kubernetes-validations:
+ - message: either componentName or shardingName
+ rule: (has(self.componentName) && !has(self.shardingName)) ||
+ (has(self.shardingName) && !has(self.componentName))
type: array
- x-kubernetes-list-map-keys:
- - componentName
- x-kubernetes-list-type: map
+ x-kubernetes-validations:
+ - message: forbidden to update spec.reconfigure
+ rule: self == oldSelf
restart:
description: Restarts the specified components.
items:
description: ComponentOps represents the common variables required
- for operations within the scope of a component.
+ for operations within the scope of a normal component/shard component.
properties:
componentName:
description: Specifies the name of the cluster component.
type: string
- required:
- - componentName
+ shardingName:
+ description: Specifies the name of the cluster sharding component.
+ type: string
type: object
+ x-kubernetes-validations:
+ - message: either componentName or shardingName
+ rule: (has(self.componentName) && !has(self.shardingName)) ||
+ (has(self.shardingName) && !has(self.componentName))
type: array
- x-kubernetes-list-map-keys:
- - componentName
- x-kubernetes-list-type: map
x-kubernetes-validations:
- message: forbidden to update spec.restart
rule: self == oldSelf
@@ -3592,9 +3262,14 @@ spec:
x-kubernetes-validations:
- message: forbidden to update spec.scriptSpec.script.selector
rule: self == oldSelf
- required:
- - componentName
+ shardingName:
+ description: Specifies the name of the cluster sharding component.
+ type: string
type: object
+ x-kubernetes-validations:
+ - message: either componentName or shardingName
+ rule: (has(self.componentName) && !has(self.shardingName)) || (has(self.shardingName)
+ && !has(self.componentName))
switchover:
description: Switches over the specified components.
items:
@@ -3617,14 +3292,17 @@ spec:
will be executed, and it is mandatory that clusterDefinition.componentDefs[x].switchoverSpec.withCandidate
is not left blank."
type: string
+ shardingName:
+ description: Specifies the name of the cluster sharding component.
+ type: string
required:
- - componentName
- instanceName
type: object
+ x-kubernetes-validations:
+ - message: either componentName or shardingName
+ rule: (has(self.componentName) && !has(self.shardingName)) ||
+ (has(self.shardingName) && !has(self.componentName))
type: array
- x-kubernetes-list-map-keys:
- - componentName
- x-kubernetes-list-type: map
x-kubernetes-validations:
- message: forbidden to update spec.switchover
rule: self == oldSelf
@@ -3706,6 +3384,91 @@ spec:
componentName:
description: Specifies the name of the cluster component.
type: string
+ instances:
+ description: Specifies the instance template that need to vertical
+ scale.
+ items:
+ properties:
+ claims:
+ description: "Claims lists the names of resources, defined
+ in spec.resourceClaims, that are used by this container.
+ \n This is an alpha field and requires enabling the
+ DynamicResourceAllocation feature gate. \n This field
+ is immutable. It can only be set for containers."
+ items:
+ description: ResourceClaim references one entry in PodSpec.ResourceClaims.
+ properties:
+ name:
+ description: Name must match the name of one entry
+ in pod.spec.resourceClaims of the Pod where this
+ field is used. It makes that resource available
+ inside a container.
+ type: string
+ required:
+ - name
+ type: object
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ limits:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ description: 'Limits describes the maximum amount of compute
+ resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
+ type: object
+ name:
+ description: Refer to the instance template name of the
+ component or sharding.
+ type: string
+ requests:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ description: 'Requests describes the minimum amount of
+ compute resources required. If Requests is omitted for
+ a container, it defaults to Limits if that is explicitly
+ specified, otherwise to an implementation-defined value.
+ Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
+ type: object
+ volumeClaimTemplates:
+ description: volumeClaimTemplates specifies the storage
+ size and volumeClaimTemplate name.
+ items:
+ properties:
+ name:
+ description: A reference to the volumeClaimTemplate
+ name from the cluster components.
+ type: string
+ storage:
+ anyOf:
+ - type: integer
+ - type: string
+ description: Specifies the requested storage size
+ for the volume.
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ required:
+ - name
+ - storage
+ type: object
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ required:
+ - name
+ - volumeClaimTemplates
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ type: array
limits:
additionalProperties:
anyOf:
@@ -3729,14 +3492,16 @@ spec:
to an implementation-defined value. Requests cannot exceed
Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
type: object
- required:
- - componentName
+ shardingName:
+ description: Specifies the name of the cluster sharding component.
+ type: string
type: object
x-kubernetes-preserve-unknown-fields: true
+ x-kubernetes-validations:
+ - message: either componentName or shardingName
+ rule: (has(self.componentName) && !has(self.shardingName)) ||
+ (has(self.shardingName) && !has(self.componentName))
type: array
- x-kubernetes-list-map-keys:
- - componentName
- x-kubernetes-list-type: map
volumeExpansion:
description: 'Note: Quantity struct can not do immutable check by
CEL. Defines what component and volumeClaimTemplate need to expand
@@ -3748,6 +3513,94 @@ spec:
componentName:
description: Specifies the name of the cluster component.
type: string
+ instances:
+ description: Specifies the instance template that need to volume
+ expand.
+ items:
+ properties:
+ claims:
+ description: "Claims lists the names of resources, defined
+ in spec.resourceClaims, that are used by this container.
+ \n This is an alpha field and requires enabling the
+ DynamicResourceAllocation feature gate. \n This field
+ is immutable. It can only be set for containers."
+ items:
+ description: ResourceClaim references one entry in PodSpec.ResourceClaims.
+ properties:
+ name:
+ description: Name must match the name of one entry
+ in pod.spec.resourceClaims of the Pod where this
+ field is used. It makes that resource available
+ inside a container.
+ type: string
+ required:
+ - name
+ type: object
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ limits:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ description: 'Limits describes the maximum amount of compute
+ resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
+ type: object
+ name:
+ description: Refer to the instance template name of the
+ component or sharding.
+ type: string
+ requests:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ description: 'Requests describes the minimum amount of
+ compute resources required. If Requests is omitted for
+ a container, it defaults to Limits if that is explicitly
+ specified, otherwise to an implementation-defined value.
+ Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
+ type: object
+ volumeClaimTemplates:
+ description: volumeClaimTemplates specifies the storage
+ size and volumeClaimTemplate name.
+ items:
+ properties:
+ name:
+ description: A reference to the volumeClaimTemplate
+ name from the cluster components.
+ type: string
+ storage:
+ anyOf:
+ - type: integer
+ - type: string
+ description: Specifies the requested storage size
+ for the volume.
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ required:
+ - name
+ - storage
+ type: object
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ required:
+ - name
+ - volumeClaimTemplates
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ type: array
+ shardingName:
+ description: Specifies the name of the cluster sharding component.
+ type: string
volumeClaimTemplates:
description: volumeClaimTemplates specifies the storage size
and volumeClaimTemplate name.
@@ -3774,13 +3627,13 @@ spec:
- name
x-kubernetes-list-type: map
required:
- - componentName
- volumeClaimTemplates
type: object
+ x-kubernetes-validations:
+ - message: either componentName or shardingName
+ rule: (has(self.componentName) && !has(self.shardingName)) ||
+ (has(self.shardingName) && !has(self.componentName))
type: array
- x-kubernetes-list-map-keys:
- - componentName
- x-kubernetes-list-type: map
required:
- clusterRef
- type
@@ -4152,174 +4005,43 @@ spec:
description: Defines VolumeClaimTemplates to override.
Add new or override existing volume claim templates.
items:
- description: PersistentVolumeClaim is a user's request
- for and claim to a persistent volume
properties:
- apiVersion:
- description: 'APIVersion defines the versioned
- schema of this representation of an object.
- Servers should convert recognized schemas
- to the latest internal value, and may reject
- unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
- type: string
- kind:
- description: 'Kind is a string value representing
- the REST resource this object represents.
- Servers may infer this from the endpoint the
- client submits requests to. Cannot be updated.
- In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ name:
+ description: "Refers to the name of a volumeMount
+ defined in either: \n - `componentDefinition.spec.runtime.containers[*].volumeMounts`
+ - `clusterDefinition.spec.componentDefs[*].podSpec.containers[*].volumeMounts`
+ (deprecated) \n The value of `name` must match
+ the `name` field of a volumeMount specified
+ in the corresponding `volumeMounts` array."
type: string
- metadata:
- description: 'Standard object''s metadata. More
- info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata'
- properties:
- annotations:
- additionalProperties:
- type: string
- type: object
- finalizers:
- items:
- type: string
- type: array
- labels:
- additionalProperties:
- type: string
- type: object
- name:
- type: string
- namespace:
- type: string
- type: object
spec:
- description: 'spec defines the desired characteristics
- of a volume requested by a pod author. More
- info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
+ description: "Defines the desired characteristics
+ of a PersistentVolumeClaim that will be created
+ for the volume with the mount name specified
+ in the `name` field. \n When a Pod is created
+ for this ClusterComponent, a new PVC will
+ be created based on the specification defined
+ in the `spec` field. The PVC will be associated
+ with the volume mount specified by the `name`
+ field."
properties:
accessModes:
- description: 'accessModes contains the desired
- access modes the volume should have. More
- info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
+ description: 'Contains the desired access
+ modes the volume should have. More info:
+ https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1.'
items:
type: string
type: array
- dataSource:
- description: 'dataSource field can be used
- to specify either: * An existing VolumeSnapshot
- object (snapshot.storage.k8s.io/VolumeSnapshot)
- * An existing PVC (PersistentVolumeClaim)
- If the provisioner or an external controller
- can support the specified data source,
- it will create a new volume based on the
- contents of the specified data source.
- When the AnyVolumeDataSource feature gate
- is enabled, dataSource contents will be
- copied to dataSourceRef, and dataSourceRef
- contents will be copied to dataSource
- when dataSourceRef.namespace is not specified.
- If the namespace is specified, then dataSourceRef
- will not be copied to dataSource.'
- properties:
- apiGroup:
- description: APIGroup is the group for
- the resource being referenced. If
- APIGroup is not specified, the specified
- Kind must be in the core API group.
- For any other third-party types, APIGroup
- is required.
- type: string
- kind:
- description: Kind is the type of resource
- being referenced
- type: string
- name:
- description: Name is the name of resource
- being referenced
- type: string
- required:
- - kind
- - name
- type: object
- x-kubernetes-map-type: atomic
- dataSourceRef:
- description: 'dataSourceRef specifies the
- object from which to populate the volume
- with data, if a non-empty volume is desired.
- This may be any object from a non-empty
- API group (non core object) or a PersistentVolumeClaim
- object. When this field is specified,
- volume binding will only succeed if the
- type of the specified object matches some
- installed volume populator or dynamic
- provisioner. This field will replace the
- functionality of the dataSource field
- and as such if both fields are non-empty,
- they must have the same value. For backwards
- compatibility, when namespace isn''t specified
- in dataSourceRef, both fields (dataSource
- and dataSourceRef) will be set to the
- same value automatically if one of them
- is empty and the other is non-empty. When
- namespace is specified in dataSourceRef,
- dataSource isn''t set to the same value
- and must be empty. There are three important
- differences between dataSource and dataSourceRef:
- * While dataSource only allows two specific
- types of objects, dataSourceRef allows
- any non-core object, as well as PersistentVolumeClaim
- objects. * While dataSource ignores disallowed
- values (dropping them), dataSourceRef
- preserves all values, and generates an
- error if a disallowed value is specified.
- * While dataSource only allows local objects,
- dataSourceRef allows objects in any namespaces.
- (Beta) Using this field requires the AnyVolumeDataSource
- feature gate to be enabled. (Alpha) Using
- the namespace field of dataSourceRef requires
- the CrossNamespaceVolumeDataSource feature
- gate to be enabled.'
- properties:
- apiGroup:
- description: APIGroup is the group for
- the resource being referenced. If
- APIGroup is not specified, the specified
- Kind must be in the core API group.
- For any other third-party types, APIGroup
- is required.
- type: string
- kind:
- description: Kind is the type of resource
- being referenced
- type: string
- name:
- description: Name is the name of resource
- being referenced
- type: string
- namespace:
- description: Namespace is the namespace
- of resource being referenced Note
- that when a namespace is specified,
- a gateway.networking.k8s.io/ReferenceGrant
- object is required in the referent
- namespace to allow that namespace's
- owner to accept the reference. See
- the ReferenceGrant documentation for
- details. (Alpha) This field requires
- the CrossNamespaceVolumeDataSource
- feature gate to be enabled.
- type: string
- required:
- - kind
- - name
- type: object
+ x-kubernetes-preserve-unknown-fields: true
resources:
- description: 'resources represents the minimum
- resources the volume should have. If RecoverVolumeExpansionFailure
- feature is enabled users are allowed to
- specify resource requirements that are
- lower than previous value but must still
- be higher than capacity recorded in the
- status field of the claim. More info:
- https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources'
+ description: 'Represents the minimum resources
+ the volume should have. If the RecoverVolumeExpansionFailure
+ feature is enabled, users are allowed
+ to specify resource requirements that
+ are lower than the previous value but
+ must still be higher than the capacity
+ recorded in the status field of the claim.
+ More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources.'
properties:
claims:
description: "Claims lists the names
@@ -4375,248 +4097,19 @@ spec:
info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
type: object
type: object
- selector:
- description: selector is a label query over
- volumes to consider for binding.
- properties:
- matchExpressions:
- description: matchExpressions is a list
- of label selector requirements. The
- requirements are ANDed.
- items:
- description: A label selector requirement
- is a selector that contains values,
- a key, and an operator that relates
- the key and values.
- properties:
- key:
- description: key is the label
- key that the selector applies
- to.
- type: string
- operator:
- description: operator represents
- a key's relationship to a set
- of values. Valid operators are
- In, NotIn, Exists and DoesNotExist.
- type: string
- values:
- description: values is an array
- of string values. If the operator
- is In or NotIn, the values array
- must be non-empty. If the operator
- is Exists or DoesNotExist, the
- values array must be empty.
- This array is replaced during
- a strategic merge patch.
- items:
- type: string
- type: array
- required:
- - key
- - operator
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- description: matchLabels is a map of
- {key,value} pairs. A single {key,value}
- in the matchLabels map is equivalent
- to an element of matchExpressions,
- whose key field is "key", the operator
- is "In", and the values array contains
- only "value". The requirements are
- ANDed.
- type: object
- type: object
- x-kubernetes-map-type: atomic
+ x-kubernetes-preserve-unknown-fields: true
storageClassName:
- description: 'storageClassName is the name
- of the StorageClass required by the claim.
- More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1'
+ description: '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. Value
- of Filesystem is implied when not included
- in claim spec.
- type: string
- volumeName:
- description: volumeName is the binding reference
- to the PersistentVolume backing this claim.
- type: string
- type: object
- status:
- description: 'status represents the current
- information/status of a persistent volume
- claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
- properties:
- accessModes:
- description: 'accessModes contains the actual
- access modes the volume backing the PVC
- has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
- items:
- type: string
- type: array
- allocatedResourceStatuses:
- additionalProperties:
- description: When a controller receives
- persistentvolume claim update with ClaimResourceStatus
- for a resource that it does not recognizes,
- then it should ignore that update and
- let other controllers handle it.
- type: string
- description: "allocatedResourceStatuses
- stores status of resource being resized
- for the given PVC. Key names follow standard
- Kubernetes label syntax. Valid values
- are either: * Un-prefixed keys: - storage
- - the capacity of the volume. * Custom
- resources must use implementation-defined
- prefixed names such as \"example.com/my-custom-resource\"
- Apart from above values - keys that are
- unprefixed or have kubernetes.io prefix
- are considered reserved and hence may
- not be used. \n ClaimResourceStatus can
- be in any of following states: - ControllerResizeInProgress:
- State set when resize controller starts
- resizing the volume in control-plane.
- - ControllerResizeFailed: State set when
- resize has failed in resize controller
- with a terminal error. - NodeResizePending:
- State set when resize controller has finished
- resizing the volume but further resizing
- of volume is needed on the node. - NodeResizeInProgress:
- State set when kubelet starts resizing
- the volume. - NodeResizeFailed: State
- set when resizing has failed in kubelet
- with a terminal error. Transient errors
- don't set NodeResizeFailed. For example:
- if expanding a PVC for more capacity -
- this field can be one of the following
- states: - pvc.status.allocatedResourceStatus['storage']
- = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage']
- = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizeFailed\" When this field
- is not set, it means that no resize operation
- is in progress for the given PVC. \n A
- controller that receives PVC update with
- previously unknown resourceName or ClaimResourceStatus
- should ignore the update for the purpose
- it was designed. For example - a controller
- that only is responsible for resizing
- capacity of the volume, should ignore
- PVC updates that change other valid resources
- associated with PVC. \n This is an alpha
- field and requires enabling RecoverVolumeExpansionFailure
- feature."
- type: object
- x-kubernetes-map-type: granular
- allocatedResources:
- additionalProperties:
- anyOf:
- - type: integer
- - type: string
- pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
- x-kubernetes-int-or-string: true
- description: "allocatedResources tracks
- the resources allocated to a PVC including
- its capacity. Key names follow standard
- Kubernetes label syntax. Valid values
- are either: * Un-prefixed keys: - storage
- - the capacity of the volume. * Custom
- resources must use implementation-defined
- prefixed names such as \"example.com/my-custom-resource\"
- Apart from above values - keys that are
- unprefixed or have kubernetes.io prefix
- are considered reserved and hence may
- not be used. \n Capacity reported here
- may be larger than the actual capacity
- when a volume expansion operation is requested.
- For storage quota, the larger value from
- allocatedResources and PVC.spec.resources
- is used. If allocatedResources is not
- set, PVC.spec.resources alone is used
- for quota calculation. If a volume expansion
- capacity request is lowered, allocatedResources
- is only lowered if there are no expansion
- operations in progress and if the actual
- volume capacity is equal or lower than
- the requested capacity. \n A controller
- that receives PVC update with previously
- unknown resourceName should ignore the
- update for the purpose it was designed.
- For example - a controller that only is
- responsible for resizing capacity of the
- volume, should ignore PVC updates that
- change other valid resources associated
- with PVC. \n This is an alpha field and
- requires enabling RecoverVolumeExpansionFailure
- feature."
- type: object
- capacity:
- additionalProperties:
- anyOf:
- - type: integer
- - type: string
- pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
- x-kubernetes-int-or-string: true
- description: capacity represents the actual
- resources of the underlying volume.
- type: object
- conditions:
- description: conditions is the current Condition
- of persistent volume claim. If underlying
- persistent volume is being resized then
- the Condition will be set to 'ResizeStarted'.
- items:
- description: PersistentVolumeClaimCondition
- contains details about state of pvc
- properties:
- lastProbeTime:
- description: lastProbeTime is the
- time we probed the condition.
- format: date-time
- type: string
- lastTransitionTime:
- description: lastTransitionTime is
- the time the condition transitioned
- from one status to another.
- format: date-time
- type: string
- message:
- description: message is the human-readable
- message indicating details about
- last transition.
- type: string
- reason:
- description: reason is a unique, this
- should be a short, machine understandable
- string that gives the reason for
- condition's last transition. If
- it reports "ResizeStarted" that
- means the underlying persistent
- volume is being resized.
- type: string
- status:
- type: string
- type:
- description: PersistentVolumeClaimConditionType
- is a valid value of PersistentVolumeClaimCondition.Type
- type: string
- required:
- - status
- - type
- type: object
- type: array
- phase:
- description: phase represents the current
- phase of PersistentVolumeClaim.
+ description: Defines what type of volume
+ is required by the claim, either Block
+ or Filesystem.
type: string
type: object
+ required:
+ - name
type: object
type: array
volumeMounts:
@@ -6801,7 +6294,7 @@ spec:
- status
type: object
x-kubernetes-validations:
- - message: either objectKey and actionName.
+ - message: at least one objectKey or actionName.
rule: has(self.objectKey) || has(self.actionName)
type: array
reason:
@@ -6817,8 +6310,8 @@ spec:
- Replication
type: string
type: object
- description: Records the status information of components changed
- due to the operation request.
+ description: Records the status information of components, including
+ the sharding component, that have changed due to the operation request.
type: object
conditions:
description: Describes the detailed status of the OpsRequest.
@@ -7238,174 +6731,43 @@ spec:
description: Defines VolumeClaimTemplates to override.
Add new or override existing volume claim templates.
items:
- description: PersistentVolumeClaim is a user's request
- for and claim to a persistent volume
properties:
- apiVersion:
- description: 'APIVersion defines the versioned
- schema of this representation of an object.
- Servers should convert recognized schemas
- to the latest internal value, and may reject
- unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
- type: string
- kind:
- description: 'Kind is a string value representing
- the REST resource this object represents.
- Servers may infer this from the endpoint the
- client submits requests to. Cannot be updated.
- In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ name:
+ description: "Refers to the name of a volumeMount
+ defined in either: \n - `componentDefinition.spec.runtime.containers[*].volumeMounts`
+ - `clusterDefinition.spec.componentDefs[*].podSpec.containers[*].volumeMounts`
+ (deprecated) \n The value of `name` must match
+ the `name` field of a volumeMount specified
+ in the corresponding `volumeMounts` array."
type: string
- metadata:
- description: 'Standard object''s metadata. More
- info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata'
- properties:
- annotations:
- additionalProperties:
- type: string
- type: object
- finalizers:
- items:
- type: string
- type: array
- labels:
- additionalProperties:
- type: string
- type: object
- name:
- type: string
- namespace:
- type: string
- type: object
spec:
- description: 'spec defines the desired characteristics
- of a volume requested by a pod author. More
- info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
+ description: "Defines the desired characteristics
+ of a PersistentVolumeClaim that will be created
+ for the volume with the mount name specified
+ in the `name` field. \n When a Pod is created
+ for this ClusterComponent, a new PVC will
+ be created based on the specification defined
+ in the `spec` field. The PVC will be associated
+ with the volume mount specified by the `name`
+ field."
properties:
accessModes:
- description: 'accessModes contains the desired
- access modes the volume should have. More
- info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
+ description: 'Contains the desired access
+ modes the volume should have. More info:
+ https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1.'
items:
type: string
type: array
- dataSource:
- description: 'dataSource field can be used
- to specify either: * An existing VolumeSnapshot
- object (snapshot.storage.k8s.io/VolumeSnapshot)
- * An existing PVC (PersistentVolumeClaim)
- If the provisioner or an external controller
- can support the specified data source,
- it will create a new volume based on the
- contents of the specified data source.
- When the AnyVolumeDataSource feature gate
- is enabled, dataSource contents will be
- copied to dataSourceRef, and dataSourceRef
- contents will be copied to dataSource
- when dataSourceRef.namespace is not specified.
- If the namespace is specified, then dataSourceRef
- will not be copied to dataSource.'
- properties:
- apiGroup:
- description: APIGroup is the group for
- the resource being referenced. If
- APIGroup is not specified, the specified
- Kind must be in the core API group.
- For any other third-party types, APIGroup
- is required.
- type: string
- kind:
- description: Kind is the type of resource
- being referenced
- type: string
- name:
- description: Name is the name of resource
- being referenced
- type: string
- required:
- - kind
- - name
- type: object
- x-kubernetes-map-type: atomic
- dataSourceRef:
- description: 'dataSourceRef specifies the
- object from which to populate the volume
- with data, if a non-empty volume is desired.
- This may be any object from a non-empty
- API group (non core object) or a PersistentVolumeClaim
- object. When this field is specified,
- volume binding will only succeed if the
- type of the specified object matches some
- installed volume populator or dynamic
- provisioner. This field will replace the
- functionality of the dataSource field
- and as such if both fields are non-empty,
- they must have the same value. For backwards
- compatibility, when namespace isn''t specified
- in dataSourceRef, both fields (dataSource
- and dataSourceRef) will be set to the
- same value automatically if one of them
- is empty and the other is non-empty. When
- namespace is specified in dataSourceRef,
- dataSource isn''t set to the same value
- and must be empty. There are three important
- differences between dataSource and dataSourceRef:
- * While dataSource only allows two specific
- types of objects, dataSourceRef allows
- any non-core object, as well as PersistentVolumeClaim
- objects. * While dataSource ignores disallowed
- values (dropping them), dataSourceRef
- preserves all values, and generates an
- error if a disallowed value is specified.
- * While dataSource only allows local objects,
- dataSourceRef allows objects in any namespaces.
- (Beta) Using this field requires the AnyVolumeDataSource
- feature gate to be enabled. (Alpha) Using
- the namespace field of dataSourceRef requires
- the CrossNamespaceVolumeDataSource feature
- gate to be enabled.'
- properties:
- apiGroup:
- description: APIGroup is the group for
- the resource being referenced. If
- APIGroup is not specified, the specified
- Kind must be in the core API group.
- For any other third-party types, APIGroup
- is required.
- type: string
- kind:
- description: Kind is the type of resource
- being referenced
- type: string
- name:
- description: Name is the name of resource
- being referenced
- type: string
- namespace:
- description: Namespace is the namespace
- of resource being referenced Note
- that when a namespace is specified,
- a gateway.networking.k8s.io/ReferenceGrant
- object is required in the referent
- namespace to allow that namespace's
- owner to accept the reference. See
- the ReferenceGrant documentation for
- details. (Alpha) This field requires
- the CrossNamespaceVolumeDataSource
- feature gate to be enabled.
- type: string
- required:
- - kind
- - name
- type: object
+ x-kubernetes-preserve-unknown-fields: true
resources:
- description: 'resources represents the minimum
- resources the volume should have. If RecoverVolumeExpansionFailure
- feature is enabled users are allowed to
- specify resource requirements that are
- lower than previous value but must still
- be higher than capacity recorded in the
- status field of the claim. More info:
- https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources'
+ description: 'Represents the minimum resources
+ the volume should have. If the RecoverVolumeExpansionFailure
+ feature is enabled, users are allowed
+ to specify resource requirements that
+ are lower than the previous value but
+ must still be higher than the capacity
+ recorded in the status field of the claim.
+ More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources.'
properties:
claims:
description: "Claims lists the names
@@ -7461,248 +6823,19 @@ spec:
info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
type: object
type: object
- selector:
- description: selector is a label query over
- volumes to consider for binding.
- properties:
- matchExpressions:
- description: matchExpressions is a list
- of label selector requirements. The
- requirements are ANDed.
- items:
- description: A label selector requirement
- is a selector that contains values,
- a key, and an operator that relates
- the key and values.
- properties:
- key:
- description: key is the label
- key that the selector applies
- to.
- type: string
- operator:
- description: operator represents
- a key's relationship to a set
- of values. Valid operators are
- In, NotIn, Exists and DoesNotExist.
- type: string
- values:
- description: values is an array
- of string values. If the operator
- is In or NotIn, the values array
- must be non-empty. If the operator
- is Exists or DoesNotExist, the
- values array must be empty.
- This array is replaced during
- a strategic merge patch.
- items:
- type: string
- type: array
- required:
- - key
- - operator
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- description: matchLabels is a map of
- {key,value} pairs. A single {key,value}
- in the matchLabels map is equivalent
- to an element of matchExpressions,
- whose key field is "key", the operator
- is "In", and the values array contains
- only "value". The requirements are
- ANDed.
- type: object
- type: object
- x-kubernetes-map-type: atomic
+ x-kubernetes-preserve-unknown-fields: true
storageClassName:
- description: 'storageClassName is the name
- of the StorageClass required by the claim.
- More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1'
+ description: '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. Value
- of Filesystem is implied when not included
- in claim spec.
- type: string
- volumeName:
- description: volumeName is the binding reference
- to the PersistentVolume backing this claim.
- type: string
- type: object
- status:
- description: 'status represents the current
- information/status of a persistent volume
- claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
- properties:
- accessModes:
- description: 'accessModes contains the actual
- access modes the volume backing the PVC
- has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
- items:
- type: string
- type: array
- allocatedResourceStatuses:
- additionalProperties:
- description: When a controller receives
- persistentvolume claim update with ClaimResourceStatus
- for a resource that it does not recognizes,
- then it should ignore that update and
- let other controllers handle it.
- type: string
- description: "allocatedResourceStatuses
- stores status of resource being resized
- for the given PVC. Key names follow standard
- Kubernetes label syntax. Valid values
- are either: * Un-prefixed keys: - storage
- - the capacity of the volume. * Custom
- resources must use implementation-defined
- prefixed names such as \"example.com/my-custom-resource\"
- Apart from above values - keys that are
- unprefixed or have kubernetes.io prefix
- are considered reserved and hence may
- not be used. \n ClaimResourceStatus can
- be in any of following states: - ControllerResizeInProgress:
- State set when resize controller starts
- resizing the volume in control-plane.
- - ControllerResizeFailed: State set when
- resize has failed in resize controller
- with a terminal error. - NodeResizePending:
- State set when resize controller has finished
- resizing the volume but further resizing
- of volume is needed on the node. - NodeResizeInProgress:
- State set when kubelet starts resizing
- the volume. - NodeResizeFailed: State
- set when resizing has failed in kubelet
- with a terminal error. Transient errors
- don't set NodeResizeFailed. For example:
- if expanding a PVC for more capacity -
- this field can be one of the following
- states: - pvc.status.allocatedResourceStatus['storage']
- = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage']
- = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage']
- = \"NodeResizeFailed\" When this field
- is not set, it means that no resize operation
- is in progress for the given PVC. \n A
- controller that receives PVC update with
- previously unknown resourceName or ClaimResourceStatus
- should ignore the update for the purpose
- it was designed. For example - a controller
- that only is responsible for resizing
- capacity of the volume, should ignore
- PVC updates that change other valid resources
- associated with PVC. \n This is an alpha
- field and requires enabling RecoverVolumeExpansionFailure
- feature."
- type: object
- x-kubernetes-map-type: granular
- allocatedResources:
- additionalProperties:
- anyOf:
- - type: integer
- - type: string
- pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
- x-kubernetes-int-or-string: true
- description: "allocatedResources tracks
- the resources allocated to a PVC including
- its capacity. Key names follow standard
- Kubernetes label syntax. Valid values
- are either: * Un-prefixed keys: - storage
- - the capacity of the volume. * Custom
- resources must use implementation-defined
- prefixed names such as \"example.com/my-custom-resource\"
- Apart from above values - keys that are
- unprefixed or have kubernetes.io prefix
- are considered reserved and hence may
- not be used. \n Capacity reported here
- may be larger than the actual capacity
- when a volume expansion operation is requested.
- For storage quota, the larger value from
- allocatedResources and PVC.spec.resources
- is used. If allocatedResources is not
- set, PVC.spec.resources alone is used
- for quota calculation. If a volume expansion
- capacity request is lowered, allocatedResources
- is only lowered if there are no expansion
- operations in progress and if the actual
- volume capacity is equal or lower than
- the requested capacity. \n A controller
- that receives PVC update with previously
- unknown resourceName should ignore the
- update for the purpose it was designed.
- For example - a controller that only is
- responsible for resizing capacity of the
- volume, should ignore PVC updates that
- change other valid resources associated
- with PVC. \n This is an alpha field and
- requires enabling RecoverVolumeExpansionFailure
- feature."
- type: object
- capacity:
- additionalProperties:
- anyOf:
- - type: integer
- - type: string
- pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
- x-kubernetes-int-or-string: true
- description: capacity represents the actual
- resources of the underlying volume.
- type: object
- conditions:
- description: conditions is the current Condition
- of persistent volume claim. If underlying
- persistent volume is being resized then
- the Condition will be set to 'ResizeStarted'.
- items:
- description: PersistentVolumeClaimCondition
- contains details about state of pvc
- properties:
- lastProbeTime:
- description: lastProbeTime is the
- time we probed the condition.
- format: date-time
- type: string
- lastTransitionTime:
- description: lastTransitionTime is
- the time the condition transitioned
- from one status to another.
- format: date-time
- type: string
- message:
- description: message is the human-readable
- message indicating details about
- last transition.
- type: string
- reason:
- description: reason is a unique, this
- should be a short, machine understandable
- string that gives the reason for
- condition's last transition. If
- it reports "ResizeStarted" that
- means the underlying persistent
- volume is being resized.
- type: string
- status:
- type: string
- type:
- description: PersistentVolumeClaimConditionType
- is a valid value of PersistentVolumeClaimCondition.Type
- type: string
- required:
- - status
- - type
- type: object
- type: array
- phase:
- description: phase represents the current
- phase of PersistentVolumeClaim.
+ description: Defines what type of volume
+ is required by the claim, either Block
+ or Filesystem.
type: string
type: object
+ required:
+ - name
type: object
type: array
volumeMounts:
diff --git a/config/crd/bases/workloads.kubeblocks.io_instancesets.yaml b/config/crd/bases/workloads.kubeblocks.io_instancesets.yaml
index 018a67172a4..b936792ab7b 100644
--- a/config/crd/bases/workloads.kubeblocks.io_instancesets.yaml
+++ b/config/crd/bases/workloads.kubeblocks.io_instancesets.yaml
@@ -3259,6 +3259,9 @@ spec:
- name
type: object
type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
memberUpdateStrategy:
description: "Members(Pods) update strategy. \n - serial: update Members
one by one that guarantee minimum component unavailable time. -
diff --git a/controllers/apps/operations/custom.go b/controllers/apps/operations/custom.go
index f762cafb210..6d8369dd47e 100644
--- a/controllers/apps/operations/custom.go
+++ b/controllers/apps/operations/custom.go
@@ -74,13 +74,13 @@ func (c CustomOpsHandler) ReconcileAction(reqCtx intctrlutil.RequestCtx, cli cli
opsRequestPhase = opsRes.OpsRequest.Status.Phase
customSpec = opsRes.OpsRequest.Spec.CustomSpec
workflowContext = NewWorkflowContext(reqCtx, cli, opsRes)
- compCount = len(customSpec.CustomOpsComponents)
+ compCount = len(customSpec.CustomOpsItems)
completedActionCount int
compFailedCount int
compCompleteCount int
)
// TODO: support Parallelism
- for _, v := range customSpec.CustomOpsComponents {
+ for _, v := range customSpec.CustomOpsItems {
// 1. init component action progress and preCheck if the conditions for executing ops are met.
passed := c.initCompActionStatusAndPreCheck(reqCtx, cli, opsRes, v)
if !passed {
@@ -124,17 +124,17 @@ func (c CustomOpsHandler) checkExpression(reqCtx intctrlutil.RequestCtx,
cli client.Client,
opsRes *OpsResource,
rule *appsv1alpha1.Rule,
- compCustomOSpec appsv1alpha1.CustomOpsComponent) error {
+ compCustomItem appsv1alpha1.CustomOpsItem) error {
opsSpec := opsRes.OpsRequest.Spec
if opsSpec.Force {
return nil
}
- componentObjName := constant.GenerateClusterComponentName(opsSpec.ClusterRef, compCustomOSpec.ComponentName)
+ componentObjName := constant.GenerateClusterComponentName(opsSpec.ClusterRef, compCustomItem.ComponentName)
comp := &appsv1alpha1.Component{}
if err := cli.Get(reqCtx.Ctx, client.ObjectKey{Name: componentObjName, Namespace: opsRes.OpsRequest.Namespace}, comp); err != nil {
return err
}
- params := covertParametersToMap(compCustomOSpec.Parameters)
+ params := covertParametersToMap(compCustomItem.Parameters)
// get the built-in objects and covert the json tag
getBuiltInObjs := func() (map[string]interface{}, error) {
b, err := json.Marshal(map[string]interface{}{
@@ -174,19 +174,19 @@ func (c CustomOpsHandler) checkExpression(reqCtx intctrlutil.RequestCtx,
func (c CustomOpsHandler) initCompActionStatusAndPreCheck(reqCtx intctrlutil.RequestCtx,
cli client.Client,
opsRes *OpsResource,
- compCustomSpec appsv1alpha1.CustomOpsComponent) bool {
+ compCustomItem appsv1alpha1.CustomOpsItem) bool {
if opsRes.OpsRequest.Status.Components == nil {
opsRes.OpsRequest.Status.Components = map[string]appsv1alpha1.OpsRequestComponentStatus{}
}
- compStatus := opsRes.OpsRequest.Status.Components[compCustomSpec.ComponentName]
- compStatus.Phase = opsRes.Cluster.Status.Components[compCustomSpec.ComponentName].Phase
+ compStatus := opsRes.OpsRequest.Status.Components[compCustomItem.ComponentName]
+ compStatus.Phase = opsRes.Cluster.Status.Components[compCustomItem.ComponentName].Phase
if len(compStatus.ProgressDetails) == 0 {
// 1. do preChecks
for _, v := range opsRes.OpsDef.Spec.PreConditions {
if v.Rule != nil {
- if err := c.checkExpression(reqCtx, cli, opsRes, v.Rule, compCustomSpec); err != nil {
+ if err := c.checkExpression(reqCtx, cli, opsRes, v.Rule, compCustomItem); err != nil {
compStatus.PreCheckResult = &appsv1alpha1.PreCheckResult{Pass: false, Message: err.Error()}
- opsRes.OpsRequest.Status.Components[compCustomSpec.ComponentName] = compStatus
+ opsRes.OpsRequest.Status.Components[compCustomItem.ComponentName] = compStatus
opsRes.Recorder.Event(opsRes.OpsRequest, corev1.EventTypeWarning, "PreCheckFailed", err.Error())
return false
}
@@ -200,7 +200,7 @@ func (c CustomOpsHandler) initCompActionStatusAndPreCheck(reqCtx intctrlutil.Req
ActionName: opsRes.OpsDef.Spec.Actions[i].Name,
})
}
- opsRes.OpsRequest.Status.Components[compCustomSpec.ComponentName] = compStatus
+ opsRes.OpsRequest.Status.Components[compCustomItem.ComponentName] = compStatus
}
return true
}
@@ -228,7 +228,7 @@ func initOpsDefAndValidate(reqCtx intctrlutil.RequestCtx,
opsRes.OpsDef = opsDef
// 1. validate OpenApV3Schema
parametersSchema := opsDef.Spec.ParametersSchema
- for _, v := range customSpec.CustomOpsComponents {
+ for _, v := range customSpec.CustomOpsItems {
// covert to type map[string]interface{}
params, err := common.CoverStringToInterfaceBySchemaType(parametersSchema.OpenAPIV3Schema, covertParametersToMap(v.Parameters))
if err != nil {
diff --git a/controllers/apps/operations/custom/action_exec.go b/controllers/apps/operations/custom/action_exec.go
index 7b9ff134f5c..3b36a4334d3 100644
--- a/controllers/apps/operations/custom/action_exec.go
+++ b/controllers/apps/operations/custom/action_exec.go
@@ -33,7 +33,7 @@ type ExecAction struct {
OpsRequest *appsv1alpha1.OpsRequest
Cluster *appsv1alpha1.Cluster
OpsDef *appsv1alpha1.OpsDefinition
- CompCustomSpec *appsv1alpha1.CustomOpsComponent
+ CustomOpsItem *appsv1alpha1.CustomOpsItem
Comp *appsv1alpha1.ClusterComponentSpec
progressDetail appsv1alpha1.ProgressStatusDetail
}
@@ -41,14 +41,14 @@ type ExecAction struct {
func NewExecAction(opsRequest *appsv1alpha1.OpsRequest,
cluster *appsv1alpha1.Cluster,
opsDef *appsv1alpha1.OpsDefinition,
- comCustomSpec *appsv1alpha1.CustomOpsComponent,
+ customOpsItem *appsv1alpha1.CustomOpsItem,
comp *appsv1alpha1.ClusterComponentSpec,
progressDetail appsv1alpha1.ProgressStatusDetail) *ExecAction {
return &ExecAction{
OpsRequest: opsRequest,
Cluster: cluster,
OpsDef: opsDef,
- CompCustomSpec: comCustomSpec,
+ CustomOpsItem: customOpsItem,
Comp: comp,
progressDetail: progressDetail,
}
@@ -68,7 +68,7 @@ func (e *ExecAction) Execute(actionCtx ActionContext) (*ActionStatus, error) {
if targetPodTemplate == nil {
return nil, intctrlutil.NewFatalError("can not found the targetPodTemplate by " + podTemplateName)
}
- targetPods, err := getTargetPods(actionCtx.ReqCtx.Ctx, actionCtx.Client, e.Cluster, targetPodTemplate.PodSelector, e.CompCustomSpec.ComponentName)
+ targetPods, err := getTargetPods(actionCtx.ReqCtx.Ctx, actionCtx.Client, e.Cluster, targetPodTemplate.PodSelector, e.CustomOpsItem.ComponentName)
if err != nil {
return nil, err
}
@@ -142,7 +142,7 @@ func (e *ExecAction) buildExecPodSpec(actionCtx ActionContext,
targetPod *corev1.Pod) (*corev1.PodSpec, error) {
// inject component and componentDef envs
env, err := buildActionPodEnv(actionCtx.ReqCtx, actionCtx.Client, e.Cluster, e.OpsDef,
- e.OpsRequest, e.Comp, e.CompCustomSpec, targetPodTemplate, targetPod)
+ e.OpsRequest, e.Comp, e.CustomOpsItem, targetPodTemplate, targetPod)
if err != nil {
return nil, err
}
diff --git a/controllers/apps/operations/custom/action_workload.go b/controllers/apps/operations/custom/action_workload.go
index 450f2a0c3b7..a32b9070860 100644
--- a/controllers/apps/operations/custom/action_workload.go
+++ b/controllers/apps/operations/custom/action_workload.go
@@ -33,7 +33,7 @@ type WorkloadAction struct {
OpsRequest *appsv1alpha1.OpsRequest
Cluster *appsv1alpha1.Cluster
OpsDef *appsv1alpha1.OpsDefinition
- CompCustomSpec *appsv1alpha1.CustomOpsComponent
+ CompCustomItem *appsv1alpha1.CustomOpsItem
Comp *appsv1alpha1.ClusterComponentSpec
progressDetail appsv1alpha1.ProgressStatusDetail
}
@@ -41,14 +41,14 @@ type WorkloadAction struct {
func NewWorkloadAction(opsRequest *appsv1alpha1.OpsRequest,
cluster *appsv1alpha1.Cluster,
opsDef *appsv1alpha1.OpsDefinition,
- comCustomSpec *appsv1alpha1.CustomOpsComponent,
+ compCustomItem *appsv1alpha1.CustomOpsItem,
comp *appsv1alpha1.ClusterComponentSpec,
progressDetail appsv1alpha1.ProgressStatusDetail) *WorkloadAction {
return &WorkloadAction{
OpsRequest: opsRequest,
Cluster: cluster,
OpsDef: opsDef,
- CompCustomSpec: comCustomSpec,
+ CompCustomItem: compCustomItem,
Comp: comp,
progressDetail: progressDetail,
}
@@ -71,7 +71,7 @@ func (w *WorkloadAction) Execute(actionCtx ActionContext) (*ActionStatus, error)
if targetPodTemplate == nil {
return nil, intctrlutil.NewFatalError("can not found the targetPodTemplate by " + podTemplateName)
}
- targetPods, err = getTargetPods(actionCtx.ReqCtx.Ctx, actionCtx.Client, w.Cluster, targetPodTemplate.PodSelector, w.CompCustomSpec.ComponentName)
+ targetPods, err = getTargetPods(actionCtx.ReqCtx.Ctx, actionCtx.Client, w.Cluster, targetPodTemplate.PodSelector, w.CompCustomItem.ComponentName)
if err != nil {
return nil, err
}
@@ -144,7 +144,7 @@ func (w *WorkloadAction) buildPodSpec(actionCtx ActionContext,
)
env, err := buildActionPodEnv(actionCtx.ReqCtx, actionCtx.Client, w.Cluster, w.OpsDef, w.OpsRequest,
- w.Comp, w.CompCustomSpec, targetPodTemplate, targetPod)
+ w.Comp, w.CompCustomItem, targetPodTemplate, targetPod)
if err != nil {
return nil, err
}
diff --git a/controllers/apps/operations/custom/utils.go b/controllers/apps/operations/custom/utils.go
index e7926a1cef3..b87c41defc2 100644
--- a/controllers/apps/operations/custom/utils.go
+++ b/controllers/apps/operations/custom/utils.go
@@ -236,7 +236,7 @@ func buildActionPodEnv(reqCtx intctrlutil.RequestCtx,
opsDef *appsv1alpha1.OpsDefinition,
ops *appsv1alpha1.OpsRequest,
comp *appsv1alpha1.ClusterComponentSpec,
- compCustomSpec *appsv1alpha1.CustomOpsComponent,
+ compCustomItem *appsv1alpha1.CustomOpsItem,
targetPodTemplate *appsv1alpha1.TargetPodTemplate,
targetPod *corev1.Pod) ([]corev1.EnvVar, error) {
var env = []corev1.EnvVar{
@@ -264,7 +264,7 @@ func buildActionPodEnv(reqCtx intctrlutil.RequestCtx,
}
// inject params env
- params := compCustomSpec.Parameters
+ params := compCustomItem.Parameters
for i := range params {
env = append(env, corev1.EnvVar{Name: params[i].Name, Value: params[i].Value})
}
diff --git a/controllers/apps/operations/custom_test.go b/controllers/apps/operations/custom_test.go
index a93eb4ef149..3d889c85788 100644
--- a/controllers/apps/operations/custom_test.go
+++ b/controllers/apps/operations/custom_test.go
@@ -81,10 +81,12 @@ var _ = Describe("CustomOps", func() {
cluster.Name, appsv1alpha1.CustomType)
ops.Spec.CustomSpec = &appsv1alpha1.CustomOpsSpec{
OpsDefinitionRef: opsDef.Name,
- CustomOpsComponents: []appsv1alpha1.CustomOpsComponent{
+ CustomOpsItems: []appsv1alpha1.CustomOpsItem{
{
- ComponentName: comp,
- Parameters: params,
+ ComponentOps: appsv1alpha1.ComponentOps{
+ ComponentName: comp,
+ },
+ Parameters: params,
},
},
}
diff --git a/controllers/apps/operations/custom_workflow.go b/controllers/apps/operations/custom_workflow.go
index d20364a7c0d..8d206601f50 100644
--- a/controllers/apps/operations/custom_workflow.go
+++ b/controllers/apps/operations/custom_workflow.go
@@ -53,7 +53,7 @@ func NewWorkflowContext(
}
// Run actions execution layer.
-func (w *WorkflowContext) Run(compCustomSpec *appsv1alpha1.CustomOpsComponent) (*WorkflowStatus, error) {
+func (w *WorkflowContext) Run(compCustomSpec *appsv1alpha1.CustomOpsItem) (*WorkflowStatus, error) {
var (
err error
actionStatus *custom.ActionStatus
@@ -145,16 +145,16 @@ steps:
}
func (w *WorkflowContext) getAction(action appsv1alpha1.OpsAction,
- compCustomSpec *appsv1alpha1.CustomOpsComponent,
+ compCustomItem *appsv1alpha1.CustomOpsItem,
comp *appsv1alpha1.ClusterComponentSpec,
progressDetail appsv1alpha1.ProgressStatusDetail) custom.OpsAction {
switch {
case action.Workload != nil:
return custom.NewWorkloadAction(w.OpsRes.OpsRequest, w.OpsRes.Cluster,
- w.OpsRes.OpsDef, compCustomSpec, comp, progressDetail)
+ w.OpsRes.OpsDef, compCustomItem, comp, progressDetail)
case action.Exec != nil:
return custom.NewExecAction(w.OpsRes.OpsRequest, w.OpsRes.Cluster,
- w.OpsRes.OpsDef, compCustomSpec, comp, progressDetail)
+ w.OpsRes.OpsDef, compCustomItem, comp, progressDetail)
case action.ResourceModifier != nil:
// TODO: implement it.
return nil
diff --git a/controllers/apps/operations/expose.go b/controllers/apps/operations/expose.go
index 490ba240c97..4eab15c3a39 100644
--- a/controllers/apps/operations/expose.go
+++ b/controllers/apps/operations/expose.go
@@ -27,6 +27,7 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/util/sets"
"sigs.k8s.io/controller-runtime/pkg/client"
appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1"
@@ -225,10 +226,15 @@ func (e ExposeOpsHandler) ActionStartedCondition(reqCtx intctrlutil.RequestCtx,
}
func (e ExposeOpsHandler) SaveLastConfiguration(reqCtx intctrlutil.RequestCtx, cli client.Client, opsResource *OpsResource) error {
- componentNameSet := opsResource.OpsRequest.GetComponentNameSet()
+ compOpsSet := map[string]sets.Empty{}
+ for _, v := range opsResource.OpsRequest.Spec.ExposeList {
+ if v.ComponentName != "" {
+ compOpsSet[v.ComponentName] = sets.Empty{}
+ }
+ }
lastComponentInfo := map[string]appsv1alpha1.LastComponentConfiguration{}
for _, v := range opsResource.Cluster.Spec.ComponentSpecs {
- if _, ok := componentNameSet[v.Name]; !ok {
+ if _, ok := compOpsSet[v.Name]; !ok {
continue
}
lastComponentInfo[v.Name] = appsv1alpha1.LastComponentConfiguration{
diff --git a/controllers/apps/operations/expose_test.go b/controllers/apps/operations/expose_test.go
index c27fe878c7d..3c6c3ec3370 100644
--- a/controllers/apps/operations/expose_test.go
+++ b/controllers/apps/operations/expose_test.go
@@ -76,8 +76,8 @@ var _ = Describe("", func() {
clusterObject.Name, appsv1alpha1.ExposeType)
ops.Spec.ExposeList = []appsv1alpha1.Expose{
{
- ComponentOps: appsv1alpha1.ComponentOps{ComponentName: consensusCompName},
- Switch: appsv1alpha1.EnableExposeSwitch,
+ ComponentName: consensusCompName,
+ Switch: appsv1alpha1.EnableExposeSwitch,
Services: []appsv1alpha1.OpsService{
{
Name: testapps.ServiceVPCName,
@@ -113,8 +113,7 @@ var _ = Describe("", func() {
clusterObject.Name, appsv1alpha1.ExposeType)
ops.Spec.ExposeList = []appsv1alpha1.Expose{
{
- ComponentOps: appsv1alpha1.ComponentOps{ComponentName: ""},
- Switch: appsv1alpha1.EnableExposeSwitch,
+ Switch: appsv1alpha1.EnableExposeSwitch,
Services: []appsv1alpha1.OpsService{
{
Name: testapps.ServiceVPCName,
diff --git a/controllers/apps/operations/horizontal_scaling.go b/controllers/apps/operations/horizontal_scaling.go
index 5636d2d2e24..93dcba99e42 100644
--- a/controllers/apps/operations/horizontal_scaling.go
+++ b/controllers/apps/operations/horizontal_scaling.go
@@ -23,10 +23,10 @@ import (
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client"
appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1"
- intctrlcomp "github.com/apecloud/kubeblocks/pkg/controller/component"
intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil"
)
@@ -55,23 +55,17 @@ func (hs horizontalScalingOpsHandler) ActionStartedCondition(reqCtx intctrlutil.
// Action modifies Cluster.spec.components[*].replicas from the opsRequest
func (hs horizontalScalingOpsHandler) Action(reqCtx intctrlutil.RequestCtx, cli client.Client, opsRes *OpsResource) error {
- var (
- horizontalScalingMap = opsRes.OpsRequest.Spec.ToHorizontalScalingListToMap()
- horizontalScaling appsv1alpha1.HorizontalScaling
- ok bool
- )
- for index, component := range opsRes.Cluster.Spec.ComponentSpecs {
- if horizontalScaling, ok = horizontalScalingMap[component.Name]; !ok {
- continue
- }
-
- instances := buildInstances(opsRes.Cluster.Spec.ComponentSpecs[index], horizontalScaling)
- opsRes.Cluster.Spec.ComponentSpecs[index].Instances = instances
+ applyHorizontalScaling := func(compSpec *appsv1alpha1.ClusterComponentSpec, obj ComponentOpsInteface) {
+ horizontalScaling := obj.(appsv1alpha1.HorizontalScaling)
+ instances := buildInstances(*compSpec, horizontalScaling)
+ compSpec.Instances = instances
if horizontalScaling.OfflineInstances != nil {
- opsRes.Cluster.Spec.ComponentSpecs[index].OfflineInstances = horizontalScaling.OfflineInstances
+ compSpec.OfflineInstances = horizontalScaling.OfflineInstances
}
- opsRes.Cluster.Spec.ComponentSpecs[index].Replicas = horizontalScaling.Replicas
+ compSpec.Replicas = horizontalScaling.Replicas
}
+ compOpsSet := newComponentOpsHelper(opsRes.OpsRequest.Spec.HorizontalScalingList)
+ compOpsSet.updateClusterComponentsAndShardings(opsRes.Cluster, applyHorizontalScaling)
return cli.Update(reqCtx.Ctx, opsRes.Cluster)
}
@@ -107,79 +101,57 @@ func (hs horizontalScalingOpsHandler) ReconcileAction(reqCtx intctrlutil.Request
compStatus *appsv1alpha1.OpsRequestComponentStatus) (int32, int32, error) {
return handleComponentProgressForScalingReplicas(reqCtx, cli, opsRes, pgRes, compStatus, hs.getExpectReplicas)
}
- return reconcileActionWithComponentOps(reqCtx, cli, opsRes, "", syncOverrideByOpsForScaleReplicas, handleComponentProgress)
+ compOpsHelper := newComponentOpsHelper(opsRes.OpsRequest.Spec.HorizontalScalingList)
+ return compOpsHelper.reconcileActionWithComponentOps(reqCtx, cli, opsRes, "", syncOverrideByOpsForScaleReplicas, handleComponentProgress)
}
// SaveLastConfiguration records last configuration to the OpsRequest.status.lastConfiguration
func (hs horizontalScalingOpsHandler) SaveLastConfiguration(reqCtx intctrlutil.RequestCtx, cli client.Client, opsRes *OpsResource) error {
- opsRequest := opsRes.OpsRequest
- lastComponentInfo := map[string]appsv1alpha1.LastComponentConfiguration{}
- componentNameMap := opsRequest.Spec.ToHorizontalScalingListToMap()
- for _, v := range opsRes.Cluster.Spec.ComponentSpecs {
- hsInfo, ok := componentNameMap[v.Name]
- if !ok {
- continue
- }
- copyReplicas := v.Replicas
+ compOpsHelper := newComponentOpsHelper(opsRes.OpsRequest.Spec.HorizontalScalingList)
+ getLastComponentInfo := func(compSpec appsv1alpha1.ClusterComponentSpec, comOps ComponentOpsInteface) appsv1alpha1.LastComponentConfiguration {
var (
- copyInstances *[]appsv1alpha1.InstanceTemplate
- copyOfflineInstances *[]string
+ copyInstances []appsv1alpha1.InstanceTemplate
+ copyOfflineInstances []string
)
- if len(v.Instances) > 0 {
+ if len(compSpec.Instances) > 0 {
var instances []appsv1alpha1.InstanceTemplate
- instances = append(instances, v.Instances...)
- copyInstances = &instances
+ instances = append(instances, compSpec.Instances...)
+ copyInstances = instances
}
- if len(v.OfflineInstances) > 0 {
+ if len(compSpec.OfflineInstances) > 0 {
var offlineInstances []string
- offlineInstances = append(offlineInstances, v.OfflineInstances...)
- copyOfflineInstances = &offlineInstances
+ offlineInstances = append(offlineInstances, compSpec.OfflineInstances...)
+ copyOfflineInstances = offlineInstances
}
lastCompConfiguration := appsv1alpha1.LastComponentConfiguration{
- Replicas: ©Replicas,
+ Replicas: pointer.Int32(compSpec.Replicas),
Instances: copyInstances,
OfflineInstances: copyOfflineInstances,
}
- if hsInfo.Replicas < copyReplicas {
- podNames, err := getCompPodNamesBeforeScaleDownReplicas(reqCtx, cli, *opsRes.Cluster, v.Name)
- if err != nil {
- return err
- }
- lastCompConfiguration.TargetResources = map[appsv1alpha1.ComponentResourceKey][]string{
- appsv1alpha1.PodsCompResourceKey: podNames,
- }
- }
- lastComponentInfo[v.Name] = lastCompConfiguration
+ return lastCompConfiguration
}
- opsRequest.Status.LastConfiguration.Components = lastComponentInfo
+ compOpsHelper.saveLastConfigurations(opsRes, getLastComponentInfo)
return nil
}
-func (hs horizontalScalingOpsHandler) getExpectReplicas(opsRequest *appsv1alpha1.OpsRequest, componentName string) *int32 {
+func (hs horizontalScalingOpsHandler) getExpectReplicas(opsRequest *appsv1alpha1.OpsRequest, shardName, componentName string) *int32 {
compStatus := opsRequest.Status.Components[componentName]
if compStatus.OverrideBy != nil {
return compStatus.OverrideBy.Replicas
}
for _, v := range opsRequest.Spec.HorizontalScalingList {
+ if shardName != "" {
+ if v.ShardingName == shardName {
+ return &v.Replicas
+ }
+ continue
+ }
if v.ComponentName == componentName {
return &v.Replicas
}
- }
- return nil
-}
-// getCompPodNamesBeforeScaleDownReplicas gets the component pod names before scale down replicas.
-func getCompPodNamesBeforeScaleDownReplicas(reqCtx intctrlutil.RequestCtx,
- cli client.Client, cluster appsv1alpha1.Cluster, compName string) ([]string, error) {
- podNames := make([]string, 0)
- podList, err := intctrlcomp.GetComponentPodList(reqCtx.Ctx, cli, cluster, compName)
- if err != nil {
- return podNames, err
- }
- for _, v := range podList.Items {
- podNames = append(podNames, v.Name)
}
- return podNames, nil
+ return nil
}
// Cancel this function defines the cancel horizontalScaling action.
@@ -189,25 +161,17 @@ func (hs horizontalScalingOpsHandler) Cancel(reqCtx intctrlutil.RequestCtx, cli
return intctrlutil.NewErrorf(intctrlutil.ErrorIgnoreCancel, `can not cancel the opsRequest due to another opsRequest "%s" is running`, v.OverrideBy.OpsName)
}
}
- return cancelComponentOps(reqCtx.Ctx, cli, opsRes, func(lastConfig *appsv1alpha1.LastComponentConfiguration, comp *appsv1alpha1.ClusterComponentSpec) error {
+ compOpsHelper := newComponentOpsHelper(opsRes.OpsRequest.Spec.VerticalScalingList)
+ return compOpsHelper.cancelComponentOps(reqCtx.Ctx, cli, opsRes, func(lastConfig *appsv1alpha1.LastComponentConfiguration, comp *appsv1alpha1.ClusterComponentSpec) {
if lastConfig.Replicas == nil {
- return nil
- }
- podNames, err := getCompPodNamesBeforeScaleDownReplicas(reqCtx, cli, *opsRes.Cluster, comp.Name)
- if err != nil {
- return err
+ return
}
- if lastConfig.TargetResources == nil {
- lastConfig.TargetResources = map[appsv1alpha1.ComponentResourceKey][]string{}
- }
- lastConfig.TargetResources[appsv1alpha1.PodsCompResourceKey] = podNames
comp.Replicas = *lastConfig.Replicas
if lastConfig.Instances != nil {
- comp.Instances = *lastConfig.Instances
+ comp.Instances = lastConfig.Instances
}
if lastConfig.OfflineInstances != nil {
- comp.OfflineInstances = *lastConfig.OfflineInstances
+ comp.OfflineInstances = lastConfig.OfflineInstances
}
- return nil
})
}
diff --git a/controllers/apps/operations/horizontal_scaling_test.go b/controllers/apps/operations/horizontal_scaling_test.go
index beda8cd6238..322b4f062a6 100644
--- a/controllers/apps/operations/horizontal_scaling_test.go
+++ b/controllers/apps/operations/horizontal_scaling_test.go
@@ -123,15 +123,15 @@ var _ = Describe("HorizontalScaling OpsRequest", func() {
Expect(err).ShouldNot(HaveOccurred())
Expect(opsRes.OpsRequest.Status.Phase).Should(Equal(appsv1alpha1.OpsCancelledPhase))
opsProgressDetails := opsRes.OpsRequest.Status.Components[consensusComp].ProgressDetails
- Expect(len(opsProgressDetails)).Should(Equal(1))
- Expect(opsProgressDetails[0].Status).Should(Equal(appsv1alpha1.SucceedProgressStatus))
+ Expect(opsRes.OpsRequest.Status.Progress).Should(Equal("2/2"))
+ Expect(len(opsProgressDetails)).Should(Equal(2))
}
It("test scaling down replicas", func() {
reqCtx := intctrlutil.RequestCtx{Ctx: testCtx.Ctx}
opsRes, podList := commonHScaleConsensusCompTest(reqCtx, 1, nil)
By("mock two pods are deleted")
- for i := 0; i < 2; i++ {
+ for i := 1; i < 3; i++ {
pod := &podList[i]
pod.Kind = constant.PodKind
testk8s.MockPodIsTerminating(ctx, testCtx, pod)
@@ -156,7 +156,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() {
opsRes, podList := commonHScaleConsensusCompTest(reqCtx, 1, nil)
By("mock one pod has been deleted")
- pod := &podList[0]
+ pod := &podList[2]
pod.Kind = constant.PodKind
testk8s.MockPodIsTerminating(ctx, testCtx, pod)
testk8s.RemovePodFinalizer(ctx, testCtx, pod)
@@ -165,12 +165,14 @@ var _ = Describe("HorizontalScaling OpsRequest", func() {
cancelOpsRequest(reqCtx, opsRes, time.Now().Add(-1*time.Second))
By("re-create the deleted pod")
- podName := fmt.Sprintf("%s-%s-%d", clusterName, consensusComp, 0)
- testapps.MockInstanceSetPod(&testCtx, nil, clusterName, consensusComp, podName, "leader", "ReadWrite")
+ podName := fmt.Sprintf("%s-%s-%d", clusterName, consensusComp, 2)
+ testapps.MockInstanceSetPod(&testCtx, nil, clusterName, consensusComp, podName, "follower", "ReadOnly")
By("expect for opsRequest phase is Succeed after pods has been scaled and component phase is Running")
mockConsensusCompToRunning(opsRes)
checkCancelledSucceed(reqCtx, opsRes)
+ Expect(findStatusProgressDetail(opsRes.OpsRequest.Status.Components[consensusComp].ProgressDetails,
+ getProgressObjectKey(constant.PodKind, podName)).Status).Should(Equal(appsv1alpha1.SucceedProgressStatus))
})
It("test canceling HScale opsRequest which scales out replicas of component", func() {
@@ -192,6 +194,8 @@ var _ = Describe("HorizontalScaling OpsRequest", func() {
By("expect for opsRequest phase is Succeed after pods has been scaled and component phase is Running")
mockConsensusCompToRunning(opsRes)
checkCancelledSucceed(reqCtx, opsRes)
+ Expect(findStatusProgressDetail(opsRes.OpsRequest.Status.Components[consensusComp].ProgressDetails,
+ getProgressObjectKey(constant.PodKind, pod.Name)).Status).Should(Equal(appsv1alpha1.SucceedProgressStatus))
})
It("force run horizontal scaling opsRequests ", func() {
diff --git a/controllers/apps/operations/ops_comp_helper.go b/controllers/apps/operations/ops_comp_helper.go
new file mode 100644
index 00000000000..680f7d4e0e8
--- /dev/null
+++ b/controllers/apps/operations/ops_comp_helper.go
@@ -0,0 +1,308 @@
+/*
+Copyright (C) 2022-2024 ApeCloud Co., Ltd
+
+# This file is part of KubeBlocks project
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see
-(Appears on:ClusterComponentSpec, ComponentSpec) +(Appears on:ClusterComponentSpec, ComponentSpec, InstanceTemplate)
map[string]struct{}
alias)-(Appears on:Expose, HorizontalScaling, OpsRequestSpec, RebuildInstance, Reconfigure, ScriptSpec, Switchover, VerticalScaling, VolumeExpansion) +(Appears on:CustomOpsItem, HorizontalScaling, OpsRequestSpec, RebuildInstance, Reconfigure, ScriptSpec, Switchover, VerticalScaling, VolumeExpansion)
ComponentOps represents the common variables required for operations within the scope of a component.
+ComponentOps represents the common variables required for operations within the scope of a normal component/shard component.
+shardingName + +string + + |
+
+ Specifies the name of the cluster sharding component. + |
+
(Appears on:CustomOpsSpec) @@ -11028,13 +11035,17 @@ string
name
ComponentOps
Specifies the unique identifier of the cluster component
+
+(Members of ComponentOps
are embedded into this type.)
+
components
items
Defines which components need to perform the actions defined by this OpsDefinition. -At least one component is required. The components are identified by their name and can be merged or retained.
+At least one component/shardComponent is required. The components are identified by their name and can be merged or retained.ComponentOps
componentName
-(Members of ComponentOps
are embedded into this type.)
-
Specifies the name of the cluster component.
A list of services that are to be exposed or removed.
-If componentNamem is not specified, each OpsService
in the list must specify ports and selectors.
OpsService
in the list must specify ports and selectors.
volumeClaimTemplates
instances
offlineInstances
Records the status information of components changed due to the operation request.
+Records the status information of components, including the sharding component, that have changed due to the operation request.
-(Appears on:LastComponentConfiguration, VolumeExpansion) +(Appears on:LastComponentConfiguration, PartInstanceTemplate, VolumeExpansion)
-(Appears on:CustomOpsComponent) +(Appears on:CustomOpsItem)
+(Appears on:VerticalScaling, VolumeExpansion) +
+Field | +Description | +
---|---|
+name + +string + + |
+
+ Refer to the instance template name of the component or sharding. + |
+
+ResourceRequirements + + +Kubernetes core/v1.ResourceRequirements + + + |
+
+
+(Members of Defines the computational resource size for vertical scaling. + |
+
+volumeClaimTemplates + + +[]OpsRequestVolumeClaimTemplate + + + |
+
+ volumeClaimTemplates specifies the storage size and volumeClaimTemplate name. + |
+
@@ -20186,6 +20250,19 @@ Kubernetes core/v1.ResourceRequirements
Defines the computational resource size for vertical scaling.
+instances
Specifies the instance template that need to vertical scale.
+volumeClaimTemplates specifies the storage size and volumeClaimTemplate name.
+instances
Specifies the instance template that need to volume expand.
+