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

Commit e185ea3

Browse files
authored
Merge pull request #8 from docker/memory-fix
Memory fix
2 parents 7af84f9 + aa96c60 commit e185ea3

File tree

12 files changed

+320
-128
lines changed

12 files changed

+320
-128
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/anchore/stereoscope v0.0.0-20221006201143-d24c9d626b33
88
github.com/anchore/syft v0.62.1
99
github.com/aquasecurity/trivy v0.30.4
10-
github.com/atomist-skills/go-skill v0.0.6-0.20221003172518-c3d268e1f3f1
10+
github.com/atomist-skills/go-skill v0.0.6-0.20221221214636-a7de163fd901
1111
github.com/briandowns/spinner v1.12.0
1212
github.com/docker/cli v20.10.21+incompatible
1313
github.com/docker/docker v20.10.17+incompatible

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:l
209209
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=
210210
github.com/atomist-skills/go-skill v0.0.6-0.20221003172518-c3d268e1f3f1 h1:EzSOh9LLtL/3IzbPUFSp/6OF4DrgiCPxCC3x3jjD9Bs=
211211
github.com/atomist-skills/go-skill v0.0.6-0.20221003172518-c3d268e1f3f1/go.mod h1:DRmwrZL5kG68Mn8VDw/Xr7rDhyl+laD7NFHIrQr54yo=
212+
github.com/atomist-skills/go-skill v0.0.6-0.20221221214636-a7de163fd901 h1:0fqUAo4MmWXnWIDCG7JBe903M3WJ+tqQetPIkVfcXKo=
213+
github.com/atomist-skills/go-skill v0.0.6-0.20221221214636-a7de163fd901/go.mod h1:DRmwrZL5kG68Mn8VDw/Xr7rDhyl+laD7NFHIrQr54yo=
212214
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
213215
github.com/aws/aws-sdk-go v1.44.46 h1:BsKENvu24eXg7CWQ2wJAjKbDFkGP+hBtxKJIR3UdcB8=
214216
github.com/aws/aws-sdk-go v1.44.46/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=

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: 106 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@ package registry
1919
import (
2020
"context"
2121
"fmt"
22+
"io"
2223
"os"
2324
"path/filepath"
2425
"strings"
2526

27+
stereoscopeimage "github.com/anchore/stereoscope/pkg/image"
28+
"github.com/anchore/syft/syft/source"
2629
"github.com/atomist-skills/go-skill"
2730
"github.com/docker/cli/cli/command"
2831
"github.com/docker/index-cli-plugin/internal"
@@ -70,18 +73,22 @@ type ImageCache struct {
7073
Tags []string
7174

7275
Image *v1.Image
76+
Source *source.Source
7377
ImagePath string
7478
Ref *name.Reference
7579

76-
copy bool
77-
cli command.Cli
80+
remote bool
81+
copy bool
82+
cli command.Cli
83+
sourceCleanup func()
7884
}
7985

8086
func (c *ImageCache) StoreImage() error {
8187
if !c.copy {
8288
return nil
8389
}
8490
skill.Log.Debugf("Copying image to %s", c.ImagePath)
91+
var imageSource stereoscopeimage.Source
8592

8693
if format := os.Getenv("ATOMIST_CACHE_FORMAT"); format == "" || format == "oci" {
8794
spinner := internal.StartSpinner("info", "Copying image", c.cli.Out().IsTerminal())
@@ -96,53 +103,113 @@ func (c *ImageCache) StoreImage() error {
96103
if err = p.AppendImage(*c.Image); err != nil {
97104
return err
98105
}
106+
107+
imageSource = stereoscopeimage.OciDirectorySource
108+
99109
spinner.Stop()
100-
skill.Log.Infof("Copied image")
101-
return nil
102110
} else if format == "tar" {
103-
u := make(chan v1.Update, 0)
104-
errchan := make(chan error)
105-
go func() {
106-
if err := tarball.WriteToFile(c.ImagePath, *c.Ref, *c.Image, tarball.WithProgress(u)); err != nil {
107-
errchan <- errors.Wrapf(err, "failed to write tmp image archive")
108-
}
109-
errchan <- nil
110-
}()
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+
}()
111120

112-
var update v1.Update
113-
var err error
114-
var pp int64
115-
spinner := internal.StartSpinner("info", "Copying image", c.cli.Out().IsTerminal())
116-
defer spinner.Stop()
117-
for {
118-
select {
119-
case update = <-u:
120-
if update.Total > 0 {
121-
p := 100 * update.Complete / update.Total
122-
if pp != p {
123-
spinner.WithFields(internal.Fields{
124-
"event": "progress",
125-
"total": update.Total,
126-
"complete": update.Complete,
127-
}).Update(fmt.Sprintf("Copying image %d%% %s/%s", p, humanize.Bytes(uint64(update.Complete)), humanize.Bytes(uint64(update.Total))))
128-
pp = p
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
129148
}
130149
}
131-
case err = <-errchan:
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)
156+
if err != nil {
157+
return errors.Wrap(err, "unable to create temp file for image")
158+
}
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+
}()
165+
166+
readCloser, err := c.cli.Client().ImageSave(context.Background(), []string{c.Id})
167+
if err != nil {
168+
return errors.Wrap(err, "unable to save image tar")
169+
}
170+
defer func() {
171+
err := readCloser.Close()
132172
if err != nil {
133-
return err
134-
} else {
135-
spinner.Stop()
136-
skill.Log.Infof("Copied image")
137-
return nil
173+
skill.Log.Errorf("unable to close temp file (%s): %w", tempTarFile.Name(), err)
138174
}
175+
}()
176+
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")
139183
}
184+
spinner.Stop()
140185
}
186+
187+
imageSource = stereoscopeimage.DockerTarballSource
141188
}
189+
190+
skill.Log.Debugf("Parsing image")
191+
input := source.Input{
192+
Scheme: source.ImageScheme,
193+
ImageSource: imageSource,
194+
Location: c.ImagePath,
195+
}
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+
142206
return nil
143207
}
144208

