@@ -30,6 +30,58 @@ import (
30
30
storageTypes "zotregistry.dev/zot/pkg/storage/types"
31
31
)
32
32
33
+ // Platform represents an OS/architecture combination
34
+ type Platform struct {
35
+ OS string
36
+ Architecture string
37
+ }
38
+
39
+ // ParsePlatform parses a platform string into a Platform struct
40
+ // The string can be in the format "os/arch" or just "arch"
41
+ func ParsePlatform (platform string ) Platform {
42
+ parts := strings .Split (platform , "/" )
43
+ if len (parts ) == 2 {
44
+ return Platform {
45
+ OS : parts [0 ],
46
+ Architecture : parts [1 ],
47
+ }
48
+ }
49
+ // If only one part, assume it's the architecture
50
+ return Platform {
51
+ OS : "" ,
52
+ Architecture : platform ,
53
+ }
54
+ }
55
+
56
+ // MatchesPlatform checks if the given platform matches any of the platform specifications
57
+ // Platform specs can be in format "os/arch" or just "arch"
58
+ func MatchesPlatform (platform * ispec.Platform , platformSpecs []string ) bool {
59
+ if platform == nil || len (platformSpecs ) == 0 {
60
+ return true
61
+ }
62
+
63
+ for _ , spec := range platformSpecs {
64
+ specPlatform := ParsePlatform (spec )
65
+
66
+ // Check if architecture matches
67
+ if specPlatform .Architecture != "" &&
68
+ specPlatform .Architecture != platform .Architecture {
69
+ continue
70
+ }
71
+
72
+ // Check if OS matches (if specified)
73
+ if specPlatform .OS != "" &&
74
+ specPlatform .OS != platform .OS {
75
+ continue
76
+ }
77
+
78
+ // If we got here, it's a match
79
+ return true
80
+ }
81
+
82
+ return false
83
+ }
84
+
33
85
type DestinationRegistry struct {
34
86
storeController storage.StoreController
35
87
tempStorage OciLayoutStorage
@@ -236,33 +288,46 @@ func (registry *DestinationRegistry) copyManifest(repo string, desc ispec.Descri
236
288
return err
237
289
}
238
290
239
- // Filter manifests based on architectures if configured
291
+ // Filter manifests based on platforms/ architectures if configured
240
292
var filteredManifests []ispec.Descriptor
241
- if registry .config != nil && len (registry .config .Architectures ) > 0 {
242
- registry .log .Info ().
243
- Strs ("architectures" , registry .config .Architectures ).
244
- Str ("repository" , repo ).
245
- Str ("reference" , reference ).
246
- Msg ("filtering manifest list by architectures" )
247
293
248
- for _ , manifest := range indexManifest .Manifests {
249
- if manifest .Platform != nil && manifest .Platform .Architecture != "" {
250
- // Check if this architecture should be included
251
- shouldInclude := false
252
- for _ , configArch := range registry .config .Architectures {
253
- if manifest .Platform .Architecture == configArch {
254
- shouldInclude = true
255
- break
256
- }
257
- }
294
+ // Determine which platform specifications to use
295
+ var platformSpecs []string
296
+ if registry .config != nil {
297
+ if len (registry .config .Platforms ) > 0 {
298
+ platformSpecs = registry .config .Platforms
299
+ registry .log .Info ().
300
+ Strs ("platforms" , registry .config .Platforms ).
301
+ Str ("repository" , repo ).
302
+ Str ("reference" , reference ).
303
+ Msg ("filtering manifest list by platforms" )
304
+ } else if len (registry .config .Architectures ) > 0 {
305
+ platformSpecs = registry .config .Architectures
306
+ registry .log .Info ().
307
+ Strs ("architectures" , registry .config .Architectures ).
308
+ Str ("repository" , repo ).
309
+ Str ("reference" , reference ).
310
+ Msg ("filtering manifest list by architectures (deprecated)" )
311
+ }
312
+ }
258
313
259
- if shouldInclude {
314
+ // Apply filtering if we have platform specifications
315
+ if len (platformSpecs ) > 0 {
316
+ for _ , manifest := range indexManifest .Manifests {
317
+ if manifest .Platform != nil {
318
+ // Check if this platform should be included
319
+ if MatchesPlatform (manifest .Platform , platformSpecs ) {
260
320
filteredManifests = append (filteredManifests , manifest )
261
321
} else {
322
+ platformDesc := manifest .Platform .Architecture
323
+ if manifest .Platform .OS != "" {
324
+ platformDesc = manifest .Platform .OS + "/" + manifest .Platform .Architecture
325
+ }
326
+
262
327
registry .log .Info ().
263
328
Str ("repository" , repo ).
264
- Str ("architecture " , manifest . Platform . Architecture ).
265
- Msg ("skipping architecture during sync" )
329
+ Str ("platform " , platformDesc ).
330
+ Msg ("skipping platform during sync" )
266
331
}
267
332
} else {
268
333
// No platform info, include the manifest
@@ -275,7 +340,7 @@ func (registry *DestinationRegistry) copyManifest(repo string, desc ispec.Descri
275
340
registry .log .Warn ().
276
341
Str ("repository" , repo ).
277
342
Str ("reference" , reference ).
278
- Msg ("no architecture matched the configured filters, manifest list might be empty" )
343
+ Msg ("no platform matched the configured filters, manifest list might be empty" )
279
344
}
280
345
} else {
281
346
// No filtering, use all manifests
@@ -311,7 +376,8 @@ func (registry *DestinationRegistry) copyManifest(repo string, desc ispec.Descri
311
376
}
312
377
313
378
// If we've filtered the manifest list, we need to update it
314
- if registry .config != nil && len (registry .config .Architectures ) > 0 &&
379
+ if registry .config != nil &&
380
+ (len (registry .config .Architectures ) > 0 || len (registry .config .Platforms ) > 0 ) &&
315
381
len (filteredManifests ) != len (indexManifest .Manifests ) && len (filteredManifests ) > 0 {
316
382
// Create a new index with the filtered manifests
317
383
indexManifest .Manifests = filteredManifests
0 commit comments