Skip to content

Commit

Permalink
Merge pull request #68346 from CaoShuFeng/400_500
Browse files Browse the repository at this point in the history
return 400 status when invalid json patch passed to apiserver
  • Loading branch information
k8s-ci-robot committed Sep 25, 2018
2 parents 1113687 + 1248f56 commit 48e93c7
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 7 deletions.
16 changes: 10 additions & 6 deletions staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ func (p *jsonPatcher) applyPatchToCurrentObject(currentObject runtime.Object) (r
// Apply the patch.
patchedObjJS, err := p.applyJSPatch(currentObjJS)
if err != nil {
return nil, interpretPatchError(err)
return nil, err
}

// Construct the resulting typed, unversioned object.
Expand All @@ -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())
}
patchedJS, err := patchObj.Apply(versionedJS)
if err != nil {
return nil, errors.NewGenericServerResponse(http.StatusUnprocessableEntity, "", schema.GroupResource{}, "", err.Error(), 0, false)
}
return patchObj.Apply(versionedJS)
return patchedJS, nil
case types.MergePatchType:
return jsonpatch.MergePatch(versionedJS, p.patchJS)
default:
Expand Down Expand Up @@ -415,7 +419,7 @@ func applyPatchToObject(
) error {
patchedObjMap, err := strategicpatch.StrategicMergeMapPatch(originalMap, patchMap, schemaReferenceObj)
if err != nil {
return interpretPatchError(err)
return interpretStrategicMergePatchError(err)
}

// Rather than serialize the patched map to JSON, then decode it to an object, we go directly from a map to an object
Expand All @@ -428,8 +432,8 @@ func applyPatchToObject(
return nil
}

// interpretPatchError interprets the error type and returns an error with appropriate HTTP code.
func interpretPatchError(err error) error {
// interpretStrategicMergePatchError interprets the error type and returns an error with appropriate HTTP code.
func interpretStrategicMergePatchError(err error) error {
switch err {
case mergepatch.ErrBadJSONDoc, mergepatch.ErrBadPatchFormatForPrimitiveList, mergepatch.ErrBadPatchFormatForRetainKeys, mergepatch.ErrBadPatchFormatForSetElementOrderList, mergepatch.ErrUnsupportedStrategicMergePatchFormat:
return errors.NewBadRequest(err.Error())
Expand Down
57 changes: 56 additions & 1 deletion staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func TestPatchAnonymousField(t *testing.T) {
}
}

func TestPatchInvalid(t *testing.T) {
func TestStrategicMergePatchInvalid(t *testing.T) {
testGV := schema.GroupVersion{Group: "", Version: "v"}
scheme.AddKnownTypes(testGV, &testPatchType{})
defaulter := runtime.ObjectDefaulter(scheme)
Expand All @@ -123,6 +123,61 @@ func TestPatchInvalid(t *testing.T) {
}
}

func TestJSONPatch(t *testing.T) {
for _, test := range []struct {
name string
patch string
expectedError string
expectedErrorType metav1.StatusReason
}{
{
name: "valid",
patch: `[{"op": "test", "value": "podA", "path": "/metadata/name"}]`,
},
{
name: "invalid-syntax",
patch: `invalid json patch`,
expectedError: "invalid character 'i' looking for beginning of value",
expectedErrorType: metav1.StatusReasonBadRequest,
},
{
name: "invalid-semantics",
patch: `[{"op": "test", "value": "podA", "path": "/invalid/path"}]`,
expectedError: "the server rejected our request due to an error in our request",
expectedErrorType: metav1.StatusReasonInvalid,
},
} {
p := &patcher{
patchType: types.JSONPatchType,
patchJS: []byte(test.patch),
}
jp := jsonPatcher{p}
codec := codecs.LegacyCodec(examplev1.SchemeGroupVersion)
pod := &examplev1.Pod{}
pod.Name = "podA"
versionedJS, err := runtime.Encode(codec, pod)
if err != nil {
t.Errorf("%s: unexpected error: %v", test.name, err)
continue
}
_, err = jp.applyJSPatch(versionedJS)
if err != nil {
if len(test.expectedError) == 0 {
t.Errorf("%s: expect no error when applying json patch, but got %v", test.name, err)
continue
}
if err.Error() != test.expectedError {
t.Errorf("%s: expected error %v, but got %v", test.name, test.expectedError, err)
}
if test.expectedErrorType != apierrors.ReasonForError(err) {
t.Errorf("%s: expected error type %v, but got %v", test.name, test.expectedErrorType, apierrors.ReasonForError(err))
}
} else if len(test.expectedError) > 0 {
t.Errorf("%s: expected err %s", test.name, test.expectedError)
}
}
}

func TestPatchCustomResource(t *testing.T) {
testGV := schema.GroupVersion{Group: "mygroup.example.com", Version: "v1beta1"}
scheme.AddKnownTypes(testGV, &unstructured.Unstructured{})
Expand Down

0 comments on commit 48e93c7

Please sign in to comment.