diff --git a/pkg/deploy/elbv2/frontend_nlb_target_synthesizer.go b/pkg/deploy/elbv2/frontend_nlb_target_synthesizer.go index a21a6897a3..d180785471 100644 --- a/pkg/deploy/elbv2/frontend_nlb_target_synthesizer.go +++ b/pkg/deploy/elbv2/frontend_nlb_target_synthesizer.go @@ -16,7 +16,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -func NewFrontendNlbTargetSynthesizer(k8sClient client.Client, trackingProvider tracking.Provider, taggingManager TaggingManager, frontendNlbTargetsManager FrontendNlbTargetsManager, logger logr.Logger, featureGates config.FeatureGates, stack core.Stack, frontendNlbTargetGroupDesiredState *core.FrontendNlbTargetGroupDesiredState) *frontendNlbTargetSynthesizer { +type TargetGroupsResult struct { + TargetGroups []TargetGroupWithTags + Err error +} + +func NewFrontendNlbTargetSynthesizer(k8sClient client.Client, trackingProvider tracking.Provider, taggingManager TaggingManager, frontendNlbTargetsManager FrontendNlbTargetsManager, logger logr.Logger, featureGates config.FeatureGates, stack core.Stack, frontendNlbTargetGroupDesiredState *core.FrontendNlbTargetGroupDesiredState, findSDKTargetGroups func() TargetGroupsResult) *frontendNlbTargetSynthesizer { return &frontendNlbTargetSynthesizer{ k8sClient: k8sClient, trackingProvider: trackingProvider, @@ -26,6 +31,7 @@ func NewFrontendNlbTargetSynthesizer(k8sClient client.Client, trackingProvider t logger: logger, stack: stack, frontendNlbTargetGroupDesiredState: frontendNlbTargetGroupDesiredState, + findSDKTargetGroups: findSDKTargetGroups, } } @@ -38,16 +44,18 @@ type frontendNlbTargetSynthesizer struct { logger logr.Logger stack core.Stack frontendNlbTargetGroupDesiredState *core.FrontendNlbTargetGroupDesiredState + findSDKTargetGroups func() TargetGroupsResult } // Synthesize processes AWS target groups and deregisters ALB targets based on the desired state. func (s *frontendNlbTargetSynthesizer) Synthesize(ctx context.Context) error { var resTGs []*elbv2model.TargetGroup s.stack.ListResources(&resTGs) - sdkTGs, err := s.findSDKTargetGroups(ctx) - if err != nil { - return err + res := s.findSDKTargetGroups() + if res.Err != nil { + return res.Err } + sdkTGs := res.TargetGroups _, _, unmatchedSDKTGs, err := matchResAndSDKTargetGroups(resTGs, sdkTGs, s.trackingProvider.ResourceIDTagKey(), s.featureGates) if err != nil { @@ -158,9 +166,3 @@ func filterALBTargetGroups(targetGroups []*elbv2model.TargetGroup) []*elbv2model } return filteredTargetGroups } - -func (s *frontendNlbTargetSynthesizer) findSDKTargetGroups(ctx context.Context) ([]TargetGroupWithTags, error) { - stackTags := s.trackingProvider.StackTags(s.stack) - return s.taggingManager.ListTargetGroups(ctx, - tracking.TagsAsTagFilter(stackTags)) -} diff --git a/pkg/deploy/elbv2/target_group_synthesizer.go b/pkg/deploy/elbv2/target_group_synthesizer.go index 11d7e54221..8e3be2a3f6 100644 --- a/pkg/deploy/elbv2/target_group_synthesizer.go +++ b/pkg/deploy/elbv2/target_group_synthesizer.go @@ -16,16 +16,17 @@ import ( // NewTargetGroupSynthesizer constructs targetGroupSynthesizer func NewTargetGroupSynthesizer(elbv2Client services.ELBV2, trackingProvider tracking.Provider, taggingManager TaggingManager, - tgManager TargetGroupManager, logger logr.Logger, featureGates config.FeatureGates, stack core.Stack) *targetGroupSynthesizer { + tgManager TargetGroupManager, logger logr.Logger, featureGates config.FeatureGates, stack core.Stack, findSDKTargetGroups func() TargetGroupsResult) *targetGroupSynthesizer { return &targetGroupSynthesizer{ - elbv2Client: elbv2Client, - trackingProvider: trackingProvider, - taggingManager: taggingManager, - tgManager: tgManager, - featureGates: featureGates, - logger: logger, - stack: stack, - unmatchedSDKTGs: nil, + elbv2Client: elbv2Client, + trackingProvider: trackingProvider, + taggingManager: taggingManager, + tgManager: tgManager, + featureGates: featureGates, + logger: logger, + stack: stack, + unmatchedSDKTGs: nil, + findSDKTargetGroups: findSDKTargetGroups, } } @@ -38,17 +39,19 @@ type targetGroupSynthesizer struct { featureGates config.FeatureGates logger logr.Logger - stack core.Stack - unmatchedSDKTGs []TargetGroupWithTags + stack core.Stack + unmatchedSDKTGs []TargetGroupWithTags + findSDKTargetGroups func() TargetGroupsResult } func (s *targetGroupSynthesizer) Synthesize(ctx context.Context) error { var resTGs []*elbv2model.TargetGroup s.stack.ListResources(&resTGs) - sdkTGs, err := s.findSDKTargetGroups(ctx) - if err != nil { - return err + res := s.findSDKTargetGroups() + if res.Err != nil { + return res.Err } + sdkTGs := res.TargetGroups matchedResAndSDKTGs, unmatchedResTGs, unmatchedSDKTGs, err := matchResAndSDKTargetGroups(resTGs, sdkTGs, s.trackingProvider.ResourceIDTagKey(), s.featureGates) if err != nil { @@ -85,15 +88,6 @@ func (s *targetGroupSynthesizer) PostSynthesize(ctx context.Context) error { return nil } -// findSDKTargetGroups will find all AWS TargetGroups created for stack. -func (s *targetGroupSynthesizer) findSDKTargetGroups(ctx context.Context) ([]TargetGroupWithTags, error) { - stackTags := s.trackingProvider.StackTags(s.stack) - stackTagsLegacy := s.trackingProvider.StackTagsLegacy(s.stack) - return s.taggingManager.ListTargetGroups(ctx, - tracking.TagsAsTagFilter(stackTags), - tracking.TagsAsTagFilter(stackTagsLegacy)) -} - type resAndSDKTargetGroupPair struct { resTG *elbv2model.TargetGroup sdkTG TargetGroupWithTags diff --git a/pkg/deploy/stack_deployer.go b/pkg/deploy/stack_deployer.go index 86510d3edb..f73395e078 100644 --- a/pkg/deploy/stack_deployer.go +++ b/pkg/deploy/stack_deployer.go @@ -3,6 +3,7 @@ package deploy import ( "context" "fmt" + "sync" "github.com/go-logr/logr" "sigs.k8s.io/aws-load-balancer-controller/pkg/aws/services" @@ -24,6 +25,8 @@ const ( ingressController = "ingress" ) +// Using elbv2.TargetGroupsResult instead of defining our own + // StackDeployer will deploy a resource stack into AWS and K8S. type StackDeployer interface { // Deploy a resource stack. @@ -105,12 +108,24 @@ func (d *defaultStackDeployer) Deploy(ctx context.Context, stack core.Stack, met ec2.NewSecurityGroupSynthesizer(d.cloud.EC2(), d.trackingProvider, d.ec2TaggingManager, d.ec2SGManager, d.vpcID, d.logger, stack), } + // Create a cached function that will only execute once to fetch target groups + // This is to avoid duplicate ListTargetGroups API call + findSDKTargetGroups := sync.OnceValue(func() elbv2.TargetGroupsResult { + stackTags := d.trackingProvider.StackTags(stack) + stackTagsLegacy := d.trackingProvider.StackTagsLegacy(stack) + tgs, err := d.elbv2TaggingManager.ListTargetGroups(ctx, + tracking.TagsAsTagFilter(stackTags), + tracking.TagsAsTagFilter(stackTagsLegacy)) + return elbv2.TargetGroupsResult{TargetGroups: tgs, Err: err} + }) + if controllerName == ingressController { - synthesizers = append(synthesizers, elbv2.NewFrontendNlbTargetSynthesizer(d.k8sClient, d.trackingProvider, d.elbv2TaggingManager, d.elbv2FrontendNlbTargetsManager, d.logger, d.featureGates, stack, frontendNlbTargetGroupDesiredState)) + synthesizers = append(synthesizers, elbv2.NewFrontendNlbTargetSynthesizer( + d.k8sClient, d.trackingProvider, d.elbv2TaggingManager, d.elbv2FrontendNlbTargetsManager, d.logger, d.featureGates, stack, frontendNlbTargetGroupDesiredState, findSDKTargetGroups)) } synthesizers = append(synthesizers, - elbv2.NewTargetGroupSynthesizer(d.cloud.ELBV2(), d.trackingProvider, d.elbv2TaggingManager, d.elbv2TGManager, d.logger, d.featureGates, stack), + elbv2.NewTargetGroupSynthesizer(d.cloud.ELBV2(), d.trackingProvider, d.elbv2TaggingManager, d.elbv2TGManager, d.logger, d.featureGates, stack, findSDKTargetGroups), elbv2.NewLoadBalancerSynthesizer(d.cloud.ELBV2(), d.trackingProvider, d.elbv2TaggingManager, d.elbv2LBManager, d.logger, d.featureGates, d.controllerConfig, stack), elbv2.NewListenerSynthesizer(d.cloud.ELBV2(), d.elbv2TaggingManager, d.elbv2LSManager, d.logger, stack), elbv2.NewListenerRuleSynthesizer(d.cloud.ELBV2(), d.elbv2TaggingManager, d.elbv2LRManager, d.logger, d.featureGates, stack),