Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit aa96c60

Browse files
committed
Bring back remote download
1 parent 022a6eb commit aa96c60

File tree

2 files changed

+111
-52
lines changed

2 files changed

+111
-52
lines changed

registry/read.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package registry
1818

1919
import (
20+
stereoscopeimage "github.com/anchore/stereoscope/pkg/image"
21+
"github.com/anchore/syft/syft/source"
2022
"github.com/atomist-skills/go-skill"
2123
"github.com/google/go-containerregistry/pkg/v1/layout"
2224
"github.com/pkg/errors"
@@ -31,15 +33,31 @@ func ReadImage(name string, path string) (*ImageCache, error) {
3133
mani, err := index.IndexManifest()
3234
hash := mani.Manifests[0].Digest
3335
img, _ := index.Image(hash)
36+
37+
skill.Log.Debugf("Parsing image")
38+
input := source.Input{
39+
Scheme: source.ImageScheme,
40+
ImageSource: stereoscopeimage.OciDirectorySource,
41+
Location: path,
42+
}
43+
src, cleanup, err := source.New(input, nil, nil)
44+
if err != nil {
45+
return nil, errors.Wrap(err, "failed to create new source")
46+
}
47+
skill.Log.Debugf("Parse image")
3448
skill.Log.Infof("Loaded image")
49+
3550
return &ImageCache{
3651
Id: hash.String(),
3752
Digest: hash.String(),
3853
Tags: []string{},
3954
Name: name,
4055
Image: &img,
56+
Source: src,
4157
ImagePath: path,
4258
Ref: nil,
43-
copy: false,
59+
60+
copy: false,
61+
sourceCleanup: cleanup,
4462
}, nil
4563
}

registry/save.go

Lines changed: 92 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,15 @@ import (
2929
"github.com/atomist-skills/go-skill"
3030
"github.com/docker/cli/cli/command"
3131
"github.com/docker/index-cli-plugin/internal"
32+
"github.com/dustin/go-humanize"
3233
"github.com/google/go-containerregistry/pkg/authn"
3334
"github.com/google/go-containerregistry/pkg/name"
3435
v1 "github.com/google/go-containerregistry/pkg/v1"
3536
"github.com/google/go-containerregistry/pkg/v1/daemon"
3637
"github.com/google/go-containerregistry/pkg/v1/empty"
3738
"github.com/google/go-containerregistry/pkg/v1/layout"
3839
"github.com/google/go-containerregistry/pkg/v1/remote"
40+
"github.com/google/go-containerregistry/pkg/v1/tarball"
3941
"github.com/google/uuid"
4042
"github.com/pkg/errors"
4143
)
@@ -75,6 +77,7 @@ type ImageCache struct {
7577
ImagePath string
7678
Ref *name.Reference
7779

80+
remote bool
7881
copy bool
7982
cli command.Cli
8083
sourceCleanup func()
@@ -85,6 +88,7 @@ func (c *ImageCache) StoreImage() error {
8588
return nil
8689
}
8790
skill.Log.Debugf("Copying image to %s", c.ImagePath)
91+
var imageSource stereoscopeimage.Source
8892

8993
if format := os.Getenv("ATOMIST_CACHE_FORMAT"); format == "" || format == "oci" {
9094
spinner := internal.StartSpinner("info", "Copying image", c.cli.Out().IsTerminal())
@@ -100,70 +104,105 @@ func (c *ImageCache) StoreImage() error {
100104
return err
101105
}
102106

103-
input := source.Input{
104-
Scheme: source.ImageScheme,
105-
ImageSource: stereoscopeimage.OciDirectorySource,
106-
Location: c.ImagePath,
107-
}
108-
src, cleanup, err := source.New(input, nil, nil)
109-
if err != nil {
110-
return errors.Wrap(err, "failed to create new source")
111-
}
112-
c.Source = src
113-
c.sourceCleanup = cleanup
107+
imageSource = stereoscopeimage.OciDirectorySource
114108

115109
spinner.Stop()
116-
skill.Log.Infof("Copied image")
117-
return nil
118-
119110
} else if format == "tar" {
120-
spinner := internal.StartSpinner("info", "Copying image", c.cli.Out().IsTerminal())
121-
defer spinner.Stop()
122-
tempTarFile, err := os.Create(c.ImagePath)
123-
if err != nil {
124-
return errors.Wrap(err, "unable to create temp file for image")
125-
}
126-
defer func() {
127-
err := tempTarFile.Close()
111+
if c.remote {
112+
u := make(chan v1.Update, 0)
113+
errchan := make(chan error)
114+
go func() {
115+
if err := tarball.WriteToFile(c.ImagePath, *c.Ref, *c.Image, tarball.WithProgress(u)); err != nil {
116+
errchan <- errors.Wrapf(err, "failed to write tmp image archive")
117+
}
118+
errchan <- nil
119+
}()
120+
121+
var update v1.Update
122+
var err error
123+
var pp int64
124+
spinner := internal.StartSpinner("info", "Copying image", c.cli.Out().IsTerminal())
125+
defer spinner.Stop()
126+
loop := true
127+
for loop {
128+
select {
129+
case update = <-u:
130+
if update.Total > 0 {
131+
p := 100 * update.Complete / update.Total
132+
if pp != p {
133+
spinner.WithFields(internal.Fields{
134+
"event": "progress",
135+
"total": update.Total,
136+
"complete": update.Complete,
137+
}).Update(fmt.Sprintf("Copying image %d%% %s/%s", p, humanize.Bytes(uint64(update.Complete)), humanize.Bytes(uint64(update.Total))))
138+
pp = p
139+
}
140+
}
141+
case err = <-errchan:
142+
if err != nil {
143+
return err
144+
} else {
145+
spinner.Stop()
146+
skill.Log.Infof("Copied image")
147+
loop = false
148+
}
149+
}
150+
}
151+
152+
} else {
153+
spinner := internal.StartSpinner("info", "Copying image", c.cli.Out().IsTerminal())
154+
defer spinner.Stop()
155+
tempTarFile, err := os.Create(c.ImagePath)
128156
if err != nil {
129-
skill.Log.Errorf("unable to close temp file (%s): %w", tempTarFile.Name(), err)
157+
return errors.Wrap(err, "unable to create temp file for image")
130158
}
131-
}()
159+
defer func() {
160+
err := tempTarFile.Close()
161+
if err != nil {
162+
skill.Log.Errorf("unable to close temp file (%s): %w", tempTarFile.Name(), err)
163+
}
164+
}()
132165

133-
readCloser, err := c.cli.Client().ImageSave(context.Background(), []string{c.Id})
134-
if err != nil {
135-
return errors.Wrap(err, "unable to save image tar")
136-
}
137-
defer func() {
138-
err := readCloser.Close()
166+
readCloser, err := c.cli.Client().ImageSave(context.Background(), []string{c.Id})
139167
if err != nil {
140-
skill.Log.Errorf("unable to close temp file (%s): %w", tempTarFile.Name(), err)
168+
return errors.Wrap(err, "unable to save image tar")
141169
}
142-
}()
170+
defer func() {
171+
err := readCloser.Close()
172+
if err != nil {
173+
skill.Log.Errorf("unable to close temp file (%s): %w", tempTarFile.Name(), err)
174+
}
175+
}()
143176

144-
nBytes, err := io.Copy(tempTarFile, readCloser)
145-
if err != nil {
146-
return fmt.Errorf("unable to save image to tar: %w", err)
147-
}
148-
if nBytes == 0 {
149-
return errors.New("cannot provide an empty image")
177+
nBytes, err := io.Copy(tempTarFile, readCloser)
178+
if err != nil {
179+
return fmt.Errorf("unable to save image to tar: %w", err)
180+
}
181+
if nBytes == 0 {
182+
return errors.New("cannot provide an empty image")
183+
}
184+
spinner.Stop()
150185
}
151186

152-
input := source.Input{
153-
Scheme: source.ImageScheme,
154-
ImageSource: stereoscopeimage.DockerTarballSource,
155-
Location: c.ImagePath,
156-
}
157-
src, cleanup, err := source.New(input, nil, nil)
158-
if err != nil {
159-
return errors.Wrap(err, "failed to create new source")
160-
}
161-
c.Source = src
162-
c.sourceCleanup = cleanup
187+
imageSource = stereoscopeimage.DockerTarballSource
188+
}
163189

164-
spinner.Stop()
165-
skill.Log.Infof("Copied image")
190+
skill.Log.Debugf("Parsing image")
191+
input := source.Input{
192+
Scheme: source.ImageScheme,
193+
ImageSource: imageSource,
194+
Location: c.ImagePath,
166195
}
196+
src, cleanup, err := source.New(input, nil, nil)
197+
if err != nil {
198+
return errors.Wrap(err, "failed to create new image source")
199+
}
200+
c.Source = src
201+
c.sourceCleanup = cleanup
202+
203+
skill.Log.Debugf("Parsed image")
204+
skill.Log.Infof("Copied image")
205+
167206
return nil
168207
}
169208

@@ -243,6 +282,7 @@ func SaveImage(image string, cli command.Cli) (*ImageCache, error) {
243282
Ref: &ref,
244283
ImagePath: imagePath,
245284
copy: true,
285+
remote: false,
246286
cli: cli,
247287
}, nil
248288
}
@@ -279,6 +319,7 @@ func SaveImage(image string, cli command.Cli) (*ImageCache, error) {
279319
Ref: &ref,
280320
ImagePath: imagePath,
281321
copy: true,
322+
remote: true,
282323
cli: cli,
283324
}, nil
284325
}

0 commit comments

Comments
 (0)