@@ -300,11 +300,17 @@ func (t *defaultModelBuildTask) buildLoadBalancerTags(ctx context.Context) (map[
300300func (t * defaultModelBuildTask ) buildLoadBalancerSubnetMappings (_ context.Context , ipAddressType elbv2model.IPAddressType , scheme elbv2model.LoadBalancerScheme , ec2Subnets []ec2types.Subnet ) ([]elbv2model.SubnetMapping , error ) {
301301 var eipAllocation []string
302302 eipConfigured := t .annotationParser .ParseStringSliceAnnotation (annotations .SvcLBSuffixEIPAllocations , & eipAllocation , t .service .Annotations )
303+ var subnetsId []string
304+ subnetIDConfigured := t .annotationParser .ParseStringSliceAnnotation (annotations .SvcLBSuffixSubnets , & subnetsId , t .service .Annotations )
305+ reorderedSubnets := append (ec2Subnets [:0 :0 ], ec2Subnets ... )
306+ if subnetIDConfigured {
307+ reorderedSubnets = sortSubnetsBySubnetIdConfigured (subnetsId , ec2Subnets )
308+ }
303309 if eipConfigured {
304310 if scheme != elbv2model .LoadBalancerSchemeInternetFacing {
305311 return nil , errors .Errorf ("EIP allocations can only be set for internet facing load balancers" )
306312 }
307- if len (eipAllocation ) != len (ec2Subnets ) {
313+ if len (eipAllocation ) != len (reorderedSubnets ) {
308314 return nil , errors .Errorf ("count of EIP allocations (%d) and subnets (%d) must match" , len (eipAllocation ), len (ec2Subnets ))
309315 }
310316 }
@@ -317,7 +323,7 @@ func (t *defaultModelBuildTask) buildLoadBalancerSubnetMappings(_ context.Contex
317323 return nil , errors .Errorf ("private IPv4 addresses can only be set for internal load balancers" )
318324 }
319325 // TODO: consider relax this requirement as ELBv2 API don't require every subnet to have IPv4 address specified.
320- if len (rawIPv4Addresses ) != len (ec2Subnets ) {
326+ if len (rawIPv4Addresses ) != len (reorderedSubnets ) {
321327 return nil , errors .Errorf ("count of private IPv4 addresses (%d) and subnets (%d) must match" , len (rawIPv4Addresses ), len (ec2Subnets ))
322328 }
323329 for _ , rawIPv4Address := range rawIPv4Addresses {
@@ -340,7 +346,7 @@ func (t *defaultModelBuildTask) buildLoadBalancerSubnetMappings(_ context.Contex
340346 return nil , errors .Errorf ("IPv6 addresses can only be set for dualstack load balancers" )
341347 }
342348 // TODO: consider relax this requirement as ELBv2 API don't require every subnet to have IPv6 address specified.
343- if len (rawIPv6Addresses ) != len (ec2Subnets ) {
349+ if len (rawIPv6Addresses ) != len (reorderedSubnets ) {
344350 return nil , errors .Errorf ("count of IPv6 addresses (%d) and subnets (%d) must match" , len (rawIPv6Addresses ), len (ec2Subnets ))
345351 }
346352 for _ , rawIPv6Address := range rawIPv6Addresses {
@@ -355,8 +361,8 @@ func (t *defaultModelBuildTask) buildLoadBalancerSubnetMappings(_ context.Contex
355361 }
356362 }
357363
358- subnetMappings := make ([]elbv2model.SubnetMapping , 0 , len (ec2Subnets ))
359- for idx , subnet := range ec2Subnets {
364+ subnetMappings := make ([]elbv2model.SubnetMapping , 0 , len (reorderedSubnets ))
365+ for idx , subnet := range reorderedSubnets {
360366 mapping := elbv2model.SubnetMapping {
361367 SubnetID : awssdk .ToString (subnet .SubnetId ),
362368 }
@@ -534,3 +540,15 @@ func (t *defaultModelBuildTask) buildLoadBalancerName(_ context.Context, scheme
534540 sanitizedName := invalidLoadBalancerNamePattern .ReplaceAllString (t .service .Name , "" )
535541 return fmt .Sprintf ("k8s-%.8s-%.8s-%.10s" , sanitizedNamespace , sanitizedName , uuid ), nil
536542}
543+
544+ func sortSubnetsBySubnetIdConfigured (subnetId []string , ec2Subnets []ec2types.Subnet ) []ec2types.Subnet {
545+ subnetIndex := make (map [string ]int )
546+ for index , id := range subnetId {
547+ subnetIndex [id ] = index
548+ }
549+ sortedSubnets := append (ec2Subnets [:0 :0 ], ec2Subnets ... )
550+ sort .Slice (sortedSubnets , func (i , j int ) bool {
551+ return subnetIndex [* sortedSubnets [i ].SubnetId ] < subnetIndex [* sortedSubnets [j ].SubnetId ]
552+ })
553+ return sortedSubnets
554+ }
0 commit comments