diff --git a/controllers/apps/component_controller_test.go b/controllers/apps/component_controller_test.go index 1beeb8fc318..b322172620f 100644 --- a/controllers/apps/component_controller_test.go +++ b/controllers/apps/component_controller_test.go @@ -380,32 +380,6 @@ var _ = Describe("Component Controller", func() { } } - testChangeReplicasFromZero := func(compName, compDefName string) { - var ( - init = int32(0) - target = int32(3) - ) - - createClusterObjV2(compName, compDefObj.Name, func(f *testapps.MockClusterFactory) { - f.SetReplicas(init) - }) - - By(fmt.Sprintf("change replicas to %d", target)) - changeComponentReplicas(clusterKey, target) - - By("checking the number of replicas in component and ITS as expected") - Eventually(testapps.CheckObj(&testCtx, compKey, func(g Gomega, comp *appsv1alpha1.Component) { - g.Expect(comp.Spec.Replicas).Should(Equal(target)) - g.Expect(comp.Generation).Should(Equal(comp.Status.ObservedGeneration)) - })).Should(Succeed()) - - By("checking the number of replicas in ITS as expected") - itsKey := compKey - Eventually(testapps.CheckObj(&testCtx, itsKey, func(g Gomega, its *workloads.InstanceSet) { - g.Expect(*its.Spec.Replicas).Should(Equal(target)) - })).Should(Succeed()) - } - testChangeReplicasToZero := func(compName, compDefName string) { var ( init = int32(3) @@ -2134,9 +2108,16 @@ var _ = Describe("Component Controller", func() { }) It("with component zero replicas", func() { - createClusterObjV2(defaultCompName, compDefName, func(f *testapps.MockClusterFactory) { - f.SetReplicas(0) - }) + phase := appsv1alpha1.ClusterPhase("") + createClusterObjVx("", defaultCompName, compDefName, true, + func(f *testapps.MockClusterFactory) { + f.SetReplicas(0) + }, &phase) + + By("checking the component status can't be reconciled well") + Eventually(testapps.CheckObj(&testCtx, compKey, func(g Gomega, comp *appsv1alpha1.Component) { + g.Expect(comp.Generation > comp.Status.ObservedGeneration).Should(BeTrue()) + })).Should(Succeed()) }) It("with component services", func() { @@ -2202,10 +2183,6 @@ var _ = Describe("Component Controller", func() { testChangeReplicas(replicationCompName, replicationCompDefName) }) - It("scale-out from 0", func() { - testChangeReplicasFromZero(replicationCompName, replicationCompDefName) - }) - It("scale-in to 0", func() { testChangeReplicasToZero(replicationCompName, replicationCompDefName) }) @@ -2340,10 +2317,6 @@ var _ = Describe("Component Controller", func() { It("scale-in to 0 and PVCs should not been deleted", func() { testHorizontalScale(compName, compDefObj.Name, 3, 0, appsv1alpha1.HScaleDataClonePolicyCloneVolume) }) - - It("scale-out from 0 and should work well", func() { - testHorizontalScale(compName, compDefObj.Name, 0, 3, appsv1alpha1.HScaleDataClonePolicyCloneVolume) - }) }) Context(fmt.Sprintf("[comp: %s] scale-out after volume expansion", compName), func() { diff --git a/controllers/apps/transformer_component_validation.go b/controllers/apps/transformer_component_validation.go index 127ea77005d..6f1abbcf184 100644 --- a/controllers/apps/transformer_component_validation.go +++ b/controllers/apps/transformer_component_validation.go @@ -21,14 +21,17 @@ package apps import ( "fmt" + "math" appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" "github.com/apecloud/kubeblocks/pkg/controller/graph" ) -const ( - defaultMinReplicas int32 = 0 - defaultMinReplicas4ScaleIn int32 = 1 +var ( + defaultReplicasLimit = appsv1alpha1.ReplicasLimit{ + MinReplicas: 1, + MaxReplicas: math.MaxInt32, + } ) // componentValidationTransformer validates the consistency between spec & definition. @@ -86,44 +89,19 @@ func validateEnabledLogConfigs(compDef *appsv1alpha1.ComponentDefinition, enable } func validateCompReplicas(comp *appsv1alpha1.Component, compDef *appsv1alpha1.ComponentDefinition) error { - if err := validateCompReplicasGeneral(comp, compDef); err != nil { - return err + replicasLimit := &defaultReplicasLimit + // always respect the replicas limit if set. + if compDef.Spec.ReplicasLimit != nil { + replicasLimit = compDef.Spec.ReplicasLimit } - return validateCompReplicas4Runtime(comp, compDef) -} -func validateCompReplicasGeneral(comp *appsv1alpha1.Component, compDef *appsv1alpha1.ComponentDefinition) error { - if compDef.Spec.ReplicasLimit == nil { - return nil - } replicas := comp.Spec.Replicas - replicasLimit := compDef.Spec.ReplicasLimit if replicas >= replicasLimit.MinReplicas && replicas <= replicasLimit.MaxReplicas { return nil } return replicasOutOfLimitError(replicas, *replicasLimit) } -func validateCompReplicas4Runtime(comp *appsv1alpha1.Component, compDef *appsv1alpha1.ComponentDefinition) error { - minReplicas := func() int32 { - // always respect the replicas limit if it is set. - if compDef.Spec.ReplicasLimit != nil { - return compDef.Spec.ReplicasLimit.MinReplicas - } - // HACK: take observedGeneration == 0 as the provisioning. - if comp.Status.ObservedGeneration == 0 { - return defaultMinReplicas - } - return min(comp.Spec.Replicas, defaultMinReplicas4ScaleIn) - }() - - replicas := comp.Spec.Replicas - if replicas < minReplicas { - return fmt.Errorf("replicas %d is less than required min replicas %d", replicas, minReplicas) - } - return nil -} - func replicasOutOfLimitError(replicas int32, replicasLimit appsv1alpha1.ReplicasLimit) error { return fmt.Errorf("replicas %d out-of-limit [%d, %d]", replicas, replicasLimit.MinReplicas, replicasLimit.MaxReplicas) }