-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Always snapshot files in COPY and RUN commands #289
Changes from 3 commits
607af5f
6dccd4e
2fe93f2
7f64037
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
FROM alpine@sha256:5ce5f501c457015c4b91f91a15ac69157d9b06f1a75cf9107bf2b62e0843983a | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
COPY context/foo /foo | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -135,11 +135,10 @@ func TestMain(m *testing.M) { | |
defer DeleteFromBucket(fileInBucket) | ||
|
||
fmt.Println("Building kaniko image") | ||
buildKaniko := exec.Command("docker", "build", "-t", ExecutorImage, "-f", "../deploy/Dockerfile", "..") | ||
err = buildKaniko.Run() | ||
cmd := exec.Command("docker", "build", "-t", ExecutorImage, "-f", "../deploy/Dockerfile", "..") | ||
_, err = RunCommandWithoutTest(cmd) | ||
if err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: I think go convention is to write error messages like this as if _, err := RunCommandWithoutTest(cmd); err != nil {
} |
||
fmt.Print(err) | ||
fmt.Print("Building kaniko failed.") | ||
fmt.Printf("Building kaniko failed: %s", err) | ||
os.Exit(1) | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,10 +19,12 @@ package snapshot | |
import ( | ||
"archive/tar" | ||
"bytes" | ||
"fmt" | ||
"io" | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
"syscall" | ||
|
||
"github.com/GoogleContainerTools/kaniko/pkg/constants" | ||
"github.com/GoogleContainerTools/kaniko/pkg/util" | ||
|
@@ -49,17 +51,28 @@ func (s *Snapshotter) Init() error { | |
return nil | ||
} | ||
|
||
// TakeSnapshot takes a snapshot of the filesystem, avoiding directories in the whitelist, and creates | ||
// TakeSnapshot takes a snapshot of the specified files, avoiding directories in the whitelist, and creates | ||
// a tarball of the changed files. Return contents of the tarball, and whether or not any files were changed | ||
func (s *Snapshotter) TakeSnapshot(files []string) ([]byte, error) { | ||
buf := bytes.NewBuffer([]byte{}) | ||
var filesAdded bool | ||
var err error | ||
if files == nil { | ||
filesAdded, err = s.snapShotFS(buf) | ||
} else { | ||
filesAdded, err = s.snapshotFiles(buf, files) | ||
filesAdded, err := s.snapshotFiles(buf, files) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: I don't think you need to declare There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. whops thanks! |
||
if err != nil { | ||
return nil, err | ||
} | ||
contents := buf.Bytes() | ||
if !filesAdded { | ||
return nil, nil | ||
} | ||
return contents, err | ||
} | ||
|
||
// TakeSnapshotFS takes a snapshot of the filesystem, avoiding directories in the whitelist, and creates | ||
// a tarball of the changed files. Return contents of the tarball, and whether or not any files were changed | ||
func (s *Snapshotter) TakeSnapshotFS() ([]byte, error) { | ||
buf := bytes.NewBuffer([]byte{}) | ||
var filesAdded bool | ||
filesAdded, err := s.snapShotFS(buf) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
@@ -70,8 +83,8 @@ func (s *Snapshotter) TakeSnapshot(files []string) ([]byte, error) { | |
return contents, err | ||
} | ||
|
||
// snapshotFiles takes a snapshot of specific files | ||
// Used for ADD/COPY commands, when we know which files have changed | ||
// snapshotFiles creates a snapshot (tar) and adds the specified files. | ||
// It will not add files which are whitelisted. | ||
func (s *Snapshotter) snapshotFiles(f io.Writer, files []string) (bool, error) { | ||
s.hardlinks = map[uint64]string{} | ||
s.l.Snapshot() | ||
|
@@ -81,16 +94,19 @@ func (s *Snapshotter) snapshotFiles(f io.Writer, files []string) (bool, error) { | |
} | ||
logrus.Infof("Taking snapshot of files %v...", files) | ||
snapshottedFiles := make(map[string]bool) | ||
n := len(files) | ||
for _, file := range files { | ||
parentDirs := util.ParentDirectories(file) | ||
// If we do end up snapshotting the dirs, we need to snapshot them before | ||
// we snapshot their contents | ||
files = append(parentDirs, files...) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @priyawadhwa can you confirm if the comment i added is correct? I was trying to understand why we were actually appending to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. actually, I don't think the order matters! I'm pretty sure I did that bc when I was writing the function and debugging it the logging was easier to read as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah kk! if we're going to have 2 separate lists it wont matter too much anyway |
||
} | ||
filesAdded := false | ||
w := tar.NewWriter(f) | ||
defer w.Close() | ||
|
||
// Now create the tar. | ||
for _, file := range files { | ||
for i, file := range files { | ||
file = filepath.Clean(file) | ||
if val, ok := snapshottedFiles[file]; ok && val { | ||
continue | ||
|
@@ -108,12 +124,24 @@ func (s *Snapshotter) snapshotFiles(f io.Writer, files []string) (bool, error) { | |
if err != nil { | ||
return false, err | ||
} | ||
// Only add to the tar if we add it to the layeredmap. | ||
addFile, err := s.l.MaybeAdd(file) | ||
|
||
var fileAdded bool | ||
lastParentFileIndex := len(files) - n | ||
isParentDir := i < lastParentFileIndex | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is one of the grossest things ive written in a long time (knock on wood) @priyawadhwa so let me know if it's not clear and/or you'd just like it to be nicer i think the next step to making this better would be to break some of this logic out into a separate function or two There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you think we could have two separate lists, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. kk let's do it! |
||
|
||
// If this is parent dir of the file we're snapshotting, only snapshot it | ||
// if it changed | ||
if isParentDir { | ||
fileAdded, err = s.l.MaybeAdd(file) | ||
} else { | ||
// If this is one of the files we are snapshotting, definitely snapshot it | ||
err = s.l.Add(file) | ||
fileAdded = true | ||
} | ||
if err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: same error formatting as I commented above |
||
return false, err | ||
return false, fmt.Errorf("Unable to add file %s to layered map: %s", file, err) | ||
} | ||
if addFile { | ||
if fileAdded { | ||
filesAdded = true | ||
if err := util.AddToTar(file, info, s.hardlinks, w); err != nil { | ||
return false, err | ||
|
@@ -132,8 +160,17 @@ func isBuildFile(file string) bool { | |
return false | ||
} | ||
|
||
// shapShotFS creates a snapshot (tar) of all files in the system which are not | ||
// whitelisted and which have changed. | ||
func (s *Snapshotter) snapShotFS(f io.Writer) (bool, error) { | ||
logrus.Info("Taking snapshot of full filesystem...") | ||
|
||
// Some of the operations that follow (e.g. hashing) depend on the file system being synced, | ||
// for example the hashing function that determines if files are equal uses the mtime of the files, | ||
// which can lag if sync is not called. Unfortunately there can still be lag if too much data needs | ||
// to be flushed or the disk does its own caching/buffering. | ||
syscall.Sync() | ||
|
||
s.hardlinks = map[uint64]string{} | ||
s.l.Snapshot() | ||
existingPaths := s.l.GetFlattenedPathsForWhiteOut() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SOLID
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
X'D