Skip to content

Commit f55ce01

Browse files
authored
Merge pull request #150 from nayihz/feat-startup-policy
feat: support startup policy
2 parents 02039b4 + e10d6ba commit f55ce01

File tree

11 files changed

+185
-21
lines changed

11 files changed

+185
-21
lines changed

api/leaderworkerset/v1/leaderworkerset_types.go

+16
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ type LeaderWorkerSetSpec struct {
109109
// when a revision is made to the leaderWorkerTemplate.
110110
// +optional
111111
RolloutStrategy RolloutStrategy `json:"rolloutStrategy,omitempty"`
112+
113+
// StartupPolicy determines the startup policy for the worker statefulset.
114+
// +kubebuilder:default=LeaderCreated
115+
// +kubebuilder:validation:Enum={LeaderCreated,LeaderReady}
116+
// +optional
117+
StartupPolicy StartupPolicyType `json:"startupPolicy"`
112118
}
113119

114120
// Template of the leader/worker pods, the group will include at least one leader pod.
@@ -227,6 +233,16 @@ const (
227233
DefaultRestartPolicy RestartPolicyType = "Default"
228234
)
229235

236+
type StartupPolicyType string
237+
238+
const (
239+
// LeaderReady creates the workers statefulset after the leader pod is ready.
240+
LeaderReadyStartupPolicy StartupPolicyType = "LeaderReady"
241+
242+
// LeaderCreated creates the workers statefulset immediately after the leader pod is created.
243+
LeaderCreatedStartupPolicy StartupPolicyType = "LeaderCreated"
244+
)
245+
230246
// LeaderWorkerSetStatus defines the observed state of LeaderWorkerSet
231247
type LeaderWorkerSetStatus struct {
232248
// Conditions track the condition of the leaderworkerset.

config/crd/bases/leaderworkerset.x-k8s.io_leaderworkersets.yaml

+8
Original file line numberDiff line numberDiff line change
@@ -15340,6 +15340,14 @@ spec:
1534015340
required:
1534115341
- type
1534215342
type: object
15343+
startupPolicy:
15344+
default: LeaderCreated
15345+
description: StartupPolicy determines the startup policy for the worker
15346+
statefulset.
15347+
enum:
15348+
- LeaderCreated
15349+
- LeaderReady
15350+
type: string
1534315351
required:
1534415352
- leaderWorkerTemplate
1534515353
type: object

go.mod

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module sigs.k8s.io/lws
22

3-
go 1.22
3+
go 1.22.0
44

55
require (
66
github.com/google/go-cmp v0.6.0
@@ -12,7 +12,8 @@ require (
1212
k8s.io/apimachinery v0.29.5
1313
k8s.io/client-go v0.29.5
1414
k8s.io/code-generator v0.29.5
15-
k8s.io/klog/v2 v2.110.1
15+
k8s.io/klog/v2 v2.120.1
16+
k8s.io/kubernetes v1.29.5
1617
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
1718
sigs.k8s.io/controller-runtime v0.17.3
1819
sigs.k8s.io/structured-merge-diff/v4 v4.4.1
@@ -60,6 +61,7 @@ require (
6061
golang.org/x/mod v0.17.0 // indirect
6162
golang.org/x/net v0.25.0 // indirect
6263
golang.org/x/oauth2 v0.12.0 // indirect
64+
golang.org/x/sync v0.7.0 // indirect
6365
golang.org/x/sys v0.20.0 // indirect
6466
golang.org/x/term v0.20.0 // indirect
6567
golang.org/x/text v0.15.0 // indirect
@@ -73,7 +75,8 @@ require (
7375
gopkg.in/yaml.v3 v3.0.1 // indirect
7476
k8s.io/component-base v0.29.5 // indirect
7577
k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 // indirect
76-
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
78+
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 // indirect
79+
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
7780
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
7881
sigs.k8s.io/yaml v1.4.0 // indirect
7982
)

go.sum

+8-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ github.com/evanphx/json-patch/v5 v5.8.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq
1515
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
1616
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
1717
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
18-
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
1918
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
2019
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
2120
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
@@ -200,13 +199,17 @@ k8s.io/component-base v0.29.5 h1:Ptj8AzG+p8c2a839XriHwxakDpZH9uvIgYz+o1agjg8=
200199
k8s.io/component-base v0.29.5/go.mod h1:9nBUoPxW/yimISIgAG7sJDrUGJlu7t8HnDafIrOdU8Q=
201200
k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks=
202201
k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
202+
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 h1:NGrVE502P0s0/1hudf8zjgwki1X/TByhmAoILTarmzo=
203+
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8=
203204
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
204-
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
205-
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
205+
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
206+
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
206207
k8s.io/kube-aggregator v0.28.1 h1:rvG4llYnQKHjj6YjjoBPEJxfD1uH0DJwkrJTNKGAaCs=
207208
k8s.io/kube-aggregator v0.28.1/go.mod h1:JaLizMe+AECSpO2OmrWVsvnG0V3dX1RpW+Wq/QHbu18=
208-
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
209-
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
209+
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
210+
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
211+
k8s.io/kubernetes v1.29.5 h1:G+i73mlMcmqRge1STYospiN8X9FYHGeBOer/e2uGJ1k=
212+
k8s.io/kubernetes v1.29.5/go.mod h1:28sDhcb87LX5z3GWAKYmLrhrifxi4W9bEWua4DRTIvk=
210213
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
211214
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
212215
sigs.k8s.io/controller-runtime v0.17.3 h1:65QmN7r3FWgTxDMz9fvGnO1kbf2nu+acg9p2R9oYYYk=

pkg/controllers/leaderworkerset_controller.go

-3
Original file line numberDiff line numberDiff line change
@@ -371,9 +371,6 @@ func (r *LeaderWorkerSetReconciler) updateConditions(ctx context.Context, lws *l
371371
return false, err
372372
}
373373

374-
if err != nil {
375-
return false, err
376-
}
377374
var ready, updated bool
378375
if statefulsetutils.StatefulsetReady(sts) && podutils.PodRunningAndReady(leaderPod) {
379376
ready = true

pkg/controllers/pod_controller.go

+6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
coreapplyv1 "k8s.io/client-go/applyconfigurations/core/v1"
3333
metaapplyv1 "k8s.io/client-go/applyconfigurations/meta/v1"
3434
"k8s.io/klog/v2"
35+
k8spodutils "k8s.io/kubernetes/pkg/api/v1/pod"
3536
"k8s.io/utils/ptr"
3637
ctrl "sigs.k8s.io/controller-runtime"
3738
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -102,6 +103,11 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
102103
}
103104

104105
// logic for handling leader pod
106+
if leaderWorkerSet.Spec.StartupPolicy == leaderworkerset.LeaderReadyStartupPolicy && !k8spodutils.IsPodReady(&pod) {
107+
log.V(2).Info("defer the creation of the worker statefulset because leader pod is not ready.")
108+
return ctrl.Result{}, nil
109+
}
110+
105111
statefulSet, err := constructWorkerStatefulSetApplyConfiguration(pod, leaderWorkerSet)
106112
if err != nil {
107113
return ctrl.Result{}, err

test/integration/controllers/leaderworkerset_test.go

+42-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"github.com/onsi/gomega"
2424
appsv1 "k8s.io/api/apps/v1"
2525
autoscalingv1 "k8s.io/api/autoscaling/v1"
26-
v1 "k8s.io/api/autoscaling/v1"
2726
corev1 "k8s.io/api/core/v1"
2827
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2928
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -271,7 +270,7 @@ var _ = ginkgo.Describe("LeaderWorkerSet controller", func() {
271270
updates: []*update{
272271
{
273272
checkLWSState: func(lws *leaderworkerset.LeaderWorkerSet) {
274-
var scale v1.Scale
273+
var scale autoscalingv1.Scale
275274
gomega.Expect(k8sClient.SubResource("scale").Get(ctx, lws, &scale)).To(gomega.Succeed())
276275
gomega.Expect(int32(scale.Spec.Replicas)).To(gomega.Equal(*lws.Spec.Replicas))
277276
gomega.Expect(int32(scale.Status.Replicas)).To(gomega.Equal(lws.Status.Replicas))
@@ -1512,6 +1511,47 @@ var _ = ginkgo.Describe("LeaderWorkerSet controller", func() {
15121511
},
15131512
},
15141513
}),
1514+
ginkgo.Entry("create a leaderworkerset with spec.startupPolicyy=LeaderReady", &testCase{
1515+
makeLeaderWorkerSet: func(nsName string) *testing.LeaderWorkerSetWrapper {
1516+
return testing.BuildLeaderWorkerSet(nsName).Replica(4).StartupPolicy(leaderworkerset.LeaderReadyStartupPolicy)
1517+
},
1518+
updates: []*update{
1519+
{
1520+
checkLWSState: func(lws *leaderworkerset.LeaderWorkerSet) {
1521+
testing.ExpectWorkerStatefulSetsNotCreated(ctx, k8sClient, lws)
1522+
},
1523+
},
1524+
{
1525+
lwsUpdateFn: func(lws *leaderworkerset.LeaderWorkerSet) {
1526+
testing.SetLeaderPodsToReady(ctx, k8sClient, lws, 0, 2)
1527+
},
1528+
checkLWSState: func(lws *leaderworkerset.LeaderWorkerSet) {
1529+
testing.ExpectSpecifiedWorkerStatefulSetsCreated(ctx, k8sClient, lws, 0, 2)
1530+
testing.ExpectSpecifiedWorkerStatefulSetsNotCreated(ctx, k8sClient, lws, 2, 4)
1531+
},
1532+
},
1533+
{
1534+
lwsUpdateFn: func(lws *leaderworkerset.LeaderWorkerSet) {
1535+
testing.SetLeaderPodsToReady(ctx, k8sClient, lws, 2, 4)
1536+
},
1537+
checkLWSState: func(lws *leaderworkerset.LeaderWorkerSet) {
1538+
testing.ExpectSpecifiedWorkerStatefulSetsCreated(ctx, k8sClient, lws, 2, 4)
1539+
},
1540+
},
1541+
},
1542+
}),
1543+
ginkgo.Entry("create a leaderworkerset with spec.startupPolicyy=LeaderCreated", &testCase{
1544+
makeLeaderWorkerSet: func(nsName string) *testing.LeaderWorkerSetWrapper {
1545+
return testing.BuildLeaderWorkerSet(nsName).Replica(4).StartupPolicy(leaderworkerset.LeaderCreatedStartupPolicy)
1546+
},
1547+
updates: []*update{
1548+
{
1549+
checkLWSState: func(lws *leaderworkerset.LeaderWorkerSet) {
1550+
testing.ExpectSpecifiedWorkerStatefulSetsCreated(ctx, k8sClient, lws, 0, 4)
1551+
},
1552+
},
1553+
},
1554+
}),
15151555
) // end of DescribeTable
15161556
}) // end of Describe
15171557

test/integration/webhooks/leaderworkerset_test.go

+31
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,22 @@ var _ = ginkgo.Describe("leaderworkerset defaulting, creation and update", func(
108108
return testutils.BuildLeaderWorkerSet(ns.Name).Replica(2).Size(2).RestartPolicy(leaderworkerset.RecreateGroupOnPodRestart)
109109
},
110110
}),
111+
ginkgo.Entry("defaulting logic applies when spec.startpolicy is not set", &testDefaultingCase{
112+
makeLeaderWorkerSet: func(ns *corev1.Namespace) *testutils.LeaderWorkerSetWrapper {
113+
return testutils.BuildLeaderWorkerSet(ns.Name).Replica(2).Size(2)
114+
},
115+
getExpectedLWS: func(lws *leaderworkerset.LeaderWorkerSet) *testutils.LeaderWorkerSetWrapper {
116+
return testutils.BuildLeaderWorkerSet(ns.Name).Replica(2).Size(2).StartupPolicy(leaderworkerset.LeaderCreatedStartupPolicy)
117+
},
118+
}),
119+
ginkgo.Entry("defaulting logic applies when spec.startpolicy is set", &testDefaultingCase{
120+
makeLeaderWorkerSet: func(ns *corev1.Namespace) *testutils.LeaderWorkerSetWrapper {
121+
return testutils.BuildLeaderWorkerSet(ns.Name).Replica(2).Size(2).StartupPolicy(leaderworkerset.LeaderReadyStartupPolicy)
122+
},
123+
getExpectedLWS: func(lws *leaderworkerset.LeaderWorkerSet) *testutils.LeaderWorkerSetWrapper {
124+
return testutils.BuildLeaderWorkerSet(ns.Name).Replica(2).Size(2).StartupPolicy(leaderworkerset.LeaderReadyStartupPolicy)
125+
},
126+
}),
111127
ginkgo.Entry("apply default rollout strategy", &testDefaultingCase{
112128
makeLeaderWorkerSet: func(ns *corev1.Namespace) *testutils.LeaderWorkerSetWrapper {
113129
return testutils.BuildLeaderWorkerSet(ns.Name).RolloutStrategy(leaderworkerset.RolloutStrategy{}) // unset rollout strategy
@@ -197,6 +213,12 @@ var _ = ginkgo.Describe("leaderworkerset defaulting, creation and update", func(
197213
},
198214
lwsCreationShouldFail: true,
199215
}),
216+
ginkgo.Entry("creation with invalid startpolicy should fail", &testValidationCase{
217+
makeLeaderWorkerSet: func(ns *corev1.Namespace) *testutils.LeaderWorkerSetWrapper {
218+
return testutils.BuildLeaderWorkerSet(ns.Name).StartupPolicy("invalidValue")
219+
},
220+
lwsCreationShouldFail: true,
221+
}),
200222
ginkgo.Entry("creation with invalid subGroupSize should fail", &testValidationCase{
201223
makeLeaderWorkerSet: func(ns *corev1.Namespace) *testutils.LeaderWorkerSetWrapper {
202224
return testutils.BuildLeaderWorkerSet(ns.Name).Size(2).SubGroupSize(-1)
@@ -227,6 +249,15 @@ var _ = ginkgo.Describe("leaderworkerset defaulting, creation and update", func(
227249
},
228250
updateShouldFail: true,
229251
}),
252+
ginkgo.Entry("update with invalid startpolicy should fail", &testValidationCase{
253+
makeLeaderWorkerSet: func(ns *corev1.Namespace) *testutils.LeaderWorkerSetWrapper {
254+
return testutils.BuildLeaderWorkerSet(ns.Name).StartupPolicy(leaderworkerset.LeaderReadyStartupPolicy)
255+
},
256+
updateLeaderWorkerSet: func(lws *leaderworkerset.LeaderWorkerSet) {
257+
lws.Spec.StartupPolicy = "invalidValue"
258+
},
259+
updateShouldFail: true,
260+
}),
230261
ginkgo.Entry("number of size can not be updated", &testValidationCase{
231262
makeLeaderWorkerSet: func(ns *corev1.Namespace) *testutils.LeaderWorkerSetWrapper {
232263
return testutils.BuildLeaderWorkerSet(ns.Name).Replica(1).Size(1)

test/testutils/util.go

+21-4
Original file line numberDiff line numberDiff line change
@@ -237,11 +237,10 @@ func SetPodGroupsToReady(ctx context.Context, k8sClient client.Client, lws *lead
237237
}
238238
}
239239

240-
// SetPodGroupToReady set one podGroup(leaderPod+workerStatefulset) of leaderWorkerSet to ready state, workerPods not included.
241-
func SetPodGroupToReady(ctx context.Context, k8sClient client.Client, statefulsetName string, lws *leaderworkerset.LeaderWorkerSet) {
240+
func SetLeaderPodToReady(ctx context.Context, k8sClient client.Client, podName string, lws *leaderworkerset.LeaderWorkerSet) {
242241
gomega.Eventually(func() error {
243242
var leaderPod corev1.Pod
244-
if err := k8sClient.Get(ctx, client.ObjectKey{Namespace: lws.Namespace, Name: statefulsetName}, &leaderPod); err != nil {
243+
if err := k8sClient.Get(ctx, client.ObjectKey{Namespace: lws.Namespace, Name: podName}, &leaderPod); err != nil {
245244
return err
246245
}
247246

@@ -256,7 +255,7 @@ func SetPodGroupToReady(ctx context.Context, k8sClient client.Client, statefulse
256255

257256
gomega.Eventually(func() error {
258257
var leaderPod corev1.Pod
259-
if err := k8sClient.Get(ctx, client.ObjectKey{Namespace: lws.Namespace, Name: statefulsetName}, &leaderPod); err != nil {
258+
if err := k8sClient.Get(ctx, client.ObjectKey{Namespace: lws.Namespace, Name: podName}, &leaderPod); err != nil {
260259
return err
261260
}
262261

@@ -268,7 +267,11 @@ func SetPodGroupToReady(ctx context.Context, k8sClient client.Client, statefulse
268267
leaderPod.Status.Conditions = append(leaderPod.Status.Conditions, condition)
269268
return k8sClient.Status().Update(ctx, &leaderPod)
270269
}, Timeout, Interval).Should(gomega.Succeed())
270+
}
271271

272+
// SetPodGroupToReady set one podGroup(leaderPod+workerStatefulset) of leaderWorkerSet to ready state, workerPods not included.
273+
func SetPodGroupToReady(ctx context.Context, k8sClient client.Client, statefulsetName string, lws *leaderworkerset.LeaderWorkerSet) {
274+
SetLeaderPodToReady(ctx, k8sClient, statefulsetName, lws)
272275
gomega.Eventually(func() error {
273276
var sts appsv1.StatefulSet
274277
if err := k8sClient.Get(ctx, types.NamespacedName{Name: statefulsetName, Namespace: lws.Namespace}, &sts); err != nil {
@@ -492,3 +495,17 @@ func DeleteNamespace(ctx context.Context, c client.Client, ns *corev1.Namespace)
492495
}
493496
return nil
494497
}
498+
499+
func SetLeaderPodsToReady(ctx context.Context, k8sClient client.Client, lws *leaderworkerset.LeaderWorkerSet, start, end int) {
500+
var leaderSts appsv1.StatefulSet
501+
gomega.Eventually(func() error {
502+
if err := k8sClient.Get(ctx, types.NamespacedName{Name: lws.Name, Namespace: lws.Namespace}, &leaderSts); err != nil {
503+
return err
504+
}
505+
return nil
506+
}, Timeout, Interval).Should(gomega.Succeed())
507+
508+
for i := start; i < end; i++ {
509+
SetLeaderPodToReady(ctx, k8sClient, fmt.Sprintf("%s-%d", leaderSts.Name, i), lws)
510+
}
511+
}

test/testutils/validators.go

+37
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
appsv1 "k8s.io/api/apps/v1"
2828
corev1 "k8s.io/api/core/v1"
2929
eventsv1 "k8s.io/api/events/v1"
30+
apierrors "k8s.io/apimachinery/pkg/api/errors"
3031
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3132
"k8s.io/apimachinery/pkg/types"
3233
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -373,3 +374,39 @@ func ValidateLatestEvent(ctx context.Context, k8sClient client.Client, eventReas
373374

374375
}, Timeout, Interval).Should(gomega.BeNil())
375376
}
377+
378+
func ExpectWorkerStatefulSetsNotCreated(ctx context.Context, k8sClient client.Client, lws *leaderworkerset.LeaderWorkerSet) {
379+
ginkgo.By("checking no worker statefulset created")
380+
gomega.Consistently(func() bool {
381+
var statefulSetList appsv1.StatefulSetList
382+
if err := k8sClient.List(ctx, &statefulSetList, client.InNamespace(lws.Namespace), &client.MatchingLabels{leaderworkerset.SetNameLabelKey: lws.Name}); err != nil {
383+
return false
384+
}
385+
return len(statefulSetList.Items) == 1 && statefulSetList.Items[0].Name == lws.Name
386+
}, Timeout, Interval).Should(gomega.Equal(true))
387+
}
388+
389+
func ExpectSpecifiedWorkerStatefulSetsCreated(ctx context.Context, k8sClient client.Client, lws *leaderworkerset.LeaderWorkerSet, start, end int) {
390+
gomega.Eventually(func() error {
391+
var sts appsv1.StatefulSet
392+
for i := start; i < end; i++ {
393+
if err := k8sClient.Get(ctx, types.NamespacedName{Name: fmt.Sprintf("%s-%d", lws.Name, i), Namespace: lws.Namespace}, &sts); err != nil {
394+
return err
395+
}
396+
}
397+
return nil
398+
}, Timeout, Interval).Should(gomega.BeNil())
399+
}
400+
401+
func ExpectSpecifiedWorkerStatefulSetsNotCreated(ctx context.Context, k8sClient client.Client, lws *leaderworkerset.LeaderWorkerSet, start, end int) {
402+
gomega.Consistently(func() bool {
403+
var sts appsv1.StatefulSet
404+
for i := start; i < end; i++ {
405+
if err := k8sClient.Get(ctx, types.NamespacedName{Name: fmt.Sprintf("%s-%d", lws.Name, i), Namespace: lws.Namespace}, &sts); err == nil ||
406+
!apierrors.IsNotFound(err) {
407+
return false
408+
}
409+
}
410+
return true
411+
}, Timeout, Interval).Should(gomega.Equal(true))
412+
}

0 commit comments

Comments
 (0)