-
Notifications
You must be signed in to change notification settings - Fork 38.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
return 400 status when invalid json patch passed to apiserver #68346
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's important to distinguish between an invalid patch and a failed test
operation.
} | ||
patchedJS, err := patchObj.Apply(versionedJS) | ||
if err != nil { | ||
return nil, errors.NewBadRequest(err.Error()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume that this is the branch that gets hit when a test
operation fails. Is there a way to check for that error specifically and send a 409 Conflict? A failed test
operation is very different from an "invalid" patch (e.g. wrong paths etc) and it needs to be possible to handle it specifically on the client. A failed test
operation means a failed precondition and the client likely just wants to update the local state from the server, regenerate the patch and try again. If the patch is invalid it would not try again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree that 400 is not good here.
/assign @caesarxuchao |
@@ -284,9 +284,13 @@ func (p *jsonPatcher) applyJSPatch(versionedJS []byte) (patchedJS []byte, retErr | |||
case types.JSONPatchType: | |||
patchObj, err := jsonpatch.DecodePatch(p.patchJS) | |||
if err != nil { | |||
return nil, err | |||
return nil, errors.NewBadRequest(err.Error()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use the interpretPatchError(err)
like other places in this file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interpretPatchError can only deal with mergepatch errors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it.
-
Can you remove the
interpretPatchError
at this line:return nil, interpretPatchError(err) -
Could you rename the
interpretPatchError
function tointerpretStrategicMergePatchError
, since that's what it handles.
I agree that we should fix upstream to make json-patch return typed errors. Then we can make interpretPatchError
interprets json-patch errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
} | ||
patchedJS, err := patchObj.Apply(versionedJS) | ||
if err != nil { | ||
return nil, errors.NewGenericServerResponse(http.StatusUnprocessableEntity, "", schema.GroupResource{}, "", err.Error(), 0, false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
@@ -326,6 +327,9 @@ func (tc *patchTestCase) Run(t *testing.T) { | |||
patch := []byte{} | |||
switch patchType { | |||
case types.StrategicMergePatchType: | |||
if len(tc.jsonPatch) > 0 { | |||
continue | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these lines for debugging only? If so please remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
tc.startingPod.UID = uid | ||
tc.startingPod.ResourceVersion = "2" | ||
tc.startingPod.APIVersion = examplev1.SchemeGroupVersion.String() | ||
tc.updatePod = tc.startingPod |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you don't need updatePod at all? It's weird to have updatePod: &example.Pod{}
and then tc.updatePod = tc.startingPod
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually why not using setTcPod
like other test cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
tc.startingPod.UID = uid | ||
tc.startingPod.ResourceVersion = "2" | ||
tc.startingPod.APIVersion = examplev1.SchemeGroupVersion.String() | ||
tc.updatePod = tc.startingPod |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have made a utility function to return a pod pointer to avoid duplicate code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
My comment above got collapsed by GitHub, but this still does not fix the linked issue. It is an improvement, but #68202 is specifically about failed test operations which should return a distinct status code (409 Conflict). |
I see. Maybe we should fix this in upstream first. https://github.com/evanphx/json-patch/blob/master/patch.go#L536 |
@CaoShuFeng got it. In that case please remove the "Fix: #68202" from the PR description so the issue doesn't get closed. Thanks for the improvements in this PR! |
Done. |
@@ -604,6 +618,52 @@ func TestPatchResourceWithRacingVersionConflict(t *testing.T) { | |||
tc.Run(t) | |||
} | |||
|
|||
func TestPatchResourceWithInvalidJSONPatch(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems you need to change the patchTestCase
framework a bit to make it work for your two test cases.
Instead of making that framework more complicated, how about making a focused test for applyJSPatch
? You don't need to fake too much to make it work.
And you can move the tests to right below TestPatchInvalid. (And you can rename TestPatchInvalid
to TestStrategicMergePatchInvalid
to make is clear).
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm except for one nit.
versionedJS, err := runtime.Encode(codec, pod) | ||
if err != nil { | ||
t.Errorf("%s: unexpected error: %v", test.name, err) | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use Fatalf
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
replace return
with continue
, just as other places do.
/lgtm |
/assign @sttts |
@CaoShuFeng: GitHub didn't allow me to assign the following users: for, approve. Note that only kubernetes members and repo collaborators can be assigned. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
/assign @lavalamp for approval and possibly apply milestone. |
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: caesarxuchao, CaoShuFeng, lavalamp The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Please add a release note explaining the status code change. |
(I think this isn't urgent and can wait until master opens back up for merges.) |
Done. |
related to : #68202
What this PR does / why we need it:
Which issue(s) this PR fixes (optional, in
fixes #<issue number>(, fixes #<issue_number>, ...)
format, will close the issue(s) when PR gets merged):Fixes #
Special notes for your reviewer:
Release note: