@@ -34,7 +34,9 @@ import (
34
34
"k8s.io/klog/v2"
35
35
"k8s.io/utils/pointer"
36
36
"sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader"
37
+ azcache "sigs.k8s.io/cloud-provider-azure/pkg/cache"
37
38
azure "sigs.k8s.io/cloud-provider-azure/pkg/provider"
39
+ "sigs.k8s.io/cloud-provider-azure/pkg/retry"
38
40
)
39
41
40
42
const (
@@ -170,9 +172,10 @@ func getKubeConfig(kubeconfig string, enableWindowsHostProcess bool) (config *re
170
172
return config , err
171
173
}
172
174
173
- func (d * Driver ) updateSubnetServiceEndpoints (ctx context.Context , vnetResourceGroup , vnetName , subnetName string ) error {
175
+ func (d * Driver ) updateSubnetServiceEndpoints (ctx context.Context , vnetResourceGroup , vnetName , subnetName string ) ([]string , error ) {
176
+ var vnetResourceIDs []string
174
177
if d .cloud .SubnetsClient == nil {
175
- return fmt .Errorf ("SubnetsClient is nil" )
178
+ return vnetResourceIDs , fmt .Errorf ("SubnetsClient is nil" )
176
179
}
177
180
178
181
if vnetResourceGroup == "" {
@@ -186,55 +189,89 @@ func (d *Driver) updateSubnetServiceEndpoints(ctx context.Context, vnetResourceG
186
189
if vnetName == "" {
187
190
vnetName = d .cloud .VnetName
188
191
}
189
- if subnetName == "" {
190
- subnetName = d .cloud .SubnetName
191
- }
192
192
193
193
klog .V (2 ).Infof ("updateSubnetServiceEndpoints on vnetName: %s, subnetName: %s, location: %s" , vnetName , subnetName , location )
194
- if subnetName == "" || vnetName == "" || location == "" {
195
- return fmt .Errorf ("value of subnetName, vnetName or location is empty" )
194
+ if vnetName == "" || location == "" {
195
+ return vnetResourceIDs , fmt .Errorf ("vnetName or location is empty" )
196
196
}
197
197
198
198
lockKey := vnetResourceGroup + vnetName + subnetName
199
- d .subnetLockMap .LockEntry (lockKey )
200
- defer d .subnetLockMap .UnlockEntry (lockKey )
201
-
202
- subnet , err := d .cloud .SubnetsClient .Get (ctx , vnetResourceGroup , vnetName , subnetName , "" )
199
+ cache , err := d .subnetCache .Get (lockKey , azcache .CacheReadTypeDefault )
203
200
if err != nil {
204
- return fmt .Errorf ("failed to get the subnet %s under vnet %s: %v" , subnetName , vnetName , err )
205
- }
206
- endpointLocaions := []string {location }
207
- storageServiceEndpoint := network.ServiceEndpointPropertiesFormat {
208
- Service : & storageService ,
209
- Locations : & endpointLocaions ,
210
- }
211
- storageServiceExists := false
212
- if subnet .SubnetPropertiesFormat == nil {
213
- subnet .SubnetPropertiesFormat = & network.SubnetPropertiesFormat {}
201
+ return nil , err
214
202
}
215
- if subnet .SubnetPropertiesFormat .ServiceEndpoints == nil {
216
- subnet .SubnetPropertiesFormat .ServiceEndpoints = & []network.ServiceEndpointPropertiesFormat {}
203
+ if cache != nil {
204
+ vnetResourceIDs = cache .([]string )
205
+ klog .V (2 ).Infof ("subnet %s under vnet %s in rg %s is already updated, vnetResourceIDs: %v" , subnetName , vnetName , vnetResourceGroup , vnetResourceIDs )
206
+ return vnetResourceIDs , nil
217
207
}
218
- serviceEndpoints := * subnet .SubnetPropertiesFormat .ServiceEndpoints
219
- for _ , v := range serviceEndpoints {
220
- if strings .HasPrefix (pointer .StringDeref (v .Service , "" ), storageService ) {
221
- storageServiceExists = true
222
- klog .V (4 ).Infof ("serviceEndpoint(%s) is already in subnet(%s)" , storageService , subnetName )
223
- break
208
+
209
+ d .subnetLockMap .LockEntry (lockKey )
210
+ defer d .subnetLockMap .UnlockEntry (lockKey )
211
+
212
+ var subnets []network.Subnet
213
+ if subnetName != "" {
214
+ // list multiple subnets separated by comma
215
+ subnetNames := strings .Split (subnetName , "," )
216
+ for _ , sn := range subnetNames {
217
+ sn = strings .TrimSpace (sn )
218
+ subnet , rerr := d .cloud .SubnetsClient .Get (ctx , vnetResourceGroup , vnetName , sn , "" )
219
+ if rerr != nil {
220
+ return vnetResourceIDs , fmt .Errorf ("failed to get the subnet %s under rg %s vnet %s: %v" , subnetName , vnetResourceGroup , vnetName , rerr .Error ())
221
+ }
222
+ subnets = append (subnets , subnet )
223
+ }
224
+ } else {
225
+ var rerr * retry.Error
226
+ subnets , rerr = d .cloud .SubnetsClient .List (ctx , vnetResourceGroup , vnetName )
227
+ if rerr != nil {
228
+ return vnetResourceIDs , fmt .Errorf ("failed to list the subnets under rg %s vnet %s: %v" , vnetResourceGroup , vnetName , rerr .Error ())
224
229
}
225
230
}
226
231
227
- if ! storageServiceExists {
228
- serviceEndpoints = append (serviceEndpoints , storageServiceEndpoint )
229
- subnet .SubnetPropertiesFormat .ServiceEndpoints = & serviceEndpoints
232
+ for _ , subnet := range subnets {
233
+ if subnet .Name == nil {
234
+ return vnetResourceIDs , fmt .Errorf ("subnet name is nil" )
235
+ }
236
+ sn := * subnet .Name
237
+ vnetResourceID := d .getSubnetResourceID (vnetResourceGroup , vnetName , sn )
238
+ klog .V (2 ).Infof ("set vnetResourceID %s" , vnetResourceID )
239
+ vnetResourceIDs = append (vnetResourceIDs , vnetResourceID )
240
+
241
+ endpointLocaions := []string {location }
242
+ storageServiceEndpoint := network.ServiceEndpointPropertiesFormat {
243
+ Service : & storageService ,
244
+ Locations : & endpointLocaions ,
245
+ }
246
+ storageServiceExists := false
247
+ if subnet .SubnetPropertiesFormat == nil {
248
+ subnet .SubnetPropertiesFormat = & network.SubnetPropertiesFormat {}
249
+ }
250
+ if subnet .SubnetPropertiesFormat .ServiceEndpoints == nil {
251
+ subnet .SubnetPropertiesFormat .ServiceEndpoints = & []network.ServiceEndpointPropertiesFormat {}
252
+ }
253
+ serviceEndpoints := * subnet .SubnetPropertiesFormat .ServiceEndpoints
254
+ for _ , v := range serviceEndpoints {
255
+ if strings .HasPrefix (pointer .StringDeref (v .Service , "" ), storageService ) {
256
+ storageServiceExists = true
257
+ klog .V (4 ).Infof ("serviceEndpoint(%s) is already in subnet(%s)" , storageService , sn )
258
+ break
259
+ }
260
+ }
261
+
262
+ if ! storageServiceExists {
263
+ serviceEndpoints = append (serviceEndpoints , storageServiceEndpoint )
264
+ subnet .SubnetPropertiesFormat .ServiceEndpoints = & serviceEndpoints
230
265
231
- if err := d .cloud .SubnetsClient .CreateOrUpdate (ctx , vnetResourceGroup , vnetName , subnetName , subnet ); err != nil {
232
- return fmt .Errorf ("failed to update the subnet %s under vnet %s: %v" , subnetName , vnetName , err )
266
+ klog .V (2 ).Infof ("begin to update the subnet %s under vnet %s in rg %s" , sn , vnetName , vnetResourceGroup )
267
+ if err := d .cloud .SubnetsClient .CreateOrUpdate (ctx , vnetResourceGroup , vnetName , sn , subnet ); err != nil {
268
+ return vnetResourceIDs , fmt .Errorf ("failed to update the subnet %s under vnet %s: %v" , sn , vnetName , err )
269
+ }
233
270
}
234
- klog .V (2 ).Infof ("serviceEndpoint(%s) is appended in subnet(%s)" , storageService , subnetName )
235
271
}
236
-
237
- return nil
272
+ // cache the subnet update
273
+ d .subnetCache .Set (lockKey , vnetResourceIDs )
274
+ return vnetResourceIDs , nil
238
275
}
239
276
240
277
// inClusterConfig is copied from https://github.com/kubernetes/client-go/blob/b46677097d03b964eab2d67ffbb022403996f4d4/rest/config.go#L507-L541
0 commit comments