Adjust API calls for compression

Add the various compression API calls as created by @nalind in #28807

Signed-off-by: Tom Sweeney <tsweeney@redhat.com>
This commit is contained in:
Tom Sweeney 2026-05-28 13:34:11 -04:00
parent 6b02641f73
commit 8b1e46170b
5 changed files with 88 additions and 5 deletions

View file

@ -26,6 +26,7 @@ import (
"go.podman.io/common/pkg/completion"
"go.podman.io/common/pkg/config"
"go.podman.io/image/v5/docker/reference"
"go.podman.io/image/v5/pkg/compression"
"go.podman.io/image/v5/types"
"go.podman.io/podman/v6/cmd/podman/registry"
"go.podman.io/podman/v6/cmd/podman/utils"
@ -425,9 +426,9 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *Buil
return nil, err
}
compression := buildahDefine.Gzip
compressionIntent := buildahDefine.Gzip
if flags.DisableCompression {
compression = buildahDefine.Uncompressed
compressionIntent = buildahDefine.Uncompressed
}
isolation := buildahDefine.IsolationDefault
@ -562,6 +563,44 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *Buil
sbomScanOptions = append(sbomScanOptions, *sbomScanOption)
}
if c.Flag("disable-compression").Changed && flags.DisableCompression {
if c.Flag("compression-format").Changed {
return nil, errors.New("--disable-compression and --compression-format cannot be used together")
}
if c.Flag("force-compression").Changed {
return nil, errors.New("--disable-compression and --force-compression cannot be used together")
}
}
var compressionLevel *int
if c.Flag("compression-level").Changed {
compressionLevel = &flags.CompressionLevel
} else {
compressionLevel = podmanConfig.ContainersConfDefaultsRO.Engine.CompressionLevel
}
var compressionFormat *compression.Algorithm
forceCompressionFormat := flags.ForceCompressionFormat
if c.Flag("compression-format").Changed {
algo, err := compression.AlgorithmByName(flags.CompressionFormat)
if err != nil {
return nil, fmt.Errorf("unable to parse value provided %q as --compression-format: %w", flags.CompressionFormat, err)
}
compressionFormat = &algo
if !c.Flag("disable-compression").Changed {
compressionIntent = buildahDefine.Gzip
}
} else {
algo, err := compression.AlgorithmByName(podmanConfig.ContainersConfDefaultsRO.Engine.CompressionFormat)
if err != nil {
return nil, fmt.Errorf("parsing compression_format from containers.conf: %w", err)
}
compressionFormat = &algo
if !c.Flag("force-compression").Changed {
forceCompressionFormat = true
}
if !c.Flag("disable-compression").Changed {
compressionIntent = buildahDefine.Gzip
}
}
opts := buildahDefine.BuildOptions{
AddCapabilities: flags.CapAdd,
AdditionalTags: tags,
@ -576,7 +615,9 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *Buil
CacheTTL: cacheTTL,
ConfidentialWorkload: confidentialWorkloadOptions,
CommonBuildOpts: commonOpts,
Compression: compression,
Compression: compressionIntent,
CompressionFormat: compressionFormat,
CompressionLevel: compressionLevel,
ConfigureNetwork: networkPolicy,
ContextDirectory: contextDir,
CPPFlags: flags.CPPFlags,
@ -585,6 +626,7 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *Buil
DropCapabilities: flags.CapDrop,
Envs: buildahCLI.LookupEnvVarReferences(flags.Envs, os.Environ()),
Err: stderr,
ForceCompressionFormat: forceCompressionFormat,
ForceRmIntermediateCtrs: flags.ForceRm,
From: flags.From,
GroupAdd: flags.GroupAdd,

View file

@ -25,6 +25,7 @@ import (
"go.podman.io/buildah/pkg/parse"
"go.podman.io/common/pkg/config"
"go.podman.io/image/v5/docker/reference"
"go.podman.io/image/v5/pkg/compression"
"go.podman.io/image/v5/types"
"go.podman.io/podman/v6/internal/localapi"
"go.podman.io/podman/v6/libpod"
@ -57,6 +58,8 @@ type BuildQuery struct {
CgroupParent string `schema:"cgroupparent"`
CompatVolumes bool `schema:"compatvolumes"`
Compression uint64 `schema:"compression"`
CompressionFormat string `schema:"compressionFormat"`
CompressionLevel *int `schema:"compressionLevel"`
ConfigureNetwork string `schema:"networkmode"`
CPPFlags string `schema:"cppflags"`
CpuPeriod uint64 `schema:"cpuperiod"`
@ -74,6 +77,7 @@ type BuildQuery struct {
Envs []string `schema:"setenv"`
Excludes string `schema:"excludes"`
ForceRm bool `schema:"forcerm"`
ForceCompressionFormat bool `schema:"forceCompressionFormat"`
From string `schema:"from"`
GroupAdd []string `schema:"groupadd"`
HTTPProxy bool `schema:"httpproxy"`
@ -385,7 +389,7 @@ func createBuildOptions(query *BuildQuery, buildCtx *BuildContext, queryValues u
compatVolumes, _ := utils.ParseOptionalBool(query.CompatVolumes, "compatvolumes", queryValues)
compression := archive.Compression(query.Compression)
compressionIntent := archive.Compression(query.Compression)
if query.StageLabels && !query.SaveStages {
return nil, nil, utils.GetGenericBadRequestError(errors.New("stage-labels requires save-stages be set as well"))
@ -694,6 +698,15 @@ func createBuildOptions(query *BuildQuery, buildCtx *BuildContext, queryValues u
sbomScanOptions = append(sbomScanOptions, *sbomScanOption)
}
var compressionFormat *compression.Algorithm
if query.CompressionFormat != "" {
algo, err := compression.AlgorithmByName(query.CompressionFormat)
if err != nil {
return nil, cleanup, utils.GetBadRequestError("compressionFormat", query.CompressionFormat, err)
}
compressionFormat = &algo
}
// Create build options
buildOptions := &buildahDefine.BuildOptions{
AddCapabilities: addCaps,
@ -732,8 +745,10 @@ func createBuildOptions(query *BuildQuery, buildCtx *BuildContext, queryValues u
Volumes: query.Volumes,
},
CompatVolumes: compatVolumes,
CompressionFormat: compressionFormat,
CompressionLevel: query.CompressionLevel,
CreatedAnnotation: query.CreatedAnnotation,
Compression: compression,
Compression: compressionIntent,
ConfigureNetwork: parseNetworkConfigurationPolicy(query.ConfigureNetwork),
ContextDirectory: buildCtx.ContextDirectory,
Devices: devices,

View file

@ -289,6 +289,18 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// type: boolean
// description: Use compression on image.
// - in: query
// name: compressionFormat
// type: string
// description: The type of compression to apply to layer blobs pushed to build caches in registries.
// - in: query
// name: compressionLevel
// type: integer
// description: The level of compression to apply to layer blobs pushed to build caches in registries. The range of acceptable values varies based on the compression format.
// - in: query
// name: forceCompressionFormat
// type: boolean
// description: Use the specified compression format for layer blobs, even when pushing to a location where an equivalent blob which differs only in how it's compressed could be reused.
// - in: query
// name: destination
// type: string
// description: Allows for pushing the image to a different destination than the image refers to.

View file

@ -175,6 +175,17 @@ func prepareParams(options types.BuildOptions) (url.Values, error) {
}
params.Set("idmappingoptions", string(idmappingsOptions))
}
if options.CompressionFormat != nil {
params.Set("compressionFormat", options.CompressionFormat.Name())
}
if options.CompressionLevel != nil {
params.Set("compressionLevel", strconv.Itoa(*options.CompressionLevel))
}
if options.ForceCompressionFormat {
params.Set("forceCompressionFormat", "1")
} else {
params.Set("forceCompressionFormat", "0")
}
if buildArgs := options.Args; len(buildArgs) > 0 {
bArgs, err := jsoniter.MarshalToString(buildArgs)
if err != nil {

View file

@ -349,6 +349,9 @@ skip "Requires bit-identical tar outputs when using process substitution" \
"use-secret-to-env-variable" \
"use-secret-to-env-variable-and-file-path"
skip_if_remote "remote builds only commit to local storage, and this test isn't worth working around that" \
"build --compression-format zstd to dir and oci-archive"
# END temporary workarounds that must be reevaluated periodically
###############################################################################