support empty images in cache to handle WORKDIR w/o implicit folders created

This commit is contained in:
Martin Zihlmann 2024-10-13 10:56:06 +01:00
parent caebb2a538
commit 0561cc5664
No known key found for this signature in database
GPG Key ID: 0F7784F41354DE99
3 changed files with 29 additions and 24 deletions

View File

@ -88,11 +88,7 @@ func (w *WorkdirCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile
// FilesToSnapshot returns the workingdir, which should have been created if it didn't already exist // FilesToSnapshot returns the workingdir, which should have been created if it didn't already exist
func (w *WorkdirCommand) FilesToSnapshot() []string { func (w *WorkdirCommand) FilesToSnapshot() []string {
return nil return w.snapshotFiles
}
func (r *WorkdirCommand) ProvidesFilesToSnapshot() bool {
return false
} }
// String returns some information about the command for the image config history // String returns some information about the command for the image config history
@ -154,8 +150,11 @@ func (wr *CachingWorkdirCommand) ExecuteCommand(config *v1.Config, buildArgs *do
return errors.Wrap(err, "retrieving image layers") return errors.Wrap(err, "retrieving image layers")
} }
if len(layers) != 1 { if len(layers) > 1 {
return errors.New(fmt.Sprintf("expected %d layers but got %d", 1, len(layers))) return errors.New(fmt.Sprintf("expected %d layers but got %d", 1, len(layers)))
} else if len(layers) == 0 {
// an empty image in cache indicates that no directory was created by WORKDIR
return nil
} }
wr.layer = layers[0] wr.layer = layers[0]

View File

@ -414,11 +414,13 @@ func (s *stageBuilder) build() error {
continue continue
} }
if isCacheCommand { if isCacheCommand {
if files != nil && len(files) == 0 { v := command.(commands.Cached)
layer := v.Layer()
if (files != nil || layer == nil) && len(files) == 0 {
// a cache image with a layer with no files indicates that no files were changed, ie. by 'RUN echo hello'
// a cache image without a layer indicates that no files were changed too, ie. by 'WORKDIR /'
logrus.Info("No files were changed, appending empty layer to config. No layer added to image.") logrus.Info("No files were changed, appending empty layer to config. No layer added to image.")
} else { } else {
v := command.(commands.Cached)
layer := v.Layer()
if err := s.saveLayerToImage(layer, command.String()); err != nil { if err := s.saveLayerToImage(layer, command.String()); err != nil {
return errors.Wrap(err, "failed to save layer") return errors.Wrap(err, "failed to save layer")
} }

View File

@ -369,11 +369,6 @@ func pushLayerToCache(opts *config.KanikoOptions, cacheKey string, tarPath strin
// layer already gzipped by default // layer already gzipped by default
} }
layer, err := tarball.LayerFromFile(tarPath, layerOpts...)
if err != nil {
return err
}
cache, err := cache.Destination(opts, cacheKey) cache, err := cache.Destination(opts, cacheKey)
if err != nil { if err != nil {
return errors.Wrap(err, "getting cache destination") return errors.Wrap(err, "getting cache destination")
@ -385,18 +380,27 @@ func pushLayerToCache(opts *config.KanikoOptions, cacheKey string, tarPath strin
return errors.Wrap(err, "setting empty image created time") return errors.Wrap(err, "setting empty image created time")
} }
empty, err = mutate.Append(empty, // WORKDIR can create empty layers by design, yet still we must cache them
mutate.Addendum{ // to transfer the knowledge that they are empty.
Layer: layer, if tarPath != "" {
History: v1.History{ layer, err := tarball.LayerFromFile(tarPath, layerOpts...)
Author: constants.Author, if err != nil {
CreatedBy: createdBy, return err
}
empty, err = mutate.Append(empty,
mutate.Addendum{
Layer: layer,
History: v1.History{
Author: constants.Author,
CreatedBy: createdBy,
},
}, },
}, )
) if err != nil {
if err != nil { return errors.Wrap(err, "appending layer onto empty image")
return errors.Wrap(err, "appending layer onto empty image") }
} }
cacheOpts := *opts cacheOpts := *opts
cacheOpts.TarPath = "" // tarPath doesn't make sense for Docker layers cacheOpts.TarPath = "" // tarPath doesn't make sense for Docker layers
cacheOpts.NoPush = opts.NoPushCache // we do not want to push cache if --no-push-cache is set. cacheOpts.NoPush = opts.NoPushCache // we do not want to push cache if --no-push-cache is set.