@@ -34,6 +34,7 @@ import (
3434 "time"
3535
3636 "github.com/containerd/accelerated-container-image/cmd/convertor/database"
37+ "github.com/containerd/accelerated-container-image/pkg/utils"
3738 "github.com/containerd/containerd/v2/core/images"
3839 "github.com/containerd/containerd/v2/core/remotes"
3940 "github.com/containerd/containerd/v2/core/remotes/docker"
@@ -73,6 +74,10 @@ type BuilderOptions struct {
7374
7475 // Push manifests with subject
7576 Referrer bool
77+
78+ // CustomResolver allows using a custom resolver instead of the default docker resolver
79+ // Used for tar import/export functionality
80+ CustomResolver remotes.Resolver
7681}
7782
7883type graphBuilder struct {
@@ -129,6 +134,16 @@ func (b *graphBuilder) Build(ctx context.Context) error {
129134}
130135
131136func (b * graphBuilder ) process (ctx context.Context , src v1.Descriptor , tag bool ) (v1.Descriptor , error ) {
137+ // Skip provenance and attestation manifests (check by platform and content)
138+ if src .Platform != nil && src .Platform .OS == "unknown" && src .Platform .Architecture == "unknown" {
139+ // This might be a provenance manifest, check if it should be skipped
140+ if utils .IsProvenanceDescriptor (src ) {
141+ log .G (ctx ).Infof ("skipping provenance manifest: %s (platform: %s/%s)" , src .Digest , src .Platform .OS , src .Platform .Architecture )
142+ // Return a special "skipped" descriptor instead of an error
143+ return v1.Descriptor {}, nil
144+ }
145+ }
146+
132147 switch src .MediaType {
133148 case v1 .MediaTypeImageManifest , images .MediaTypeDockerSchema2Manifest :
134149 return b .buildOne (ctx , src , tag )
@@ -147,24 +162,34 @@ func (b *graphBuilder) process(ctx context.Context, src v1.Descriptor, tag bool)
147162 return v1.Descriptor {}, fmt .Errorf ("failed to unmarshal index: %w" , err )
148163 }
149164 var wg sync.WaitGroup
150- for _i , _m := range index .Manifests {
151- i := _i
152- m := _m
165+ var mu sync.Mutex
166+ var filteredManifests []v1.Descriptor
167+
168+ for _ , m := range index .Manifests {
169+ manifest := m
153170 wg .Add (1 )
154171 b .group .Go (func () error {
155172 defer wg .Done ()
156- target , err := b .process (ctx , m , false )
173+ target , err := b .process (ctx , manifest , false )
157174 if err != nil {
158- return fmt .Errorf ("failed to build %q: %w" , m .Digest , err )
175+ return fmt .Errorf ("failed to build %q: %w" , manifest .Digest , err )
176+ }
177+ // Only add non-empty descriptors (skip provenance manifests)
178+ if target .Digest != "" {
179+ mu .Lock ()
180+ filteredManifests = append (filteredManifests , target )
181+ mu .Unlock ()
159182 }
160- index .Manifests [i ] = target
161183 return nil
162184 })
163185 }
164186 wg .Wait ()
165187 if ctx .Err () != nil {
166188 return v1.Descriptor {}, ctx .Err ()
167189 }
190+
191+ // Update index with only the non-provenance manifests
192+ index .Manifests = filteredManifests
168193
169194 // upload index
170195 if b .Referrer {
@@ -299,46 +324,55 @@ func (b *graphBuilder) buildOne(ctx context.Context, src v1.Descriptor, tag bool
299324}
300325
301326func Build (ctx context.Context , opt BuilderOptions ) error {
302- tlsConfig , err := loadTLSConfig (opt .CertOption )
303- if err != nil {
304- return fmt .Errorf ("failed to load certifications: %w" , err )
305- }
306- transport := & http.Transport {
307- DialContext : (& net.Dialer {
308- Timeout : 30 * time .Second ,
309- KeepAlive : 30 * time .Second ,
310- FallbackDelay : 300 * time .Millisecond ,
311- }).DialContext ,
312- MaxConnsPerHost : 32 , // max http concurrency
313- MaxIdleConns : 32 ,
314- IdleConnTimeout : 30 * time .Second ,
315- TLSHandshakeTimeout : 10 * time .Second ,
316- TLSClientConfig : tlsConfig ,
317- ExpectContinueTimeout : 5 * time .Second ,
318- }
319- client := & http.Client {Transport : transport }
320- resolver := docker .NewResolver (docker.ResolverOptions {
321- Hosts : docker .ConfigureDefaultRegistries (
322- docker .WithAuthorizer (docker .NewDockerAuthorizer (
323- docker .WithAuthClient (client ),
324- docker .WithAuthHeader (make (http.Header )),
325- docker .WithAuthCreds (func (s string ) (string , string , error ) {
326- if i := strings .IndexByte (opt .Auth , ':' ); i > 0 {
327- return opt .Auth [0 :i ], opt .Auth [i + 1 :], nil
327+ var resolver remotes.Resolver
328+
329+ // Use custom resolver if provided, otherwise create default docker resolver
330+ if opt .CustomResolver != nil {
331+ log .G (ctx ).Info ("using custom resolver (tar import mode)" )
332+ resolver = opt .CustomResolver
333+ } else {
334+ log .G (ctx ).Info ("using docker registry resolver" )
335+ tlsConfig , err := loadTLSConfig (opt .CertOption )
336+ if err != nil {
337+ return fmt .Errorf ("failed to load certifications: %w" , err )
338+ }
339+ transport := & http.Transport {
340+ DialContext : (& net.Dialer {
341+ Timeout : 30 * time .Second ,
342+ KeepAlive : 30 * time .Second ,
343+ FallbackDelay : 300 * time .Millisecond ,
344+ }).DialContext ,
345+ MaxConnsPerHost : 32 , // max http concurrency
346+ MaxIdleConns : 32 ,
347+ IdleConnTimeout : 30 * time .Second ,
348+ TLSHandshakeTimeout : 10 * time .Second ,
349+ TLSClientConfig : tlsConfig ,
350+ ExpectContinueTimeout : 5 * time .Second ,
351+ }
352+ client := & http.Client {Transport : transport }
353+ resolver = docker .NewResolver (docker.ResolverOptions {
354+ Hosts : docker .ConfigureDefaultRegistries (
355+ docker .WithAuthorizer (docker .NewDockerAuthorizer (
356+ docker .WithAuthClient (client ),
357+ docker .WithAuthHeader (make (http.Header )),
358+ docker .WithAuthCreds (func (s string ) (string , string , error ) {
359+ if i := strings .IndexByte (opt .Auth , ':' ); i > 0 {
360+ return opt .Auth [0 :i ], opt .Auth [i + 1 :], nil
361+ }
362+ return "" , "" , nil
363+ }),
364+ )),
365+ docker .WithClient (client ),
366+ docker .WithPlainHTTP (func (s string ) (bool , error ) {
367+ if opt .PlainHTTP {
368+ return docker .MatchAllHosts (s )
369+ } else {
370+ return false , nil
328371 }
329- return "" , "" , nil
330372 }),
331- )),
332- docker .WithClient (client ),
333- docker .WithPlainHTTP (func (s string ) (bool , error ) {
334- if opt .PlainHTTP {
335- return docker .MatchAllHosts (s )
336- } else {
337- return false , nil
338- }
339- }),
340- ),
341- })
373+ ),
374+ })
375+ }
342376
343377 return (& graphBuilder {
344378 Resolver : resolver ,
0 commit comments