diff --git a/cmd/executor/cmd/root.go b/cmd/executor/cmd/root.go index eadda2eaec..5597d33dfc 100644 --- a/cmd/executor/cmd/root.go +++ b/cmd/executor/cmd/root.go @@ -225,6 +225,8 @@ func addKanikoOptionsFlags() { RootCmd.PersistentFlags().StringVarP(&opts.ImageNameDigestFile, "image-name-with-digest-file", "", "", "Specify a file to save the image name w/ digest of the built image to.") RootCmd.PersistentFlags().StringVarP(&opts.ImageNameTagDigestFile, "image-name-tag-with-digest-file", "", "", "Specify a file to save the image name w/ image tag w/ digest of the built image to.") RootCmd.PersistentFlags().StringVarP(&opts.OCILayoutPath, "oci-layout-path", "", "", "Path to save the OCI image layout of the built image.") + RootCmd.PersistentFlags().VarP(&opts.Compression, "compression", "", "Compression algorithm (gzip, zstd)") + RootCmd.PersistentFlags().IntVarP(&opts.CompressionLevel, "compression-level", "", -1, "Compression level") RootCmd.PersistentFlags().BoolVarP(&opts.Cache, "cache", "", false, "Use cache when building image") RootCmd.PersistentFlags().BoolVarP(&opts.CompressedCaching, "compressed-caching", "", true, "Compress the cached layers. Decreases build time, but increases memory usage.") RootCmd.PersistentFlags().BoolVarP(&opts.Cleanup, "cleanup", "", false, "Clean the filesystem at the end") diff --git a/pkg/config/options.go b/pkg/config/options.go index d368db139a..b330f4a263 100644 --- a/pkg/config/options.go +++ b/pkg/config/options.go @@ -68,6 +68,8 @@ type KanikoOptions struct { ImageNameDigestFile string ImageNameTagDigestFile string OCILayoutPath string + Compression Compression + CompressionLevel int ImageFSExtractRetry int SingleSnapshot bool Reproducible bool @@ -125,6 +127,33 @@ func (k *KanikoGitOptions) Set(s string) error { return nil } +// Compression is an enumeration of the supported compression algorithms +type Compression string + +// The collection of known MediaType values. +const ( + GZip Compression = "gzip" + ZStd Compression = "zstd" +) + +func (c *Compression) String() string { + return string(*c) +} + +func (c *Compression) Set(v string) error { + switch v { + case "gzip", "zstd": + *c = Compression(v) + return nil + default: + return errors.New(`must be either "gzip" or "zstd"`) + } +} + +func (c *Compression) Type() string { + return "compression" +} + // WarmerOptions are options that are set by command line arguments to the cache warmer. type WarmerOptions struct { CacheOptions diff --git a/pkg/executor/build.go b/pkg/executor/build.go index 2860626087..02575776ec 100644 --- a/pkg/executor/build.go +++ b/pkg/executor/build.go @@ -515,12 +515,25 @@ func (s *stageBuilder) saveSnapshotToLayer(tarPath string) (v1.Layer, error) { return nil, nil } - var layer v1.Layer + var layerOpts []tarball.LayerOption + if s.opts.CompressedCaching == true { - layer, err = tarball.LayerFromFile(tarPath, tarball.WithCompressedCaching) - } else { - layer, err = tarball.LayerFromFile(tarPath) + layerOpts = append(layerOpts, tarball.WithCompressedCaching) + } + + if s.opts.CompressionLevel > 0 { + layerOpts = append(layerOpts, tarball.WithCompressionLevel(s.opts.CompressionLevel)) } + + switch s.opts.Compression { + case config.ZStd: + layerOpts = append(layerOpts, tarball.WithCompression("zstd")) + + case config.GZip: + // layer already gzipped by default + } + + layer, err := tarball.LayerFromFile(tarPath, layerOpts...) if err != nil { return nil, err } diff --git a/pkg/executor/push.go b/pkg/executor/push.go index 7e2e156a21..f8620dbd68 100644 --- a/pkg/executor/push.go +++ b/pkg/executor/push.go @@ -296,16 +296,28 @@ func writeImageOutputs(image v1.Image, destRefs []name.Tag) error { // pushLayerToCache pushes layer (tagged with cacheKey) to opts.CacheRepo // if opts.CacheRepo doesn't exist, infer the cache from the given destination func pushLayerToCache(opts *config.KanikoOptions, cacheKey string, tarPath string, createdBy string) error { - var layer v1.Layer - var err error + var layerOpts []tarball.LayerOption if opts.CompressedCaching == true { - layer, err = tarball.LayerFromFile(tarPath, tarball.WithCompressedCaching) - } else { - layer, err = tarball.LayerFromFile(tarPath) + layerOpts = append(layerOpts, tarball.WithCompressedCaching) } + + if opts.CompressionLevel > 0 { + layerOpts = append(layerOpts, tarball.WithCompressionLevel(opts.CompressionLevel)) + } + + switch opts.Compression { + case config.ZStd: + layerOpts = append(layerOpts, tarball.WithCompression("zstd")) + + case config.GZip: + // layer already gzipped by default + } + + layer, err := tarball.LayerFromFile(tarPath, layerOpts...) if err != nil { return err } + cache, err := cache.Destination(opts, cacheKey) if err != nil { return errors.Wrap(err, "getting cache destination")