@@ -19,26 +19,15 @@ package cmd
1919import (
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
5645type validatefxn func (args []string ) error
5746
58- const (
59- DaemonPrefix = "daemon://"
60- RemotePrefix = "remote://"
61- )
62-
6347var 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
291140func cacheDir (imageName string ) (string , error ) {
0 commit comments