From e1614f95e662e9e6f7f520eb2b33181d7b264a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Hu=C3=9F?= Date: Wed, 10 Jul 2019 20:18:10 +0200 Subject: [PATCH] fix(service update): Retry an update in case of a conflict. (#240) * fix(service update): Retry an update in case of a conflict. Is related to #224 and should fix one flake. * chore(service): Fixed retry-loop for kn service create/update --- pkg/kn/commands/service/service.go | 5 +++ pkg/kn/commands/service/service_create.go | 28 ++++++++++------ pkg/kn/commands/service/service_update.go | 41 ++++++++++++++--------- 3 files changed, 48 insertions(+), 26 deletions(-) diff --git a/pkg/kn/commands/service/service.go b/pkg/kn/commands/service/service.go index 7a4ff8ef2..9f719a939 100644 --- a/pkg/kn/commands/service/service.go +++ b/pkg/kn/commands/service/service.go @@ -19,6 +19,11 @@ import ( "github.com/spf13/cobra" ) +const ( + // How often to retry in case of an optimistic lock error when replacing a service (--force) + MaxUpdateRetries = 3 +) + func NewServiceCommand(p *commands.KnParams) *cobra.Command { serviceCmd := &cobra.Command{ Use: "service", diff --git a/pkg/kn/commands/service/service_create.go b/pkg/kn/commands/service/service_create.go index dcf5b4843..6310e87fb 100644 --- a/pkg/kn/commands/service/service_create.go +++ b/pkg/kn/commands/service/service_create.go @@ -147,17 +147,25 @@ func createService(client v1alpha1.KnClient, service *serving_v1alpha1_api.Servi } func replaceService(client v1alpha1.KnClient, service *serving_v1alpha1_api.Service, namespace string, out io.Writer) error { - existingService, err := client.GetService(service.Name) - if err != nil { - return err + var retries = 0 + for { + existingService, err := client.GetService(service.Name) + if err != nil { + return err + } + service.ResourceVersion = existingService.ResourceVersion + err = client.UpdateService(service) + if err != nil { + // Retry to update when a resource version conflict exists + if api_errors.IsConflict(err) && retries < MaxUpdateRetries { + retries++ + continue + } + return err + } + fmt.Fprintf(out, "Service '%s' successfully replaced in namespace '%s'.\n", service.Name, namespace) + return nil } - service.ResourceVersion = existingService.ResourceVersion - err = client.UpdateService(service) - if err != nil { - return err - } - fmt.Fprintf(out, "Service '%s' successfully replaced in namespace '%s'.\n", service.Name, namespace) - return nil } func serviceExists(client v1alpha1.KnClient, name string, namespace string) (bool, error) { diff --git a/pkg/kn/commands/service/service_update.go b/pkg/kn/commands/service/service_update.go index da4711b98..6ea08ef6e 100644 --- a/pkg/kn/commands/service/service_update.go +++ b/pkg/kn/commands/service/service_update.go @@ -18,8 +18,10 @@ import ( "errors" "fmt" - "github.com/knative/client/pkg/kn/commands" "github.com/spf13/cobra" + api_errors "k8s.io/apimachinery/pkg/api/errors" + + "github.com/knative/client/pkg/kn/commands" ) func NewServiceUpdateCommand(p *commands.KnParams) *cobra.Command { @@ -52,24 +54,31 @@ func NewServiceUpdateCommand(p *commands.KnParams) *cobra.Command { return err } - service, err := client.GetService(args[0]) - if err != nil { - return err - } - service = service.DeepCopy() + var retries = 0 + for { + service, err := client.GetService(args[0]) + if err != nil { + return err + } + service = service.DeepCopy() - err = editFlags.Apply(service, cmd) - if err != nil { - return err - } + err = editFlags.Apply(service, cmd) + if err != nil { + return err + } - err = client.UpdateService(service) - if err != nil { - return err + err = client.UpdateService(service) + if err != nil { + // Retry to update when a resource version conflict exists + if api_errors.IsConflict(err) && retries < MaxUpdateRetries { + retries++ + continue + } + return err + } + fmt.Fprintf(cmd.OutOrStdout(), "Service '%s' updated in namespace '%s'.\n", args[0], namespace) + return nil } - - fmt.Fprintf(cmd.OutOrStdout(), "Service '%s' updated in namespace '%s'.\n", args[0], namespace) - return nil }, }