mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 17:30:00 +00:00
Merge pull request #68346 from CaoShuFeng/400_500
return 400 status when invalid json patch passed to apiserver
This commit is contained in:
commit
48e93c7329
@ -265,7 +265,7 @@ func (p *jsonPatcher) applyPatchToCurrentObject(currentObject runtime.Object) (r
|
|||||||
// Apply the patch.
|
// Apply the patch.
|
||||||
patchedObjJS, err := p.applyJSPatch(currentObjJS)
|
patchedObjJS, err := p.applyJSPatch(currentObjJS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, interpretPatchError(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct the resulting typed, unversioned object.
|
// Construct the resulting typed, unversioned object.
|
||||||
@ -284,9 +284,13 @@ func (p *jsonPatcher) applyJSPatch(versionedJS []byte) (patchedJS []byte, retErr
|
|||||||
case types.JSONPatchType:
|
case types.JSONPatchType:
|
||||||
patchObj, err := jsonpatch.DecodePatch(p.patchJS)
|
patchObj, err := jsonpatch.DecodePatch(p.patchJS)
|
||||||
if err != nil {
|
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:
|
case types.MergePatchType:
|
||||||
return jsonpatch.MergePatch(versionedJS, p.patchJS)
|
return jsonpatch.MergePatch(versionedJS, p.patchJS)
|
||||||
default:
|
default:
|
||||||
@ -415,7 +419,7 @@ func applyPatchToObject(
|
|||||||
) error {
|
) error {
|
||||||
patchedObjMap, err := strategicpatch.StrategicMergeMapPatch(originalMap, patchMap, schemaReferenceObj)
|
patchedObjMap, err := strategicpatch.StrategicMergeMapPatch(originalMap, patchMap, schemaReferenceObj)
|
||||||
if err != nil {
|
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
|
// 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// interpretPatchError interprets the error type and returns an error with appropriate HTTP code.
|
// interpretStrategicMergePatchError interprets the error type and returns an error with appropriate HTTP code.
|
||||||
func interpretPatchError(err error) error {
|
func interpretStrategicMergePatchError(err error) error {
|
||||||
switch err {
|
switch err {
|
||||||
case mergepatch.ErrBadJSONDoc, mergepatch.ErrBadPatchFormatForPrimitiveList, mergepatch.ErrBadPatchFormatForRetainKeys, mergepatch.ErrBadPatchFormatForSetElementOrderList, mergepatch.ErrUnsupportedStrategicMergePatchFormat:
|
case mergepatch.ErrBadJSONDoc, mergepatch.ErrBadPatchFormatForPrimitiveList, mergepatch.ErrBadPatchFormatForRetainKeys, mergepatch.ErrBadPatchFormatForSetElementOrderList, mergepatch.ErrUnsupportedStrategicMergePatchFormat:
|
||||||
return errors.NewBadRequest(err.Error())
|
return errors.NewBadRequest(err.Error())
|
||||||
|
@ -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"}
|
testGV := schema.GroupVersion{Group: "", Version: "v"}
|
||||||
scheme.AddKnownTypes(testGV, &testPatchType{})
|
scheme.AddKnownTypes(testGV, &testPatchType{})
|
||||||
defaulter := runtime.ObjectDefaulter(scheme)
|
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) {
|
func TestPatchCustomResource(t *testing.T) {
|
||||||
testGV := schema.GroupVersion{Group: "mygroup.example.com", Version: "v1beta1"}
|
testGV := schema.GroupVersion{Group: "mygroup.example.com", Version: "v1beta1"}
|
||||||
scheme.AddKnownTypes(testGV, &unstructured.Unstructured{})
|
scheme.AddKnownTypes(testGV, &unstructured.Unstructured{})
|
||||||
|
Loading…
Reference in New Issue
Block a user