145209
func (c *ImageCache) Cleanup() {
210+
if c.sourceCleanup != nil {
211+
c.sourceCleanup()
212+
}
146213
if !c.copy {
147214
return
148215
}
@@ -169,7 +236,7 @@ func SaveImage(image string, cli command.Cli) (*ImageCache, error) {
169236
}
170237
tarPath := filepath.Join(path, "sha256", digest[7:])
171238
tarFileName := filepath.Join(tarPath, uuid.NewString())
172-
if os.Getenv("ATOMIST_CACHE_FORMAT") == "tar" {
239+
if os.Getenv("ATOMIST_CACHE_FORMAT") != "oci" {
173240
tarFileName += ".tar"
174241
}
175242

@@ -204,6 +271,7 @@ func SaveImage(image string, cli command.Cli) (*ImageCache, error) {
204271
name = strings.Split(t, ":")[0]
205272
tags = append(tags, strings.Split(t, ":")[1])
206273
}
274+
207275
return &ImageCache{
208276
Id: im.ID,
209277
Digest: digest,
@@ -214,6 +282,7 @@ func SaveImage(image string, cli command.Cli) (*ImageCache, error) {
214282
Ref: &ref,
215283
ImagePath: imagePath,
216284
copy: true,
285+
remote: false,
217286
cli: cli,
218287
}, nil
219288
}
@@ -250,6 +319,7 @@ func SaveImage(image string, cli command.Cli) (*ImageCache, error) {
250319
Ref: &ref,
251320
ImagePath: imagePath,
252321
copy: true,
322+
remote: true,
253323
cli: cli,
254324
}, nil
255325
}

sbom/detect/detect.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ import (
2828
"github.com/docker/index-cli-plugin/types"
2929
)
3030

31-
type PackageDetector = func(packages []types.Package, image source.Source, lm types.LayerMapping) []types.Package
31+
type PackageDetector = func(packages []types.Package, image *source.Source, lm *types.LayerMapping) []types.Package
3232

3333
var detectors []PackageDetector
3434

3535
func init() {
3636
detectors = []PackageDetector{nodePackageDetector()}
3737
}
3838

39-
func AdditionalPackages(packages []types.Package, image source.Source, lm types.LayerMapping) []types.Package {
39+
func AdditionalPackages(packages []types.Package, image *source.Source, lm *types.LayerMapping) []types.Package {
4040
additionalPackages := make([]types.Package, 0)
4141
for _, d := range detectors {
4242
additionalPackages = append(additionalPackages, d(packages, image, lm)...)
@@ -45,7 +45,7 @@ func AdditionalPackages(packages []types.Package, image source.Source, lm types.
4545
}
4646

4747
func stringsNodeDetector(executable string, versionEnvVar string, expr *regexp.Regexp, pkg types.Package, filterFunc func(purl string) bool) PackageDetector {
48-
return func(packages []types.Package, image source.Source, lm types.LayerMapping) []types.Package {
48+
return func(packages []types.Package, image *source.Source, lm *types.LayerMapping) []types.Package {
4949
// Already found via package manager
5050
for _, p := range packages {
5151
if filterFunc(p.Purl) {

0 commit comments

Comments
 (0)