Change:
Spawned from is converting an AlreadyExists error into a server timeout error if it has a generateName That means that this returns really confusing errors:
/cc
- a simple if for the objectMeta.Name seems to do the trick... is this enough? or were you looking for better way instead of NewServerTimeoutForKind ?
if no name was provided originally, the alreadyexists error occurs after the name field is populated with a generated name, so returning in that case makes this entire function a no-op in every case I can find. I just think inferring a ServerTimeout error from an AlreadyExists error and the presence of GenerateName is really odd
This needs to be triaged as a release-blocker or not for 1.5
Not a blocker
thanks
Is it appropriate to move this to the next milestone or clear the 1.5 milestone? (and remove the non-release-blocker tag as well)
Issues go stale after 30d of inactivity. Mark the issue as fresh with . Stale issues rot after an additional 30d of inactivity and eventually close. Prevent issues from auto-closing with an comment. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle stale
Stale issues rot after 30d of inactivity. Mark the issue as fresh with . Rotten issues close after an additional 30d of inactivity. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle rotten /remove-lifecycle stale
/remove-lifecycle rotten
/help
This request has been marked as needing help from a contributor. Please ensure the request meets the requirements listed . If this request no longer meets these requirements, the label can be removed by commenting with the command. <detailsIn response to : /help Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/sig cli
Issues go stale after 90d of inactivity. Mark the issue as fresh with . Stale issues rot after an additional 30d of inactivity and eventually close. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle stale
/remove-lifecycle stale
Should we return another instead of to include the generate name information ?
seems like the correct error in other cases involving an object that already exists with that name.
Looks like is not active due to age. If anyone is interested, please feel free to work on this! Like mentioned in , a unit test along with the required changes would be good to add.
Issues go stale after 90d of inactivity. Mark the issue as fresh with . Stale issues rot after an additional 30d of inactivity and eventually close. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle stale
Stale issues rot after 30d of inactivity. Mark the issue as fresh with . Rotten issues close after an additional 30d of inactivity. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle rotten
Would be really helpful if solved :) /remove-lifecycle rotten
I am new to Kubernetes community and was going through role board recommendations on older threads - If everyone is ok, can I pick this issue and work on it.
It seems already created PR for this issue - It doesn't seem to have merged. - Let me know if you are still working, else I can take a stab (Though most of the work is already done by you) to further drive this.
I'm not working on it. Please take it forward. Thanks
Thanks for the confirmation. I will work on this.
I have taken a look at the complete flow of the issue. From what I understand, there are a couple of choices Option - (1) Validate in function if an object has both name and generateName and fail the request if that is the case. Option - (2) in , set generateName to empty if it also has a name. This will make sure that the error in CheckGeneratedNameError is (when the generated name is conflicting with the already existing name of some other object). This is essentially the approach took in this , which no longer is actively worked on. /cc
Issues go stale after 90d of inactivity. Mark the issue as fresh with . Stale issues rot after an additional 30d of inactivity and eventually close. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle stale
Stale issues rot after 30d of inactivity. Mark the issue as fresh with . Rotten issues close after an additional 30d of inactivity. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle rotten
/lifecycle frozen
/needs-triage It's kind of embarrassing that this is still open.
(I think the fix may be to delete the mentioned function entirely-- why would we describe this situation as a timeout error?)
do you know someone who's interested working on this? We will come back on this issue in the next triage meeting.
/help
/triage accepted
The origin of :

