@@ -31,8 +31,10 @@ import (
3131 "k8s.io/klog/v2"
3232 "k8s.io/utils/pointer"
3333 "sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader"
34+ azcache "sigs.k8s.io/cloud-provider-azure/pkg/cache"
3435 azure "sigs.k8s.io/cloud-provider-azure/pkg/provider"
3536 providerconfig "sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
37+ "sigs.k8s.io/cloud-provider-azure/pkg/retry"
3638)
3739
3840var (
@@ -181,9 +183,10 @@ func (d *Driver) getKeyvaultToken() (authorizer autorest.Authorizer, err error)
181183 return authorizer , nil
182184}
183185
184- func (d * Driver ) updateSubnetServiceEndpoints (ctx context.Context , vnetResourceGroup , vnetName , subnetName string ) error {
186+ func (d * Driver ) updateSubnetServiceEndpoints (ctx context.Context , vnetResourceGroup , vnetName , subnetName string ) ([]string , error ) {
187+ var vnetResourceIDs []string
185188 if d .cloud .SubnetsClient == nil {
186- return fmt .Errorf ("SubnetsClient is nil" )
189+ return vnetResourceIDs , fmt .Errorf ("SubnetsClient is nil" )
187190 }
188191
189192 if vnetResourceGroup == "" {
@@ -197,56 +200,89 @@ func (d *Driver) updateSubnetServiceEndpoints(ctx context.Context, vnetResourceG
197200 if vnetName == "" {
198201 vnetName = d .cloud .VnetName
199202 }
200- if subnetName == "" {
201- subnetName = d .cloud .SubnetName
202- }
203203
204204 klog .V (2 ).Infof ("updateSubnetServiceEndpoints on vnetName: %s, subnetName: %s, location: %s" , vnetName , subnetName , location )
205- if subnetName == "" || vnetName == "" || location == "" {
206- return fmt .Errorf ("value of subnetName, vnetName or location is empty" )
205+ if vnetName == "" || location == "" {
206+ return vnetResourceIDs , fmt .Errorf ("vnetName or location is empty" )
207207 }
208208
209209 lockKey := vnetResourceGroup + vnetName + subnetName
210- d .subnetLockMap .LockEntry (lockKey )
211- defer d .subnetLockMap .UnlockEntry (lockKey )
212-
213- subnet , err := d .cloud .SubnetsClient .Get (ctx , vnetResourceGroup , vnetName , subnetName , "" )
210+ cache , err := d .subnetCache .Get (lockKey , azcache .CacheReadTypeDefault )
214211 if err != nil {
215- return fmt .Errorf ("failed to get the subnet %s under vnet %s: %v" , subnetName , vnetName , err )
216- }
217- endpointLocaions := []string {location }
218- storageServiceEndpoint := network.ServiceEndpointPropertiesFormat {
219- Service : & storageService ,
220- Locations : & endpointLocaions ,
221- }
222- storageServiceExists := false
223- if subnet .SubnetPropertiesFormat == nil {
224- subnet .SubnetPropertiesFormat = & network.SubnetPropertiesFormat {}
212+ return nil , err
225213 }
226- if subnet .SubnetPropertiesFormat .ServiceEndpoints == nil {
227- subnet .SubnetPropertiesFormat .ServiceEndpoints = & []network.ServiceEndpointPropertiesFormat {}
214+ if cache != nil {
215+ vnetResourceIDs = cache .([]string )
216+ klog .V (2 ).Infof ("subnet %s under vnet %s in rg %s is already updated, vnetResourceIDs: %v" , subnetName , vnetName , vnetResourceGroup , vnetResourceIDs )
217+ return vnetResourceIDs , nil
228218 }
229- serviceEndpoints := * subnet .SubnetPropertiesFormat .ServiceEndpoints
230- for _ , v := range serviceEndpoints {
231- if strings .HasPrefix (pointer .StringDeref (v .Service , "" ), storageService ) {
232- storageServiceExists = true
233- klog .V (4 ).Infof ("serviceEndpoint(%s) is already in subnet(%s)" , storageService , subnetName )
234- break
219+
220+ d .subnetLockMap .LockEntry (lockKey )
221+ defer d .subnetLockMap .UnlockEntry (lockKey )
222+
223+ var subnets []network.Subnet
224+ if subnetName != "" {
225+ // list multiple subnets separated by comma
226+ subnetNames := strings .Split (subnetName , "," )
227+ for _ , sn := range subnetNames {
228+ sn = strings .TrimSpace (sn )
229+ subnet , rerr := d .cloud .SubnetsClient .Get (ctx , vnetResourceGroup , vnetName , sn , "" )
230+ if rerr != nil {
231+ return vnetResourceIDs , fmt .Errorf ("failed to get the subnet %s under rg %s vnet %s: %v" , subnetName , vnetResourceGroup , vnetName , rerr .Error ())
232+ }
233+ subnets = append (subnets , subnet )
234+ }
235+ } else {
236+ var rerr * retry.Error
237+ subnets , rerr = d .cloud .SubnetsClient .List (ctx , vnetResourceGroup , vnetName )
238+ if rerr != nil {
239+ return vnetResourceIDs , fmt .Errorf ("failed to list the subnets under rg %s vnet %s: %v" , vnetResourceGroup , vnetName , rerr .Error ())
235240 }
236241 }
237242
238- if ! storageServiceExists {
239- serviceEndpoints = append (serviceEndpoints , storageServiceEndpoint )
240- subnet .SubnetPropertiesFormat .ServiceEndpoints = & serviceEndpoints
243+ for _ , subnet := range subnets {
244+ if subnet .Name == nil {
245+ return vnetResourceIDs , fmt .Errorf ("subnet name is nil" )
246+ }
247+ sn := * subnet .Name
248+ vnetResourceID := d .getSubnetResourceID (vnetResourceGroup , vnetName , sn )
249+ klog .V (2 ).Infof ("set vnetResourceID %s" , vnetResourceID )
250+ vnetResourceIDs = append (vnetResourceIDs , vnetResourceID )
251+
252+ endpointLocaions := []string {location }
253+ storageServiceEndpoint := network.ServiceEndpointPropertiesFormat {
254+ Service : & storageService ,
255+ Locations : & endpointLocaions ,
256+ }
257+ storageServiceExists := false
258+ if subnet .SubnetPropertiesFormat == nil {
259+ subnet .SubnetPropertiesFormat = & network.SubnetPropertiesFormat {}
260+ }
261+ if subnet .SubnetPropertiesFormat .ServiceEndpoints == nil {
262+ subnet .SubnetPropertiesFormat .ServiceEndpoints = & []network.ServiceEndpointPropertiesFormat {}
263+ }
264+ serviceEndpoints := * subnet .SubnetPropertiesFormat .ServiceEndpoints
265+ for _ , v := range serviceEndpoints {
266+ if strings .HasPrefix (pointer .StringDeref (v .Service , "" ), storageService ) {
267+ storageServiceExists = true
268+ klog .V (4 ).Infof ("serviceEndpoint(%s) is already in subnet(%s)" , storageService , sn )
269+ break
270+ }
271+ }
272+
273+ if ! storageServiceExists {
274+ serviceEndpoints = append (serviceEndpoints , storageServiceEndpoint )
275+ subnet .SubnetPropertiesFormat .ServiceEndpoints = & serviceEndpoints
241276
242- klog .V (2 ).Infof ("begin to update the subnet %s under vnet %s rg %s" , subnetName , vnetName , vnetResourceGroup )
243- if err := d .cloud .SubnetsClient .CreateOrUpdate (ctx , vnetResourceGroup , vnetName , subnetName , subnet ); err != nil {
244- return fmt .Errorf ("failed to update the subnet %s under vnet %s: %v" , subnetName , vnetName , err )
277+ klog .V (2 ).Infof ("begin to update the subnet %s under vnet %s in rg %s" , sn , vnetName , vnetResourceGroup )
278+ if err := d .cloud .SubnetsClient .CreateOrUpdate (ctx , vnetResourceGroup , vnetName , sn , subnet ); err != nil {
279+ return vnetResourceIDs , fmt .Errorf ("failed to update the subnet %s under vnet %s: %v" , sn , vnetName , err )
280+ }
245281 }
246- klog .V (2 ).Infof ("serviceEndpoint(%s) is appended in subnet(%s)" , storageService , subnetName )
247282 }
248-
249- return nil
283+ // cache the subnet update
284+ d .subnetCache .Set (lockKey , vnetResourceIDs )
285+ return vnetResourceIDs , nil
250286}
251287
252288func (d * Driver ) getStorageEndPointSuffix () string {
0 commit comments