@@ -69,6 +69,7 @@ func TestLeaderStatefulSetApplyConfig(t *testing.T) {
6969 revisionKey string
7070 lws * leaderworkerset.LeaderWorkerSet
7171 wantApplyConfig * appsapplyv1.StatefulSetApplyConfiguration
72+ stsReplicas * int32
7273 }{
7374 {
7475 name : "1 replica, size 1, with empty leader template, exclusive placement disabled" ,
@@ -403,7 +404,9 @@ func TestLeaderStatefulSetApplyConfig(t *testing.T) {
403404 PodManagementPolicy : ptr.To [appsv1.PodManagementPolicyType ](appsv1 .ParallelPodManagement ),
404405 UpdateStrategy : appsapplyv1 .StatefulSetUpdateStrategy ().
405406 WithType (appsv1 .RollingUpdateStatefulSetStrategyType ).
406- WithRollingUpdate (appsapplyv1 .RollingUpdateStatefulSetStrategy ().WithPartition (0 ).WithMaxUnavailable (intstr .FromInt32 (2 ))),
407+ // maxSurge is capped at 1 (the value of lwsReplicas),
408+ // so stsMaxUnavailableInt = 0 (lwsMaxUnavailable) + 1 (capped maxSurge) = 1.
409+ WithRollingUpdate (appsapplyv1 .RollingUpdateStatefulSetStrategy ().WithPartition (0 ).WithMaxUnavailable (intstr .FromInt32 (1 ))),
407410 },
408411 },
409412 },
@@ -662,11 +665,86 @@ func TestLeaderStatefulSetApplyConfig(t *testing.T) {
662665 },
663666 },
664667 },
668+ {
669+ // Validates maxSurge uses lws replicas, not sts replicas.
670+ name : "1 maxUnavailable, 50% maxSurge, 2 lws replicas, 3 sts replicas currently" ,
671+ revisionKey : revisionKey2 ,
672+ stsReplicas : ptr.To [int32 ](3 ),
673+ lws : wrappers .BuildBasicLeaderWorkerSet ("test-sample" , "default" ).
674+ Replica (2 ).
675+ RolloutStrategy (leaderworkerset.RolloutStrategy {
676+ Type : leaderworkerset .RollingUpdateStrategyType ,
677+ RollingUpdateConfiguration : & leaderworkerset.RollingUpdateConfiguration {
678+ MaxUnavailable : intstr .FromInt32 (1 ),
679+ MaxSurge : intstr .FromString ("50%" ),
680+ },
681+ }).
682+ WorkerTemplateSpec (wrappers .MakeWorkerPodSpec ()).
683+ Size (1 ).
684+ RestartPolicy (leaderworkerset .RecreateGroupOnPodRestart ).Obj (),
685+ wantApplyConfig : & appsapplyv1.StatefulSetApplyConfiguration {
686+ TypeMetaApplyConfiguration : metaapplyv1.TypeMetaApplyConfiguration {
687+ Kind : ptr.To [string ]("StatefulSet" ),
688+ APIVersion : ptr.To [string ]("apps/v1" ),
689+ },
690+ ObjectMetaApplyConfiguration : & metaapplyv1.ObjectMetaApplyConfiguration {
691+ Name : ptr.To [string ]("test-sample" ),
692+ Namespace : ptr.To [string ]("default" ),
693+ Labels : map [string ]string {
694+ "leaderworkerset.sigs.k8s.io/name" : "test-sample" ,
695+ "leaderworkerset.sigs.k8s.io/template-revision-hash" : revisionKey2 ,
696+ },
697+ Annotations : map [string ]string {"leaderworkerset.sigs.k8s.io/replicas" : "2" },
698+ },
699+ Spec : & appsapplyv1.StatefulSetSpecApplyConfiguration {
700+ Replicas : ptr.To [int32 ](3 ), // using stsReplicas
701+ Selector : & metaapplyv1.LabelSelectorApplyConfiguration {
702+ MatchLabels : map [string ]string {
703+ "leaderworkerset.sigs.k8s.io/name" : "test-sample" ,
704+ "leaderworkerset.sigs.k8s.io/worker-index" : "0" ,
705+ },
706+ },
707+ Template : & coreapplyv1.PodTemplateSpecApplyConfiguration {
708+ ObjectMetaApplyConfiguration : & metaapplyv1.ObjectMetaApplyConfiguration {
709+ Labels : map [string ]string {
710+ "leaderworkerset.sigs.k8s.io/name" : "test-sample" ,
711+ "leaderworkerset.sigs.k8s.io/worker-index" : "0" ,
712+ "leaderworkerset.sigs.k8s.io/template-revision-hash" : revisionKey2 ,
713+ },
714+ Annotations : map [string ]string {
715+ "leaderworkerset.sigs.k8s.io/size" : "1" ,
716+ },
717+ },
718+ Spec : & coreapplyv1.PodSpecApplyConfiguration {
719+ Containers : []coreapplyv1.ContainerApplyConfiguration {
720+ {
721+ Name : ptr.To [string ]("worker" ),
722+ Image : ptr.To [string ]("docker.io/nginxinc/nginx-unprivileged:1.27" ),
723+ Ports : []coreapplyv1.ContainerPortApplyConfiguration {{ContainerPort : ptr.To [int32 ](8080 ), Protocol : ptr.To [corev1.Protocol ](corev1 .ProtocolTCP )}},
724+ Resources : & coreapplyv1.ResourceRequirementsApplyConfiguration {},
725+ },
726+ },
727+ },
728+ },
729+ ServiceName : ptr.To [string ]("test-sample" ),
730+ PodManagementPolicy : ptr.To [appsv1.PodManagementPolicyType ](appsv1 .ParallelPodManagement ),
731+ UpdateStrategy : appsapplyv1 .StatefulSetUpdateStrategy ().
732+ WithType (appsv1 .RollingUpdateStatefulSetStrategyType ).
733+ // maxUnavailable=1, maxSurge=50% of 2 replicas (lwsReplicas) = 1.
734+ // So stsMaxUnavailableInt = 1 + 1 = 2
735+ WithRollingUpdate (appsapplyv1 .RollingUpdateStatefulSetStrategy ().WithPartition (0 ).WithMaxUnavailable (intstr .FromInt32 (2 ))),
736+ },
737+ },
738+ },
665739 }
666740
667741 for _ , tc := range tests {
668742 t .Run (tc .name , func (t * testing.T ) {
669- stsApplyConfig , err := constructLeaderStatefulSetApplyConfiguration (tc .lws , 0 , * tc .lws .Spec .Replicas , tc .revisionKey )
743+ stsReplicas := * tc .lws .Spec .Replicas
744+ if tc .stsReplicas != nil {
745+ stsReplicas = * tc .stsReplicas
746+ }
747+ stsApplyConfig , err := constructLeaderStatefulSetApplyConfiguration (tc .lws , 0 , stsReplicas , tc .revisionKey )
670748 if err != nil {
671749 t .Errorf ("failed with error: %s" , err .Error ())
672750 }
0 commit comments