Skip to content

Commit f05e3d6

Browse files
authored
Merge pull request #1 from runloopai/gautam-standalone-tar
Add tar import/export support
2 parents 453e5be + 4976db8 commit f05e3d6

File tree

5 files changed

+1064
-72
lines changed

5 files changed

+1064
-72
lines changed

cmd/convertor/builder/builder.go

Lines changed: 78 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -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

7883
type graphBuilder struct {
@@ -129,6 +134,16 @@ func (b *graphBuilder) Build(ctx context.Context) error {
129134
}
130135

131136
func (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

301326
func 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

Comments
 (0)