Merge pull request #68346 from CaoShuFeng/400_500

return 400 status when invalid json patch passed to apiserver
This commit is contained in:
k8s-ci-robot 2018-09-25 11:03:53 -07:00 committed by GitHub
commit 48e93c7329
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 7 deletions

View File

@ -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.
@ -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())
}
return patchObj.Apply(versionedJS)
patchedJS, err := patchObj.Apply(versionedJS)
if err != nil {
return nil, errors.NewGenericServerResponse(http.StatusUnprocessableEntity, "", schema.GroupResource{}, "", err.Error(), 0, false)
}
return patchedJS, nil
case types.MergePatchType:
return jsonpatch.MergePatch(versionedJS, p.patchJS)
default:
@ -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
@ -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())

View File

@ -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)
@ -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{})