mirror of https://github.com/containers/podman.git
Add support for podman push --retry --retry-delay
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
parent
e5ee0bb5f3
commit
c3c0c4ab96
|
@ -114,10 +114,10 @@ func pullFlags(cmd *cobra.Command) {
|
||||||
_ = cmd.RegisterFlagCompletionFunc(decryptionKeysFlagName, completion.AutocompleteDefault)
|
_ = cmd.RegisterFlagCompletionFunc(decryptionKeysFlagName, completion.AutocompleteDefault)
|
||||||
|
|
||||||
retryFlagName := "retry"
|
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)
|
_ = cmd.RegisterFlagCompletionFunc(retryFlagName, completion.AutocompleteNone)
|
||||||
retryDelayFlagName := "retry-delay"
|
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)
|
_ = cmd.RegisterFlagCompletionFunc(retryDelayFlagName, completion.AutocompleteNone)
|
||||||
|
|
||||||
if registry.IsRemote() {
|
if registry.IsRemote() {
|
||||||
|
|
|
@ -111,6 +111,13 @@ func pushFlags(cmd *cobra.Command) {
|
||||||
flags.BoolVarP(&pushOptions.Quiet, "quiet", "q", false, "Suppress output information when pushing images")
|
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")
|
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"
|
signByFlagName := "sign-by"
|
||||||
flags.StringVar(&pushOptions.SignBy, signByFlagName, "", "Add a signature at the destination using the specified key")
|
flags.StringVar(&pushOptions.SignBy, signByFlagName, "", "Add a signature at the destination using the specified key")
|
||||||
_ = cmd.RegisterFlagCompletionFunc(signByFlagName, completion.AutocompleteNone)
|
_ = cmd.RegisterFlagCompletionFunc(signByFlagName, completion.AutocompleteNone)
|
||||||
|
@ -208,6 +215,24 @@ func imagePush(cmd *cobra.Command, args []string) error {
|
||||||
pushOptions.OciEncryptConfig = encConfig
|
pushOptions.OciEncryptConfig = encConfig
|
||||||
pushOptions.OciEncryptLayers = encLayers
|
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") {
|
if cmd.Flags().Changed("compression-level") {
|
||||||
val, err := cmd.Flags().GetInt("compression-level")
|
val, err := cmd.Flags().GetInt("compression-level")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -166,3 +166,19 @@ func setXdgDirs() error {
|
||||||
}
|
}
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
####> This option file is used in:
|
####> 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
|
####> If file is edited, make sure the changes
|
||||||
####> are applicable to all of those.
|
####> are applicable to all of those.
|
||||||
#### **--retry-delay**=*duration*
|
#### **--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.
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
####> This option file is used in:
|
####> 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
|
####> If file is edited, make sure the changes
|
||||||
####> are applicable to all of those.
|
####> are applicable to all of those.
|
||||||
#### **--retry**=*attempts*
|
#### **--retry**=*attempts*
|
||||||
|
|
||||||
Number of times to retry in case of failure when performing pull of
|
Number of times to retry pulling or pushing images between the registry and
|
||||||
images from registry. Default is **3**.
|
local storage in case of failure. Default is **3**.
|
||||||
|
|
|
@ -84,6 +84,10 @@ When writing the output image, suppress progress output
|
||||||
|
|
||||||
Discard any pre-existing signatures in the image.
|
Discard any pre-existing signatures in the image.
|
||||||
|
|
||||||
|
@@option retry
|
||||||
|
|
||||||
|
@@option retry-delay
|
||||||
|
|
||||||
#### **--sign-by**=*key*
|
#### **--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)
|
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)
|
||||||
|
|
|
@ -32,6 +32,8 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
|
||||||
Destination string `schema:"destination"`
|
Destination string `schema:"destination"`
|
||||||
Format string `schema:"format"`
|
Format string `schema:"format"`
|
||||||
RemoveSignatures bool `schema:"removeSignatures"`
|
RemoveSignatures bool `schema:"removeSignatures"`
|
||||||
|
Retry uint `schema:"retry"`
|
||||||
|
RetryDelay string `schema:"retryDelay"`
|
||||||
TLSVerify bool `schema:"tlsVerify"`
|
TLSVerify bool `schema:"tlsVerify"`
|
||||||
Quiet bool `schema:"quiet"`
|
Quiet bool `schema:"quiet"`
|
||||||
}{
|
}{
|
||||||
|
@ -83,9 +85,14 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
|
||||||
Password: password,
|
Password: password,
|
||||||
Quiet: query.Quiet,
|
Quiet: query.Quiet,
|
||||||
RemoveSignatures: query.RemoveSignatures,
|
RemoveSignatures: query.RemoveSignatures,
|
||||||
|
RetryDelay: query.RetryDelay,
|
||||||
Username: username,
|
Username: username,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, found := r.URL.Query()["retry"]; found {
|
||||||
|
options.Retry = &query.Retry
|
||||||
|
}
|
||||||
|
|
||||||
if _, found := r.URL.Query()["compressionFormat"]; found {
|
if _, found := r.URL.Query()["compressionFormat"]; found {
|
||||||
if _, foundForceCompression := r.URL.Query()["forceCompressionFormat"]; !foundForceCompression {
|
if _, foundForceCompression := r.URL.Query()["forceCompressionFormat"]; !foundForceCompression {
|
||||||
// If `compressionFormat` is set and no value for `forceCompressionFormat`
|
// If `compressionFormat` is set and no value for `forceCompressionFormat`
|
||||||
|
|
|
@ -162,6 +162,10 @@ type PushOptions struct {
|
||||||
SkipTLSVerify *bool `schema:"-"`
|
SkipTLSVerify *bool `schema:"-"`
|
||||||
// RemoveSignatures Discard any pre-existing signatures in the image.
|
// RemoveSignatures Discard any pre-existing signatures in the image.
|
||||||
RemoveSignatures *bool
|
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 for authenticating against the registry.
|
||||||
Username *string `schema:"-"`
|
Username *string `schema:"-"`
|
||||||
// Quiet can be specified to suppress progress when pushing.
|
// Quiet can be specified to suppress progress when pushing.
|
||||||
|
|
|
@ -198,6 +198,36 @@ func (o *PushOptions) GetRemoveSignatures() bool {
|
||||||
return *o.RemoveSignatures
|
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
|
// WithUsername set field Username to given value
|
||||||
func (o *PushOptions) WithUsername(value string) *PushOptions {
|
func (o *PushOptions) WithUsername(value string) *PushOptions {
|
||||||
o.Username = &value
|
o.Username = &value
|
||||||
|
|
|
@ -151,6 +151,10 @@ type ImagePushOptions struct {
|
||||||
// RemoveSignatures, discard any pre-existing signatures in the image.
|
// RemoveSignatures, discard any pre-existing signatures in the image.
|
||||||
// Ignored for remote calls.
|
// Ignored for remote calls.
|
||||||
RemoveSignatures bool
|
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 to use when pulling. Ignored for remote calls.
|
||||||
SignaturePolicy string
|
SignaturePolicy string
|
||||||
// Signers, if non-empty, asks for signatures to be added during the copy
|
// Signers, if non-empty, asks for signatures to be added during the copy
|
||||||
|
|
|
@ -254,8 +254,8 @@ func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, options entiti
|
||||||
pullOptions.InsecureSkipTLSVerify = options.SkipTLSVerify
|
pullOptions.InsecureSkipTLSVerify = options.SkipTLSVerify
|
||||||
pullOptions.Writer = options.Writer
|
pullOptions.Writer = options.Writer
|
||||||
pullOptions.OciDecryptConfig = options.OciDecryptConfig
|
pullOptions.OciDecryptConfig = options.OciDecryptConfig
|
||||||
|
|
||||||
pullOptions.MaxRetries = options.Retry
|
pullOptions.MaxRetries = options.Retry
|
||||||
|
|
||||||
if options.RetryDelay != "" {
|
if options.RetryDelay != "" {
|
||||||
duration, err := time.ParseDuration(options.RetryDelay)
|
duration, err := time.ParseDuration(options.RetryDelay)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -343,6 +343,14 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
|
||||||
pushOptions.OciEncryptLayers = options.OciEncryptLayers
|
pushOptions.OciEncryptLayers = options.OciEncryptLayers
|
||||||
pushOptions.CompressionLevel = options.CompressionLevel
|
pushOptions.CompressionLevel = options.CompressionLevel
|
||||||
pushOptions.ForceCompressionFormat = options.ForceCompressionFormat
|
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
|
compressionFormat := options.CompressionFormat
|
||||||
if compressionFormat == "" {
|
if compressionFormat == "" {
|
||||||
|
|
|
@ -273,6 +273,12 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
|
||||||
options.WithSkipTLSVerify(false)
|
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 {
|
if err := images.Push(ir.ClientCtx, source, destination, options); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 pull -q --retry 4 --retry-delay "10s" $IMAGE
|
||||||
run_podman 125 pull -q --retry 4 --retry-delay "bogus" $IMAGE
|
run_podman 125 pull -q --retry 4 --retry-delay "bogus" $IMAGE
|
||||||
is "$output" 'Error: time: invalid duration "bogus"' "bad retry-delay"
|
is "$output" 'Error: time: invalid duration "bogus"' "bad retry-delay"
|
||||||
|
@ -367,6 +367,30 @@ function _test_skopeo_credential_sharing() {
|
||||||
run_podman rmi $image1
|
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 cooperation with skopeo
|
||||||
# END actual tests
|
# END actual tests
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
Loading…
Reference in New Issue