Skip to content

Commit 0668f96

Browse files
authored
Fix directory contents cache in imagefs (#26)
1 parent 8cd5f9f commit 0668f96

File tree

3 files changed

+54
-22
lines changed

3 files changed

+54
-22
lines changed

pkg/executor/cache_probe_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,7 @@ COPY foo/baz.txt copied/
177177
ENV test test
178178
179179
From scratch as second
180-
COPY --from=first copied/bam.txt output/bam.txt
181-
COPY --from=first copied/bam.link output/bam.link`
180+
COPY --from=first copied/ output/`
182181
err := filesystem.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755)
183182
testutil.CheckNoError(t, err)
184183
opts := &config.KanikoOptions{

pkg/imagefs/imagefs.go

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,16 @@ type imageFSFile interface {
5454
}
5555

5656
func New(parent vfs.FS, root string, image v1.Image, filesToCache []string) (vfs.FS, error) {
57-
var ifs *imageFS
57+
if image == nil {
58+
return nil, errors.New("imagefs: image cannot be nil")
59+
}
5860

61+
layers, err := image.Layers()
62+
if err != nil {
63+
return nil, errors.Wrap(err, "imagefs: get layers failed")
64+
}
65+
66+
var ifs *imageFS
5967
// Multiple layers of imageFS might get confusing, enable delayering.
6068
if pfs, ok := parent.(*imageFS); ok {
6169
pfs.mu.Lock()
@@ -75,43 +83,66 @@ func New(parent vfs.FS, root string, image v1.Image, filesToCache []string) (vfs
7583
}
7684
}
7785

86+
logrus.Debugf("imagefs: Caching files for %s", root)
87+
88+
// Keep track of directories so we can cache all of their contents.
89+
var dirsToCache []string
7890
// Walk the image and cache file info and hash of the requested files.
79-
_, err := util.GetFSFromImage(root, image, func(dest string, hdr *tar.Header, cleanedName string, tr io.Reader) error {
91+
_, err = util.GetFSFromLayers(root, layers, util.ExtractFunc(func(dest string, hdr *tar.Header, cleanedName string, tr io.Reader) error {
8092
// Trim prefix for consistent path.
8193
cleanedName = strings.TrimPrefix(cleanedName, "/")
94+
path := filepath.Join(dest, cleanedName)
95+
96+
cacheFile := func() error {
97+
logrus.Debugf("imagefs: Found cacheable file /%s (path=%s) (%d:%d)", cleanedName, path, hdr.Uid, hdr.Gid)
98+
99+
cf := newCachedFileInfo(path, hdr)
100+
if cf.IsDir() {
101+
dirsToCache = append(dirsToCache, cleanedName)
102+
}
103+
104+
sum, err := hashFile(hdr, tr)
105+
if err != nil {
106+
return errors.Wrap(err, "imagefs: hash file failed")
107+
}
108+
ifs.files[path] = newCachedFileInfoWithMD5Sum(cf, sum)
109+
110+
return nil
111+
}
112+
113+
// All files inside a cached directory should be cached as well.
114+
for _, dir := range dirsToCache {
115+
if strings.HasPrefix(cleanedName, dir+"/") {
116+
return cacheFile()
117+
}
118+
}
82119

83120
for _, f := range filesToCache {
84-
dest := filepath.Join(root, cleanedName)
85121
f = strings.TrimPrefix(f, "/")
122+
f = strings.TrimSuffix(f, "/")
86123

87124
// Check if the file matches the requested file.
88125
if ok, err := filepath.Match(f, cleanedName); ok && err == nil {
89-
logrus.Debugf("imagefs: Found cacheable file %q (%s) (%d:%d)", f, dest, hdr.Uid, hdr.Gid)
90-
91-
sum, err := hashFile(hdr, tr)
92-
if err != nil {
93-
return errors.Wrap(err, "imagefs: hash file failed")
94-
}
95-
96-
f := newCachedFileInfo(dest, hdr)
97-
ifs.files[dest] = newCachedFileInfoWithMD5Sum(f, sum)
98-
99-
return nil
126+
return cacheFile()
100127
}
101128

102-
// Parent directories are needed for lookup.
129+
// Cache parent directories for directory lookups.
103130
if cleanedName == "" || strings.HasPrefix(f, cleanedName+"/") {
104-
logrus.Debugf("imagefs: Found cacheable file parent %q (%s)", f, dest)
105-
106-
ifs.files[dest] = newCachedFileInfo(dest, hdr)
131+
if _, ok := ifs.files[path]; !ok {
132+
logrus.Debugf("imagefs: Found cacheable file parent /%s (file=/%s)", cleanedName, f)
133+
ifs.files[path] = newCachedFileInfo(dest, hdr)
134+
}
107135
}
108136
}
137+
109138
return nil
110-
})
139+
}))
111140
if err != nil {
112141
return nil, errors.Wrap(err, "imagefs: walk image failed")
113142
}
114143

144+
logrus.Debugf("imagefs: Creating cached directories for %s", root)
145+
115146
for dir, d := range ifs.files {
116147
if !d.IsDir() {
117148
continue
@@ -124,6 +155,8 @@ func New(parent vfs.FS, root string, image v1.Image, filesToCache []string) (vfs
124155
}
125156
}
126157

158+
logrus.Debugf("imagefs: Cached files for %s", root)
159+
127160
return ifs, nil
128161
}
129162

pkg/util/fs_util.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ func ExtractFile(dest string, hdr *tar.Header, cleanedName string, tr io.Reader)
483483
}
484484
}
485485
link := filepath.Clean(filepath.Join(dest, hdr.Linkname))
486-
if err := os.Link(link, path); err != nil {
486+
if err := filesystem.FS.Link(link, path); err != nil {
487487
return err
488488
}
489489

0 commit comments

Comments
 (0)