Skip to content

Commit 98e93aa

Browse files
authored
chore(test): fix zero-replica component scale-out coverage (#10824)
1 parent 8295e5e commit 98e93aa

2 files changed

Lines changed: 92 additions & 21 deletions

File tree

controllers/apps/component/component_controller_test.go

Lines changed: 59 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2065,27 +2065,29 @@ var _ = Describe("Component Controller", func() {
20652065

20662066
By("check comp & its")
20672067
Eventually(testapps.CheckObj(&testCtx, compKey, func(g Gomega, comp *kbappsv1.Component) {
2068-
g.Expect(comp.Spec.Replicas).Should(Equal(3))
2068+
g.Expect(comp.Spec.Replicas).Should(Equal(int32(3)))
20692069
g.Expect(comp.Status.ObservedGeneration < comp.Generation).Should(BeTrue())
20702070
g.Expect(comp.Status.Phase).Should(Equal(kbappsv1.StoppedComponentPhase))
2071-
}))
2071+
})).Should(Succeed())
20722072
itsKey := compKey
20732073
Consistently(testapps.CheckObj(&testCtx, itsKey, func(g Gomega, its *workloads.InstanceSet) {
2074-
g.Expect(*its.Spec.Replicas).To(BeEquivalentTo(0))
2075-
}))
2074+
g.Expect(its.Spec.Stop).ShouldNot(BeNil())
2075+
g.Expect(*its.Spec.Stop).Should(BeTrue())
2076+
g.Expect(*its.Spec.Replicas).Should(BeEquivalentTo(1))
2077+
})).Should(Succeed())
20762078

20772079
By("start it")
20782080
startComp()
20792081

20802082
By("check comp & its")
20812083
Eventually(testapps.CheckObj(&testCtx, compKey, func(g Gomega, comp *kbappsv1.Component) {
2082-
g.Expect(comp.Spec.Replicas).Should(Equal(3))
2084+
g.Expect(comp.Spec.Replicas).Should(Equal(int32(3)))
20832085
g.Expect(comp.Status.ObservedGeneration).Should(Equal(comp.Generation))
2084-
g.Expect(comp.Status.Phase).Should(Equal(kbappsv1.UpdatingComponentPhase))
2085-
}))
2086+
})).Should(Succeed())
20862087
Eventually(testapps.CheckObj(&testCtx, itsKey, func(g Gomega, its *workloads.InstanceSet) {
2087-
g.Expect(*its.Spec.Replicas).To(BeEquivalentTo(3))
2088-
}))
2088+
g.Expect(its.Spec.Stop).Should(BeNil())
2089+
g.Expect(*its.Spec.Replicas).Should(BeEquivalentTo(3))
2090+
})).Should(Succeed())
20892091
})
20902092

20912093
It("h-scale a stopped component - w/ data actions", func() {
@@ -2111,27 +2113,63 @@ var _ = Describe("Component Controller", func() {
21112113

21122114
By("check comp & its")
21132115
Eventually(testapps.CheckObj(&testCtx, compKey, func(g Gomega, comp *kbappsv1.Component) {
2114-
g.Expect(comp.Spec.Replicas).Should(Equal(3))
2116+
g.Expect(comp.Spec.Replicas).Should(Equal(int32(3)))
21152117
g.Expect(comp.Status.ObservedGeneration < comp.Generation).Should(BeTrue())
21162118
g.Expect(comp.Status.Phase).Should(Equal(kbappsv1.StoppedComponentPhase))
2117-
}))
2119+
})).Should(Succeed())
21182120
itsKey := compKey
21192121
Consistently(testapps.CheckObj(&testCtx, itsKey, func(g Gomega, its *workloads.InstanceSet) {
2120-
g.Expect(*its.Spec.Replicas).To(BeEquivalentTo(0))
2121-
}))
2122+
g.Expect(its.Spec.Stop).ShouldNot(BeNil())
2123+
g.Expect(*its.Spec.Stop).Should(BeTrue())
2124+
g.Expect(*its.Spec.Replicas).Should(BeEquivalentTo(1))
2125+
})).Should(Succeed())
21222126

21232127
By("start it")
21242128
startComp()
21252129