Discussion:
out, err := rs.services.Create(ctx, service, createValidation, options) if err != nil { <del> err = rest.CheckGeneratedNameError(rs.strategy, err, service) </del> <ins> err = rest.CheckGeneratedNameError(ctx, rs.strategy, err, service) </ins> } if err == nil {

} func TestCheckGeneratedNameError(t *testing.T) { <ins> ctx := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{ Resource: "foos", }) </ins> testStrategy, _ := newStrategy("10.0.0.0/16", false) expect := errors.NewNotFound(api.Resource("foos"), "bar") <del> if err := rest.CheckGeneratedNameError(testStrategy, expect, &api.Service{}); err != expect { </del> <ins> if err := rest.CheckGeneratedNameError(ctx, testStrategy, expect, &api.Service{}); err != expect { </ins> t.Errorf("NotFoundError should be ignored: %v", err) } expect = errors.NewAlreadyExists(api.Resource("foos"), "bar") <del> if err := rest.CheckGeneratedNameError(testStrategy, expect, &api.Service{}); err != expect { </del> <ins> if err := rest.CheckGeneratedNameError(ctx, testStrategy, expect, &api.Service{}); err != expect { </ins> t.Errorf("AlreadyExists should be returned when no GenerateName field: %v", err) } expect = errors.NewAlreadyExists(api.Resource("foos"), "bar") <del> if err := rest.CheckGeneratedNameError(testStrategy, expect, &api.Service{ObjectMeta: metav1.ObjectMeta{GenerateName: "foo"}}); err == nil || !errors.IsServerTimeout(err) { </del> <ins> if err := rest.CheckGeneratedNameError(ctx, testStrategy, expect, &api.Service{ObjectMeta: metav1.ObjectMeta{GenerateName: "foo"}}); err == nil || !errors.IsAlreadyExists(err) { </ins> t.Errorf("expected try again later error: %v", err) } }

}} } <ins> // NewGenerateNameConflict returns an error indicating the server // was not able to generate a valid name for a resource. func NewGenerateNameConflict(qualifiedResource schema.GroupResource, name string, retryAfterSeconds int) *StatusError { return &StatusError{metav1.Status{ Status: metav1.StatusFailure, Code:   http.StatusConflict, Reason: metav1.StatusReasonAlreadyExists, Details: &metav1.StatusDetails{ Group:             qualifiedResource.Group, Kind:              qualifiedResource.Resource, Name:              name, RetryAfterSeconds: int32(retryAfterSeconds), }, Message: fmt.Sprintf( "%s %q already exists, the server was not able to generate a unique name for the object", qualifiedResource.String(), name), }} } </ins> // NewUnauthorized returns an error indicating the client is not authorized to perform the requested // action. func NewUnauthorized(reason string) *StatusError {

} if !IsConflict(NewConflict(resource("tests"), "2", errors.New("message"))) { <del> t.Errorf("expected to be conflict") </del> <ins> t.Errorf("expected to be %s", metav1.StatusReasonAlreadyExists) </ins> } if !IsNotFound(NewNotFound(resource("tests"), "3")) { t.Errorf("expected to be %s", metav1.StatusReasonNotFound)

t.Errorf("expected to be %s", metav1.StatusReasonMethodNotAllowed) } <ins> if !IsAlreadyExists(NewGenerateNameConflict(resource("tests"), "3", 1)) { t.Errorf("expected to be %s", metav1.StatusReasonAlreadyExists) } if time, ok := SuggestsClientDelay(NewGenerateNameConflict(resource("tests"), "3", 1)); time != 1 || !ok { t.Errorf("unexpected %d", time) } </ins> if time, ok := SuggestsClientDelay(NewServerTimeout(resource("tests"), "doing something", 10)); time != 10 || !ok { t.Errorf("unexpected %d", time) }

out := e.NewFunc() if err := e.Storage.Create(ctx, key, obj, out, ttl, dryrun.IsDryRun(options.DryRun)); err != nil { err = storeerr.InterpretCreateError(err, qualifiedResource, name) <del> err = rest.CheckGeneratedNameError(e.CreateStrategy, err, obj) </del> <ins> err = rest.CheckGeneratedNameError(ctx, e.CreateStrategy, err, obj) </ins> if !apierrors.IsAlreadyExists(err) { return nil, err }

} if creating { err = storeerr.InterpretCreateError(err, qualifiedResource, name) <del> err = rest.CheckGeneratedNameError(e.CreateStrategy, err, creatingObj) </del> <ins> err = rest.CheckGeneratedNameError(ctx, e.CreateStrategy, err, creatingObj) </ins> } else { err = storeerr.InterpretUpdateError(err, qualifiedResource, name) }

"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apiserver/pkg/admission" <ins> genericapirequest "k8s.io/apiserver/pkg/endpoints/request" </ins> "k8s.io/apiserver/pkg/features" "k8s.io/apiserver/pkg/storage/names" utilfeature "k8s.io/apiserver/pkg/util/feature"

objectMeta.SetDeletionGracePeriodSeconds(nil) strategy.PrepareForCreate(ctx, obj) FillObjectMetaSystemFields(objectMeta) if len(objectMeta.GetGenerateName()) > 0 && len(objectMeta.GetName()) == 0 { objectMeta.SetName(strategy.GenerateName(objectMeta.GetGenerateName())) }

// CheckGeneratedNameError checks whether an error that occurred creating a resource is due // to generation being unable to pick a valid name. <del> func CheckGeneratedNameError(strategy RESTCreateStrategy, err error, obj runtime.Object) error { </del> <ins> func CheckGeneratedNameError(ctx context.Context, strategy RESTCreateStrategy, err error, obj runtime.Object) error { </ins> if !errors.IsAlreadyExists(err) { return err } <del> objectMeta, kind, kerr := objectMetaAndKind(strategy, obj) </del> <ins> objectMeta, gvk, kerr := objectMetaAndKind(strategy, obj) </ins> if kerr != nil { return kerr } if len(objectMeta.GetGenerateName()) == 0 { <ins> // If we don't have a generated name, return the original error (AlreadyExists). // When we're here, the user picked a name that is causing a conflict. </ins> return err } <del> return errors.NewServerTimeoutForKind(kind.GroupKind(), "POST", 0) </del> <ins> // Get the group resource information from the context, if populated. gr := schema.GroupResource{} if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found { gr = schema.GroupResource{Group: gvk.Group, Resource: requestInfo.Resource} } // If we have a name and generated name, the server picked a name // that already exists. return errors.NewGenerateNameConflict(gr, objectMeta.GetName(), 1) </ins> } // objectMetaAndKind retrieves kind and ObjectMeta from a runtime object, or returns an error.