Merge pull request #104573 from sxllwx/refine/clear-comments-for-metaclient

Explain the reason why metaclient special processing metav1.DeleteOptions encoding

Kubernetes-commit: 7a0638da76cb9843def65708b661d2c6aa58ed5a
This commit is contained in:
Kubernetes Publisher 2021-08-31 21:56:58 -07:00
commit a31b18a6ac
2 changed files with 69 additions and 0 deletions

View File

@ -124,6 +124,12 @@ func (c *client) Delete(ctx context.Context, name string, opts metav1.DeleteOpti
if len(name) == 0 {
return fmt.Errorf("name is required")
}
// if DeleteOptions are delivered to Negotiator for serialization,
// HTTP-Request header will bring "Content-Type: application/vnd.kubernetes.protobuf"
// apiextensions-apiserver uses unstructuredNegotiatedSerializer to decode the input,
// server-side will reply with 406 errors.
// The special treatment here is to be compatible with CRD Handler
// see: https://github.com/kubernetes/kubernetes/blob/1a845ccd076bbf1b03420fe694c85a5cd3bd6bed/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go#L843
deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), &opts)
if err != nil {
return err
@ -132,6 +138,7 @@ func (c *client) Delete(ctx context.Context, name string, opts metav1.DeleteOpti
result := c.client.client.
Delete().
AbsPath(append(c.makeURLSegments(name), subresources...)...).
SetHeader("Content-Type", runtime.ContentTypeJSON).
Body(deleteOptionsByte).
Do(ctx)
return result.Error()
@ -139,6 +146,7 @@ func (c *client) Delete(ctx context.Context, name string, opts metav1.DeleteOpti
// DeleteCollection triggers deletion of all resources in the specified scope (namespace or cluster).
func (c *client) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOptions metav1.ListOptions) error {
// See comment on Delete
deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), &opts)
if err != nil {
return err
@ -147,6 +155,7 @@ func (c *client) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions
result := c.client.client.
Delete().
AbsPath(c.makeURLSegments("")...).
SetHeader("Content-Type", runtime.ContentTypeJSON).
Body(deleteOptionsByte).
SpecificallyVersionedParams(&listOptions, dynamicParameterCodec, versionV1).
Do(ctx)

View File

@ -19,6 +19,7 @@ package metadata
import (
"context"
"encoding/json"
"io/ioutil"
"net/http"
"net/http/httptest"
"reflect"
@ -35,6 +36,10 @@ import (
func TestClient(t *testing.T) {
gvr := schema.GroupVersionResource{Group: "group", Version: "v1", Resource: "resource"}
statusOK := &metav1.Status{
Status: metav1.StatusSuccess,
Code: http.StatusOK,
}
writeJSON := func(t *testing.T, w http.ResponseWriter, obj runtime.Object) {
data, err := json.Marshal(obj)
@ -229,6 +234,61 @@ func TestClient(t *testing.T) {
}
},
},
{
name: "Delete fails if DeleteOptions cannot be serialized to JSON",
handler: func(t *testing.T, w http.ResponseWriter, req *http.Request) {
if req.Header.Get("Content-Type") != runtime.ContentTypeJSON {
t.Fatal(req.Header.Get("Content-Type"))
}
if req.Method != "DELETE" && req.URL.String() != "/apis/group/v1/namespaces/ns/resource/name" {
t.Fatal(req.URL.String())
}
defer req.Body.Close()
buf, err := ioutil.ReadAll(req.Body)
if err != nil {
t.Fatal(err)
}
if !json.Valid(buf) {
t.Fatalf("request body is not a valid JSON: %s", buf)
}
writeJSON(t, w, statusOK)
},
want: func(t *testing.T, client *Client) {
err := client.Resource(gvr).Namespace("ns").Delete(context.TODO(), "name", metav1.DeleteOptions{})
if err != nil {
t.Fatal(err)
}
},
},
{
name: "DeleteCollection fails if DeleteOptions cannot be serialized to JSON",
handler: func(t *testing.T, w http.ResponseWriter, req *http.Request) {
if req.Header.Get("Content-Type") != runtime.ContentTypeJSON {
t.Fatal(req.Header.Get("Content-Type"))
}
if req.Method != "DELETE" && req.URL.String() != "/apis/group/v1/namespaces/ns/resource/name" {
t.Fatal(req.URL.String())
}
defer req.Body.Close()
buf, err := ioutil.ReadAll(req.Body)
if err != nil {
t.Fatal(err)
}
if !json.Valid(buf) {
t.Fatalf("request body is not a valid JSON: %s", buf)
}
writeJSON(t, w, statusOK)
},
want: func(t *testing.T, client *Client) {
err := client.Resource(gvr).Namespace("ns").DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
if err != nil {
t.Fatal(err)
}
},
},
}
for _, tt := range testCases {