@@ -38,7 +38,6 @@ import (
38
38
39
39
"github.com/containerd/nerdctl/v2/pkg/api/types"
40
40
"github.com/containerd/nerdctl/v2/pkg/labels"
41
- "github.com/containerd/nerdctl/v2/pkg/lockutil"
42
41
"github.com/containerd/nerdctl/v2/pkg/netutil/nettype"
43
42
subnetutil "github.com/containerd/nerdctl/v2/pkg/netutil/subnet"
44
43
"github.com/containerd/nerdctl/v2/pkg/strutil"
@@ -53,14 +52,7 @@ type CNIEnv struct {
53
52
type CNIEnvOpt func (e * CNIEnv ) error
54
53
55
54
func (e * CNIEnv ) ListNetworksMatch (reqs []string , allowPseudoNetwork bool ) (list map [string ][]* NetworkConfig , errs []error ) {
56
- var err error
57
-
58
- var networkConfigs []* NetworkConfig
59
- // NOTE: we cannot lock NetconfPath directly, as Cilium (maybe others) are also locking it.
60
- err = lockutil .WithDirLock (filepath .Join (e .NetconfPath , ".nerdctl.lock" ), func () error {
61
- networkConfigs , err = e .networkConfigList ()
62
- return err
63
- })
55
+ networkConfigs , err := fsRead (e )
64
56
if err != nil {
65
57
return nil , []error {err }
66
58
}
@@ -188,7 +180,8 @@ func WithDefaultNetwork(bridgeIP string) CNIEnvOpt {
188
180
189
181
func WithNamespace (namespace string ) CNIEnvOpt {
190
182
return func (e * CNIEnv ) error {
191
- if err := os .MkdirAll (filepath .Join (e .NetconfPath , namespace ), 0755 ); err != nil {
183
+ err := fsEnsureRoot (e , namespace )
184
+ if err != nil {
192
185
return err
193
186
}
194
187
e .Namespace = namespace
@@ -201,7 +194,8 @@ func NewCNIEnv(cniPath, cniConfPath string, opts ...CNIEnvOpt) (*CNIEnv, error)
201
194
Path : cniPath ,
202
195
NetconfPath : cniConfPath ,
203
196
}
204
- if err := os .MkdirAll (e .NetconfPath , 0755 ); err != nil {
197
+
198
+ if err := fsEnsureRoot (& e , "" ); err != nil {
205
199
return nil , err
206
200
}
207
201
@@ -215,25 +209,17 @@ func NewCNIEnv(cniPath, cniConfPath string, opts ...CNIEnvOpt) (*CNIEnv, error)
215
209
}
216
210
217
211
func (e * CNIEnv ) NetworkList () ([]* NetworkConfig , error ) {
218
- var netConfigList []* NetworkConfig
219
- var err error
220
- fn := func () error {
221
- netConfigList , err = e .networkConfigList ()
222
- return err
223
- }
224
- err = lockutil .WithDirLock (filepath .Join (e .NetconfPath , ".nerdctl.lock" ), fn )
225
-
226
- return netConfigList , err
212
+ return fsRead (e )
227
213
}
228
214
229
215
func (e * CNIEnv ) NetworkMap () (map [string ]* NetworkConfig , error ) { //nolint:revive
230
- networks , err := e . networkConfigList ( )
216
+ netConfigList , err := fsRead ( e )
231
217
if err != nil {
232
218
return nil , err
233
219
}
234
220
235
- m := make (map [string ]* NetworkConfig , len (networks ))
236
- for _ , n := range networks {
221
+ m := make (map [string ]* NetworkConfig , len (netConfigList ))
222
+ for _ , n := range netConfigList {
237
223
if original , exists := m [n .Name ]; exists {
238
224
log .L .Warnf ("duplicate network name %q, %#v will get superseded by %#v" , n .Name , original , n )
239
225
}
@@ -243,12 +229,12 @@ func (e *CNIEnv) NetworkMap() (map[string]*NetworkConfig, error) { //nolint:revi
243
229
}
244
230
245
231
func (e * CNIEnv ) NetworkByNameOrID (key string ) (* NetworkConfig , error ) {
246
- networks , err := e . networkConfigList ( )
232
+ netConfigList , err := fsRead ( e )
247
233
if err != nil {
248
234
return nil , err
249
235
}
250
236
251
- for _ , n := range networks {
237
+ for _ , n := range netConfigList {
252
238
if n .Name == key {
253
239
return n , nil
254
240
}
@@ -261,36 +247,31 @@ func (e *CNIEnv) NetworkByNameOrID(key string) (*NetworkConfig, error) {
261
247
}
262
248
263
249
func (e * CNIEnv ) filterNetworks (filterf func (* NetworkConfig ) bool ) ([]* NetworkConfig , error ) {
264
- networkConfigs , err := e . networkConfigList ( )
250
+ netConfigList , err := fsRead ( e )
265
251
if err != nil {
266
252
return nil , err
267
253
}
268
254
result := []* NetworkConfig {}
269
- for _ , networkConfig := range networkConfigs {
255
+ for _ , networkConfig := range netConfigList {
270
256
if filterf (networkConfig ) {
271
257
result = append (result , networkConfig )
272
258
}
273
259
}
274
260
return result , nil
275
261
}
276
262
277
- func (e * CNIEnv ) getConfigPathForNetworkName (netName string ) string {
278
- if netName == DefaultNetworkName || e .Namespace == "" {
279
- return filepath .Join (e .NetconfPath , "nerdctl-" + netName + ".conflist" )
280
- }
281
- return filepath .Join (e .NetconfPath , e .Namespace , "nerdctl-" + netName + ".conflist" )
282
- }
283
-
284
263
func (e * CNIEnv ) usedSubnets () ([]* net.IPNet , error ) {
285
264
usedSubnets , err := subnetutil .GetLiveNetworkSubnets ()
286
265
if err != nil {
287
266
return nil , err
288
267
}
289
- networkConfigs , err := e .networkConfigList ()
268
+
269
+ netConfigList , err := fsRead (e )
290
270
if err != nil {
291
271
return nil , err
292
272
}
293
- for _ , netConf := range networkConfigs {
273
+
274
+ for _ , netConf := range netConfigList {
294
275
usedSubnets = append (usedSubnets , netConf .subnets ()... )
295
276
}
296
277
return usedSubnets , nil
@@ -314,44 +295,39 @@ type cniNetworkConfig struct {
314
295
func (e * CNIEnv ) CreateNetwork (opts types.NetworkCreateOptions ) (* NetworkConfig , error ) { //nolint:revive
315
296
var netConf * NetworkConfig
316
297
317
- fn := func () error {
318
- netMap , err := e .NetworkMap ()
319
- if err != nil {
320
- return err
321
- }
298
+ netMap , err := e .NetworkMap ()
299
+ if err != nil {
300
+ return nil , err
301
+ }
322
302
323
- if _ , ok := netMap [opts .Name ]; ok {
324
- return errdefs .ErrAlreadyExists
325
- }
326
- ipam , err := e .generateIPAM (opts .IPAMDriver , opts .Subnets , opts .Gateway , opts .IPRange , opts .IPAMOptions , opts .IPv6 )
327
- if err != nil {
328
- return err
329
- }
330
- plugins , err := e .generateCNIPlugins (opts .Driver , opts .Name , ipam , opts .Options , opts .IPv6 )
331
- if err != nil {
332
- return err
333
- }
334
- netConf , err = e .generateNetworkConfig (opts .Name , opts .Labels , plugins )
335
- if err != nil {
336
- return err
337
- }
338
- return e .writeNetworkConfig (netConf )
303
+ // See note in fsWrite. Just because it does not exist now does not guarantee it will still not exist later.
304
+ // This is more a perf optimization at this point than a true check.
305
+ if _ , ok := netMap [opts .Name ]; ok {
306
+ return nil , errdefs .ErrAlreadyExists
339
307
}
340
- err := lockutil . WithDirLock ( filepath . Join ( e . NetconfPath , ".nerdctl.lock" ), fn )
308
+ ipam , err := e . generateIPAM ( opts . IPAMDriver , opts . Subnets , opts . Gateway , opts . IPRange , opts . IPAMOptions , opts . IPv6 )
341
309
if err != nil {
342
310
return nil , err
343
311
}
312
+ plugins , err := e .generateCNIPlugins (opts .Driver , opts .Name , ipam , opts .Options , opts .IPv6 )
313
+ if err != nil {
314
+ return nil , err
315
+ }
316
+ netConf , err = e .generateNetworkConfig (opts .Name , opts .Labels , plugins )
317
+ if err != nil {
318
+ return nil , err
319
+ }
320
+ err = fsWrite (e , netConf )
321
+
322
+ // See note above. If it exists, we got raced out by another process. Consider this to NOT be a hard error.
323
+ if err != nil && ! errdefs .IsAlreadyExists (err ) {
324
+ return nil , err
325
+ }
344
326
return netConf , nil
345
327
}
346
328
347
329
func (e * CNIEnv ) RemoveNetwork (net * NetworkConfig ) error {
348
- fn := func () error {
349
- if err := os .RemoveAll (net .File ); err != nil {
350
- return err
351
- }
352
- return net .clean ()
353
- }
354
- return lockutil .WithDirLock (filepath .Join (e .NetconfPath , ".nerdctl.lock" ), fn )
330
+ return fsRemove (e , net )
355
331
}
356
332
357
333
// GetDefaultNetworkConfig checks whether the default network exists
@@ -394,8 +370,8 @@ func (e *CNIEnv) GetDefaultNetworkConfig() (*NetworkConfig, error) {
394
370
395
371
// Warn the user if the default network was not created by nerdctl.
396
372
match := nameMatches [0 ]
397
- _ , statErr := os . Stat ( e . getConfigPathForNetworkName ( DefaultNetworkName ) )
398
- if match .NerdctlID == nil || statErr != nil {
373
+ exists , statErr := fsExists ( e , DefaultNetworkName )
374
+ if match .NerdctlID == nil || statErr != nil || ! exists {
399
375
log .L .Warnf ("default network named %q does not have an internal nerdctl ID or nerdctl-managed config file, it was most likely NOT created by nerdctl" , DefaultNetworkName )
400
376
}
401
377
@@ -419,9 +395,12 @@ func (e *CNIEnv) ensureDefaultNetworkConfig(bridgeIP string) error {
419
395
}
420
396
421
397
func (e * CNIEnv ) createDefaultNetworkConfig (bridgeIP string ) error {
422
- filename := e .getConfigPathForNetworkName (DefaultNetworkName )
423
- if _ , err := os .Stat (filename ); err == nil {
424
- return fmt .Errorf ("already found existing network config at %q, cannot create new network named %q" , filename , DefaultNetworkName )
398
+ exist , err := fsExists (e , DefaultNetworkName )
399
+ if err != nil && ! os .IsNotExist (err ) {
400
+ return err
401
+ }
402
+ if exist {
403
+ return fmt .Errorf ("already found existing network config, cannot create new network named %q" , DefaultNetworkName )
425
404
}
426
405
427
406
bridgeCIDR := DefaultCIDR
@@ -443,7 +422,7 @@ func (e *CNIEnv) createDefaultNetworkConfig(bridgeIP string) error {
443
422
Labels : []string {fmt .Sprintf ("%s=true" , labels .NerdctlDefaultNetwork )},
444
423
}
445
424
446
- _ , err : = e .CreateNetwork (opts )
425
+ _ , err = e .CreateNetwork (opts )
447
426
if err != nil && ! errdefs .IsAlreadyExists (err ) {
448
427
return err
449
428
}
@@ -490,31 +469,6 @@ func (e *CNIEnv) generateNetworkConfig(name string, labels []string, plugins []C
490
469
}, nil
491
470
}
492
471
493
- // writeNetworkConfig writes NetworkConfig file to cni config path.
494
- func (e * CNIEnv ) writeNetworkConfig (net * NetworkConfig ) error {
495
- filename := e .getConfigPathForNetworkName (net .Name )
496
- if _ , err := os .Stat (filename ); err == nil {
497
- return errdefs .ErrAlreadyExists
498
- }
499
- return os .WriteFile (filename , net .Bytes , 0644 )
500
- }
501
-
502
- // networkConfigList loads config from dir if dir exists.
503
- func (e * CNIEnv ) networkConfigList () ([]* NetworkConfig , error ) {
504
- common , err := libcni .ConfFiles (e .NetconfPath , []string {".conf" , ".conflist" , ".json" })
505
- if err != nil {
506
- return nil , err
507
- }
508
- namespaced := []string {}
509
- if e .Namespace != "" {
510
- namespaced , err = libcni .ConfFiles (filepath .Join (e .NetconfPath , e .Namespace ), []string {".conf" , ".conflist" , ".json" })
511
- if err != nil {
512
- return nil , err
513
- }
514
- }
515
- return cniLoad (append (common , namespaced ... ))
516
- }
517
-
518
472
func wrapCNIError (fileName string , err error ) error {
519
473
return fmt .Errorf ("failed marshalling json out of network configuration file %q: %w\n " +
520
474
"For details on the schema, see https://pkg.go.dev/github.com/containernetworking/cni/libcni#NetworkConfigList" , fileName , err )
0 commit comments