diff --git a/go.mod b/go.mod index 8abca96fc..8d65a4ba2 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( k8s.io/api v0.0.0-20221019235207-4e8dc44b5ed4 k8s.io/apimachinery v0.0.0-20221017194938-70a38aaa19ef k8s.io/client-go v0.0.0-20221019075459-ef8a2e522779 - k8s.io/component-base v0.0.0-20221019000337-4f487d08c46c + k8s.io/component-base v0.0.0-20221020195653-9fd3a641bd31 k8s.io/klog/v2 v2.80.1 k8s.io/kms v0.0.0-20221014080727-25ac69204108 k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 @@ -125,6 +125,6 @@ replace ( k8s.io/api => k8s.io/api v0.0.0-20221019235207-4e8dc44b5ed4 k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20221017194938-70a38aaa19ef k8s.io/client-go => k8s.io/client-go v0.0.0-20221019075459-ef8a2e522779 - k8s.io/component-base => k8s.io/component-base v0.0.0-20221019000337-4f487d08c46c + k8s.io/component-base => k8s.io/component-base v0.0.0-20221020195653-9fd3a641bd31 k8s.io/kms => k8s.io/kms v0.0.0-20221014080727-25ac69204108 ) diff --git a/go.sum b/go.sum index a25ad7649..0cf0d1de6 100644 --- a/go.sum +++ b/go.sum @@ -988,8 +988,8 @@ k8s.io/apimachinery v0.0.0-20221017194938-70a38aaa19ef h1:4lKLUMgwg9xi0UV4qjwS2N k8s.io/apimachinery v0.0.0-20221017194938-70a38aaa19ef/go.mod h1:/x4E+/xaA5ap3q0tWNh5IPFt63dzY1I2qP8zT4sr5Yg= k8s.io/client-go v0.0.0-20221019075459-ef8a2e522779 h1:+u8zTIggt94pLdjOWhaoW2iJwCaArrP2HnBlmJwk0mM= k8s.io/client-go v0.0.0-20221019075459-ef8a2e522779/go.mod h1:r+Jiu2RH1zXcJsmml1qRHg9oBq4sHHcMRaiEV0GN0ME= -k8s.io/component-base v0.0.0-20221019000337-4f487d08c46c h1:JEJlkqGJMe1WCIri8MWhUc1vryNLbP6SFmspoSwMbt8= -k8s.io/component-base v0.0.0-20221019000337-4f487d08c46c/go.mod h1:GzuOBZLTCAovez80ouX6fNL7eTjPnb0b2WDJkqL1k5c= +k8s.io/component-base v0.0.0-20221020195653-9fd3a641bd31 h1:54deIoyIYAFi9VM0xBsnGa8bINsWZ2W31ol7rILtomM= +k8s.io/component-base v0.0.0-20221020195653-9fd3a641bd31/go.mod h1:7LKizYk+wpA8YDdOijXEUHif9/8WZFqSvUxFo1YNl2M= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kms v0.0.0-20221014080727-25ac69204108 h1:tTFI4wvtZiV5ul+HoBvvBvuDg83kHt5ybfRW1NCSRXY= diff --git a/pkg/endpoints/handlers/delete.go b/pkg/endpoints/handlers/delete.go index 6bbf8c197..43b5e76c2 100644 --- a/pkg/endpoints/handlers/delete.go +++ b/pkg/endpoints/handlers/delete.go @@ -71,7 +71,8 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope *RequestSc options := &metav1.DeleteOptions{} if allowsOptions { - body, err := limitedReadBodyWithRecordMetric(ctx, req, scope.MaxRequestBodyBytes, scope.Resource.GroupResource().String(), requestmetrics.Patch) + body, err := limitedReadBodyWithRecordMetric(ctx, req, scope.MaxRequestBodyBytes, scope.Resource.GroupResource().String(), requestmetrics.Delete) + trace.Step("limitedReadBody done", utiltrace.Field{"len", len(body)}, utiltrace.Field{"err", err}) if err != nil { scope.err(err, w, req) return @@ -214,13 +215,14 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope *RequestSc options := &metav1.DeleteOptions{} if checkBody { - body, err := limitedReadBody(req, scope.MaxRequestBodyBytes) + body, err := limitedReadBodyWithRecordMetric(ctx, req, scope.MaxRequestBodyBytes, scope.Resource.GroupResource().String(), requestmetrics.DeleteCollection) + trace.Step("limitedReadBody done", utiltrace.Field{"len", len(body)}, utiltrace.Field{"err", err}) if err != nil { scope.err(err, w, req) return } if len(body) > 0 { - s, err := negotiation.NegotiateInputSerializer(req, false, scope.Serializer) + s, err := negotiation.NegotiateInputSerializer(req, false, metainternalversionscheme.Codecs) if err != nil { scope.err(err, w, req) return diff --git a/pkg/endpoints/handlers/delete_test.go b/pkg/endpoints/handlers/delete_test.go index edf764a1a..ad0dc567a 100644 --- a/pkg/endpoints/handlers/delete_test.go +++ b/pkg/endpoints/handlers/delete_test.go @@ -19,6 +19,8 @@ package handlers import ( "context" "io" + "net/http" + "strings" "testing" metainternalversionscheme "k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme" @@ -28,6 +30,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/serializer" auditapis "k8s.io/apiserver/pkg/apis/audit" "k8s.io/apiserver/pkg/audit" + "k8s.io/apiserver/pkg/endpoints/handlers/negotiation" "k8s.io/utils/pointer" ) @@ -132,3 +135,72 @@ func TestDeleteResourceAuditLogRequestObject(t *testing.T) { }) } } + +func TestDeleteCollection(t *testing.T) { + req := &http.Request{ + Header: http.Header{}, + } + req.Header.Set("Content-Type", "application/json") + + fakeCorev1GroupVersion := schema.GroupVersion{ + Group: "", + Version: "v1", + } + fakeCorev1Scheme := runtime.NewScheme() + fakeCorev1Scheme.AddKnownTypes(fakeCorev1GroupVersion, &metav1.DeleteOptions{}) + fakeCorev1Codec := serializer.NewCodecFactory(fakeCorev1Scheme) + + tests := []struct { + name string + codecFactory serializer.CodecFactory + data []byte + expectErr string + }{ + // for issue: https://github.com/kubernetes/kubernetes/issues/111985 + { + name: "decode '{}' to metav1.DeleteOptions with fakeCorev1Codecs", + codecFactory: fakeCorev1Codec, + data: []byte("{}"), + expectErr: "no kind \"DeleteOptions\" is registered", + }, + { + name: "decode '{}' to metav1.DeleteOptions with metainternalversionscheme.Codecs", + codecFactory: metainternalversionscheme.Codecs, + data: []byte("{}"), + expectErr: "", + }, + { + name: "decode versioned (corev1) DeleteOptions with metainternalversionscheme.Codecs", + codecFactory: metainternalversionscheme.Codecs, + data: []byte(`{"apiVersion":"v1","kind":"DeleteOptions","gracePeriodSeconds":123}`), + expectErr: "", + }, + { + name: "decode versioned (foo) DeleteOptions with metainternalversionscheme.Codecs", + codecFactory: metainternalversionscheme.Codecs, + data: []byte(`{"apiVersion":"foo/v1","kind":"DeleteOptions","gracePeriodSeconds":123}`), + expectErr: "", + }, + } + + defaultGVK := metav1.SchemeGroupVersion.WithKind("DeleteOptions") + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + s, err := negotiation.NegotiateInputSerializer(req, false, test.codecFactory) + if err != nil { + t.Fatal(err) + } + + options := &metav1.DeleteOptions{} + _, _, err = metainternalversionscheme.Codecs.DecoderToVersion(s.Serializer, defaultGVK.GroupVersion()).Decode(test.data, &defaultGVK, options) + if test.expectErr != "" { + if err == nil { + t.Fatalf("expect %s but got nil", test.expectErr) + } + if !strings.Contains(err.Error(), test.expectErr) { + t.Fatalf("expect %s but got %s", test.expectErr, err.Error()) + } + } + }) + } +} diff --git a/pkg/endpoints/handlers/metrics/metrics.go b/pkg/endpoints/handlers/metrics/metrics.go index a870f3db4..cf3205a9a 100644 --- a/pkg/endpoints/handlers/metrics/metrics.go +++ b/pkg/endpoints/handlers/metrics/metrics.go @@ -24,10 +24,11 @@ import ( type RequestBodyVerb string const ( - Patch RequestBodyVerb = "patch" - Delete RequestBodyVerb = "delete" - Update RequestBodyVerb = "update" - Create RequestBodyVerb = "create" + Patch RequestBodyVerb = "patch" + Delete RequestBodyVerb = "delete" + Update RequestBodyVerb = "update" + Create RequestBodyVerb = "create" + DeleteCollection RequestBodyVerb = "delete_collection" ) var (