@@ -113,7 +113,7 @@ func (s *Service) reconcileV2LB(lbSpec *infrav1.AWSLoadBalancerSpec) error {
113
113
lb .LoadBalancerType = lbSpec .LoadBalancerType
114
114
if lb .IsManaged (s .scope .Name ()) {
115
115
// Reconcile the target groups and listeners from the spec and the ones currently attached to the load balancer.
116
- _ , err := s .reconcileTargetGroupsAndListeners (lb , lbSpec )
116
+ _ , _ , err := s .reconcileTargetGroupsAndListeners (lb , lbSpec )
117
117
if err != nil {
118
118
return errors .Wrapf (err , "failed to create target groups/listeners for load balancer %q" , lb .Name )
119
119
}
@@ -1529,111 +1529,162 @@ func (s *Service) reconcileV2LBTags(lb *infrav1.LoadBalancer, desiredTags map[st
1529
1529
return nil
1530
1530
}
1531
1531
1532
- func (s * Service ) reconcileTargetGroupsAndListeners (spec * infrav1.LoadBalancer , lbSpec * infrav1.AWSLoadBalancerSpec ) ([]* elbv2.TargetGroup , error ) {
1533
-
1534
- describeInput := & elbv2.DescribeTargetGroupsInput {
1535
- LoadBalancerArn : aws .String (spec .ARN ),
1536
- }
1537
- targetGroups , err := s .ELBV2Client .DescribeTargetGroups (describeInput )
1532
+ // reconcileTargetGroupsAndListeners reconciles a Load Balancer's defined listeners with corresponding AWS Target Groups and Listeners.
1533
+ // These are combined into a single function since they are tightly integrated.
1534
+ func (s * Service ) reconcileTargetGroupsAndListeners (spec * infrav1.LoadBalancer , lbSpec * infrav1.AWSLoadBalancerSpec ) ([]* elbv2.TargetGroup , []* elbv2.Listener , error ) {
1535
+ existingTargetGroups , err := s .ELBV2Client .DescribeTargetGroups (
1536
+ & elbv2.DescribeTargetGroupsInput {
1537
+ LoadBalancerArn : aws .String (spec .ARN ),
1538
+ })
1538
1539
if err != nil {
1539
1540
s .scope .Error (err , "could not describe target groups for load balancer" , "arn" , spec .ARN )
1540
- return nil , err
1541
+ return nil , nil , err
1542
+ }
1543
+
1544
+ existingListeners , err := s .ELBV2Client .DescribeListeners (
1545
+ & elbv2.DescribeListenersInput {
1546
+ LoadBalancerArn : aws .String (spec .ARN ),
1547
+ })
1548
+ if err != nil {
1549
+ s .scope .Error (err , "could not describe listeners for load balancer" , "arn" , spec .ARN )
1541
1550
}
1542
1551
1543
- // Target Groups already exist, no need to do additional work.
1544
- // TODO(nrb): This will need to match the infrav1.Listener type
1545
- if len (targetGroups .TargetGroups ) > 0 {
1546
- return targetGroups .TargetGroups , nil
1552
+ if len (existingTargetGroups .TargetGroups ) == len (existingListeners .Listeners ) && len (existingListeners .Listeners ) == len (spec .ELBListeners ) {
1553
+ return existingTargetGroups .TargetGroups , existingListeners .Listeners , nil
1547
1554
}
1548
1555
1549
- groups := make ([]* elbv2.TargetGroup , len (spec .ELBListeners ))
1556
+ createdTargetGroups := make ([]* elbv2.TargetGroup , 0 , len (spec .ELBListeners ))
1557
+ createdListeners := make ([]* elbv2.Listener , 0 , len (spec .ELBListeners ))
1550
1558
1551
1559
// TODO(Skarlso): Add options to set up SSL.
1552
1560
// https://github.com/kubernetes-sigs/cluster-api-provider-aws/issues/3899
1553
1561
for _ , ln := range spec .ELBListeners {
1554
- // create the target group first
1555
- targetGroupInput := & elbv2.CreateTargetGroupInput {
1556
- Name : aws .String (ln .TargetGroup .Name ),
1557
- Port : aws .Int64 (ln .TargetGroup .Port ),
1558
- Protocol : aws .String (ln .TargetGroup .Protocol .String ()),
1559
- VpcId : aws .String (ln .TargetGroup .VpcID ),
1560
- Tags : converters .MapToV2Tags (spec .Tags ),
1561
- HealthCheckIntervalSeconds : aws .Int64 (infrav1 .DefaultAPIServerHealthCheckIntervalSec ),
1562
- HealthCheckTimeoutSeconds : aws .Int64 (infrav1 .DefaultAPIServerHealthCheckTimeoutSec ),
1563
- HealthyThresholdCount : aws .Int64 (infrav1 .DefaultAPIServerHealthThresholdCount ),
1564
- UnhealthyThresholdCount : aws .Int64 (infrav1 .DefaultAPIServerUnhealthThresholdCount ),
1565
- }
1566
- if s .scope .VPC ().IsIPv6Enabled () {
1567
- targetGroupInput .IpAddressType = aws .String ("ipv6" )
1568
- }
1569
- if ln .TargetGroup .HealthCheck != nil {
1570
- targetGroupInput .HealthCheckEnabled = aws .Bool (true )
1571
- targetGroupInput .HealthCheckProtocol = ln .TargetGroup .HealthCheck .Protocol
1572
- targetGroupInput .HealthCheckPort = ln .TargetGroup .HealthCheck .Port
1573
- if ln .TargetGroup .HealthCheck .Path != nil {
1574
- targetGroupInput .HealthCheckPath = ln .TargetGroup .HealthCheck .Path
1562
+ var group * elbv2.TargetGroup
1563
+ for _ , g := range existingTargetGroups .TargetGroups {
1564
+ if * g .TargetGroupName == ln .TargetGroup .Name {
1565
+ group = g
1575
1566
}
1576
- if ln .TargetGroup .HealthCheck .IntervalSeconds != nil {
1577
- targetGroupInput .HealthCheckIntervalSeconds = ln .TargetGroup .HealthCheck .IntervalSeconds
1578
- }
1579
- if ln .TargetGroup .HealthCheck .TimeoutSeconds != nil {
1580
- targetGroupInput .HealthCheckTimeoutSeconds = ln .TargetGroup .HealthCheck .TimeoutSeconds
1581
- }
1582
- if ln .TargetGroup .HealthCheck .ThresholdCount != nil {
1583
- targetGroupInput .HealthyThresholdCount = ln .TargetGroup .HealthCheck .ThresholdCount
1567
+ }
1568
+ // create the target group first
1569
+ if group == nil {
1570
+ group , err = s .createTargetGroup (ln , spec .Tags )
1571
+ if err != nil {
1572
+ return nil , nil , err
1584
1573
}
1585
- if ln .TargetGroup .HealthCheck .UnhealthyThresholdCount != nil {
1586
- targetGroupInput .UnhealthyThresholdCount = ln .TargetGroup .HealthCheck .UnhealthyThresholdCount
1574
+ createdTargetGroups = append (createdTargetGroups , group )
1575
+
1576
+ if ! lbSpec .PreserveClientIP {
1577
+ targetGroupAttributeInput := & elbv2.ModifyTargetGroupAttributesInput {
1578
+ TargetGroupArn : group .TargetGroupArn ,
1579
+ Attributes : []* elbv2.TargetGroupAttribute {
1580
+ {
1581
+ Key : aws .String (infrav1 .TargetGroupAttributeEnablePreserveClientIP ),
1582
+ Value : aws .String ("false" ),
1583
+ },
1584
+ },
1585
+ }
1586
+ if _ , err := s .ELBV2Client .ModifyTargetGroupAttributes (targetGroupAttributeInput ); err != nil {
1587
+ return nil , nil , errors .Wrapf (err , "failed to modify target group attribute" )
1588
+ }
1587
1589
}
1588
1590
}
1589
- s .scope .Debug ("creating target group" , "group" , targetGroupInput , "listener" , ln )
1590
- group , err := s .ELBV2Client .CreateTargetGroup (targetGroupInput )
1591
- if err != nil {
1592
- return nil , errors .Wrapf (err , "failed to create target group for load balancer" )
1593
- }
1594
- if len (group .TargetGroups ) == 0 {
1595
- return nil , errors .New ("no target group was created; the returned list is empty" )
1596
- }
1597
- groups = append (groups , group .TargetGroups ... )
1598
1591
1599
- if ! lbSpec .PreserveClientIP {
1600
- targetGroupAttributeInput := & elbv2.ModifyTargetGroupAttributesInput {
1601
- TargetGroupArn : group .TargetGroups [0 ].TargetGroupArn ,
1602
- Attributes : []* elbv2.TargetGroupAttribute {
1603
- {
1604
- Key : aws .String (infrav1 .TargetGroupAttributeEnablePreserveClientIP ),
1605
- Value : aws .String ("false" ),
1606
- },
1607
- },
1592
+ var listener * elbv2.Listener
1593
+ for _ , l := range existingListeners .Listeners {
1594
+ if l .DefaultActions != nil && l .DefaultActions [0 ].TargetGroupArn == group .TargetGroupArn {
1595
+ listener = l
1608
1596
}
1609
- if _ , err := s .ELBV2Client .ModifyTargetGroupAttributes (targetGroupAttributeInput ); err != nil {
1610
- return nil , errors .Wrapf (err , "failed to modify target group attribute" )
1597
+ }
1598
+
1599
+ if listener == nil {
1600
+ listener , err = s .createListener (ln , group , spec .ARN , spec .Tags )
1601
+ if err != nil {
1602
+ return nil , nil , err
1611
1603
}
1612
1604
}
1613
1605
1614
- listenerInput := & elbv2.CreateListenerInput {
1615
- DefaultActions : []* elbv2.Action {
1616
- {
1617
- TargetGroupArn : group .TargetGroups [0 ].TargetGroupArn ,
1618
- Type : aws .String (elbv2 .ActionTypeEnumForward ),
1619
- },
1606
+ createdListeners = append (createdListeners , listener )
1607
+ }
1608
+
1609
+ return createdTargetGroups , createdListeners , nil
1610
+ }
1611
+
1612
+ // createListener creates a single Listener
1613
+ func (s * Service ) createListener (ln infrav1.Listener , group * elbv2.TargetGroup , lbARN string , tags map [string ]string ) (* elbv2.Listener , error ) {
1614
+ listenerInput := & elbv2.CreateListenerInput {
1615
+ DefaultActions : []* elbv2.Action {
1616
+ {
1617
+ TargetGroupArn : group .TargetGroupArn ,
1618
+ Type : aws .String (elbv2 .ActionTypeEnumForward ),
1620
1619
},
1621
- LoadBalancerArn : aws .String (spec .ARN ),
1622
- Port : aws .Int64 (ln .Port ),
1623
- Protocol : aws .String (string (ln .Protocol )),
1624
- Tags : converters .MapToV2Tags (spec .Tags ),
1620
+ },
1621
+ LoadBalancerArn : aws .String (lbARN ),
1622
+ Port : aws .Int64 (ln .Port ),
1623
+ Protocol : aws .String (string (ln .Protocol )),
1624
+ Tags : converters .MapToV2Tags (tags ),
1625
+ }
1626
+ // Create ClassicELBListeners
1627
+ listener , err := s .ELBV2Client .CreateListener (listenerInput )
1628
+ if err != nil {
1629
+ return nil , errors .Wrap (err , "failed to create listener" )
1630
+ }
1631
+ if len (listener .Listeners ) == 0 {
1632
+ return nil , errors .New ("no listener was created; the returned list is empty" )
1633
+ }
1634
+ if len (listener .Listeners ) > 1 {
1635
+ return nil , errors .New ("more than one listener created; expected only one" )
1636
+ }
1637
+ return listener .Listeners [0 ], nil
1638
+ }
1639
+
1640
+ // createTargetGroup creates a single Target Group
1641
+ func (s * Service ) createTargetGroup (ln infrav1.Listener , tags map [string ]string ) (* elbv2.TargetGroup , error ) {
1642
+ targetGroupInput := & elbv2.CreateTargetGroupInput {
1643
+ Name : aws .String (ln .TargetGroup .Name ),
1644
+ Port : aws .Int64 (ln .TargetGroup .Port ),
1645
+ Protocol : aws .String (ln .TargetGroup .Protocol .String ()),
1646
+ VpcId : aws .String (ln .TargetGroup .VpcID ),
1647
+ Tags : converters .MapToV2Tags (tags ),
1648
+ HealthCheckIntervalSeconds : aws .Int64 (infrav1 .DefaultAPIServerHealthCheckIntervalSec ),
1649
+ HealthCheckTimeoutSeconds : aws .Int64 (infrav1 .DefaultAPIServerHealthCheckTimeoutSec ),
1650
+ HealthyThresholdCount : aws .Int64 (infrav1 .DefaultAPIServerHealthThresholdCount ),
1651
+ UnhealthyThresholdCount : aws .Int64 (infrav1 .DefaultAPIServerUnhealthThresholdCount ),
1652
+ }
1653
+ if s .scope .VPC ().IsIPv6Enabled () {
1654
+ targetGroupInput .IpAddressType = aws .String ("ipv6" )
1655
+ }
1656
+ if ln .TargetGroup .HealthCheck != nil {
1657
+ targetGroupInput .HealthCheckEnabled = aws .Bool (true )
1658
+ targetGroupInput .HealthCheckProtocol = ln .TargetGroup .HealthCheck .Protocol
1659
+ targetGroupInput .HealthCheckPort = ln .TargetGroup .HealthCheck .Port
1660
+ if ln .TargetGroup .HealthCheck .Path != nil {
1661
+ targetGroupInput .HealthCheckPath = ln .TargetGroup .HealthCheck .Path
1625
1662
}
1626
- // Create ClassicELBListeners
1627
- listener , err := s .ELBV2Client .CreateListener (listenerInput )
1628
- if err != nil {
1629
- return nil , errors .Wrap (err , "failed to create listener" )
1663
+ if ln .TargetGroup .HealthCheck .IntervalSeconds != nil {
1664
+ targetGroupInput .HealthCheckIntervalSeconds = ln .TargetGroup .HealthCheck .IntervalSeconds
1665
+ }
1666
+ if ln .TargetGroup .HealthCheck .TimeoutSeconds != nil {
1667
+ targetGroupInput .HealthCheckTimeoutSeconds = ln .TargetGroup .HealthCheck .TimeoutSeconds
1630
1668
}
1631
- if len (listener .Listeners ) == 0 {
1632
- return nil , errors .New ("no listener was created; the returned list is empty" )
1669
+ if ln .TargetGroup .HealthCheck .ThresholdCount != nil {
1670
+ targetGroupInput .HealthyThresholdCount = ln .TargetGroup .HealthCheck .ThresholdCount
1671
+ }
1672
+ if ln .TargetGroup .HealthCheck .UnhealthyThresholdCount != nil {
1673
+ targetGroupInput .UnhealthyThresholdCount = ln .TargetGroup .HealthCheck .UnhealthyThresholdCount
1633
1674
}
1634
1675
}
1635
-
1636
- return groups , nil
1676
+ s .scope .Debug ("creating target group" , "group" , targetGroupInput , "listener" , ln )
1677
+ group , err := s .ELBV2Client .CreateTargetGroup (targetGroupInput )
1678
+ if err != nil {
1679
+ return nil , errors .Wrapf (err , "failed to create target group for load balancer" )
1680
+ }
1681
+ if len (group .TargetGroups ) == 0 {
1682
+ return nil , errors .New ("no target group was created; the returned list is empty" )
1683
+ }
1684
+ if len (group .TargetGroups ) > 1 {
1685
+ return nil , errors .New ("more than one target group created; expected only one" )
1686
+ }
1687
+ return group .TargetGroups [0 ], nil
1637
1688
}
1638
1689
1639
1690
func (s * Service ) getHealthCheckTarget () string {
0 commit comments