@@ -68,6 +68,17 @@ const DefaultNetworkLoadBalancerListenerProtocol = "TCP"
6868// https://docs.oracle.com/en-us/iaas/Content/General/Concepts/servicelimits.htm#nsg_limits
6969const MaxNsgPerVnic = 5
7070
71+ const (
72+ OkeSystemTagNamesapce = "orcl-containerengine"
73+ // MaxDefinedTagPerLB is the maximum number of defined tags that be can be associated with the resource
74+ //https://docs.oracle.com/en-us/iaas/Content/Tagging/Concepts/taggingoverview.htm#limits
75+ MaxDefinedTagPerLB = 64
76+ resourceTrackingFeatureFlagName = "CPO_ENABLE_RESOURCE_ATTRIBUTION"
77+ )
78+
79+ var MaxDefinedTagPerLBErr = fmt .Errorf ("max limit of defined tags for lb is reached. skip adding tags. sending metric" )
80+ var enableOkeSystemTags = false
81+
7182const (
7283 // Fallback value if annotation on service is not set
7384 lbDefaultShape = "100Mbps"
@@ -373,6 +384,11 @@ func (clb *CloudLoadBalancerProvider) createLoadBalancer(ctx context.Context, sp
373384 FreeformTags : spec .FreeformTags ,
374385 DefinedTags : spec .DefinedTags ,
375386 }
387+ // do not block creation if the defined tag limit is reached. defer LB to tracked by backfilling
388+ if len (details .DefinedTags ) > MaxDefinedTagPerLB {
389+ logger .Warnf ("the number of defined tags in the LB create request is beyond the limit. removing the resource tracking tags from the details.." )
390+ delete (details .DefinedTags , OkeSystemTagNamesapce )
391+ }
376392
377393 if spec .Shape == flexible {
378394 details .ShapeDetails = & client.GenericShapeDetails {
@@ -714,6 +730,19 @@ func (cp *CloudProvider) EnsureLoadBalancer(ctx context.Context, clusterName str
714730
715731 if ! lbExists {
716732 lbStatus , newLBOCID , err := lbProvider .createLoadBalancer (ctx , spec )
733+ if err != nil && client .IsSystemTagNotFoundOrNotAuthorisedError (logger , err ) {
734+ logger .Warn ("LB creation failed due to error in adding system tags. sending metric & retrying without system tags" )
735+
736+ // send resource track tagging failure metrics
737+ errorType = util .SystemTagErrTypePrefix + util .GetError (err )
738+ lbMetricDimension = util .GetMetricDimensionForComponent (errorType , util .LoadBalancerType )
739+ dimensionsMap [metrics .ComponentDimension ] = lbMetricDimension
740+ metrics .SendMetricData (cp .metricPusher , getMetric (loadBalancerType , Create ), time .Since (startTime ).Seconds (), dimensionsMap )
741+
742+ // retry create without resource tracking system tags
743+ delete (spec .DefinedTags , OkeSystemTagNamesapce )
744+ lbStatus , newLBOCID , err = lbProvider .createLoadBalancer (ctx , spec )
745+ }
717746 if err != nil {
718747 logger .With (zap .Error (err )).Error ("Failed to provision LoadBalancer" )
719748 errorType = util .GetError (err )
@@ -884,7 +913,7 @@ func (cp *CloudProvider) getLoadBalancerSubnets(ctx context.Context, logger *zap
884913
885914func (clb * CloudLoadBalancerProvider ) updateLoadBalancer (ctx context.Context , lb * client.GenericLoadBalancer , spec * LBSpec ) error {
886915 lbID := * lb .Id
887-
916+ start := time . Now ()
888917 logger := clb .logger .With ("loadBalancerID" , lbID , "compartmentID" , clb .config .CompartmentID , "loadBalancerType" , getLoadBalancerType (spec .service ), "serviceName" , spec .service .Name )
889918
890919 var actualPublicReservedIP * string
@@ -983,6 +1012,24 @@ func (clb *CloudLoadBalancerProvider) updateLoadBalancer(ctx context.Context, lb
9831012 return errors .Errorf ("The Load Balancer service reserved IP cannot be updated after the Load Balancer is created." )
9841013 }
9851014 }
1015+
1016+ dimensionsMap := make (map [string ]string )
1017+ var errType string
1018+ if enableOkeSystemTags && ! doesLbHaveOkeSystemTags (lb , spec ) {
1019+ logger .Info ("detected loadbalancer without oke system tags. proceeding to add" )
1020+ err = clb .addLoadBalancerOkeSystemTags (ctx , lb , spec )
1021+ if err != nil {
1022+ // fail open if the update request fails
1023+ logger .With (zap .Error (err )).Warn ("updateLoadBalancer didn't succeed. unable to add oke system tags" )
1024+ errType = util .SystemTagErrTypePrefix + util .GetError (err )
1025+ if errors .Is (err , MaxDefinedTagPerLBErr ) {
1026+ errType = util .ErrTagLimitReached
1027+ }
1028+ dimensionsMap [metrics .ComponentDimension ] = util .GetMetricDimensionForComponent (errType , util .LoadBalancerType )
1029+ dimensionsMap [metrics .ResourceOCIDDimension ] = * lb .Id
1030+ metrics .SendMetricData (clb .metricPusher , getMetric (spec .Type , Update ), time .Since (start ).Seconds (), dimensionsMap )
1031+ }
1032+ }
9861033 return nil
9871034}
9881035
@@ -1648,6 +1695,56 @@ func (clb *CloudLoadBalancerProvider) updateLoadBalancerNetworkSecurityGroups(ct
16481695 return nil
16491696}
16501697
1698+ func doesLbHaveOkeSystemTags (lb * client.GenericLoadBalancer , spec * LBSpec ) bool {
1699+ if lb .SystemTags == nil || spec .SystemTags == nil {
1700+ return false
1701+ }
1702+ if okeSystemTag , okeSystemTagNsExists := lb .SystemTags [OkeSystemTagNamesapce ]; okeSystemTagNsExists {
1703+ return reflect .DeepEqual (okeSystemTag , spec .SystemTags [OkeSystemTagNamesapce ])
1704+ }
1705+ return false
1706+ }
1707+ func (clb * CloudLoadBalancerProvider ) addLoadBalancerOkeSystemTags (ctx context.Context , lb * client.GenericLoadBalancer , spec * LBSpec ) error {
1708+ lbDefinedTagsRequest := make (map [string ]map [string ]interface {})
1709+
1710+ if spec .SystemTags == nil {
1711+ return fmt .Errorf ("oke system tag is not found in LB spec. ignoring.." )
1712+ }
1713+ if _ , exists := spec .SystemTags [OkeSystemTagNamesapce ]; ! exists {
1714+ return fmt .Errorf ("oke system tag namespace is not found in LB spec" )
1715+ }
1716+
1717+ if lb .DefinedTags != nil {
1718+ lbDefinedTagsRequest = lb .DefinedTags
1719+ }
1720+
1721+ // no overwriting customer tags as customer can not have a tag namespace with prefix 'orcl-'
1722+ // system tags are passed as defined tags in the request
1723+ lbDefinedTagsRequest [OkeSystemTagNamesapce ] = spec .SystemTags [OkeSystemTagNamesapce ]
1724+
1725+ // update fails if the number of defined tags is more than the service limit i.e 64
1726+ if len (lbDefinedTagsRequest ) > MaxDefinedTagPerLB {
1727+ return MaxDefinedTagPerLBErr
1728+ }
1729+
1730+ lbUpdateDetails := & client.GenericUpdateLoadBalancerDetails {
1731+ FreeformTags : lb .FreeformTags ,
1732+ DefinedTags : lbDefinedTagsRequest ,
1733+ }
1734+ wrID , err := clb .lbClient .UpdateLoadBalancer (ctx , * lb .Id , lbUpdateDetails )
1735+ if err != nil {
1736+ return errors .Wrap (err , "UpdateLoadBalancer request failed" )
1737+ }
1738+ _ , err = clb .lbClient .AwaitWorkRequest (ctx , wrID )
1739+ if err != nil {
1740+ return errors .Wrap (err , "failed to await updateloadbalancer work request" )
1741+ }
1742+
1743+ logger := clb .logger .With ("opc-workrequest-id" , wrID , "loadBalancerID" , lb .Id )
1744+ logger .Info ("UpdateLoadBalancer request to add oke system tags completed successfully" )
1745+ return nil
1746+ }
1747+
16511748// Given an OCI load balancer, return a LoadBalancerStatus
16521749func loadBalancerToStatus (lb * client.GenericLoadBalancer ) (* v1.LoadBalancerStatus , error ) {
16531750 if len (lb .IpAddresses ) == 0 {
0 commit comments