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

Commit 5498015

Browse files
committed
Add filesystem caching
1 parent e4a55a7 commit 5498015

File tree

12 files changed

+372
-10
lines changed

12 files changed

+372
-10
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: 36 additions & 5 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,13 +168,29 @@ func getImageForName(imageName string) (pkgutil.Image, error) {
164168
return pkgutil.Image{}, err
165169
}
166170
}
167-
// TODO(nkubala): implement caching
168171

169-
// create tempdir and extract fs into it
170-
path, err := ioutil.TempDir("", strings.Replace(imageName, "/", "", -1))
171-
if err != nil {
172-
return pkgutil.Image{}, err
172+
var path string
173+
if !noCache {
174+
path, err = cacheDir(imageName)
175+
if err != nil {
176+
return pkgutil.Image{}, err
177+
}
178+
// if cachedir doesn't exist, create it
179+
if _, err := os.Stat(path); err != nil && os.IsNotExist(err) {
180+
err = os.MkdirAll(path, 0700)
181+
if err != nil {
182+
return pkgutil.Image{}, err
183+
}
184+
logrus.Infof("Image fs cached at %s", path)
185+
}
186+
} else {
187+
// otherwise, create tempdir
188+
path, err = ioutil.TempDir("", strings.Replace(imageName, "/", "", -1))
189+
if err != nil {
190+
return pkgutil.Image{}, err
191+
}
173192
}
193+
// extract fs into provided dir
174194
if err := pkgutil.GetFileSystemForImage(img, path, nil); err != nil {
175195
return pkgutil.Image{
176196
FSPath: path,
@@ -183,6 +203,16 @@ func getImageForName(imageName string) (pkgutil.Image, error) {
183203
}, nil
184204
}
185205

206+
func cacheDir(imageName string) (string, error) {
207+
dir, err := homedir.Dir()
208+
if err != nil {
209+
return "", err
210+
}
211+
rootDir := filepath.Join(dir, ".container-diff", "cache")
212+
imageName = strings.Replace(imageName, string(os.PathSeparator), "", -1)
213+
return filepath.Join(rootDir, filepath.Clean(imageName)), nil
214+
}
215+
186216
func init() {
187217
RootCmd.PersistentFlags().StringVarP(&LogLevel, "verbosity", "v", "warning", "This flag controls the verbosity of container-diff.")
188218
RootCmd.PersistentFlags().StringVarP(&format, "format", "", "", "Format to output diff in.")
@@ -220,4 +250,5 @@ func addSharedFlags(cmd *cobra.Command) {
220250
cmd.Flags().VarP(&types, "type", "t", "This flag sets the list of analyzer types to use. Set it repeatedly to use multiple analyzers.")
221251
cmd.Flags().BoolVarP(&save, "save", "s", false, "Set this flag to save rather than remove the final image filesystems on exit.")
222252
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.")
253+
cmd.Flags().BoolVarP(&noCache, "no-cache", "n", false, "Set this to force retrieval of image filesystem on each run.")
223254
}

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
@@ -62,7 +62,16 @@ func SortMap(m map[string]struct{}) string {
6262
}
6363

6464
// unpack image filesystem to local disk
65+
// if provided directory is not empty, do nothing
6566
func GetFileSystemForImage(image v1.Image, root string, whitelist []string) error {
67+
empty, err := DirIsEmpty(root)
68+
if err != nil {
69+
return err
70+
}
71+
if !empty {
72+
logrus.Infof("Using cached filesystem in %s", root)
73+
return nil
74+
}
6675
if err := unpackTar(tar.NewReader(mutate.Extract(image)), root, whitelist); err != nil {
6776
return err
6877
}

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)