Skip to content

Commit

Permalink
cmd, push: expose --compression-level
Browse files Browse the repository at this point in the history
This patch adds the --compression-level option to the push command.

Closes: #18939

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
  • Loading branch information
giuseppe committed Jun 20, 2023
1 parent cc023c0 commit 66ce890
Show file tree
Hide file tree
Showing 15 changed files with 82 additions and 3 deletions.
12 changes: 12 additions & 0 deletions cmd/podman/images/push.go
Expand Up @@ -130,6 +130,10 @@ func pushFlags(cmd *cobra.Command) {
flags.StringVar(&pushOptions.CompressionFormat, compressionFormat, "", "compression format to use")
_ = cmd.RegisterFlagCompletionFunc(compressionFormat, common.AutocompleteCompressionFormat)

compressionLevel := "compression-level"
flags.Int(compressionLevel, 0, "compression level to use")
_ = cmd.RegisterFlagCompletionFunc(compressionLevel, completion.AutocompleteNone)

encryptionKeysFlagName := "encryption-key"
flags.StringSliceVar(&pushOptions.EncryptionKeys, encryptionKeysFlagName, nil, "Key with the encryption protocol to use to encrypt the image (e.g. jwe:/path/to/key.pem)")
_ = cmd.RegisterFlagCompletionFunc(encryptionKeysFlagName, completion.AutocompleteDefault)
Expand Down Expand Up @@ -201,6 +205,14 @@ func imagePush(cmd *cobra.Command, args []string) error {
pushOptions.OciEncryptConfig = encConfig
pushOptions.OciEncryptLayers = encLayers

if cmd.Flags().Changed("compression-level") {
val, err := cmd.Flags().GetInt("compression-level")
if err != nil {
return err
}
pushOptions.CompressionLevel = &val
}

// Let's do all the remaining Yoga in the API to prevent us from scattering
// logic across (too) many parts of the code.
report, err := registry.ImageEngine().Push(registry.GetContext(), source, destination, pushOptions.ImagePushOptions)
Expand Down
13 changes: 13 additions & 0 deletions cmd/podman/manifest/push.go
Expand Up @@ -100,6 +100,10 @@ func init() {
flags.StringVar(&manifestPushOpts.CompressionFormat, compressionFormat, "", "compression format to use")
_ = pushCmd.RegisterFlagCompletionFunc(compressionFormat, common.AutocompleteCompressionFormat)

compressionLevel := "compression-level"
flags.Int(compressionLevel, 0, "compression level to use")
_ = pushCmd.RegisterFlagCompletionFunc(compressionLevel, completion.AutocompleteNone)

if registry.IsRemote() {
_ = flags.MarkHidden("cert-dir")
_ = flags.MarkHidden(signByFlagName)
Expand Down Expand Up @@ -155,6 +159,15 @@ func push(cmd *cobra.Command, args []string) error {
}
manifestPushOpts.SkipTLSVerify = types.NewOptionalBool(manifestPushOpts.Insecure)
}

if cmd.Flags().Changed("compression-level") {
val, err := cmd.Flags().GetInt("compression-level")
if err != nil {
return err
}
manifestPushOpts.CompressionLevel = &val
}

digest, err := registry.ImageEngine().ManifestPush(registry.Context(), listImageSpec, destSpec, manifestPushOpts.ImagePushOptions)
if err != nil {
return err
Expand Down
7 changes: 7 additions & 0 deletions docs/source/markdown/options/compression-level.md
@@ -0,0 +1,7 @@
####> This option file is used in:
####> podman manifest push, push
####> If file is edited, make sure the changes
####> are applicable to all of those.
#### **--compression-level**=*level*

Specifies the compression level to use. The value is specific to the compression algorithm used, e.g. for zstd the accepted values are in the range 1-20 (inclusive), while for gzip it is 1-9 (inclusive).
2 changes: 2 additions & 0 deletions docs/source/markdown/podman-manifest-push.1.md.in
Expand Up @@ -25,6 +25,8 @@ the list or index itself. (Default true)

@@option compression-format

@@option compression-level

@@option creds

@@option digestfile
Expand Down
2 changes: 2 additions & 0 deletions docs/source/markdown/podman-push.1.md.in
Expand Up @@ -54,6 +54,8 @@ Note: This flag can only be set when using the **dir** transport

@@option compression-format

@@option compression-level

@@option creds

@@option digestfile
Expand Down
2 changes: 2 additions & 0 deletions pkg/api/handlers/libpod/images_push.go
Expand Up @@ -27,6 +27,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
query := struct {
All bool `schema:"all"`
CompressionFormat string `schema:"compressionFormat"`
CompressionLevel *int `schema:"compressionLevel"`
Destination string `schema:"destination"`
Format string `schema:"format"`
RemoveSignatures bool `schema:"removeSignatures"`
Expand Down Expand Up @@ -75,6 +76,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
All: query.All,
Authfile: authfile,
CompressionFormat: query.CompressionFormat,
CompressionLevel: query.CompressionLevel,
Format: query.Format,
Password: password,
Quiet: true,
Expand Down
2 changes: 2 additions & 0 deletions pkg/api/handlers/libpod/manifests.go
Expand Up @@ -328,6 +328,7 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) {
query := struct {
All bool `schema:"all"`
CompressionFormat string `schema:"compressionFormat"`
CompressionLevel *int `schema:"compressionLevel"`
Format string `schema:"format"`
RemoveSignatures bool `schema:"removeSignatures"`
TLSVerify bool `schema:"tlsVerify"`
Expand Down Expand Up @@ -366,6 +367,7 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) {
All: query.All,
Authfile: authfile,
CompressionFormat: query.CompressionFormat,
CompressionLevel: query.CompressionLevel,
Format: query.Format,
Password: password,
Quiet: true,
Expand Down
2 changes: 2 additions & 0 deletions pkg/bindings/images/types.go
Expand Up @@ -142,6 +142,8 @@ type PushOptions struct {
Compress *bool
// CompressionFormat is the format to use for the compression of the blobs
CompressionFormat *string
// CompressionLevel is the level to use for the compression of the blobs
CompressionLevel *int
// Manifest type of the pushed image
Format *string
// Password for authenticating against the registry.
Expand Down
15 changes: 15 additions & 0 deletions pkg/bindings/images/types_push_options.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pkg/domain/entities/images.go
Expand Up @@ -231,6 +231,8 @@ type ImagePushOptions struct {
Progress chan types.ProgressProperties
// CompressionFormat is the format to use for the compression of the blobs
CompressionFormat string
// CompressionLevel is the level to use for the compression of the blobs
CompressionLevel *int
// Writer is used to display copy information including progress bars.
Writer io.Writer
// OciEncryptConfig when non-nil indicates that an image should be encrypted.
Expand Down
1 change: 1 addition & 0 deletions pkg/domain/infra/abi/images.go
Expand Up @@ -316,6 +316,7 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
pushOptions.Writer = options.Writer
pushOptions.OciEncryptConfig = options.OciEncryptConfig
pushOptions.OciEncryptLayers = options.OciEncryptLayers
pushOptions.CompressionLevel = options.CompressionLevel

compressionFormat := options.CompressionFormat
if compressionFormat == "" {
Expand Down
1 change: 1 addition & 0 deletions pkg/domain/infra/abi/manifest.go
Expand Up @@ -340,6 +340,7 @@ func (ir *ImageEngine) ManifestPush(ctx context.Context, name, destination strin
pushOptions.SignSigstorePrivateKeyPassphrase = opts.SignSigstorePrivateKeyPassphrase
pushOptions.InsecureSkipTLSVerify = opts.SkipTLSVerify
pushOptions.Writer = opts.Writer
pushOptions.CompressionLevel = opts.CompressionLevel

compressionFormat := opts.CompressionFormat
if compressionFormat == "" {
Expand Down
4 changes: 4 additions & 0 deletions pkg/domain/infra/tunnel/images.go
Expand Up @@ -254,6 +254,10 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
options := new(images.PushOptions)
options.WithAll(opts.All).WithCompress(opts.Compress).WithUsername(opts.Username).WithPassword(opts.Password).WithAuthfile(opts.Authfile).WithFormat(opts.Format).WithRemoveSignatures(opts.RemoveSignatures).WithQuiet(opts.Quiet).WithCompressionFormat(opts.CompressionFormat).WithProgressWriter(opts.Writer)

if opts.CompressionLevel != nil {
options.WithCompressionLevel(*opts.CompressionLevel)
}

if s := opts.SkipTLSVerify; s != types.OptionalBoolUndefined {
if s == types.OptionalBoolTrue {
options.WithSkipTLSVerify(true)
Expand Down
9 changes: 8 additions & 1 deletion test/e2e/manifest_test.go
Expand Up @@ -434,7 +434,14 @@ var _ = Describe("Podman manifest", func() {
Expect(output).To(ContainSubstring("Writing manifest to image destination"))
Expect(output).To(ContainSubstring("Storing signatures"))

push = podmanTest.Podman([]string{"manifest", "push", "--tls-verify=false", "--creds=podmantest:wrongpasswd", "foo", "localhost:" + registry.Port + "/credstest"})
// Invalid compression format specified for gzip, it must fail
push = podmanTest.Podman([]string{"manifest", "push", "--compression-format=zstd", "--compression-level=50", "--tls-verify=false", "--creds=" + registry.User + ":" + registry.Password, "--format=v2s2", "localhost:" + registry.Port + "/alpine:latest"})
push.WaitWithDefaultTimeout()
Expect(push).Should(Exit(125))
output = push.ErrorToString()
Expect(output).To(ContainSubstring("invalid compression level"))

push = podmanTest.Podman([]string{"manifest", "push", "--compression-format=gzip", "--compression-level=2", "--tls-verify=false", "--creds=podmantest:wrongpasswd", "foo", "localhost:" + registry.Port + "/credstest"})
push.WaitWithDefaultTimeout()
Expect(push).To(ExitWithError())
Expect(push.ErrorToString()).To(ContainSubstring(": authentication required"))
Expand Down
11 changes: 9 additions & 2 deletions test/e2e/push_test.go
Expand Up @@ -99,10 +99,17 @@ var _ = Describe("Podman push", func() {
Expect(push).Should(Exit(0))
Expect(push.ErrorToString()).To(BeEmpty())

push = podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, "localhost:5000/my-alpine"})
// Invalid compression format specified for gzip, it must fail
push = podmanTest.Podman([]string{"push", "--compression-format=zstd", "--compression-level=40", "--tls-verify=false", "--remove-signatures", ALPINE, "localhost:5000/my-alpine"})
push.WaitWithDefaultTimeout()
Expect(push).Should(Exit(0))
Expect(push).Should(Exit(125))
output := push.ErrorToString()
Expect(output).To(ContainSubstring("invalid compression level"))

push = podmanTest.Podman([]string{"push", "--compression-format=gzip", "--compression-level=1", "--tls-verify=false", "--remove-signatures", ALPINE, "localhost:5000/my-alpine"})
push.WaitWithDefaultTimeout()
Expect(push).Should(Exit(0))
output = push.ErrorToString()
Expect(output).To(ContainSubstring("Copying blob "))
Expect(output).To(ContainSubstring("Copying config "))
Expect(output).To(ContainSubstring("Writing manifest to image destination"))
Expand Down

0 comments on commit 66ce890

Please sign in to comment.