@@ -19,26 +19,15 @@ package cmd
1919import  (
2020goflag "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" 
3728pkgutil "github.com/GoogleContainerTools/container-diff/pkg/util" 
3829"github.com/GoogleContainerTools/container-diff/util" 
39- "github.com/google/go-containerregistry/pkg/v1" 
4030homedir "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 {
6448Use : "container-diff" ,
6549Short : "container-diff is a tool for analyzing and comparing container images" ,
@@ -130,162 +114,27 @@ func checkIfValidAnalyzer(_ []string) error {
130114return  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 
255130var  err  error 
256131if  ! 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 )
273133if  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