k8s.io/client-go@v0.22.2/metadata/metadata_test.go (about)

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package metadata
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"net/http"
    23  	"net/http/httptest"
    24  	"reflect"
    25  	"strings"
    26  	"testing"
    27  
    28  	corev1 "k8s.io/api/core/v1"
    29  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    30  	"k8s.io/apimachinery/pkg/runtime"
    31  	"k8s.io/apimachinery/pkg/runtime/schema"
    32  	"k8s.io/apimachinery/pkg/util/diff"
    33  	"k8s.io/client-go/rest"
    34  )
    35  
    36  func TestClient(t *testing.T) {
    37  	gvr := schema.GroupVersionResource{Group: "group", Version: "v1", Resource: "resource"}
    38  
    39  	writeJSON := func(t *testing.T, w http.ResponseWriter, obj runtime.Object) {
    40  		data, err := json.Marshal(obj)
    41  		if err != nil {
    42  			t.Fatal(err)
    43  		}
    44  		w.Header().Set("Content-Type", "application/json")
    45  		if _, err := w.Write(data); err != nil {
    46  			t.Fatal(err)
    47  		}
    48  	}
    49  
    50  	testCases := []struct {
    51  		name    string
    52  		handler func(t *testing.T, w http.ResponseWriter, req *http.Request)
    53  		want    func(t *testing.T, client *Client)
    54  	}{
    55  		{
    56  			name: "GET is able to convert a JSON object to PartialObjectMetadata",
    57  			handler: func(t *testing.T, w http.ResponseWriter, req *http.Request) {
    58  				if req.Header.Get("Accept") != "application/vnd.kubernetes.protobuf;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json" {
    59  					t.Fatal(req.Header.Get("Accept"))
    60  				}
    61  				if req.Method != "GET" && req.URL.String() != "/apis/group/v1/namespaces/ns/resource/name" {
    62  					t.Fatal(req.URL.String())
    63  				}
    64  				writeJSON(t, w, &corev1.Pod{
    65  					TypeMeta: metav1.TypeMeta{
    66  						Kind:       "Pod",
    67  						APIVersion: "v1",
    68  					},
    69  					ObjectMeta: metav1.ObjectMeta{
    70  						Name:      "name",
    71  						Namespace: "ns",
    72  					},
    73  				})
    74  			},
    75  			want: func(t *testing.T, client *Client) {
    76  				obj, err := client.Resource(gvr).Namespace("ns").Get(context.TODO(), "name", metav1.GetOptions{})
    77  				if err != nil {
    78  					t.Fatal(err)
    79  				}
    80  				expect := &metav1.PartialObjectMetadata{
    81  					ObjectMeta: metav1.ObjectMeta{
    82  						Name:      "name",
    83  						Namespace: "ns",
    84  					},
    85  				}
    86  				if !reflect.DeepEqual(expect, obj) {
    87  					t.Fatal(diff.ObjectReflectDiff(expect, obj))
    88  				}
    89  			},
    90  		},
    91  
    92  		{
    93  			name: "LIST is able to convert a JSON object to PartialObjectMetadata",
    94  			handler: func(t *testing.T, w http.ResponseWriter, req *http.Request) {
    95  				if req.Header.Get("Accept") != "application/vnd.kubernetes.protobuf;as=PartialObjectMetadataList;g=meta.k8s.io;v=v1,application/json;as=PartialObjectMetadataList;g=meta.k8s.io;v=v1,application/json" {
    96  					t.Fatal(req.Header.Get("Accept"))
    97  				}
    98  				if req.Method != "GET" && req.URL.String() != "/apis/group/v1/namespaces/ns/resource" {
    99  					t.Fatal(req.URL.String())
   100  				}
   101  				writeJSON(t, w, &corev1.PodList{
   102  					TypeMeta: metav1.TypeMeta{
   103  						Kind:       "PodList",
   104  						APIVersion: "v1",
   105  					},
   106  					ListMeta: metav1.ListMeta{
   107  						ResourceVersion: "253",
   108  					},
   109  					Items: []corev1.Pod{
   110  						{
   111  							TypeMeta: metav1.TypeMeta{
   112  								Kind:       "Pod",
   113  								APIVersion: "v1",
   114  							},
   115  							ObjectMeta: metav1.ObjectMeta{
   116  								Name:      "name",
   117  								Namespace: "ns",
   118  							},
   119  						},
   120  					},
   121  				})
   122  			},
   123  			want: func(t *testing.T, client *Client) {
   124  				objs, err := client.Resource(gvr).Namespace("ns").List(context.TODO(), metav1.ListOptions{})
   125  				if err != nil {
   126  					t.Fatal(err)
   127  				}
   128  				if objs.GetResourceVersion() != "253" {
   129  					t.Fatal(objs)
   130  				}
   131  				expect := []metav1.PartialObjectMetadata{
   132  					{
   133  						TypeMeta: metav1.TypeMeta{
   134  							Kind:       "Pod",
   135  							APIVersion: "v1",
   136  						},
   137  						ObjectMeta: metav1.ObjectMeta{
   138  							Name:      "name",
   139  							Namespace: "ns",
   140  						},
   141  					},
   142  				}
   143  				if !reflect.DeepEqual(expect, objs.Items) {
   144  					t.Fatal(diff.ObjectReflectDiff(expect, objs.Items))
   145  				}
   146  			},
   147  		},
   148  
   149  		{
   150  			name: "GET fails if the object is JSON and has no kind",
   151  			handler: func(t *testing.T, w http.ResponseWriter, req *http.Request) {
   152  				if req.Header.Get("Accept") != "application/vnd.kubernetes.protobuf;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json" {
   153  					t.Fatal(req.Header.Get("Accept"))
   154  				}
   155  				if req.Method != "GET" && req.URL.String() != "/apis/group/v1/namespaces/ns/resource/name" {
   156  					t.Fatal(req.URL.String())
   157  				}
   158  				writeJSON(t, w, &corev1.Pod{
   159  					TypeMeta: metav1.TypeMeta{},
   160  					ObjectMeta: metav1.ObjectMeta{
   161  						UID: "123",
   162  					},
   163  				})
   164  			},
   165  			want: func(t *testing.T, client *Client) {
   166  				obj, err := client.Resource(gvr).Namespace("ns").Get(context.TODO(), "name", metav1.GetOptions{})
   167  				if err == nil || !runtime.IsMissingKind(err) {
   168  					t.Fatal(err)
   169  				}
   170  				if obj != nil {
   171  					t.Fatal(obj)
   172  				}
   173  			},
   174  		},
   175  
   176  		{
   177  			name: "GET fails if the object is JSON and has no apiVersion",
   178  			handler: func(t *testing.T, w http.ResponseWriter, req *http.Request) {
   179  				if req.Header.Get("Accept") != "application/vnd.kubernetes.protobuf;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json" {
   180  					t.Fatal(req.Header.Get("Accept"))
   181  				}
   182  				if req.Method != "GET" && req.URL.String() != "/apis/group/v1/namespaces/ns/resource/name" {
   183  					t.Fatal(req.URL.String())
   184  				}
   185  				writeJSON(t, w, &corev1.Pod{
   186  					TypeMeta: metav1.TypeMeta{
   187  						Kind: "Pod",
   188  					},
   189  					ObjectMeta: metav1.ObjectMeta{
   190  						UID: "123",
   191  					},
   192  				})
   193  			},
   194  			want: func(t *testing.T, client *Client) {
   195  				obj, err := client.Resource(gvr).Namespace("ns").Get(context.TODO(), "name", metav1.GetOptions{})
   196  				if err == nil || !runtime.IsMissingVersion(err) {
   197  					t.Fatal(err)
   198  				}
   199  				if obj != nil {
   200  					t.Fatal(obj)
   201  				}
   202  			},
   203  		},
   204  
   205  		{
   206  			name: "GET fails if the object is JSON and not clearly metadata",
   207  			handler: func(t *testing.T, w http.ResponseWriter, req *http.Request) {
   208  				if req.Header.Get("Accept") != "application/vnd.kubernetes.protobuf;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json" {
   209  					t.Fatal(req.Header.Get("Accept"))
   210  				}
   211  				if req.Method != "GET" && req.URL.String() != "/apis/group/v1/namespaces/ns/resource/name" {
   212  					t.Fatal(req.URL.String())
   213  				}
   214  				writeJSON(t, w, &corev1.Pod{
   215  					TypeMeta: metav1.TypeMeta{
   216  						Kind:       "Pod",
   217  						APIVersion: "v1",
   218  					},
   219  					ObjectMeta: metav1.ObjectMeta{},
   220  				})
   221  			},
   222  			want: func(t *testing.T, client *Client) {
   223  				obj, err := client.Resource(gvr).Namespace("ns").Get(context.TODO(), "name", metav1.GetOptions{})
   224  				if err == nil || !strings.Contains(err.Error(), "object does not appear to match the ObjectMeta schema") {
   225  					t.Fatal(err)
   226  				}
   227  				if obj != nil {
   228  					t.Fatal(obj)
   229  				}
   230  			},
   231  		},
   232  	}
   233  
   234  	for _, tt := range testCases {
   235  		t.Run(tt.name, func(t *testing.T) {
   236  			s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { tt.handler(t, w, req) }))
   237  			defer s.Close()
   238  
   239  			cfg := ConfigFor(&rest.Config{Host: s.URL})
   240  			client := NewForConfigOrDie(cfg).(*Client)
   241  			tt.want(t, client)
   242  		})
   243  	}
   244  }