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 }