@@ -34,80 +34,98 @@ import (
34
34
"github.com/containerd/nerdctl/v2/pkg/platformutil"
35
35
)
36
36
37
- type readCounter struct {
38
- io.Reader
39
- N int
40
- }
41
-
42
- func (r * readCounter ) Read (p []byte ) (int , error ) {
43
- n , err := r .Reader .Read (p )
44
- if n > 0 {
45
- r .N += n
46
- }
47
- return n , err
48
- }
49
-
50
- func Load (ctx context.Context , client * containerd.Client , options types.ImageLoadOptions ) error {
37
+ // FromArchive loads and unpacks the images from the tar archive specified in image load options.
38
+ func FromArchive (ctx context.Context , client * containerd.Client , options types.ImageLoadOptions ) ([]images.Image , error ) {
51
39
if options .Input != "" {
52
40
f , err := os .Open (options .Input )
53
41
if err != nil {
54
- return err
42
+ return nil , err
55
43
}
56
44
defer f .Close ()
57
45
options .Stdin = f
58
46
} else {
59
47
// check if stdin is empty.
60
48
stdinStat , err := os .Stdin .Stat ()
61
49
if err != nil {
62
- return err
50
+ return nil , err
63
51
}
64
52
if stdinStat .Size () == 0 && (stdinStat .Mode ()& os .ModeNamedPipe ) == 0 {
65
- return errors .New ("stdin is empty and input flag is not specified" )
53
+ return nil , errors .New ("stdin is empty and input flag is not specified" )
66
54
}
67
55
}
68
56
decompressor , err := compression .DecompressStream (options .Stdin )
69
57
if err != nil {
70
- return err
58
+ return nil , err
71
59
}
72
60
platMC , err := platformutil .NewMatchComparer (options .AllPlatforms , options .Platform )
73
61
if err != nil {
74
- return err
62
+ return nil , err
63
+ }
64
+ imgs , err := importImages (ctx , client , decompressor , options .GOptions .Snapshotter , platMC )
65
+ if err != nil {
66
+ return nil , err
67
+ }
68
+ unpackedImages := make ([]images.Image , 0 , len (imgs ))
69
+ for _ , img := range imgs {
70
+ err := unpackImage (ctx , client , img , platMC , options )
71
+ if err != nil {
72
+ return unpackedImages , fmt .Errorf ("error unpacking image (%s): %w" , img .Name , err )
73
+ }
74
+ unpackedImages = append (unpackedImages , img )
75
+ }
76
+ return unpackedImages , nil
77
+ }
78
+
79
+ type readCounter struct {
80
+ io.Reader
81
+ N int
82
+ }
83
+
84
+ func (r * readCounter ) Read (p []byte ) (int , error ) {
85
+ n , err := r .Reader .Read (p )
86
+ if n > 0 {
87
+ r .N += n
75
88
}
76
- return loadImage ( ctx , client , decompressor , platMC , options )
89
+ return n , err
77
90
}
78
91
79
- func loadImage (ctx context.Context , client * containerd.Client , in io.Reader , platMC platforms. MatchComparer , options types. ImageLoadOptions ) error {
92
+ func importImages (ctx context.Context , client * containerd.Client , in io.Reader , snapshotter string , platformMC platforms. MatchComparer ) ([]images. Image , error ) {
80
93
// In addition to passing WithImagePlatform() to client.Import(), we also need to pass WithDefaultPlatform() to NewClient().
81
94
// Otherwise unpacking may fail.
82
95
r := & readCounter {Reader : in }
83
- imgs , err := client .Import (ctx , r , containerd .WithDigestRef (archive .DigestTranslator (options .GOptions .Snapshotter )), containerd .WithSkipDigestRef (func (name string ) bool { return name != "" }), containerd .WithImportPlatform (platMC ))
96
+ imgs , err := client .Import (ctx , r ,
97
+ containerd .WithDigestRef (archive .DigestTranslator (snapshotter )),
98
+ containerd .WithSkipDigestRef (func (name string ) bool { return name != "" }),
99
+ containerd .WithImportPlatform (platformMC ),
100
+ )
84
101
if err != nil {
85
102
if r .N == 0 {
86
103
// Avoid confusing "unrecognized image format"
87
- return errors .New ("no image was built" )
104
+ return nil , errors .New ("no image was built" )
88
105
}
89
106
if errors .Is (err , images .ErrEmptyWalk ) {
90
107
err = fmt .Errorf ("%w (Hint: set `--platform=PLATFORM` or `--all-platforms`)" , err )
91
108
}
92
- return err
109
+ return nil , err
93
110
}
94
- for _ , img := range imgs {
95
- image := containerd . NewImageWithPlatform ( client , img , platMC )
111
+ return imgs , nil
112
+ }
96
113
97
- // TODO: Show unpack status
98
- if ! options .Quiet {
99
- fmt .Fprintf (options .Stdout , "unpacking %s (%s)...\n " , img .Name , img .Target .Digest )
100
- }
114
+ func unpackImage (ctx context.Context , client * containerd.Client , model images.Image , platform platforms.MatchComparer , options types.ImageLoadOptions ) error {
115
+ image := containerd .NewImageWithPlatform (client , model , platform )
101
116
102
- err = image .Unpack (ctx , options .GOptions .Snapshotter )
103
- if err != nil {
104
- return err
105
- }
117
+ if ! options .Quiet {
118
+ fmt .Fprintf (options .Stdout , "unpacking %s (%s)...\n " , model .Name , model .Target .Digest )
119
+ }
106
120
107
- // Loaded message is shown even when quiet.
108
- repo , tag := imgutil . ParseRepoTag ( img . Name )
109
- fmt . Fprintf ( options . Stdout , "Loaded image: %s:%s \n " , repo , tag )
121
+ err := image . Unpack ( ctx , options . GOptions . Snapshotter )
122
+ if err != nil {
123
+ return err
110
124
}
111
125
126
+ // Loaded message is shown even when quiet.
127
+ repo , tag := imgutil .ParseRepoTag (model .Name )
128
+ fmt .Fprintf (options .Stdout , "Loaded image: %s:%s\n " , repo , tag )
129
+
112
130
return nil
113
131
}
0 commit comments