diff --git a/pkg/commands/add.go b/pkg/commands/add.go index b39b5eb98..75a6b5b20 100644 --- a/pkg/commands/add.go +++ b/pkg/commands/add.go @@ -116,6 +116,10 @@ func (a *AddCommand) FilesToSnapshot() []string { return a.snapshotFiles } +func (a *AddCommand) ProvidesFilesToSnapshot() bool { + return true +} + // String returns some information about the command for the image config func (a *AddCommand) String() string { return a.cmd.String() diff --git a/pkg/commands/base_command.go b/pkg/commands/base_command.go index ddbfd650b..b96bf85d9 100644 --- a/pkg/commands/base_command.go +++ b/pkg/commands/base_command.go @@ -32,6 +32,10 @@ func (b *BaseCommand) FilesToSnapshot() []string { return []string{} } +func (b *BaseCommand) ProvidesFilesToSnapshot() bool { + return false +} + func (b *BaseCommand) FilesUsedFromContext(_ *v1.Config, _ *dockerfile.BuildArgs) ([]string, error) { return []string{}, nil } diff --git a/pkg/commands/commands.go b/pkg/commands/commands.go index a2ea7788d..0a4e57134 100644 --- a/pkg/commands/commands.go +++ b/pkg/commands/commands.go @@ -37,6 +37,10 @@ type DockerCommand interface { // A list of files to snapshot, empty for metadata commands or nil if we don't know FilesToSnapshot() []string + // ProvidesFileToSnapshot is true for all metadata commands and commands which know + // list of files changed. False for Run command. + ProvidesFilesToSnapshot() bool + // Return a cache-aware implementation of this command, if it exists. CacheCommand(v1.Image) DockerCommand diff --git a/pkg/commands/copy.go b/pkg/commands/copy.go index 472218fd6..35505284f 100644 --- a/pkg/commands/copy.go +++ b/pkg/commands/copy.go @@ -138,6 +138,10 @@ func (c *CopyCommand) MetadataOnly() bool { return false } +func (c *CopyCommand) ProvidesFilesToSnapshot() bool { + return true +} + func (c *CopyCommand) RequiresUnpackedFS() bool { return true } @@ -210,6 +214,14 @@ func (cr *CachingCopyCommand) FilesToSnapshot() []string { return f } +func (cr *CachingCopyCommand) MetadataOnly() bool { + return false +} + +func (cr *CachingCopyCommand) ProvidesFilesToSnapshot() bool { + return true +} + func (cr *CachingCopyCommand) String() string { if cr.cmd == nil { return "nil command" diff --git a/pkg/commands/run.go b/pkg/commands/run.go index d4a8003bf..d3ed0d1bb 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -151,6 +151,10 @@ func (r *RunCommand) FilesToSnapshot() []string { return nil } +func (r *RunCommand) ProvidesFilesToSnapshot() bool { + return false +} + // CacheCommand returns true since this command should be cached func (r *RunCommand) CacheCommand(img v1.Image) DockerCommand { @@ -227,3 +231,11 @@ func (cr *CachingRunCommand) String() string { } return cr.cmd.String() } + +func (cr *CachingRunCommand) MetadataOnly() bool { + return false +} + +func (cr *CachingRunCommand) RequiresUnpackedFS() bool { + return true +} diff --git a/pkg/commands/workdir.go b/pkg/commands/workdir.go index 273432052..96104bb13 100644 --- a/pkg/commands/workdir.go +++ b/pkg/commands/workdir.go @@ -75,3 +75,7 @@ func (w *WorkdirCommand) String() string { func (w *WorkdirCommand) MetadataOnly() bool { return false } + +func (w *WorkdirCommand) ProvidesFilesToSnapshot() bool { + return true +} diff --git a/pkg/executor/build.go b/pkg/executor/build.go index 45773b6c2..b6961989f 100644 --- a/pkg/executor/build.go +++ b/pkg/executor/build.go @@ -347,15 +347,18 @@ func (s *stageBuilder) build() error { default: return false } - } - if !isCacheCommand() && !initSnapshotTaken { - // Take initial snapshot - t := timing.Start("Initial FS snapshot") - if err := s.snapshotter.Init(); err != nil { - return err + }() + if !initSnapshotTaken && !isCacheCommand && !command.MetadataOnly() { + if !command.ProvidesFilesToSnapshot() { + // Take initial snapshot if command is not metadata only + // and does not return a list of files changed + t := timing.Start("Initial FS snapshot") + if err := s.snapshotter.Init(); err != nil { + return err + } + timing.DefaultRun.Stop(t) + initSnapshotTaken = true } - timing.DefaultRun.Stop(t) - initSnapshotTaken = true } if err := command.ExecuteCommand(&s.cf.Config, s.args); err != nil { @@ -368,7 +371,7 @@ func (s *stageBuilder) build() error { continue } - if isCacheCommand() { + if isCacheCommand { v := command.(commands.Cached) layer := v.Layer() if err := s.saveLayerToImage(layer, command.String()); err != nil { diff --git a/pkg/executor/fakes.go b/pkg/executor/fakes.go index e89d5ac47..41793af12 100644 --- a/pkg/executor/fakes.go +++ b/pkg/executor/fakes.go @@ -55,6 +55,9 @@ func (m MockDockerCommand) String() string { func (m MockDockerCommand) FilesToSnapshot() []string { return []string{"meow-snapshot-no-cache"} } +func (m MockDockerCommand) ProvidesFilesToSnapshot() bool { + return true +} func (m MockDockerCommand) CacheCommand(image v1.Image) commands.DockerCommand { return m.cacheCommand } @@ -84,6 +87,9 @@ func (m MockCachedDockerCommand) String() string { func (m MockCachedDockerCommand) FilesToSnapshot() []string { return []string{"meow-snapshot"} } +func (m MockCachedDockerCommand) ProvidesFilesToSnapshot() bool { + return true +} func (m MockCachedDockerCommand) CacheCommand(image v1.Image) commands.DockerCommand { return nil } diff --git a/pkg/snapshot/snapshot.go b/pkg/snapshot/snapshot.go index d750601a4..6b8f9a8a5 100644 --- a/pkg/snapshot/snapshot.go +++ b/pkg/snapshot/snapshot.go @@ -39,6 +39,7 @@ var snapshotPathPrefix = config.KanikoDir // Snapshotter holds the root directory from which to take snapshots, and a list of snapshots taken type Snapshotter struct { + i int l *LayeredMap directory string whitelist []util.WhitelistEntry @@ -51,7 +52,8 @@ func NewSnapshotter(l *LayeredMap, d string) *Snapshotter { // Init initializes a new snapshotter func (s *Snapshotter) Init() error { - logrus.Info("Taking initial snapshot") + s.i++ + logrus.Infof("Taking initial snapshot %d", s.i) _, _, err := s.scanFullFilesystem() return err }