Skip to content
This repository was archived by the owner on Mar 27, 2024. It is now read-only.

Commit 392203e

Browse files
authored
Merge pull request #270 from nkubala/get_image_refactor
Move all image processing logic into utils, and expose publically
2 parents 5438e03 + 69a4a9b commit 392203e

File tree

4 files changed

+178
-166
lines changed

4 files changed

+178
-166
lines changed

cmd/analyze.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func analyzeImage(imageName string, analyzerArgs []string) error {
5959
return errors.Wrap(err, "getting analyzers")
6060
}
6161

62-
image, err := getImageForName(imageName)
62+
image, err := getImage(imageName)
6363
if err != nil {
6464
return errors.Wrapf(err, "error retrieving image %s", imageName)
6565
}

cmd/diff.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func checkFilenameFlag(_ []string) error {
7373
// processImage is a concurrency-friendly wrapper around getImageForName
7474
func processImage(imageName string, imageMap map[string]*pkgutil.Image, wg *sync.WaitGroup, errChan chan<- error) {
7575
defer wg.Done()
76-
image, err := getImageForName(imageName)
76+
image, err := getImage(imageName)
7777
if err != nil {
7878
errChan <- fmt.Errorf("error retrieving image %s: %s", imageName, err)
7979
}

cmd/root.go

Lines changed: 11 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,15 @@ package cmd
1919
import (
2020
goflag "flag"
2121
"fmt"
22-
"io/ioutil"
23-
"net/http"
2422
"os"
2523
"path/filepath"
2624
"sort"
2725
"strings"
28-
"time"
29-
30-
"github.com/google/go-containerregistry/pkg/authn"
31-
"github.com/google/go-containerregistry/pkg/name"
32-
"github.com/google/go-containerregistry/pkg/v1/daemon"
33-
"github.com/google/go-containerregistry/pkg/v1/remote"
34-
"github.com/google/go-containerregistry/pkg/v1/tarball"
3526

3627
"github.com/GoogleContainerTools/container-diff/differs"
3728
pkgutil "github.com/GoogleContainerTools/container-diff/pkg/util"
3829
"github.com/GoogleContainerTools/container-diff/util"
39-
"github.com/google/go-containerregistry/pkg/v1"
4030
homedir "github.com/mitchellh/go-homedir"
41-
"github.com/pkg/errors"
4231
"github.com/sirupsen/logrus"
4332
"github.com/spf13/cobra"
4433
"github.com/spf13/pflag"
@@ -55,11 +44,6 @@ var format string
5544

5645
type validatefxn func(args []string) error
5746

58-
const (
59-
DaemonPrefix = "daemon://"
60-
RemotePrefix = "remote://"
61-
)
62-
6347
var RootCmd = &cobra.Command{
6448
Use: "container-diff",
6549
Short: "container-diff is a tool for analyzing and comparing container images",
@@ -130,162 +114,27 @@ func checkIfValidAnalyzer(_ []string) error {
130114
return nil
131115
}
132116

133-
// getImageForName infers the source of an image and retrieves a v1.Image reference to it.
134-
// Once a reference is obtained, it attempts to unpack the v1.Image's reader's contents
135-
// into a temp directory on the local filesystem.
136-
func getImageForName(imageName string) (pkgutil.Image, error) {
137-
logrus.Infof("retrieving image: %s", imageName)
138-
var img v1.Image
139-
var err error
140-
if pkgutil.IsTar(imageName) {
141-
start := time.Now()
142-
img, err = tarball.ImageFromPath(imageName, nil)
143-
if err != nil {
144-
return pkgutil.Image{}, errors.Wrap(err, "retrieving tar from path")
145-
}
146-
elapsed := time.Now().Sub(start)
147-
logrus.Infof("retrieving image ref from tar took %f seconds", elapsed.Seconds())
148-
} else if strings.HasPrefix(imageName, DaemonPrefix) {
149-
// remove the daemon prefix
150-
imageName = strings.Replace(imageName, DaemonPrefix, "", -1)
151-
152-
ref, err := name.ParseReference(imageName, name.WeakValidation)
153-
if err != nil {
154-
return pkgutil.Image{}, errors.Wrap(err, "parsing image reference")
155-
}
156-
157-
start := time.Now()
158-
// TODO(nkubala): specify gzip.NoCompression here when functional options are supported
159-
img, err = daemon.Image(ref, daemon.WithBufferedOpener())
160-
if err != nil {
161-
return pkgutil.Image{}, errors.Wrap(err, "retrieving image from daemon")
162-
}
163-
elapsed := time.Now().Sub(start)
164-
logrus.Infof("retrieving local image ref took %f seconds", elapsed.Seconds())
165-
} else {
166-
// either has remote prefix or has no prefix, in which case we force remote
167-
imageName = strings.Replace(imageName, RemotePrefix, "", -1)
168-
ref, err := name.ParseReference(imageName, name.WeakValidation)
169-
if err != nil {
170-
return pkgutil.Image{}, errors.Wrap(err, "parsing image reference")
171-
}
172-
auth, err := authn.DefaultKeychain.Resolve(ref.Context().Registry)
173-
if err != nil {
174-
return pkgutil.Image{}, errors.Wrap(err, "resolving auth")
175-
}
176-
start := time.Now()
177-
img, err = remote.Image(ref, remote.WithAuth(auth), remote.WithTransport(http.DefaultTransport))
178-
if err != nil {
179-
return pkgutil.Image{}, errors.Wrap(err, "retrieving remote image")
180-
}
181-
elapsed := time.Now().Sub(start)
182-
logrus.Infof("retrieving remote image ref took %f seconds", elapsed.Seconds())
183-
}
184-
185-
// create tempdir and extract fs into it
186-
var layers []pkgutil.Layer
187-
if includeLayers() {
188-
start := time.Now()
189-
imgLayers, err := img.Layers()
190-
if err != nil {
191-
return pkgutil.Image{}, errors.Wrap(err, "getting image layers")
192-
}
193-
for _, layer := range imgLayers {
194-
layerStart := time.Now()
195-
digest, err := layer.Digest()
196-
path, err := getExtractPathForName(digest.String())
197-
if err != nil {
198-
return pkgutil.Image{
199-
Layers: layers,
200-
}, errors.Wrap(err, "getting extract path for layer")
201-
}
202-
if err := pkgutil.GetFileSystemForLayer(layer, path, nil); err != nil {
203-
return pkgutil.Image{
204-
Layers: layers,
205-
}, errors.Wrap(err, "getting filesystem for layer")
117+
func includeLayers() bool {
118+
for _, t := range types {
119+
for _, a := range differs.LayerAnalyzers {
120+
if t == a {
121+
return true
206122
}
207-
layers = append(layers, pkgutil.Layer{
208-
FSPath: path,
209-
Digest: digest,
210-
})
211-
elapsed := time.Now().Sub(layerStart)
212-
logrus.Infof("time elapsed retrieving layer: %fs", elapsed.Seconds())
213123
}
214-
elapsed := time.Now().Sub(start)
215-
logrus.Infof("time elapsed retrieving image layers: %fs", elapsed.Seconds())
216-
}
217-
218-
imageDigest, err := getImageDigest(img)
219-
if err != nil {
220-
return pkgutil.Image{}, err
221-
}
222-
path, err := getExtractPathForName(pkgutil.RemoveTag(imageName) + "@" + imageDigest.String())
223-
if err != nil {
224-
return pkgutil.Image{}, err
225-
}
226-
// extract fs into provided dir
227-
if err := pkgutil.GetFileSystemForImage(img, path, nil); err != nil {
228-
return pkgutil.Image{
229-
FSPath: path,
230-
Layers: layers,
231-
}, errors.Wrap(err, "getting filesystem for image")
232124
}
233-
return pkgutil.Image{
234-
Image: img,
235-
Source: imageName,
236-
FSPath: path,
237-
Digest: imageDigest,
238-
Layers: layers,
239-
}, nil
240-
}
241-
242-
func getImageDigest(image v1.Image) (digest v1.Hash, err error) {
243-
start := time.Now()
244-
digest, err = image.Digest()
245-
if err != nil {
246-
return digest, err
247-
}
248-
elapsed := time.Now().Sub(start)
249-
logrus.Infof("time elapsed retrieving image digest: %fs", elapsed.Seconds())
250-
return digest, nil
125+
return false
251126
}
252127

253-
func getExtractPathForName(name string) (string, error) {
254-
var path string
128+
func getImage(imageName string) (pkgutil.Image, error) {
129+
var cachePath string
255130
var err error
256131
if !noCache {
257-
path, err = cacheDir(name)
258-
if err != nil {
259-
return "", err
260-
}
261-
// if cachedir doesn't exist, create it
262-
if _, err := os.Stat(path); err != nil && os.IsNotExist(err) {
263-
err = os.MkdirAll(path, 0700)
264-
if err != nil {
265-
return "", err
266-
}
267-
logrus.Infof("caching filesystem at %s", path)
268-
}
269-
} else {
270-
// otherwise, create tempdir
271-
logrus.Infof("skipping caching")
272-
path, err = ioutil.TempDir("", strings.Replace(name, "/", "", -1))
132+
cachePath, err = cacheDir(imageName)
273133
if err != nil {
274-
return "", err
275-
}
276-
}
277-
return path, nil
278-
}
279-
280-
func includeLayers() bool {
281-
for _, t := range types {
282-
for _, a := range differs.LayerAnalyzers {
283-
if t == a {
284-
return true
285-
}
134+
return pkgutil.Image{}, err
286135
}
287136
}
288-
return false
137+
return pkgutil.GetImage(imageName, includeLayers(), cachePath)
289138
}
290139

291140
func cacheDir(imageName string) (string, error) {

0 commit comments

Comments
 (0)