Add support for podman push --retry --retry-delay

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh 2024-02-21 06:11:50 -05:00
parent e5ee0bb5f3
commit c3c0c4ab96
No known key found for this signature in database
GPG Key ID: A2DF901DABE2C028
13 changed files with 138 additions and 9 deletions

View File

@ -114,10 +114,10 @@ func pullFlags(cmd *cobra.Command) {
_ = cmd.RegisterFlagCompletionFunc(decryptionKeysFlagName, completion.AutocompleteDefault)
retryFlagName := "retry"
flags.Uint(retryFlagName, cli.MaxPullPushRetries, "number of times to retry in case of failure when performing pull")
flags.Uint(retryFlagName, registry.RetryDefault(), "number of times to retry in case of failure when performing pull")
_ = cmd.RegisterFlagCompletionFunc(retryFlagName, completion.AutocompleteNone)
retryDelayFlagName := "retry-delay"
flags.String(retryDelayFlagName, cli.PullPushRetryDelay.String(), "delay between retries in case of pull failures")
flags.String(retryDelayFlagName, registry.RetryDelayDefault(), "delay between retries in case of pull failures")
_ = cmd.RegisterFlagCompletionFunc(retryDelayFlagName, completion.AutocompleteNone)
if registry.IsRemote() {

View File

@ -111,6 +111,13 @@ func pushFlags(cmd *cobra.Command) {
flags.BoolVarP(&pushOptions.Quiet, "quiet", "q", false, "Suppress output information when pushing images")
flags.BoolVar(&pushOptions.RemoveSignatures, "remove-signatures", false, "Discard any pre-existing signatures in the image")
retryFlagName := "retry"
flags.Uint(retryFlagName, registry.RetryDefault(), "number of times to retry in case of failure when performing push")
_ = cmd.RegisterFlagCompletionFunc(retryFlagName, completion.AutocompleteNone)
retryDelayFlagName := "retry-delay"
flags.String(retryDelayFlagName, registry.RetryDelayDefault(), "delay between retries in case of push failures")
_ = cmd.RegisterFlagCompletionFunc(retryDelayFlagName, completion.AutocompleteNone)
signByFlagName := "sign-by"
flags.StringVar(&pushOptions.SignBy, signByFlagName, "", "Add a signature at the destination using the specified key")
_ = cmd.RegisterFlagCompletionFunc(signByFlagName, completion.AutocompleteNone)
@ -208,6 +215,24 @@ func imagePush(cmd *cobra.Command, args []string) error {
pushOptions.OciEncryptConfig = encConfig
pushOptions.OciEncryptLayers = encLayers
if cmd.Flags().Changed("retry") {
retry, err := cmd.Flags().GetUint("retry")
if err != nil {
return err
}
pushOptions.Retry = &retry
}
if cmd.Flags().Changed("retry-delay") {
val, err := cmd.Flags().GetString("retry-delay")
if err != nil {
return err
}
pushOptions.RetryDelay = val
}
if cmd.Flags().Changed("compression-level") {
val, err := cmd.Flags().GetInt("compression-level")
if err != nil {

View File

@ -166,3 +166,19 @@ func setXdgDirs() error {
}
return nil
}
func RetryDefault() uint {
if IsRemote() {
return 0
}
return PodmanConfig().ContainersConfDefaultsRO.Engine.Retry
}
func RetryDelayDefault() string {
if IsRemote() {
return ""
}
return PodmanConfig().ContainersConfDefaultsRO.Engine.RetryDelay
}

View File

@ -1,7 +1,8 @@
####> This option file is used in:
####> podman build, farm build, pull
####> podman build, farm build, pull, push
####> If file is edited, make sure the changes
####> are applicable to all of those.
#### **--retry-delay**=*duration*
Duration of delay between retry attempts in case of failure when performing pull of images from registry. Default is **2s**.
Duration of delay between retry attempts when pulling or pushing images between
the registry and local storage in case of failure. The default is to start at two seconds and then exponentially back off. The delay is used when this value is set, and no exponential back off occurs.

View File

@ -1,8 +1,8 @@
####> This option file is used in:
####> podman build, farm build, pull
####> podman build, farm build, pull, push
####> If file is edited, make sure the changes
####> are applicable to all of those.
#### **--retry**=*attempts*
Number of times to retry in case of failure when performing pull of
images from registry. Default is **3**.
Number of times to retry pulling or pushing images between the registry and
local storage in case of failure. Default is **3**.

View File

@ -84,6 +84,10 @@ When writing the output image, suppress progress output
Discard any pre-existing signatures in the image.
@@option retry
@@option retry-delay
#### **--sign-by**=*key*
Add a “simple signing” signature at the destination using the specified key. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)

View File

@ -32,6 +32,8 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
Destination string `schema:"destination"`
Format string `schema:"format"`
RemoveSignatures bool `schema:"removeSignatures"`
Retry uint `schema:"retry"`
RetryDelay string `schema:"retryDelay"`
TLSVerify bool `schema:"tlsVerify"`
Quiet bool `schema:"quiet"`
}{
@ -83,9 +85,14 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
Password: password,
Quiet: query.Quiet,
RemoveSignatures: query.RemoveSignatures,
RetryDelay: query.RetryDelay,
Username: username,
}
if _, found := r.URL.Query()["retry"]; found {
options.Retry = &query.Retry
}
if _, found := r.URL.Query()["compressionFormat"]; found {
if _, foundForceCompression := r.URL.Query()["forceCompressionFormat"]; !foundForceCompression {
// If `compressionFormat` is set and no value for `forceCompressionFormat`

View File

@ -162,6 +162,10 @@ type PushOptions struct {
SkipTLSVerify *bool `schema:"-"`
// RemoveSignatures Discard any pre-existing signatures in the image.
RemoveSignatures *bool
// Retry number of times to retry push in case of failure
Retry *uint
// RetryDelay between retries in case of push failures
RetryDelay *string
// Username for authenticating against the registry.
Username *string `schema:"-"`
// Quiet can be specified to suppress progress when pushing.

View File

@ -198,6 +198,36 @@ func (o *PushOptions) GetRemoveSignatures() bool {
return *o.RemoveSignatures
}
// WithRetry set field Retry to given value
func (o *PushOptions) WithRetry(value uint) *PushOptions {
o.Retry = &value
return o
}
// GetRetry returns value of field Retry
func (o *PushOptions) GetRetry() uint {
if o.Retry == nil {
var z uint
return z
}
return *o.Retry
}
// WithRetryDelay set field RetryDelay to given value
func (o *PushOptions) WithRetryDelay(value string) *PushOptions {
o.RetryDelay = &value
return o
}
// GetRetryDelay returns value of field RetryDelay
func (o *PushOptions) GetRetryDelay() string {
if o.RetryDelay == nil {
var z string
return z
}
return *o.RetryDelay
}
// WithUsername set field Username to given value
func (o *PushOptions) WithUsername(value string) *PushOptions {
o.Username = &value

View File

@ -151,6 +151,10 @@ type ImagePushOptions struct {
// RemoveSignatures, discard any pre-existing signatures in the image.
// Ignored for remote calls.
RemoveSignatures bool
// Retry number of times to retry push in case of failure
Retry *uint
// RetryDelay between retries in case of push failures
RetryDelay string
// SignaturePolicy to use when pulling. Ignored for remote calls.
SignaturePolicy string
// Signers, if non-empty, asks for signatures to be added during the copy

View File

@ -254,8 +254,8 @@ func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, options entiti
pullOptions.InsecureSkipTLSVerify = options.SkipTLSVerify
pullOptions.Writer = options.Writer
pullOptions.OciDecryptConfig = options.OciDecryptConfig
pullOptions.MaxRetries = options.Retry
if options.RetryDelay != "" {
duration, err := time.ParseDuration(options.RetryDelay)
if err != nil {
@ -343,6 +343,14 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
pushOptions.OciEncryptLayers = options.OciEncryptLayers
pushOptions.CompressionLevel = options.CompressionLevel
pushOptions.ForceCompressionFormat = options.ForceCompressionFormat
pushOptions.MaxRetries = options.Retry
if options.RetryDelay != "" {
duration, err := time.ParseDuration(options.RetryDelay)
if err != nil {
return nil, err
}
pushOptions.RetryDelay = &duration
}
compressionFormat := options.CompressionFormat
if compressionFormat == "" {

View File

@ -273,6 +273,12 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
options.WithSkipTLSVerify(false)
}
}
if opts.Retry != nil {
options.WithRetry(*opts.Retry)
}
if opts.RetryDelay != "" {
options.WithRetryDelay(opts.RetryDelay)
}
if err := images.Push(ir.ClientCtx, source, destination, options); err != nil {
return nil, err
}

View File

@ -327,7 +327,7 @@ function _test_skopeo_credential_sharing() {
}
@test "podman images with retry" {
@test "podman pull images with retry" {
run_podman pull -q --retry 4 --retry-delay "10s" $IMAGE
run_podman 125 pull -q --retry 4 --retry-delay "bogus" $IMAGE
is "$output" 'Error: time: invalid duration "bogus"' "bad retry-delay"
@ -367,6 +367,30 @@ function _test_skopeo_credential_sharing() {
run_podman rmi $image1
}
@test "podman containers.conf retry" {
skip_if_remote "containers.conf settings not set for remote connections"
run_podman pull --help
assert "$output" =~ "--retry .*performing pull \(default 3\)"
run_podman push --help
assert "$output" =~ "--retry .*performing push \(default 3\)"
containersConf=$PODMAN_TMPDIR/containers.conf
cat >$containersConf <<EOF
[engine]
retry=10
retry_delay="5s"
EOF
CONTAINERS_CONF="$containersConf" run_podman pull --help
assert "$output" =~ "--retry .*performing pull \(default 10\)"
assert "$output" =~ "--retry-delay .*pull failures \(default \"5s\"\)"
CONTAINERS_CONF="$containersConf" run_podman push --help
assert "$output" =~ "--retry .*performing push \(default 10\)"
assert "$output" =~ "--retry-delay .*push failures \(default \"5s\"\)"
}
# END cooperation with skopeo
# END actual tests
###############################################################################