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

Commit 3017d53

Browse files
committed
Add filesystem caching
1 parent 4f9b781 commit 3017d53

File tree

12 files changed

+373
-9
lines changed

12 files changed

+373
-9
lines changed

Gopkg.lock

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ go_library(
2121
"//vendor/github.com/google/go-containerregistry/v1/daemon:go_default_library",
2222
"//vendor/github.com/google/go-containerregistry/v1/remote:go_default_library",
2323
"//vendor/github.com/google/go-containerregistry/v1/tarball:go_default_library",
24+
"//vendor/github.com/mitchellh/go-homedir:go_default_library",
2425
"//vendor/github.com/sirupsen/logrus:go_default_library",
2526
"//vendor/github.com/spf13/cobra:go_default_library",
2627
"//vendor/github.com/spf13/pflag:go_default_library",

cmd/analyze.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func analyzeImage(imageName string, analyzerArgs []string) error {
6464
return err
6565
}
6666

67-
if !save {
67+
if noCache && !save {
6868
defer pkgutil.CleanupImage(image)
6969
}
7070
if err != nil {
@@ -82,7 +82,7 @@ func analyzeImage(imageName string, analyzerArgs []string) error {
8282
output.PrintToStdErr("Retrieving analyses\n")
8383
outputResults(analyses)
8484

85-
if save {
85+
if noCache && save {
8686
logrus.Infof("Image was saved at %s", image.FSPath)
8787
}
8888

cmd/diff.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func diffImages(image1Arg, image2Arg string, diffArgs []string) error {
9797
}
9898
wg.Wait()
9999

100-
if !save {
100+
if noCache && !save {
101101
defer pkgutil.CleanupImage(*imageMap[image1Arg])
102102
defer pkgutil.CleanupImage(*imageMap[image2Arg])
103103
}
@@ -121,7 +121,7 @@ func diffImages(image1Arg, image2Arg string, diffArgs []string) error {
121121
}
122122
}
123123

124-
if save {
124+
if noCache && save {
125125
logrus.Infof("Images were saved at %s and %s", imageMap[image1Arg].FSPath,
126126
imageMap[image2Arg].FSPath)
127127
}

cmd/root.go

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"io/ioutil"
2323
"net/http"
2424
"os"
25+
"path/filepath"
2526
"sort"
2627
"strings"
2728

@@ -35,14 +36,17 @@ import (
3536
pkgutil "github.com/GoogleContainerTools/container-diff/pkg/util"
3637
"github.com/GoogleContainerTools/container-diff/util"
3738
"github.com/google/go-containerregistry/v1"
39+
homedir "github.com/mitchellh/go-homedir"
3840
"github.com/sirupsen/logrus"
3941
"github.com/spf13/cobra"
4042
"github.com/spf13/pflag"
4143
)
4244

4345
var json bool
46+
4447
var save bool
4548
var types diffTypes
49+
var noCache bool
4650

4751
var LogLevel string
4852
var format string
@@ -164,7 +168,6 @@ func getImageForName(imageName string) (pkgutil.Image, error) {
164168
return pkgutil.Image{}, err
165169
}
166170
}
167-
// TODO(nkubala): implement caching
168171

169172
// create tempdir and extract fs into it
170173
var layers []pkgutil.Layer
@@ -190,10 +193,29 @@ func getImageForName(imageName string) (pkgutil.Image, error) {
190193
})
191194
}
192195
}
193-
path, err := ioutil.TempDir("", strings.Replace(imageName, "/", "", -1))
194-
if err != nil {
195-
return pkgutil.Image{}, err
196+
197+
var path string
198+
if !noCache {
199+
path, err = cacheDir(imageName)
200+
if err != nil {
201+
return pkgutil.Image{}, err
202+
}
203+
// if cachedir doesn't exist, create it
204+
if _, err := os.Stat(path); err != nil && os.IsNotExist(err) {
205+
err = os.MkdirAll(path, 0700)
206+
if err != nil {
207+
return pkgutil.Image{}, err
208+
}
209+
logrus.Infof("Image fs cached at %s", path)
210+
}
211+
} else {
212+
// otherwise, create tempdir
213+
path, err = ioutil.TempDir("", strings.Replace(imageName, "/", "", -1))
214+
if err != nil {
215+
return pkgutil.Image{}, err
216+
}
196217
}
218+
// extract fs into provided dir
197219
if err := pkgutil.GetFileSystemForImage(img, path, nil); err != nil {
198220
return pkgutil.Image{
199221
FSPath: path,
@@ -217,6 +239,16 @@ func includeLayers() bool {
217239
return false
218240
}
219241

242+
func cacheDir(imageName string) (string, error) {
243+
dir, err := homedir.Dir()
244+
if err != nil {
245+
return "", err
246+
}
247+
rootDir := filepath.Join(dir, ".container-diff", "cache")
248+
imageName = strings.Replace(imageName, string(os.PathSeparator), "", -1)
249+
return filepath.Join(rootDir, filepath.Clean(imageName)), nil
250+
}
251+
220252
func init() {
221253
RootCmd.PersistentFlags().StringVarP(&LogLevel, "verbosity", "v", "warning", "This flag controls the verbosity of container-diff.")
222254
RootCmd.PersistentFlags().StringVarP(&format, "format", "", "", "Format to output diff in.")
@@ -254,4 +286,5 @@ func addSharedFlags(cmd *cobra.Command) {
254286
cmd.Flags().VarP(&types, "type", "t", "This flag sets the list of analyzer types to use. Set it repeatedly to use multiple analyzers.")
255287
cmd.Flags().BoolVarP(&save, "save", "s", false, "Set this flag to save rather than remove the final image filesystems on exit.")
256288
cmd.Flags().BoolVarP(&util.SortSize, "order", "o", false, "Set this flag to sort any file/package results by descending size. Otherwise, they will be sorted by name.")
289+
cmd.Flags().BoolVarP(&noCache, "no-cache", "n", false, "Set this to force retrieval of image filesystem on each run.")
257290
}

pkg/util/fs_utils.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package util
1818

1919
import (
2020
"bytes"
21+
"io"
2122
"io/ioutil"
2223
"os"
2324
"path/filepath"
@@ -191,3 +192,18 @@ func HasFilepathPrefix(path, prefix string) bool {
191192
}
192193
return true
193194
}
195+
196+
// given a path to a directory, check if it has any contents
197+
func DirIsEmpty(path string) (bool, error) {
198+
f, err := os.Open(path)
199+
if err != nil {
200+
return false, err
201+
}
202+
defer f.Close()
203+
204+
_, err = f.Readdir(1)
205+
if err == io.EOF {
206+
return true, nil
207+
}
208+
return false, err
209+
}

pkg/util/image_utils.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,16 @@ func GetFileSystemForLayer(layer v1.Layer, root string, whitelist []string) erro
8383
}
8484

8585
// unpack image filesystem to local disk
86+
// if provided directory is not empty, do nothing
8687
func GetFileSystemForImage(image v1.Image, root string, whitelist []string) error {
88+
empty, err := DirIsEmpty(root)
89+
if err != nil {
90+
return err
91+
}
92+
if !empty {
93+
logrus.Infof("Using cached filesystem in %s", root)
94+
return nil
95+
}
8796
if err := unpackTar(tar.NewReader(mutate.Extract(image)), root, whitelist); err != nil {
8897
return err
8998
}

vendor/github.com/mitchellh/go-homedir/BUILD.bazel

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/mitchellh/go-homedir/LICENSE

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/mitchellh/go-homedir/README.md

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/mitchellh/go-homedir/homedir.go

Lines changed: 137 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)