@@ -2,6 +2,10 @@ package elbv2
22
33import (
44 "context"
5+ "sync"
6+ "time"
7+
8+ "k8s.io/apimachinery/pkg/util/cache"
59
610 awssdk "github.com/aws/aws-sdk-go/aws"
711 elbv2sdk "github.com/aws/aws-sdk-go/service/elbv2"
@@ -18,6 +22,8 @@ import (
1822const (
1923 // ELBV2 API supports up to 20 resource per DescribeTags API call.
2024 defaultDescribeTagsChunkSize = 20
25+ // cache ttl for tags on ELB resources.
26+ defaultResourceTagsCacheTTL = 20 * time .Minute
2127)
2228
2329// LoadBalancer with it's tags.
@@ -103,6 +109,8 @@ func NewDefaultTaggingManager(elbv2Client services.ELBV2, vpcID string, featureG
103109 featureGates : featureGates ,
104110 logger : logger ,
105111 describeTagsChunkSize : defaultDescribeTagsChunkSize ,
112+ resourceTagsCache : cache .NewExpiring (),
113+ resourceTagsCacheTTL : defaultResourceTagsCacheTTL ,
106114 rgt : rgt ,
107115 }
108116}
@@ -117,7 +125,11 @@ type defaultTaggingManager struct {
117125 featureGates config.FeatureGates
118126 logger logr.Logger
119127 describeTagsChunkSize int
120- rgt services.RGT
128+ // cache for tags on ELB resources.
129+ resourceTagsCache * cache.Expiring
130+ resourceTagsCacheTTL time.Duration
131+ resourceTagsCacheMutex sync.RWMutex
132+ rgt services.RGT
121133}
122134
123135func (m * defaultTaggingManager ) ReconcileTags (ctx context.Context , arn string , desiredTags map [string ]string , opts ... ReconcileTagsOption ) error {
@@ -128,7 +140,7 @@ func (m *defaultTaggingManager) ReconcileTags(ctx context.Context, arn string, d
128140 reconcileOpts .ApplyOptions (opts )
129141 currentTags := reconcileOpts .CurrentTags
130142 if currentTags == nil {
131- tagsByARN , err := m .describeResourceTagsNative (ctx , []string {arn })
143+ tagsByARN , err := m .describeResourceTags (ctx , []string {arn })
132144 if err != nil {
133145 return err
134146 }
@@ -153,6 +165,7 @@ func (m *defaultTaggingManager) ReconcileTags(ctx context.Context, arn string, d
153165 if _ , err := m .elbv2Client .AddTagsWithContext (ctx , req ); err != nil {
154166 return err
155167 }
168+ m .invalidateResourceTagsCache (arn )
156169 m .logger .Info ("added resource tags" ,
157170 "arn" , arn )
158171 }
@@ -170,6 +183,7 @@ func (m *defaultTaggingManager) ReconcileTags(ctx context.Context, arn string, d
170183 if _ , err := m .elbv2Client .RemoveTagsWithContext (ctx , req ); err != nil {
171184 return err
172185 }
186+ m .invalidateResourceTagsCache (arn )
173187 m .logger .Info ("removed resource tags" ,
174188 "arn" , arn )
175189 }
@@ -193,7 +207,7 @@ func (m *defaultTaggingManager) ListListeners(ctx context.Context, lbARN string)
193207 }
194208 var tagsByARN map [string ]map [string ]string
195209 if m .featureGates .Enabled (config .ListenerRulesTagging ) {
196- tagsByARN , err = m .describeResourceTagsNative (ctx , lsARNs )
210+ tagsByARN , err = m .describeResourceTags (ctx , lsARNs )
197211 if err != nil {
198212 return nil , err
199213 }
@@ -226,7 +240,7 @@ func (m *defaultTaggingManager) ListListenerRules(ctx context.Context, lsARN str
226240 }
227241 var tagsByARN map [string ]map [string ]string
228242 if m .featureGates .Enabled (config .ListenerRulesTagging ) {
229- tagsByARN , err = m .describeResourceTagsNative (ctx , lrARNs )
243+ tagsByARN , err = m .describeResourceTags (ctx , lrARNs )
230244 if err != nil {
231245 return nil , err
232246 }
@@ -242,6 +256,7 @@ func (m *defaultTaggingManager) ListListenerRules(ctx context.Context, lsARN str
242256 return sdkLRs , err
243257}
244258
259+ // TODO: we can refactor this by store provisioned LB's ARN as annotations on Ingress/Service, thus avoid this heavy lookup calls when RGT is not available.
245260func (m * defaultTaggingManager ) ListLoadBalancers (ctx context.Context , tagFilters ... tracking.TagFilter ) ([]LoadBalancerWithTags , error ) {
246261 if m .featureGates .Enabled (config .EnableRGTAPI ) {
247262 return m .listLoadBalancersRGT (ctx , tagFilters )
@@ -254,7 +269,6 @@ func (m *defaultTaggingManager) ListTargetGroups(ctx context.Context, tagFilters
254269 return m .listTargetGroupsRGT (ctx , tagFilters )
255270 }
256271 return m .listTargetGroupsNative (ctx , tagFilters )
257-
258272}
259273
260274func (m * defaultTaggingManager ) listLoadBalancersRGT (ctx context.Context , tagFilters []tracking.TagFilter ) ([]LoadBalancerWithTags , error ) {
@@ -311,7 +325,7 @@ func (m *defaultTaggingManager) listLoadBalancersNative(ctx context.Context, tag
311325 lbARNsWithinVPC = append (lbARNsWithinVPC , lbARN )
312326 lbByARNWithinVPC [lbARN ] = lb
313327 }
314- tagsByARN , err := m .describeResourceTagsNative (ctx , lbARNsWithinVPC )
328+ tagsByARN , err := m .describeResourceTags (ctx , lbARNsWithinVPC )
315329 if err != nil {
316330 return nil , err
317331 }
@@ -391,7 +405,7 @@ func (m *defaultTaggingManager) listTargetGroupsNative(ctx context.Context, tagF
391405 tgARNsWithinVPC = append (tgARNsWithinVPC , tgARN )
392406 tgByARNWithinVPC [tgARN ] = tg
393407 }
394- tagsByARN , err := m .describeResourceTagsNative (ctx , tgARNsWithinVPC )
408+ tagsByARN , err := m .describeResourceTags (ctx , tgARNsWithinVPC )
395409 if err != nil {
396410 return nil , err
397411 }
@@ -416,9 +430,34 @@ func (m *defaultTaggingManager) listTargetGroupsNative(ctx context.Context, tagF
416430 return matchedTGs , nil
417431}
418432
419- // describeResourceTagsNative describes tags for elbv2 resources.
433+ func (m * defaultTaggingManager ) describeResourceTags (ctx context.Context , arns []string ) (map [string ]map [string ]string , error ) {
434+ m .resourceTagsCacheMutex .Lock ()
435+ defer m .resourceTagsCacheMutex .Unlock ()
436+
437+ tagsByARN := make (map [string ]map [string ]string , len (arns ))
438+ var arnsWithoutTagsCache []string
439+ for _ , arn := range arns {
440+ if rawTagsCacheItem , exists := m .resourceTagsCache .Get (arn ); exists {
441+ tagsCacheItem := rawTagsCacheItem .(map [string ]string )
442+ tagsByARN [arn ] = tagsCacheItem
443+ } else {
444+ arnsWithoutTagsCache = append (arnsWithoutTagsCache , arn )
445+ }
446+ }
447+ tagsByARNFromAWS , err := m .describeResourceTagsFromAWS (ctx , arnsWithoutTagsCache )
448+ if err != nil {
449+ return nil , err
450+ }
451+ for arn , tags := range tagsByARNFromAWS {
452+ m .resourceTagsCache .Set (arn , tags , m .resourceTagsCacheTTL )
453+ tagsByARN [arn ] = tags
454+ }
455+ return tagsByARN , nil
456+ }
457+
458+ // describeResourceTagsFromAWS describes tags for elbv2 resources.
420459// returns tags indexed by resource ARN.
421- func (m * defaultTaggingManager ) describeResourceTagsNative (ctx context.Context , arns []string ) (map [string ]map [string ]string , error ) {
460+ func (m * defaultTaggingManager ) describeResourceTagsFromAWS (ctx context.Context , arns []string ) (map [string ]map [string ]string , error ) {
422461 tagsByARN := make (map [string ]map [string ]string , len (arns ))
423462 arnsChunks := algorithm .ChunkStrings (arns , m .describeTagsChunkSize )
424463 for _ , arnsChunk := range arnsChunks {
@@ -436,6 +475,13 @@ func (m *defaultTaggingManager) describeResourceTagsNative(ctx context.Context,
436475 return tagsByARN , nil
437476}
438477
478+ func (m * defaultTaggingManager ) invalidateResourceTagsCache (arn string ) {
479+ m .resourceTagsCacheMutex .Lock ()
480+ defer m .resourceTagsCacheMutex .Unlock ()
481+
482+ m .resourceTagsCache .Delete (arn )
483+ }
484+
439485// convert tags into AWS SDK tag presentation.
440486func convertTagsToSDKTags (tags map [string ]string ) []* elbv2sdk.Tag {
441487 if len (tags ) == 0 {
0 commit comments