diff --git a/api/handler/list.go b/api/handler/list.go index d5aead37..06694427 100644 --- a/api/handler/list.go +++ b/api/handler/list.go @@ -25,6 +25,10 @@ func ListHandler(request *types.APIContext, next types.RequestHandler) error { } else if request.Link == "" { data, err = store.ByID(request, request.Schema, request.ID) } else { + _, err = store.ByID(request, request.Schema, request.ID) + if err != nil { + return err + } return request.Schema.LinkHandler(request, nil) } diff --git a/controller/generic_controller.go b/controller/generic_controller.go index 0f9cd9d3..a5a37322 100644 --- a/controller/generic_controller.go +++ b/controller/generic_controller.go @@ -3,13 +3,16 @@ package controller import ( "context" "fmt" + "strings" "sync" "time" "github.com/juju/ratelimit" + errors2 "github.com/pkg/errors" "github.com/rancher/norman/clientbase" "github.com/rancher/norman/types" "github.com/sirupsen/logrus" + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -197,12 +200,47 @@ func (g *genericController) processNextWorkItem() bool { return true } - utilruntime.HandleError(fmt.Errorf("%v %v %v", g.name, key, err)) + if err := filterConflictsError(err); err != nil { + utilruntime.HandleError(fmt.Errorf("%v %v %v", g.name, key, err)) + } + g.queue.AddRateLimited(key) return true } +func ignoreError(err error, checkString bool) bool { + err = errors2.Cause(err) + if errors.IsConflict(err) { + return true + } + if _, ok := err.(*ForgetError); ok { + return true + } + if checkString { + return strings.HasSuffix(err.Error(), "please apply your changes to the latest version and try again") + } + return false +} + +func filterConflictsError(err error) error { + if ignoreError(err, false) { + return nil + } + + if errs, ok := errors2.Cause(err).(*types.MultiErrors); ok { + var newErrors []error + for _, err := range errs.Errors { + if !ignoreError(err, true) { + newErrors = append(newErrors) + } + } + return types.NewErrors(newErrors...) + } + + return err +} + func (g *genericController) syncHandler(s string) (err error) { defer utilruntime.RecoverFromPanic(&err) @@ -227,3 +265,7 @@ type handlerError struct { func (h *handlerError) Error() string { return fmt.Sprintf("[%s] failed with : %v", h.name, h.err) } + +func (h *handlerError) Cause() error { + return h.err +} diff --git a/types/schemas.go b/types/schemas.go index 2e9cb314..2ebeff3e 100644 --- a/types/schemas.go +++ b/types/schemas.go @@ -339,8 +339,8 @@ func (s *Schemas) SubContextVersionForSchema(schema *Schema) *APIVersion { return nil } -type multiErrors struct { - errors []error +type MultiErrors struct { + Errors []error } func NewErrors(errors ...error) error { @@ -349,14 +349,14 @@ func NewErrors(errors ...error) error { } else if len(errors) == 1 { return errors[0] } - return &multiErrors{ - errors: errors, + return &MultiErrors{ + Errors: errors, } } -func (m *multiErrors) Error() string { +func (m *MultiErrors) Error() string { buf := bytes.NewBuffer(nil) - for _, err := range m.errors { + for _, err := range m.Errors { if buf.Len() > 0 { buf.WriteString(", ") }