2126-
By("check comp & its")
2127-
Eventually(testapps.CheckObj(&testCtx, compKey, func(g Gomega, comp *kbappsv1.Component) {
2128-
g.Expect(comp.Spec.Replicas).Should(Equal(3))
2129-
g.Expect(comp.Status.ObservedGeneration).Should(Equal(comp.Generation))
2130-
g.Expect(comp.Status.Phase).Should(Equal(kbappsv1.UpdatingComponentPhase))
2131-
}))
2130+
By("check start is applied before scale-out is blocked by the missing source pod")
21322131
Eventually(testapps.CheckObj(&testCtx, itsKey, func(g Gomega, its *workloads.InstanceSet) {
2133-
g.Expect(*its.Spec.Replicas).To(BeEquivalentTo(3))
2134-
}))
2132+
g.Expect(its.Spec.Stop).Should(BeNil())
2133+
g.Expect(*its.Spec.Replicas).Should(BeEquivalentTo(1))
2134+
})).Should(Succeed())
2135+
Consistently(testapps.CheckObj(&testCtx, itsKey, func(g Gomega, its *workloads.InstanceSet) {
2136+
g.Expect(*its.Spec.Replicas).Should(BeEquivalentTo(1))
2137+
})).Should(Succeed())
2138+
2139+
By("restore the component to a reconcilable state")
2140+
Expect(testapps.GetAndChangeObj(&testCtx, compKey, func(comp *kbappsv1.Component) {
2141+
comp.Spec.Stop = ptr.To(true)
2142+
comp.Spec.Replicas = 1
2143+
})()).Should(Succeed())
2144+
checkCompStopped()
2145+
})
2146+
2147+
It("starts a stopped zero-replica component and then scales it to one", func() {
2148+
changeReplicasLimit(compDefObj.Name, 0, 16384)
2149+
createCompObjWithPhase(defaultCompName, compDefObj.Name, func(f *testapps.MockComponentFactory) {
2150+
f.SetReplicas(0).SetStop(ptr.To(true))
2151+
}, kbappsv1.StoppedComponentPhase)
2152+
2153+
itsKey := compKey
2154+
Eventually(testapps.CheckObj(&testCtx, itsKey, func(g Gomega, its *workloads.InstanceSet) {
2155+
g.Expect(its.Spec.Stop).ShouldNot(BeNil())
2156+
g.Expect(*its.Spec.Stop).Should(BeTrue())
2157+
g.Expect(*its.Spec.Replicas).Should(BeEquivalentTo(0))
2158+
})).Should(Succeed())
2159+
2160+
By("start the component")
2161+
startComp()
2162+
Eventually(testapps.CheckObj(&testCtx, itsKey, func(g Gomega, its *workloads.InstanceSet) {
2163+
g.Expect(its.Spec.Stop).Should(BeNil())
2164+
g.Expect(*its.Spec.Replicas).Should(BeEquivalentTo(0))
2165+
})).Should(Succeed())
2166+
2167+
By("scale the component from zero to one")
2168+
changeCompReplicas(compKey, 1)
2169+
Eventually(testapps.CheckObj(&testCtx, itsKey, func(g Gomega, its *workloads.InstanceSet) {
2170+
g.Expect(its.Spec.Stop).Should(BeNil())
2171+
g.Expect(*its.Spec.Replicas).Should(BeEquivalentTo(1))
2172+
})).Should(Succeed())
21352173
})
21362174

21372175
// TODO: stop a component in h-scaling

controllers/apps/component/transformer_component_workload_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
corev1 "k8s.io/api/core/v1"
2727
"k8s.io/apimachinery/pkg/api/resource"
2828
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29+
"k8s.io/utils/ptr"
2930

3031
appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1"
3132
workloads "github.com/apecloud/kubeblocks/apis/workloads/v1"
@@ -112,6 +113,38 @@ var _ = Describe("Component Workload Operations Test", func() {
112113
dag = newDAG(graphCli, comp)
113114
})
114115

116+
Context("Data Replication Operations", func() {
117+
It("blocks scale-out when data actions have no source pod", func() {
118+
synthesizeComp.Replicas = 1
119+
synthesizeComp.LifecycleActions.DataDump = testapps.NewLifecycleAction("data-dump")
120+
synthesizeComp.LifecycleActions.DataLoad = testapps.NewLifecycleAction("data-load")
121+
122+
runningITS := testapps.NewInstanceSetFactory(testCtx.DefaultNamespace,
123+
"test-its", clusterName, compName).
124+
AddAppInstanceLabel(clusterName).
125+
AddAppComponentLabel(compName).
126+
AddAppManagedByLabel().
127+
SetReplicas(0).
128+
GetObject()
129+
protoITS := runningITS.DeepCopy()
130+
protoITS.Spec.Replicas = ptr.To(int32(1))
131+
132+
transCtx := &componentTransformContext{
133+
Context: ctx,
134+
Client: graphCli,
135+
Logger: logger,
136+
EventRecorder: clusterRecorder,
137+
Component: comp,
138+
SynthesizeComponent: synthesizeComp,
139+
}
140+
ops, err := newComponentWorkloadOps(transCtx, k8sClient, synthesizeComp,
141+
comp, runningITS, protoITS, dag)
142+
Expect(err).ShouldNot(HaveOccurred())
143+
144+
Expect(ops.scaleOut()).Should(MatchError("no available pod to dump data"))
145+
})
146+
})
147+
115148
Context("Member Leave Operations", func() {
116149
var (
117150
ops *componentWorkloadOps

0 commit comments

Comments
 (0)