@@ -21,6 +21,7 @@ import (
21
21
"zotregistry.io/zot/pkg/api/config"
22
22
ext "zotregistry.io/zot/pkg/extensions"
23
23
extconf "zotregistry.io/zot/pkg/extensions/config"
24
+ "zotregistry.io/zot/pkg/extensions/lint"
24
25
"zotregistry.io/zot/pkg/extensions/monitoring"
25
26
"zotregistry.io/zot/pkg/log"
26
27
"zotregistry.io/zot/pkg/storage"
@@ -281,54 +282,11 @@ func (c *Controller) InitImageStore(reloadCtx context.Context) error {
281
282
if len (c .Config .Storage .SubPaths ) > 0 {
282
283
subPaths := c .Config .Storage .SubPaths
283
284
284
- subImageStore := make (map [string ]storage.ImageStore )
285
-
286
- // creating image store per subpaths
287
- for route , storageConfig := range subPaths {
288
- // no need to validate hard links work on s3
289
- if storageConfig .Dedupe && storageConfig .StorageDriver == nil {
290
- err := storage .ValidateHardLink (storageConfig .RootDirectory )
291
- if err != nil {
292
- c .Log .Warn ().Msg ("input storage root directory filesystem does not supports hardlinking, " +
293
- "disabling dedupe functionality" )
294
-
295
- storageConfig .Dedupe = false
296
- }
297
- }
285
+ subImageStore , err := c .getSubStore (subPaths , linter )
286
+ if err != nil {
287
+ c .Log .Error ().Err (err ).Msg ("controller: error getting sub image store" )
298
288
299
- if storageConfig .StorageDriver == nil {
300
- // false positive lint - linter does not implement Lint method
301
- // nolint: typecheck
302
- subImageStore [route ] = storage .NewImageStore (storageConfig .RootDirectory ,
303
- storageConfig .GC , storageConfig .GCDelay , storageConfig .Dedupe , storageConfig .Commit , c .Log , c .Metrics , linter )
304
- } else {
305
- storeName := fmt .Sprintf ("%v" , storageConfig .StorageDriver ["name" ])
306
- if storeName != storage .S3StorageDriverName {
307
- c .Log .Fatal ().Err (errors .ErrBadConfig ).Msgf ("unsupported storage driver: %s" , storageConfig .StorageDriver ["name" ])
308
- }
309
-
310
- // Init a Storager from connection string.
311
- store , err := factory .Create (storeName , storageConfig .StorageDriver )
312
- if err != nil {
313
- c .Log .Error ().Err (err ).Str ("rootDir" , storageConfig .RootDirectory ).Msg ("Unable to create s3 service" )
314
-
315
- return err
316
- }
317
-
318
- /* in the case of s3 c.Config.Storage.RootDirectory is used for caching blobs locally and
319
- c.Config.Storage.StorageDriver["rootdirectory"] is the actual rootDir in s3 */
320
- rootDir := "/"
321
- if c .Config .Storage .StorageDriver ["rootdirectory" ] != nil {
322
- rootDir = fmt .Sprintf ("%v" , c .Config .Storage .StorageDriver ["rootdirectory" ])
323
- }
324
-
325
- // false positive lint - linter does not implement Lint method
326
- // nolint: typecheck
327
- subImageStore [route ] = s3 .NewImageStore (rootDir , storageConfig .RootDirectory ,
328
- storageConfig .GC , storageConfig .GCDelay ,
329
- storageConfig .Dedupe , storageConfig .Commit , c .Log , c .Metrics , linter , store ,
330
- )
331
- }
289
+ return err
332
290
}
333
291
334
292
c .StoreController .SubStore = subImageStore
@@ -340,6 +298,100 @@ func (c *Controller) InitImageStore(reloadCtx context.Context) error {
340
298
return nil
341
299
}
342
300
301
+ func (c * Controller ) getSubStore (subPaths map [string ]config.StorageConfig ,
302
+ linter * lint.Linter ,
303
+ ) (map [string ]storage.ImageStore , error ) {
304
+ imgStoreMap := make (map [string ]storage.ImageStore , 0 )
305
+
306
+ subImageStore := make (map [string ]storage.ImageStore )
307
+
308
+ // creating image store per subpaths
309
+ for route , storageConfig := range subPaths {
310
+ // no need to validate hard links work on s3
311
+ if storageConfig .Dedupe && storageConfig .StorageDriver == nil {
312
+ err := storage .ValidateHardLink (storageConfig .RootDirectory )
313
+ if err != nil {
314
+ c .Log .Warn ().Msg ("input storage root directory filesystem does not supports hardlinking, " +
315
+ "disabling dedupe functionality" )
316
+
317
+ storageConfig .Dedupe = false
318
+ }
319
+ }
320
+
321
+ if storageConfig .StorageDriver == nil {
322
+ // Compare if subpath root dir is same as default root dir
323
+ isSame , _ := config .SameFile (c .Config .Storage .RootDirectory , storageConfig .RootDirectory )
324
+
325
+ if isSame {
326
+ c .Log .Error ().Err (errors .ErrBadConfig ).Msg ("sub path storage directory is same as root directory" )
327
+
328
+ return nil , errors .ErrBadConfig
329
+ }
330
+
331
+ isUnique := true
332
+
333
+ // Compare subpath unique files
334
+ for file := range imgStoreMap {
335
+ // We already have image storage for this file
336
+ if compareImageStore (file , storageConfig .RootDirectory ) {
337
+ subImageStore [route ] = imgStoreMap [file ]
338
+
339
+ isUnique = true
340
+ }
341
+ }
342
+
343
+ // subpath root directory is unique
344
+ // add it to uniqueSubFiles
345
+ // Create a new image store and assign it to imgStoreMap
346
+ if isUnique {
347
+ imgStoreMap [storageConfig .RootDirectory ] = storage .NewImageStore (storageConfig .RootDirectory ,
348
+ storageConfig .GC , storageConfig .GCDelay , storageConfig .Dedupe , storageConfig .Commit , c .Log , c .Metrics , linter )
349
+
350
+ subImageStore [route ] = imgStoreMap [storageConfig .RootDirectory ]
351
+ }
352
+ } else {
353
+ storeName := fmt .Sprintf ("%v" , storageConfig .StorageDriver ["name" ])
354
+ if storeName != storage .S3StorageDriverName {
355
+ c .Log .Fatal ().Err (errors .ErrBadConfig ).Msgf ("unsupported storage driver: %s" , storageConfig .StorageDriver ["name" ])
356
+ }
357
+
358
+ // Init a Storager from connection string.
359
+ store , err := factory .Create (storeName , storageConfig .StorageDriver )
360
+ if err != nil {
361
+ c .Log .Error ().Err (err ).Str ("rootDir" , storageConfig .RootDirectory ).Msg ("Unable to create s3 service" )
362
+
363
+ return nil , err
364
+ }
365
+
366
+ /* in the case of s3 c.Config.Storage.RootDirectory is used for caching blobs locally and
367
+ c.Config.Storage.StorageDriver["rootdirectory"] is the actual rootDir in s3 */
368
+ rootDir := "/"
369
+ if c .Config .Storage .StorageDriver ["rootdirectory" ] != nil {
370
+ rootDir = fmt .Sprintf ("%v" , c .Config .Storage .StorageDriver ["rootdirectory" ])
371
+ }
372
+
373
+ // false positive lint - linter does not implement Lint method
374
+ // nolint: typecheck
375
+ subImageStore [route ] = s3 .NewImageStore (rootDir , storageConfig .RootDirectory ,
376
+ storageConfig .GC , storageConfig .GCDelay ,
377
+ storageConfig .Dedupe , storageConfig .Commit , c .Log , c .Metrics , linter , store ,
378
+ )
379
+ }
380
+ }
381
+
382
+ return subImageStore , nil
383
+ }
384
+
385
+ func compareImageStore (root1 , root2 string ) bool {
386
+ isSameFile , err := config .SameFile (root1 , root2 )
387
+ // This error is path error that means either of root directory doesn't exist, in that case do string match
388
+ if err != nil {
389
+ return strings .EqualFold (root1 , root2 )
390
+ }
391
+
392
+ return isSameFile
393
+ }
394
+
343
395
func (c * Controller ) LoadNewConfig (reloadCtx context.Context , config * config.Config ) {
344
396
// reload access control config
345
397
c .Config .AccessControl = config .AccessControl
0 commit comments