in pkg/providers/v1/aws_loadbalancer.go [579:681]
func (c *Cloud) ensureTargetGroup(targetGroup *elbv2.TargetGroup, serviceName types.NamespacedName, mapping nlbPortMapping, instances []string, vpcID string, tags map[string]string) (*elbv2.TargetGroup, error) {
dirty := false
expectedTargets := c.computeTargetGroupExpectedTargets(instances, mapping.TrafficPort)
if targetGroup == nil {
targetType := "instance"
name := c.buildTargetGroupName(serviceName, mapping.FrontendPort, mapping.TrafficPort, mapping.TrafficProtocol, targetType, mapping)
klog.Infof("Creating load balancer target group for %v with name: %s", serviceName, name)
input := &elbv2.CreateTargetGroupInput{
VpcId: aws.String(vpcID),
Name: aws.String(name),
Port: aws.Int64(mapping.TrafficPort),
Protocol: aws.String(mapping.TrafficProtocol),
TargetType: aws.String(targetType),
HealthCheckIntervalSeconds: aws.Int64(mapping.HealthCheckConfig.Interval),
HealthCheckPort: aws.String(mapping.HealthCheckConfig.Port),
HealthCheckProtocol: aws.String(mapping.HealthCheckConfig.Protocol),
HealthyThresholdCount: aws.Int64(mapping.HealthCheckConfig.HealthyThreshold),
UnhealthyThresholdCount: aws.Int64(mapping.HealthCheckConfig.UnhealthyThreshold),
// HealthCheckTimeoutSeconds: Currently not configurable, 6 seconds for HTTP, 10 for TCP/HTTPS
}
if mapping.HealthCheckConfig.Protocol != elbv2.ProtocolEnumTcp {
input.HealthCheckPath = aws.String(mapping.HealthCheckConfig.Path)
}
if len(tags) != 0 {
targetGroupTags := make([]*elbv2.Tag, 0, len(tags))
for k, v := range tags {
targetGroupTags = append(targetGroupTags, &elbv2.Tag{
Key: aws.String(k), Value: aws.String(v),
})
}
input.Tags = targetGroupTags
}
result, err := c.elbv2.CreateTargetGroup(input)
if err != nil {
return nil, fmt.Errorf("error creating load balancer target group: %q", err)
}
if len(result.TargetGroups) != 1 {
return nil, fmt.Errorf("expected only one target group on CreateTargetGroup, got %d groups", len(result.TargetGroups))
}
tg := result.TargetGroups[0]
return tg, nil
}
// handle instances in service
{
tgARN := aws.StringValue(targetGroup.TargetGroupArn)
actualTargets, err := c.obtainTargetGroupActualTargets(tgARN)
if err != nil {
return nil, err
}
if err := c.ensureTargetGroupTargets(tgARN, expectedTargets, actualTargets); err != nil {
return nil, err
}
}
// ensure the health check is correct
{
dirtyHealthCheck := false
input := &elbv2.ModifyTargetGroupInput{
TargetGroupArn: targetGroup.TargetGroupArn,
}
if mapping.HealthCheckConfig.Port != aws.StringValue(targetGroup.HealthCheckPort) {
input.HealthCheckPort = aws.String(mapping.HealthCheckConfig.Port)
dirtyHealthCheck = true
}
if mapping.HealthCheckConfig.HealthyThreshold != aws.Int64Value(targetGroup.HealthyThresholdCount) {
dirtyHealthCheck = true
input.HealthyThresholdCount = aws.Int64(mapping.HealthCheckConfig.HealthyThreshold)
input.UnhealthyThresholdCount = aws.Int64(mapping.HealthCheckConfig.UnhealthyThreshold)
}
if !strings.EqualFold(mapping.HealthCheckConfig.Protocol, elbv2.ProtocolEnumTcp) {
if mapping.HealthCheckConfig.Path != aws.StringValue(input.HealthCheckPath) {
input.HealthCheckPath = aws.String(mapping.HealthCheckConfig.Path)
dirtyHealthCheck = true
}
}
if dirtyHealthCheck {
_, err := c.elbv2.ModifyTargetGroup(input)
if err != nil {
return nil, fmt.Errorf("error modifying target group health check: %q", err)
}
dirty = true
}
}
if dirty {
result, err := c.elbv2.DescribeTargetGroups(&elbv2.DescribeTargetGroupsInput{
TargetGroupArns: []*string{targetGroup.TargetGroupArn},
})
if err != nil {
return nil, fmt.Errorf("error retrieving target group after creation/update: %q", err)
}
targetGroup = result.TargetGroups[0]
}
return targetGroup, nil
}