1
16
17 package get
18
19 import (
20 "bytes"
21 "encoding/json"
22 "fmt"
23 "io"
24 "net/http"
25 "reflect"
26 "strings"
27 "testing"
28
29 "github.com/google/go-cmp/cmp"
30 appsv1 "k8s.io/api/apps/v1"
31 autoscalingv1 "k8s.io/api/autoscaling/v1"
32 batchv1 "k8s.io/api/batch/v1"
33 batchv1beta1 "k8s.io/api/batch/v1beta1"
34 corev1 "k8s.io/api/core/v1"
35 extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
36 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
37 metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
38 "k8s.io/apimachinery/pkg/runtime"
39 "k8s.io/apimachinery/pkg/runtime/serializer/streaming"
40 "k8s.io/apimachinery/pkg/watch"
41 "k8s.io/cli-runtime/pkg/genericiooptions"
42 "k8s.io/cli-runtime/pkg/resource"
43 restclient "k8s.io/client-go/rest"
44 "k8s.io/client-go/rest/fake"
45 restclientwatch "k8s.io/client-go/rest/watch"
46 cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
47 "k8s.io/kubectl/pkg/scheme"
48 )
49
50 var (
51 grace = int64(30)
52 enableServiceLinks = corev1.DefaultEnableServiceLinks
53 )
54
55 func testComponentStatusData() *corev1.ComponentStatusList {
56 good := corev1.ComponentStatus{
57 Conditions: []corev1.ComponentCondition{
58 {Type: corev1.ComponentHealthy, Status: corev1.ConditionTrue, Message: "ok"},
59 },
60 ObjectMeta: metav1.ObjectMeta{Name: "servergood"},
61 }
62
63 bad := corev1.ComponentStatus{
64 Conditions: []corev1.ComponentCondition{
65 {Type: corev1.ComponentHealthy, Status: corev1.ConditionFalse, Message: "", Error: "bad status: 500"},
66 },
67 ObjectMeta: metav1.ObjectMeta{Name: "serverbad"},
68 }
69
70 unknown := corev1.ComponentStatus{
71 Conditions: []corev1.ComponentCondition{
72 {Type: corev1.ComponentHealthy, Status: corev1.ConditionUnknown, Message: "", Error: "fizzbuzz error"},
73 },
74 ObjectMeta: metav1.ObjectMeta{Name: "serverunknown"},
75 }
76
77 return &corev1.ComponentStatusList{
78 Items: []corev1.ComponentStatus{good, bad, unknown},
79 }
80 }
81
82
83 func TestGetUnknownSchemaObject(t *testing.T) {
84 t.Skip("This test is completely broken. The first thing it does is add the object to the scheme!")
85 tf := cmdtesting.NewTestFactory().WithNamespace("test")
86 defer tf.Cleanup()
87 _, _, codec := cmdtesting.NewExternalScheme()
88
89 obj := &cmdtesting.ExternalType{
90 Kind: "Type",
91 APIVersion: "apitest/unlikelyversion",
92 Name: "foo",
93 }
94
95 tf.UnstructuredClient = &fake.RESTClient{
96 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
97 Resp: &http.Response{
98 StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(),
99 Body: cmdtesting.ObjBody(codec, obj),
100 },
101 }
102 tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
103
104 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
105 cmd := NewCmdGet("kubectl", tf, streams)
106 cmd.SetOut(buf)
107 cmd.SetErr(buf)
108 cmd.Run(cmd, []string{"type", "foo"})
109
110 expected := []runtime.Object{cmdtesting.NewInternalType("", "", "foo")}
111 actual := []runtime.Object{}
112 if len(actual) != len(expected) {
113 t.Fatalf("expected: %#v, but actual: %#v", expected, actual)
114 }
115 t.Logf("actual: %#v", actual[0])
116 for i, obj := range actual {
117 expectedJSON := runtime.EncodeOrDie(codec, expected[i])
118 expectedMap := map[string]interface{}{}
119 if err := json.Unmarshal([]byte(expectedJSON), &expectedMap); err != nil {
120 t.Fatal(err)
121 }
122
123 actualJSON := runtime.EncodeOrDie(codec, obj)
124 actualMap := map[string]interface{}{}
125 if err := json.Unmarshal([]byte(actualJSON), &actualMap); err != nil {
126 t.Fatal(err)
127 }
128
129 if !reflect.DeepEqual(expectedMap, actualMap) {
130 t.Errorf("expectedMap: %#v, but actualMap: %#v", expectedMap, actualMap)
131 }
132 }
133 }
134
135
136 func TestGetSchemaObject(t *testing.T) {
137 tf := cmdtesting.NewTestFactory().WithNamespace("test")
138 defer tf.Cleanup()
139 codec := scheme.Codecs.LegacyCodec(corev1.SchemeGroupVersion)
140 t.Logf("%v", string(runtime.EncodeOrDie(codec, &corev1.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})))
141
142 tf.UnstructuredClient = &fake.RESTClient{
143 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
144 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})},
145 }
146 tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
147
148 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
149 cmd := NewCmdGet("kubectl", tf, streams)
150 cmd.Run(cmd, []string{"replicationcontrollers", "foo"})
151
152 if !strings.Contains(buf.String(), "foo") {
153 t.Errorf("unexpected output: %s", buf.String())
154 }
155 }
156
157 func TestGetObjects(t *testing.T) {
158 pods, _, _ := cmdtesting.TestData()
159
160 tf := cmdtesting.NewTestFactory().WithNamespace("test")
161 defer tf.Cleanup()
162 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
163
164 tf.UnstructuredClient = &fake.RESTClient{
165 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
166 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
167 }
168
169 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
170 cmd := NewCmdGet("kubectl", tf, streams)
171 cmd.SetOut(buf)
172 cmd.SetErr(buf)
173 cmd.Run(cmd, []string{"pods", "foo"})
174
175 expected := `NAME AGE
176 foo <unknown>
177 `
178 if e, a := expected, buf.String(); e != a {
179 t.Errorf("expected\n%v\ngot\n%v", e, a)
180 }
181 }
182
183 func TestGetObjectSubresourceStatus(t *testing.T) {
184 _, _, replicationcontrollers := cmdtesting.TestData()
185
186 tf := cmdtesting.NewTestFactory().WithNamespace("test")
187 defer tf.Cleanup()
188 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
189
190 tf.UnstructuredClient = &fake.RESTClient{
191 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
192 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &replicationcontrollers.Items[0])},
193 }
194
195 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
196 cmd := NewCmdGet("kubectl", tf, streams)
197 cmd.SetOut(buf)
198 cmd.SetErr(buf)
199 cmd.Flags().Set("subresource", "status")
200 cmd.Run(cmd, []string{"replicationcontrollers", "rc1"})
201
202 expected := `NAME AGE
203 rc1 <unknown>
204 `
205
206 if e, a := expected, buf.String(); e != a {
207 t.Errorf("expected\n%v\ngot\n%v", e, a)
208 }
209 }
210
211 func TestGetObjectSubresourceScale(t *testing.T) {
212 _, _, replicationcontrollers := cmdtesting.TestData()
213
214 tf := cmdtesting.NewTestFactory().WithNamespace("test")
215 defer tf.Cleanup()
216 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
217
218 tf.UnstructuredClient = &fake.RESTClient{
219 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
220 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: replicationControllersScaleSubresourceTableObjBody(codec, replicationcontrollers.Items[0])},
221 }
222
223 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
224 cmd := NewCmdGet("kubectl", tf, streams)
225 cmd.SetOut(buf)
226 cmd.SetErr(buf)
227 cmd.Flags().Set("subresource", "scale")
228 cmd.Run(cmd, []string{"replicationcontrollers", "rc1"})
229
230 expected := `NAME DESIRED AVAILABLE
231 rc1 1 0
232 `
233
234 if e, a := expected, buf.String(); e != a {
235 t.Errorf("expected\n%v\ngot\n%v", e, a)
236 }
237 }
238
239 func TestGetTableObjects(t *testing.T) {
240 pods, _, _ := cmdtesting.TestData()
241
242 tf := cmdtesting.NewTestFactory().WithNamespace("test")
243 defer tf.Cleanup()
244 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
245
246 tf.UnstructuredClient = &fake.RESTClient{
247 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
248 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, pods.Items[0])},
249 }
250
251 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
252 cmd := NewCmdGet("kubectl", tf, streams)
253 cmd.SetOut(buf)
254 cmd.SetErr(buf)
255 cmd.Run(cmd, []string{"pods", "foo"})
256
257 expected := `NAME READY STATUS RESTARTS AGE
258 foo 0/0 0 <unknown>
259 `
260 if e, a := expected, buf.String(); e != a {
261 t.Errorf("expected\n%v\ngot\n%v", e, a)
262 }
263 }
264
265 func TestGetV1TableObjects(t *testing.T) {
266 pods, _, _ := cmdtesting.TestData()
267
268 tf := cmdtesting.NewTestFactory().WithNamespace("test")
269 defer tf.Cleanup()
270 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
271
272 tf.UnstructuredClient = &fake.RESTClient{
273 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
274 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podV1TableObjBody(codec, pods.Items[0])},
275 }
276
277 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
278 cmd := NewCmdGet("kubectl", tf, streams)
279 cmd.SetOut(buf)
280 cmd.SetErr(buf)
281 cmd.Run(cmd, []string{"pods", "foo"})
282
283 expected := `NAME READY STATUS RESTARTS AGE
284 foo 0/0 0 <unknown>
285 `
286 if e, a := expected, buf.String(); e != a {
287 t.Errorf("expected\n%v\ngot\n%v", e, a)
288 }
289 }
290
291 func TestGetObjectsShowKind(t *testing.T) {
292 pods, _, _ := cmdtesting.TestData()
293
294 tf := cmdtesting.NewTestFactory().WithNamespace("test")
295 defer tf.Cleanup()
296 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
297
298 tf.UnstructuredClient = &fake.RESTClient{
299 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
300 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
301 }
302
303 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
304 cmd := NewCmdGet("kubectl", tf, streams)
305 cmd.SetOut(buf)
306 cmd.SetErr(buf)
307 cmd.Flags().Set("show-kind", "true")
308 cmd.Run(cmd, []string{"pods", "foo"})
309
310 expected := `NAME AGE
311 pod/foo <unknown>
312 `
313 if e, a := expected, buf.String(); e != a {
314 t.Errorf("expected\n%v\ngot\n%v", e, a)
315 }
316 }
317
318 func TestGetTableObjectsShowKind(t *testing.T) {
319 pods, _, _ := cmdtesting.TestData()
320
321 tf := cmdtesting.NewTestFactory().WithNamespace("test")
322 defer tf.Cleanup()
323 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
324
325 tf.UnstructuredClient = &fake.RESTClient{
326 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
327 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, pods.Items[0])},
328 }
329
330 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
331 cmd := NewCmdGet("kubectl", tf, streams)
332 cmd.SetOut(buf)
333 cmd.SetErr(buf)
334 cmd.Flags().Set("show-kind", "true")
335 cmd.Run(cmd, []string{"pods", "foo"})
336
337 expected := `NAME READY STATUS RESTARTS AGE
338 pod/foo 0/0 0 <unknown>
339 `
340 if e, a := expected, buf.String(); e != a {
341 t.Errorf("expected\n%v\ngot\n%v", e, a)
342 }
343 }
344
345 func TestGetMultipleResourceTypesShowKinds(t *testing.T) {
346 pods, svcs, _ := cmdtesting.TestData()
347
348 tf := cmdtesting.NewTestFactory().WithNamespace("test")
349 defer tf.Cleanup()
350
351 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
352 tf.UnstructuredClient = &fake.RESTClient{
353 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
354 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
355 switch p, m := req.URL.Path, req.Method; {
356 case p == "/namespaces/test/pods" && m == "GET":
357 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
358 case p == "/namespaces/test/replicationcontrollers" && m == "GET":
359 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.ReplicationControllerList{})}, nil
360 case p == "/namespaces/test/services" && m == "GET":
361 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svcs)}, nil
362 case p == "/namespaces/test/statefulsets" && m == "GET":
363 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &appsv1.StatefulSetList{})}, nil
364 case p == "/namespaces/test/horizontalpodautoscalers" && m == "GET":
365 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &autoscalingv1.HorizontalPodAutoscalerList{})}, nil
366 case p == "/namespaces/test/jobs" && m == "GET":
367 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &batchv1.JobList{})}, nil
368 case p == "/namespaces/test/cronjobs" && m == "GET":
369 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &batchv1beta1.CronJobList{})}, nil
370 case p == "/namespaces/test/daemonsets" && m == "GET":
371 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &appsv1.DaemonSetList{})}, nil
372 case p == "/namespaces/test/deployments" && m == "GET":
373 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &extensionsv1beta1.DeploymentList{})}, nil
374 case p == "/namespaces/test/replicasets" && m == "GET":
375 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &extensionsv1beta1.ReplicaSetList{})}, nil
376
377 default:
378 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
379 return nil, nil
380 }
381 }),
382 }
383
384 streams, _, buf, bufErr := genericiooptions.NewTestIOStreams()
385 cmd := NewCmdGet("kubectl", tf, streams)
386 cmd.SetOut(buf)
387 cmd.SetErr(buf)
388 cmd.Run(cmd, []string{"all"})
389
390 expected := `NAME AGE
391 pod/foo <unknown>
392 pod/bar <unknown>
393
394 NAME AGE
395 service/baz <unknown>
396 `
397 if e, a := expected, buf.String(); e != a {
398 t.Errorf("expected\n%v\ngot\n%v", e, a)
399 }
400
401
402 if e, a := "", bufErr.String(); e != a {
403 t.Errorf("expected\n%v\ngot\n%v", e, a)
404 }
405 }
406
407 func TestGetMultipleTableResourceTypesShowKinds(t *testing.T) {
408 pods, svcs, _ := cmdtesting.TestData()
409
410 tf := cmdtesting.NewTestFactory().WithNamespace("test")
411 defer tf.Cleanup()
412
413 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
414 tf.UnstructuredClient = &fake.RESTClient{
415 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
416 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
417 switch p, m := req.URL.Path, req.Method; {
418 case p == "/namespaces/test/pods" && m == "GET":
419 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, pods.Items...)}, nil
420 case p == "/namespaces/test/replicationcontrollers" && m == "GET":
421 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.ReplicationControllerList{})}, nil
422 case p == "/namespaces/test/services" && m == "GET":
423 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: serviceTableObjBody(codec, svcs.Items...)}, nil
424 case p == "/namespaces/test/statefulsets" && m == "GET":
425 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &appsv1.StatefulSetList{})}, nil
426 case p == "/namespaces/test/horizontalpodautoscalers" && m == "GET":
427 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &autoscalingv1.HorizontalPodAutoscalerList{})}, nil
428 case p == "/namespaces/test/jobs" && m == "GET":
429 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &batchv1.JobList{})}, nil
430 case p == "/namespaces/test/cronjobs" && m == "GET":
431 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &batchv1beta1.CronJobList{})}, nil
432 case p == "/namespaces/test/daemonsets" && m == "GET":
433 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &appsv1.DaemonSetList{})}, nil
434 case p == "/namespaces/test/deployments" && m == "GET":
435 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &extensionsv1beta1.DeploymentList{})}, nil
436 case p == "/namespaces/test/replicasets" && m == "GET":
437 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &extensionsv1beta1.ReplicaSetList{})}, nil
438
439 default:
440 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
441 return nil, nil
442 }
443 }),
444 }
445
446 streams, _, buf, bufErr := genericiooptions.NewTestIOStreams()
447 cmd := NewCmdGet("kubectl", tf, streams)
448 cmd.SetOut(buf)
449 cmd.SetErr(buf)
450 cmd.Run(cmd, []string{"all"})
451
452 expected := `NAME READY STATUS RESTARTS AGE
453 pod/foo 0/0 0 <unknown>
454 pod/bar 0/0 0 <unknown>
455
456 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
457 service/baz ClusterIP <none> <none> <none> <unknown>
458 `
459 if e, a := expected, buf.String(); e != a {
460 t.Errorf("expected\n%v\ngot\n%v", e, a)
461 }
462
463
464 if e, a := "", bufErr.String(); e != a {
465 t.Errorf("expected\n%v\ngot\n%v", e, a)
466 }
467 }
468
469 func TestNoBlankLinesForGetMultipleTableResource(t *testing.T) {
470 pods, svcs, _ := cmdtesting.TestData()
471
472 tf := cmdtesting.NewTestFactory().WithNamespace("test")
473 defer tf.Cleanup()
474
475 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
476 tf.UnstructuredClient = &fake.RESTClient{
477 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
478 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
479 switch p, m := req.URL.Path, req.Method; {
480 case p == "/namespaces/test/pods" && m == "GET":
481 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, pods.Items...)}, nil
482 case p == "/namespaces/test/replicationcontrollers" && m == "GET":
483 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
484 case p == "/namespaces/test/services" && m == "GET":
485 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: serviceTableObjBody(codec, svcs.Items...)}, nil
486 case p == "/namespaces/test/statefulsets" && m == "GET":
487 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
488 case p == "/namespaces/test/horizontalpodautoscalers" && m == "GET":
489 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
490 case p == "/namespaces/test/jobs" && m == "GET":
491 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
492 case p == "/namespaces/test/cronjobs" && m == "GET":
493 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
494 case p == "/namespaces/test/daemonsets" && m == "GET":
495 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
496 case p == "/namespaces/test/deployments" && m == "GET":
497 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
498 case p == "/namespaces/test/replicasets" && m == "GET":
499 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
500
501 default:
502 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
503 return nil, nil
504 }
505 }),
506 }
507
508 streams, _, buf, bufErr := genericiooptions.NewTestIOStreams()
509 cmd := NewCmdGet("kubectl", tf, streams)
510 cmd.SetOut(buf)
511 cmd.SetErr(buf)
512
513 expected := `NAME READY STATUS RESTARTS AGE
514 pod/foo 0/0 0 <unknown>
515 pod/bar 0/0 0 <unknown>
516
517 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
518 service/baz ClusterIP <none> <none> <none> <unknown>
519 `
520 for _, cmdArgs := range [][]string{
521 {"pods,services,jobs"},
522 {"deployments,pods,statefulsets,services,jobs"},
523 {"all"},
524 } {
525 cmd.Run(cmd, cmdArgs)
526
527 if e, a := expected, buf.String(); e != a {
528 t.Errorf("[kubectl get %v] expected\n%v\ngot\n%v", cmdArgs, e, a)
529 }
530
531
532 if e, a := "", bufErr.String(); e != a {
533 t.Errorf("[kubectl get %v] expected\n%v\ngot\n%v", cmdArgs, e, a)
534 }
535
536 buf.Reset()
537 bufErr.Reset()
538 }
539 }
540
541 func TestNoBlankLinesForGetAll(t *testing.T) {
542 tf := cmdtesting.NewTestFactory().WithNamespace("test")
543 defer tf.Cleanup()
544
545 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
546 tf.UnstructuredClient = &fake.RESTClient{
547 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
548 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
549 switch p, m := req.URL.Path, req.Method; {
550 case p == "/namespaces/test/pods" && m == "GET":
551 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
552 case p == "/namespaces/test/replicationcontrollers" && m == "GET":
553 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
554 case p == "/namespaces/test/services" && m == "GET":
555 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
556 case p == "/namespaces/test/statefulsets" && m == "GET":
557 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
558 case p == "/namespaces/test/horizontalpodautoscalers" && m == "GET":
559 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
560 case p == "/namespaces/test/jobs" && m == "GET":
561 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
562 case p == "/namespaces/test/cronjobs" && m == "GET":
563 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
564 case p == "/namespaces/test/daemonsets" && m == "GET":
565 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
566 case p == "/namespaces/test/deployments" && m == "GET":
567 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
568 case p == "/namespaces/test/replicasets" && m == "GET":
569 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)}, nil
570
571 default:
572 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
573 return nil, nil
574 }
575 }),
576 }
577
578 streams, _, buf, errbuf := genericiooptions.NewTestIOStreams()
579 cmd := NewCmdGet("kubectl", tf, streams)
580 cmd.SetOut(buf)
581 cmd.SetErr(buf)
582 cmd.Run(cmd, []string{"all"})
583
584 expected := ``
585 if e, a := expected, buf.String(); e != a {
586 t.Errorf("expected\n%v\ngot\n%v", e, a)
587 }
588 expectedErr := `No resources found in test namespace.
589 `
590 if e, a := expectedErr, errbuf.String(); e != a {
591 t.Errorf("expectedErr\n%v\ngot\n%v", e, a)
592 }
593 }
594
595 func TestNotFoundMessageForGetNonNamespacedResources(t *testing.T) {
596 tf := cmdtesting.NewTestFactory().WithNamespace("test")
597 defer tf.Cleanup()
598
599 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
600 tf.UnstructuredClient = &fake.RESTClient{
601 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
602 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTableObjBody(codec)},
603 }
604
605 streams, _, buf, errbuf := genericiooptions.NewTestIOStreams()
606 cmd := NewCmdGet("kubectl", tf, streams)
607 cmd.SetOut(buf)
608 cmd.SetErr(buf)
609 cmd.Run(cmd, []string{"persistentvolumes"})
610
611 expected := ``
612 if e, a := expected, buf.String(); e != a {
613 t.Errorf("expected\n%v\ngot\n%v", e, a)
614 }
615 expectedErr := `No resources found
616 `
617 if e, a := expectedErr, errbuf.String(); e != a {
618 t.Errorf("expectedErr\n%v\ngot\n%v", e, a)
619 }
620 }
621
622 func TestGetObjectsShowLabels(t *testing.T) {
623 pods, _, _ := cmdtesting.TestData()
624
625 tf := cmdtesting.NewTestFactory().WithNamespace("test")
626 defer tf.Cleanup()
627 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
628
629 tf.UnstructuredClient = &fake.RESTClient{
630 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
631 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
632 }
633
634 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
635 cmd := NewCmdGet("kubectl", tf, streams)
636 cmd.SetOut(buf)
637 cmd.SetErr(buf)
638 cmd.Flags().Set("show-labels", "true")
639 cmd.Run(cmd, []string{"pods", "foo"})
640
641 expected := `NAME AGE LABELS
642 foo <unknown> <none>
643 `
644 if e, a := expected, buf.String(); e != a {
645 t.Errorf("expected\n%v\ngot\n%v", e, a)
646 }
647 }
648
649 func TestGetTableObjectsShowLabels(t *testing.T) {
650 pods, _, _ := cmdtesting.TestData()
651
652 tf := cmdtesting.NewTestFactory().WithNamespace("test")
653 defer tf.Cleanup()
654 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
655
656 tf.UnstructuredClient = &fake.RESTClient{
657 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
658 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, pods.Items[0])},
659 }
660
661 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
662 cmd := NewCmdGet("kubectl", tf, streams)
663 cmd.SetOut(buf)
664 cmd.SetErr(buf)
665 cmd.Flags().Set("show-labels", "true")
666 cmd.Run(cmd, []string{"pods", "foo"})
667
668 expected := `NAME READY STATUS RESTARTS AGE LABELS
669 foo 0/0 0 <unknown> <none>
670 `
671 if e, a := expected, buf.String(); e != a {
672 t.Errorf("expected\n%v\ngot\n%v", e, a)
673 }
674 }
675
676 func TestGetEmptyTable(t *testing.T) {
677 tf := cmdtesting.NewTestFactory().WithNamespace("test")
678 defer tf.Cleanup()
679
680 emptyTable := io.NopCloser(bytes.NewBufferString(`{
681 "kind":"Table",
682 "apiVersion":"meta.k8s.io/v1beta1",
683 "metadata":{
684 "resourceVersion":"346"
685 },
686 "columnDefinitions":[
687 {"name":"Name","type":"string","format":"name","description":"the name","priority":0}
688 ],
689 "rows":[]
690 }`))
691
692 tf.UnstructuredClient = &fake.RESTClient{
693 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
694 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: emptyTable},
695 }
696
697 streams, _, buf, errbuf := genericiooptions.NewTestIOStreams()
698 cmd := NewCmdGet("kubectl", tf, streams)
699 cmd.SetOut(buf)
700 cmd.SetErr(buf)
701 cmd.Run(cmd, []string{"pods"})
702
703 expected := ``
704 if e, a := expected, buf.String(); e != a {
705 t.Errorf("expected\n%v\ngot\n%v", e, a)
706 }
707 expectedErr := `No resources found in test namespace.
708 `
709 if e, a := expectedErr, errbuf.String(); e != a {
710 t.Errorf("expectedErr\n%v\ngot\n%v", e, a)
711 }
712 }
713
714 func TestGetObjectIgnoreNotFound(t *testing.T) {
715 cmdtesting.InitTestErrorHandler(t)
716
717 ns := &corev1.NamespaceList{
718 ListMeta: metav1.ListMeta{
719 ResourceVersion: "1",
720 },
721 Items: []corev1.Namespace{
722 {
723 ObjectMeta: metav1.ObjectMeta{Name: "testns", Namespace: "test", ResourceVersion: "11"},
724 Spec: corev1.NamespaceSpec{},
725 },
726 },
727 }
728
729 tf := cmdtesting.NewTestFactory().WithNamespace("test")
730 defer tf.Cleanup()
731 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
732
733 tf.UnstructuredClient = &fake.RESTClient{
734 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
735 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
736 switch p, m := req.URL.Path, req.Method; {
737 case p == "/namespaces/test/pods/nonexistentpod" && m == "GET":
738 return &http.Response{StatusCode: http.StatusNotFound, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.StringBody("")}, nil
739 case p == "/api/v1/namespaces/test" && m == "GET":
740 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &ns.Items[0])}, nil
741 default:
742 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
743 return nil, nil
744 }
745 }),
746 }
747
748 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
749 cmd := NewCmdGet("kubectl", tf, streams)
750 cmd.SetOut(buf)
751 cmd.SetErr(buf)
752 cmd.Flags().Set("ignore-not-found", "true")
753 cmd.Flags().Set("output", "yaml")
754 cmd.Run(cmd, []string{"pods", "nonexistentpod"})
755
756 if buf.String() != "" {
757 t.Errorf("unexpected output: %s", buf.String())
758 }
759 }
760
761 func TestEmptyResult(t *testing.T) {
762 cmdtesting.InitTestErrorHandler(t)
763
764 tf := cmdtesting.NewTestFactory().WithNamespace("test")
765 defer tf.Cleanup()
766 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
767
768 tf.UnstructuredClient = &fake.RESTClient{
769 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
770 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
771 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.PodList{})}, nil
772 }),
773 }
774
775 streams, _, _, errbuf := genericiooptions.NewTestIOStreams()
776 cmd := NewCmdGet("kubectl", tf, streams)
777
778 cmd.Flags().Set("filename", "-")
779 cmd.Run(cmd, []string{})
780
781 if !strings.Contains(errbuf.String(), "No resources found") {
782 t.Errorf("unexpected output: %q", errbuf.String())
783 }
784 }
785
786 func TestEmptyResultJSON(t *testing.T) {
787 cmdtesting.InitTestErrorHandler(t)
788
789 tf := cmdtesting.NewTestFactory().WithNamespace("test")
790 defer tf.Cleanup()
791 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
792
793 tf.UnstructuredClient = &fake.RESTClient{
794 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
795 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
796 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.PodList{})}, nil
797 }),
798 }
799
800 streams, _, outbuf, errbuf := genericiooptions.NewTestIOStreams()
801 cmd := NewCmdGet("kubectl", tf, streams)
802
803 cmd.Flags().Set("filename", "-")
804 cmd.Flags().Set("output", "json")
805 cmd.Run(cmd, []string{})
806
807 if errbuf.Len() > 0 {
808 t.Errorf("unexpected error: %q", errbuf.String())
809 }
810 if !strings.Contains(outbuf.String(), `"items": []`) {
811 t.Errorf("unexpected output: %q", outbuf.String())
812 }
813 }
814
815 func TestGetSortedObjects(t *testing.T) {
816 pods := &corev1.PodList{
817 ListMeta: metav1.ListMeta{
818 ResourceVersion: "15",
819 },
820 Items: []corev1.Pod{
821 {
822 ObjectMeta: metav1.ObjectMeta{Name: "c", Namespace: "test", ResourceVersion: "10"},
823 Spec: corev1.PodSpec{
824 RestartPolicy: corev1.RestartPolicyAlways,
825 DNSPolicy: corev1.DNSClusterFirst,
826 TerminationGracePeriodSeconds: &grace,
827 SecurityContext: &corev1.PodSecurityContext{},
828 EnableServiceLinks: &enableServiceLinks,
829 },
830 },
831 {
832 ObjectMeta: metav1.ObjectMeta{Name: "b", Namespace: "test", ResourceVersion: "11"},
833 Spec: corev1.PodSpec{
834 RestartPolicy: corev1.RestartPolicyAlways,
835 DNSPolicy: corev1.DNSClusterFirst,
836 TerminationGracePeriodSeconds: &grace,
837 SecurityContext: &corev1.PodSecurityContext{},
838 EnableServiceLinks: &enableServiceLinks,
839 },
840 },
841 {
842 ObjectMeta: metav1.ObjectMeta{Name: "a", Namespace: "test", ResourceVersion: "9"},
843 Spec: corev1.PodSpec{
844 RestartPolicy: corev1.RestartPolicyAlways,
845 DNSPolicy: corev1.DNSClusterFirst,
846 TerminationGracePeriodSeconds: &grace,
847 SecurityContext: &corev1.PodSecurityContext{},
848 EnableServiceLinks: &enableServiceLinks,
849 },
850 },
851 },
852 }
853
854 tf := cmdtesting.NewTestFactory().WithNamespace("test")
855 defer tf.Cleanup()
856 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
857
858 tf.UnstructuredClient = &fake.RESTClient{
859 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
860 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)},
861 }
862 tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &corev1.SchemeGroupVersion}}
863
864 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
865 cmd := NewCmdGet("kubectl", tf, streams)
866 cmd.SetOut(buf)
867 cmd.SetErr(buf)
868
869
870 cmd.Flags().Set("sort-by", ".metadata.name")
871 cmd.Run(cmd, []string{"pods"})
872
873 expected := `NAME AGE
874 a <unknown>
875 b <unknown>
876 c <unknown>
877 `
878 if e, a := expected, buf.String(); e != a {
879 t.Errorf("expected\n%v\ngot\n%v", e, a)
880 }
881 }
882
883 func TestGetSortedObjectsUnstructuredTable(t *testing.T) {
884 unstructuredMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(sortTestTableData()[0])
885 if err != nil {
886 t.Fatal(err)
887 }
888 unstructuredBytes, err := json.MarshalIndent(unstructuredMap, "", " ")
889 if err != nil {
890 t.Fatal(err)
891 }
892
893 body := io.NopCloser(bytes.NewReader(unstructuredBytes))
894
895 tf := cmdtesting.NewTestFactory().WithNamespace("test")
896 defer tf.Cleanup()
897
898 tf.UnstructuredClient = &fake.RESTClient{
899 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
900 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: body},
901 }
902 tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &corev1.SchemeGroupVersion}}
903
904 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
905 cmd := NewCmdGet("kubectl", tf, streams)
906 cmd.SetOut(buf)
907 cmd.SetErr(buf)
908
909
910 cmd.Flags().Set("sort-by", ".metadata.name")
911 cmd.Run(cmd, []string{"pods"})
912
913 expected := `NAME CUSTOM
914 a custom-a
915 b custom-b
916 c custom-c
917 `
918 if e, a := expected, buf.String(); e != a {
919 t.Errorf("expected\n%v\ngot\n%v", e, a)
920 }
921 }
922
923 func sortTestData() []runtime.Object {
924 return []runtime.Object{
925 &corev1.Pod{
926 TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
927 ObjectMeta: metav1.ObjectMeta{Name: "c", Namespace: "test", ResourceVersion: "10"},
928 Spec: corev1.PodSpec{
929 RestartPolicy: corev1.RestartPolicyAlways,
930 DNSPolicy: corev1.DNSClusterFirst,
931 TerminationGracePeriodSeconds: &grace,
932 SecurityContext: &corev1.PodSecurityContext{},
933 EnableServiceLinks: &enableServiceLinks,
934 },
935 },
936 &corev1.Pod{
937 TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
938 ObjectMeta: metav1.ObjectMeta{Name: "b", Namespace: "test", ResourceVersion: "11"},
939 Spec: corev1.PodSpec{
940 RestartPolicy: corev1.RestartPolicyAlways,
941 DNSPolicy: corev1.DNSClusterFirst,
942 TerminationGracePeriodSeconds: &grace,
943 SecurityContext: &corev1.PodSecurityContext{},
944 EnableServiceLinks: &enableServiceLinks,
945 },
946 },
947 &corev1.Pod{
948 TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
949 ObjectMeta: metav1.ObjectMeta{Name: "a", Namespace: "test", ResourceVersion: "9"},
950 Spec: corev1.PodSpec{
951 RestartPolicy: corev1.RestartPolicyAlways,
952 DNSPolicy: corev1.DNSClusterFirst,
953 TerminationGracePeriodSeconds: &grace,
954 SecurityContext: &corev1.PodSecurityContext{},
955 EnableServiceLinks: &enableServiceLinks,
956 },
957 },
958 }
959 }
960
961 func sortTestTableData() []runtime.Object {
962 return []runtime.Object{
963 &metav1beta1.Table{
964 TypeMeta: metav1.TypeMeta{APIVersion: "meta.k8s.io/v1beta1", Kind: "Table"},
965 ColumnDefinitions: []metav1beta1.TableColumnDefinition{
966 {Name: "NAME", Type: "string", Format: "name"},
967 {Name: "CUSTOM", Type: "string", Format: ""},
968 },
969 Rows: []metav1beta1.TableRow{
970 {
971 Cells: []interface{}{"c", "custom-c"},
972 Object: runtime.RawExtension{
973 Object: &corev1.Pod{
974 TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
975 ObjectMeta: metav1.ObjectMeta{Name: "c", Namespace: "test", ResourceVersion: "10"},
976 Spec: corev1.PodSpec{
977 RestartPolicy: corev1.RestartPolicyAlways,
978 DNSPolicy: corev1.DNSClusterFirst,
979 TerminationGracePeriodSeconds: &grace,
980 SecurityContext: &corev1.PodSecurityContext{},
981 EnableServiceLinks: &enableServiceLinks,
982 },
983 },
984 },
985 },
986 {
987 Cells: []interface{}{"b", "custom-b"},
988 Object: runtime.RawExtension{
989 Object: &corev1.Pod{
990 TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
991 ObjectMeta: metav1.ObjectMeta{Name: "b", Namespace: "test", ResourceVersion: "11"},
992 Spec: corev1.PodSpec{
993 RestartPolicy: corev1.RestartPolicyAlways,
994 DNSPolicy: corev1.DNSClusterFirst,
995 TerminationGracePeriodSeconds: &grace,
996 SecurityContext: &corev1.PodSecurityContext{},
997 EnableServiceLinks: &enableServiceLinks,
998 },
999 },
1000 },
1001 },
1002 {
1003 Cells: []interface{}{"a", "custom-a"},
1004 Object: runtime.RawExtension{
1005 Object: &corev1.Pod{
1006 TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
1007 ObjectMeta: metav1.ObjectMeta{Name: "a", Namespace: "test", ResourceVersion: "9"},
1008 Spec: corev1.PodSpec{
1009 RestartPolicy: corev1.RestartPolicyAlways,
1010 DNSPolicy: corev1.DNSClusterFirst,
1011 TerminationGracePeriodSeconds: &grace,
1012 SecurityContext: &corev1.PodSecurityContext{},
1013 EnableServiceLinks: &enableServiceLinks,
1014 },
1015 },
1016 },
1017 },
1018 },
1019 },
1020 }
1021 }
1022
1023 func TestRuntimeSorter(t *testing.T) {
1024 tests := []struct {
1025 name string
1026 field string
1027 objs []runtime.Object
1028 op func(sorter *RuntimeSorter, objs []runtime.Object, out io.Writer) error
1029 expect string
1030 expectError string
1031 }{
1032 {
1033 name: "ensure sorter works with an empty object list",
1034 field: "metadata.name",
1035 objs: []runtime.Object{},
1036 op: func(sorter *RuntimeSorter, objs []runtime.Object, out io.Writer) error {
1037 return nil
1038 },
1039 expect: "",
1040 },
1041 {
1042 name: "ensure sorter returns original position",
1043 field: "metadata.name",
1044 objs: sortTestData(),
1045 op: func(sorter *RuntimeSorter, objs []runtime.Object, out io.Writer) error {
1046 for idx := range objs {
1047 p := sorter.OriginalPosition(idx)
1048 fmt.Fprintf(out, "%v,", p)
1049 }
1050 return nil
1051 },
1052 expect: "2,1,0,",
1053 },
1054 {
1055 name: "ensure sorter handles table object position",
1056 field: "metadata.name",
1057 objs: sortTestTableData(),
1058 op: func(sorter *RuntimeSorter, objs []runtime.Object, out io.Writer) error {
1059 for idx := range objs {
1060 p := sorter.OriginalPosition(idx)
1061 fmt.Fprintf(out, "%v,", p)
1062 }
1063 return nil
1064 },
1065 expect: "0,",
1066 },
1067 {
1068 name: "ensure sorter sorts table objects",
1069 field: "metadata.name",
1070 objs: sortTestData(),
1071 op: func(sorter *RuntimeSorter, objs []runtime.Object, out io.Writer) error {
1072 for _, o := range objs {
1073 fmt.Fprintf(out, "%s,", o.(*corev1.Pod).Name)
1074 }
1075 return nil
1076 },
1077 expect: "a,b,c,",
1078 },
1079 {
1080 name: "ensure sorter rejects mixed Table + non-Table object lists",
1081 field: "metadata.name",
1082 objs: append(sortTestData(), sortTestTableData()...),
1083 op: func(sorter *RuntimeSorter, objs []runtime.Object, out io.Writer) error { return nil },
1084 expectError: "sorting is not supported on mixed Table",
1085 },
1086 {
1087 name: "ensure sorter errors out on invalid jsonpath",
1088 field: "metadata.unknown",
1089 objs: sortTestData(),
1090 op: func(sorter *RuntimeSorter, objs []runtime.Object, out io.Writer) error { return nil },
1091 expectError: "couldn't find any field with path",
1092 },
1093 }
1094
1095 for _, tc := range tests {
1096 t.Run(tc.name, func(t *testing.T) {
1097 sorter := NewRuntimeSorter(tc.objs, tc.field)
1098 if err := sorter.Sort(); err != nil {
1099 if len(tc.expectError) > 0 && strings.Contains(err.Error(), tc.expectError) {
1100 return
1101 }
1102
1103 if len(tc.expectError) > 0 {
1104 t.Fatalf("unexpected error: expecting %s, but got %s", tc.expectError, err)
1105 }
1106
1107 t.Fatalf("unexpected error: %v", err)
1108 }
1109
1110 out := bytes.NewBuffer([]byte{})
1111 err := tc.op(sorter, tc.objs, out)
1112 if err != nil {
1113 t.Fatalf("unexpected error: %v", err)
1114 }
1115
1116 if tc.expect != out.String() {
1117 t.Fatalf("unexpected output: expecting %s, but got %s", tc.expect, out.String())
1118 }
1119
1120 })
1121 }
1122
1123 }
1124
1125 func TestGetObjectsIdentifiedByFile(t *testing.T) {
1126 pods, _, _ := cmdtesting.TestData()
1127
1128 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1129 defer tf.Cleanup()
1130 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1131
1132 tf.UnstructuredClient = &fake.RESTClient{
1133 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1134 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
1135 }
1136
1137 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1138 cmd := NewCmdGet("kubectl", tf, streams)
1139 cmd.SetOut(buf)
1140 cmd.SetErr(buf)
1141 cmd.Flags().Set("filename", "../../../testdata/controller.yaml")
1142 cmd.Run(cmd, []string{})
1143
1144 expected := `NAME AGE
1145 foo <unknown>
1146 `
1147 if e, a := expected, buf.String(); e != a {
1148 t.Errorf("expected\n%v\ngot\n%v", e, a)
1149 }
1150 }
1151
1152 func TestGetTableObjectsIdentifiedByFile(t *testing.T) {
1153 pods, _, _ := cmdtesting.TestData()
1154
1155 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1156 defer tf.Cleanup()
1157 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1158
1159 tf.UnstructuredClient = &fake.RESTClient{
1160 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1161 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, pods.Items[0])},
1162 }
1163
1164 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1165 cmd := NewCmdGet("kubectl", tf, streams)
1166 cmd.SetOut(buf)
1167 cmd.SetErr(buf)
1168 cmd.Flags().Set("filename", "../../../testdata/controller.yaml")
1169 cmd.Run(cmd, []string{})
1170
1171 expected := `NAME READY STATUS RESTARTS AGE
1172 foo 0/0 0 <unknown>
1173 `
1174 if e, a := expected, buf.String(); e != a {
1175 t.Errorf("expected\n%v\ngot\n%v", e, a)
1176 }
1177 }
1178
1179 func TestGetListObjects(t *testing.T) {
1180 pods, _, _ := cmdtesting.TestData()
1181
1182 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1183 defer tf.Cleanup()
1184 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1185
1186 tf.UnstructuredClient = &fake.RESTClient{
1187 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1188 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)},
1189 }
1190
1191 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1192 cmd := NewCmdGet("kubectl", tf, streams)
1193 cmd.SetOut(buf)
1194 cmd.SetErr(buf)
1195 cmd.Run(cmd, []string{"pods"})
1196
1197 expected := `NAME AGE
1198 foo <unknown>
1199 bar <unknown>
1200 `
1201 if e, a := expected, buf.String(); e != a {
1202 t.Errorf("expected\n%v\ngot\n%v", e, a)
1203 }
1204 }
1205
1206 func TestGetListTableObjects(t *testing.T) {
1207 pods, _, _ := cmdtesting.TestData()
1208
1209 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1210 defer tf.Cleanup()
1211 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1212
1213 tf.UnstructuredClient = &fake.RESTClient{
1214 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1215 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, pods.Items...)},
1216 }
1217
1218 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1219 cmd := NewCmdGet("kubectl", tf, streams)
1220 cmd.SetOut(buf)
1221 cmd.SetErr(buf)
1222 cmd.Run(cmd, []string{"pods"})
1223
1224 expected := `NAME READY STATUS RESTARTS AGE
1225 foo 0/0 0 <unknown>
1226 bar 0/0 0 <unknown>
1227 `
1228 if e, a := expected, buf.String(); e != a {
1229 t.Errorf("expected\n%v\ngot\n%v", e, a)
1230 }
1231 }
1232
1233 func TestGetListComponentStatus(t *testing.T) {
1234 statuses := testComponentStatusData()
1235
1236 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1237 defer tf.Cleanup()
1238 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1239
1240 tf.UnstructuredClient = &fake.RESTClient{
1241 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1242 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: componentStatusTableObjBody(codec, (*statuses).Items...)},
1243 }
1244
1245 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1246 cmd := NewCmdGet("kubectl", tf, streams)
1247 cmd.SetOut(buf)
1248 cmd.SetErr(buf)
1249 cmd.Run(cmd, []string{"componentstatuses"})
1250
1251 expected := `NAME STATUS MESSAGE ERROR
1252 servergood Healthy ok
1253 serverbad Unhealthy bad status: 500
1254 serverunknown Unhealthy fizzbuzz error
1255 `
1256 if e, a := expected, buf.String(); e != a {
1257 t.Errorf("expected\n%v\ngot\n%v", e, a)
1258 }
1259 }
1260
1261 func TestGetMixedGenericObjects(t *testing.T) {
1262 cmdtesting.InitTestErrorHandler(t)
1263
1264
1265
1266 structuredObj := &metav1.Status{
1267 TypeMeta: metav1.TypeMeta{
1268 Kind: "Status",
1269 APIVersion: "v1",
1270 },
1271 Status: "Success",
1272 Message: "",
1273 Reason: "",
1274 Code: 0,
1275 }
1276
1277 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1278 defer tf.Cleanup()
1279 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1280
1281 tf.UnstructuredClient = &fake.RESTClient{
1282 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1283 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
1284 switch req.URL.Path {
1285 case "/namespaces/test/pods":
1286 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, structuredObj)}, nil
1287 default:
1288 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
1289 return nil, nil
1290 }
1291 }),
1292 }
1293 tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
1294
1295 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1296 cmd := NewCmdGet("kubectl", tf, streams)
1297 cmd.SetOut(buf)
1298 cmd.SetErr(buf)
1299 cmd.Flags().Set("output", "json")
1300 cmd.Run(cmd, []string{"pods"})
1301
1302 expected := `{
1303 "apiVersion": "v1",
1304 "items": [
1305 {
1306 "apiVersion": "v1",
1307 "kind": "Status",
1308 "metadata": {},
1309 "status": "Success"
1310 }
1311 ],
1312 "kind": "List",
1313 "metadata": {
1314 "resourceVersion": ""
1315 }
1316 }
1317 `
1318 if e, a := expected, buf.String(); e != a {
1319 t.Errorf("expected\n%v\ngot\n%v", e, a)
1320 }
1321 }
1322
1323 func TestGetMultipleTypeObjects(t *testing.T) {
1324 pods, svc, _ := cmdtesting.TestData()
1325
1326 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1327 defer tf.Cleanup()
1328 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1329
1330 tf.UnstructuredClient = &fake.RESTClient{
1331 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1332 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
1333 switch req.URL.Path {
1334 case "/namespaces/test/pods":
1335 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
1336 case "/namespaces/test/services":
1337 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
1338 default:
1339 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
1340 return nil, nil
1341 }
1342 }),
1343 }
1344
1345 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1346 cmd := NewCmdGet("kubectl", tf, streams)
1347 cmd.SetOut(buf)
1348 cmd.SetErr(buf)
1349 cmd.Run(cmd, []string{"pods,services"})
1350
1351 expected := `NAME AGE
1352 pod/foo <unknown>
1353 pod/bar <unknown>
1354
1355 NAME AGE
1356 service/baz <unknown>
1357 `
1358 if e, a := expected, buf.String(); e != a {
1359 t.Errorf("expected\n%v\ngot\n%v", e, a)
1360 }
1361 }
1362
1363 func TestGetMultipleTypeTableObjects(t *testing.T) {
1364 pods, svc, _ := cmdtesting.TestData()
1365
1366 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1367 defer tf.Cleanup()
1368 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1369
1370 tf.UnstructuredClient = &fake.RESTClient{
1371 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1372 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
1373 switch req.URL.Path {
1374 case "/namespaces/test/pods":
1375 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, pods.Items...)}, nil
1376 case "/namespaces/test/services":
1377 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: serviceTableObjBody(codec, svc.Items...)}, nil
1378 default:
1379 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
1380 return nil, nil
1381 }
1382 }),
1383 }
1384
1385 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1386 cmd := NewCmdGet("kubectl", tf, streams)
1387 cmd.SetOut(buf)
1388 cmd.SetErr(buf)
1389 cmd.Run(cmd, []string{"pods,services"})
1390
1391 expected := `NAME READY STATUS RESTARTS AGE
1392 pod/foo 0/0 0 <unknown>
1393 pod/bar 0/0 0 <unknown>
1394
1395 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
1396 service/baz ClusterIP <none> <none> <none> <unknown>
1397 `
1398 if e, a := expected, buf.String(); e != a {
1399 t.Errorf("expected\n%v\ngot\n%v", e, a)
1400 }
1401 }
1402
1403 func TestGetMultipleTypeObjectsAsList(t *testing.T) {
1404 pods, svc, _ := cmdtesting.TestData()
1405
1406 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1407 defer tf.Cleanup()
1408 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1409
1410 tf.UnstructuredClient = &fake.RESTClient{
1411 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1412 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
1413 switch req.URL.Path {
1414 case "/namespaces/test/pods":
1415 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
1416 case "/namespaces/test/services":
1417 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
1418 default:
1419 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
1420 return nil, nil
1421 }
1422 }),
1423 }
1424 tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
1425
1426 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1427 cmd := NewCmdGet("kubectl", tf, streams)
1428 cmd.SetOut(buf)
1429 cmd.SetErr(buf)
1430
1431 cmd.Flags().Set("output", "json")
1432 cmd.Run(cmd, []string{"pods,services"})
1433
1434 expected := `{
1435 "apiVersion": "v1",
1436 "items": [
1437 {
1438 "apiVersion": "v1",
1439 "kind": "Pod",
1440 "metadata": {
1441 "creationTimestamp": null,
1442 "name": "foo",
1443 "namespace": "test",
1444 "resourceVersion": "10"
1445 },
1446 "spec": {
1447 "containers": null,
1448 "dnsPolicy": "ClusterFirst",
1449 "enableServiceLinks": true,
1450 "restartPolicy": "Always",
1451 "securityContext": {},
1452 "terminationGracePeriodSeconds": 30
1453 },
1454 "status": {}
1455 },
1456 {
1457 "apiVersion": "v1",
1458 "kind": "Pod",
1459 "metadata": {
1460 "creationTimestamp": null,
1461 "name": "bar",
1462 "namespace": "test",
1463 "resourceVersion": "11"
1464 },
1465 "spec": {
1466 "containers": null,
1467 "dnsPolicy": "ClusterFirst",
1468 "enableServiceLinks": true,
1469 "restartPolicy": "Always",
1470 "securityContext": {},
1471 "terminationGracePeriodSeconds": 30
1472 },
1473 "status": {}
1474 },
1475 {
1476 "apiVersion": "v1",
1477 "kind": "Service",
1478 "metadata": {
1479 "creationTimestamp": null,
1480 "name": "baz",
1481 "namespace": "test",
1482 "resourceVersion": "12"
1483 },
1484 "spec": {
1485 "sessionAffinity": "None",
1486 "type": "ClusterIP"
1487 },
1488 "status": {
1489 "loadBalancer": {}
1490 }
1491 }
1492 ],
1493 "kind": "List",
1494 "metadata": {
1495 "resourceVersion": ""
1496 }
1497 }
1498 `
1499 if e, a := expected, buf.String(); e != a {
1500 t.Errorf("did not match:\n%v", cmp.Diff(e, a))
1501 }
1502 }
1503
1504 func TestGetMultipleTypeObjectsWithLabelSelector(t *testing.T) {
1505 pods, svc, _ := cmdtesting.TestData()
1506
1507 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1508 defer tf.Cleanup()
1509 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1510
1511 tf.UnstructuredClient = &fake.RESTClient{
1512 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1513 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
1514 if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" {
1515 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
1516 }
1517 switch req.URL.Path {
1518 case "/namespaces/test/pods":
1519 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
1520 case "/namespaces/test/services":
1521 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
1522 default:
1523 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
1524 return nil, nil
1525 }
1526 }),
1527 }
1528
1529 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1530 cmd := NewCmdGet("kubectl", tf, streams)
1531 cmd.SetOut(buf)
1532 cmd.SetErr(buf)
1533
1534 cmd.Flags().Set("selector", "a=b")
1535 cmd.Run(cmd, []string{"pods,services"})
1536
1537 expected := `NAME AGE
1538 pod/foo <unknown>
1539 pod/bar <unknown>
1540
1541 NAME AGE
1542 service/baz <unknown>
1543 `
1544 if e, a := expected, buf.String(); e != a {
1545 t.Errorf("expected\n%v\ngot\n%v", e, a)
1546 }
1547 }
1548
1549 func TestGetMultipleTypeTableObjectsWithLabelSelector(t *testing.T) {
1550 pods, svc, _ := cmdtesting.TestData()
1551
1552 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1553 defer tf.Cleanup()
1554 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1555
1556 tf.UnstructuredClient = &fake.RESTClient{
1557 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1558 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
1559 if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" {
1560 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
1561 }
1562 switch req.URL.Path {
1563 case "/namespaces/test/pods":
1564 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, pods.Items...)}, nil
1565 case "/namespaces/test/services":
1566 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: serviceTableObjBody(codec, svc.Items...)}, nil
1567 default:
1568 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
1569 return nil, nil
1570 }
1571 }),
1572 }
1573
1574 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1575 cmd := NewCmdGet("kubectl", tf, streams)
1576 cmd.SetOut(buf)
1577 cmd.SetErr(buf)
1578
1579 cmd.Flags().Set("selector", "a=b")
1580 cmd.Run(cmd, []string{"pods,services"})
1581
1582 expected := `NAME READY STATUS RESTARTS AGE
1583 pod/foo 0/0 0 <unknown>
1584 pod/bar 0/0 0 <unknown>
1585
1586 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
1587 service/baz ClusterIP <none> <none> <none> <unknown>
1588 `
1589 if e, a := expected, buf.String(); e != a {
1590 t.Errorf("expected\n%v\ngot\n%v", e, a)
1591 }
1592 }
1593
1594 func TestGetMultipleTypeObjectsWithFieldSelector(t *testing.T) {
1595 pods, svc, _ := cmdtesting.TestData()
1596
1597 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1598 defer tf.Cleanup()
1599 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1600
1601 tf.UnstructuredClient = &fake.RESTClient{
1602 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1603 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
1604 if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" {
1605 t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
1606 }
1607 switch req.URL.Path {
1608 case "/namespaces/test/pods":
1609 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
1610 case "/namespaces/test/services":
1611 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
1612 default:
1613 t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
1614 return nil, nil
1615 }
1616 }),
1617 }
1618
1619 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1620 cmd := NewCmdGet("kubectl", tf, streams)
1621 cmd.SetOut(buf)
1622 cmd.SetErr(buf)
1623
1624 cmd.Flags().Set("field-selector", "a=b")
1625 cmd.Run(cmd, []string{"pods,services"})
1626
1627 expected := `NAME AGE
1628 pod/foo <unknown>
1629 pod/bar <unknown>
1630
1631 NAME AGE
1632 service/baz <unknown>
1633 `
1634 if e, a := expected, buf.String(); e != a {
1635 t.Errorf("expected\n%v\ngot\n%v", e, a)
1636 }
1637 }
1638
1639 func TestGetMultipleTypeTableObjectsWithFieldSelector(t *testing.T) {
1640 pods, svc, _ := cmdtesting.TestData()
1641
1642 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1643 defer tf.Cleanup()
1644 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1645
1646 tf.UnstructuredClient = &fake.RESTClient{
1647 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1648 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
1649 if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" {
1650 t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
1651 }
1652 switch req.URL.Path {
1653 case "/namespaces/test/pods":
1654 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, pods.Items...)}, nil
1655 case "/namespaces/test/services":
1656 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: serviceTableObjBody(codec, svc.Items...)}, nil
1657 default:
1658 t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
1659 return nil, nil
1660 }
1661 }),
1662 }
1663
1664 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1665 cmd := NewCmdGet("kubectl", tf, streams)
1666 cmd.SetOut(buf)
1667 cmd.SetErr(buf)
1668
1669 cmd.Flags().Set("field-selector", "a=b")
1670 cmd.Run(cmd, []string{"pods,services"})
1671
1672 expected := `NAME READY STATUS RESTARTS AGE
1673 pod/foo 0/0 0 <unknown>
1674 pod/bar 0/0 0 <unknown>
1675
1676 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
1677 service/baz ClusterIP <none> <none> <none> <unknown>
1678 `
1679 if e, a := expected, buf.String(); e != a {
1680 t.Errorf("expected\n%v\ngot\n%v", e, a)
1681 }
1682 }
1683
1684 func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) {
1685 _, svc, _ := cmdtesting.TestData()
1686 node := &corev1.Node{
1687 ObjectMeta: metav1.ObjectMeta{
1688 Name: "foo",
1689 },
1690 }
1691
1692 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1693 defer tf.Cleanup()
1694 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1695
1696 tf.UnstructuredClient = &fake.RESTClient{
1697 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1698 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
1699 switch req.URL.Path {
1700 case "/nodes/foo":
1701 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, node)}, nil
1702 case "/namespaces/test/services/bar":
1703 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
1704 default:
1705 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
1706 return nil, nil
1707 }
1708 }),
1709 }
1710
1711 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1712 cmd := NewCmdGet("kubectl", tf, streams)
1713 cmd.SetOut(buf)
1714 cmd.SetErr(buf)
1715
1716 cmd.Run(cmd, []string{"services/bar", "node/foo"})
1717
1718 expected := `NAME AGE
1719 service/baz <unknown>
1720
1721 NAME AGE
1722 node/foo <unknown>
1723 `
1724 if e, a := expected, buf.String(); e != a {
1725 t.Errorf("expected\n%v\ngot\n%v", e, a)
1726 }
1727 }
1728
1729 func TestGetMultipleTypeTableObjectsWithDirectReference(t *testing.T) {
1730 _, svc, _ := cmdtesting.TestData()
1731 node := &corev1.Node{
1732 ObjectMeta: metav1.ObjectMeta{
1733 Name: "foo",
1734 },
1735 }
1736
1737 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1738 defer tf.Cleanup()
1739 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1740
1741 tf.UnstructuredClient = &fake.RESTClient{
1742 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1743 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
1744 switch req.URL.Path {
1745 case "/nodes/foo":
1746 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: nodeTableObjBody(codec, *node)}, nil
1747 case "/namespaces/test/services/bar":
1748 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: serviceTableObjBody(codec, svc.Items[0])}, nil
1749 default:
1750 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
1751 return nil, nil
1752 }
1753 }),
1754 }
1755
1756 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1757 cmd := NewCmdGet("kubectl", tf, streams)
1758 cmd.SetOut(buf)
1759 cmd.SetErr(buf)
1760
1761 cmd.Run(cmd, []string{"services/bar", "node/foo"})
1762
1763 expected := `NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
1764 service/baz ClusterIP <none> <none> <none> <unknown>
1765
1766 NAME STATUS ROLES AGE VERSION
1767 node/foo Unknown <none> <unknown>
1768 `
1769 if e, a := expected, buf.String(); e != a {
1770 t.Errorf("expected\n%v\ngot\n%v", e, a)
1771 }
1772 }
1773
1774 func watchTestData() ([]corev1.Pod, []watch.Event) {
1775 pods := []corev1.Pod{
1776 {
1777 ObjectMeta: metav1.ObjectMeta{
1778 Name: "bar",
1779 Namespace: "test",
1780 ResourceVersion: "9",
1781 },
1782 Spec: corev1.PodSpec{
1783 RestartPolicy: corev1.RestartPolicyAlways,
1784 DNSPolicy: corev1.DNSClusterFirst,
1785 TerminationGracePeriodSeconds: &grace,
1786 SecurityContext: &corev1.PodSecurityContext{},
1787 EnableServiceLinks: &enableServiceLinks,
1788 },
1789 },
1790 {
1791 ObjectMeta: metav1.ObjectMeta{
1792 Name: "foo",
1793 Namespace: "test",
1794 ResourceVersion: "10",
1795 },
1796 Spec: corev1.PodSpec{
1797 RestartPolicy: corev1.RestartPolicyAlways,
1798 DNSPolicy: corev1.DNSClusterFirst,
1799 TerminationGracePeriodSeconds: &grace,
1800 SecurityContext: &corev1.PodSecurityContext{},
1801 EnableServiceLinks: &enableServiceLinks,
1802 },
1803 },
1804 }
1805 events := []watch.Event{
1806
1807 {
1808 Type: watch.Added,
1809 Object: &corev1.Pod{
1810 ObjectMeta: metav1.ObjectMeta{
1811 Name: "bar",
1812 Namespace: "test",
1813 ResourceVersion: "9",
1814 },
1815 Spec: corev1.PodSpec{
1816 RestartPolicy: corev1.RestartPolicyAlways,
1817 DNSPolicy: corev1.DNSClusterFirst,
1818 TerminationGracePeriodSeconds: &grace,
1819 SecurityContext: &corev1.PodSecurityContext{},
1820 EnableServiceLinks: &enableServiceLinks,
1821 },
1822 },
1823 },
1824 {
1825 Type: watch.Added,
1826 Object: &corev1.Pod{
1827 ObjectMeta: metav1.ObjectMeta{
1828 Name: "foo",
1829 Namespace: "test",
1830 ResourceVersion: "10",
1831 },
1832 Spec: corev1.PodSpec{
1833 RestartPolicy: corev1.RestartPolicyAlways,
1834 DNSPolicy: corev1.DNSClusterFirst,
1835 TerminationGracePeriodSeconds: &grace,
1836 SecurityContext: &corev1.PodSecurityContext{},
1837 EnableServiceLinks: &enableServiceLinks,
1838 },
1839 },
1840 },
1841
1842 {
1843 Type: watch.Modified,
1844 Object: &corev1.Pod{
1845 ObjectMeta: metav1.ObjectMeta{
1846 Name: "foo",
1847 Namespace: "test",
1848 ResourceVersion: "11",
1849 },
1850 Spec: corev1.PodSpec{
1851 RestartPolicy: corev1.RestartPolicyAlways,
1852 DNSPolicy: corev1.DNSClusterFirst,
1853 TerminationGracePeriodSeconds: &grace,
1854 SecurityContext: &corev1.PodSecurityContext{},
1855 EnableServiceLinks: &enableServiceLinks,
1856 },
1857 },
1858 },
1859 {
1860 Type: watch.Deleted,
1861 Object: &corev1.Pod{
1862 ObjectMeta: metav1.ObjectMeta{
1863 Name: "foo",
1864 Namespace: "test",
1865 ResourceVersion: "12",
1866 },
1867 Spec: corev1.PodSpec{
1868 RestartPolicy: corev1.RestartPolicyAlways,
1869 DNSPolicy: corev1.DNSClusterFirst,
1870 TerminationGracePeriodSeconds: &grace,
1871 SecurityContext: &corev1.PodSecurityContext{},
1872 EnableServiceLinks: &enableServiceLinks,
1873 },
1874 },
1875 },
1876 }
1877 return pods, events
1878 }
1879
1880 func TestWatchLabelSelector(t *testing.T) {
1881 pods, events := watchTestData()
1882
1883 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1884 defer tf.Cleanup()
1885 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1886
1887 podList := &corev1.PodList{
1888 Items: pods,
1889 ListMeta: metav1.ListMeta{
1890 ResourceVersion: "10",
1891 },
1892 }
1893 tf.UnstructuredClient = &fake.RESTClient{
1894 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1895 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
1896 if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" {
1897 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
1898 }
1899 switch req.URL.Path {
1900 case "/namespaces/test/pods":
1901 if req.URL.Query().Get("watch") == "true" {
1902 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[2:])}, nil
1903 }
1904 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, podList)}, nil
1905 default:
1906 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
1907 return nil, nil
1908 }
1909 }),
1910 }
1911
1912 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1913 cmd := NewCmdGet("kubectl", tf, streams)
1914 cmd.SetOut(buf)
1915 cmd.SetErr(buf)
1916
1917 cmd.Flags().Set("watch", "true")
1918 cmd.Flags().Set("selector", "a=b")
1919 cmd.Run(cmd, []string{"pods"})
1920
1921 expected := `NAME AGE
1922 bar <unknown>
1923 foo <unknown>
1924 foo <unknown>
1925 foo <unknown>
1926 `
1927 if e, a := expected, buf.String(); e != a {
1928 t.Errorf("expected\n%v\ngot\n%v", e, a)
1929 }
1930 }
1931
1932 func TestWatchTableLabelSelector(t *testing.T) {
1933 pods, events := watchTestData()
1934
1935 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1936 defer tf.Cleanup()
1937 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1938
1939 podList := &corev1.PodList{
1940 Items: pods,
1941 ListMeta: metav1.ListMeta{
1942 ResourceVersion: "10",
1943 },
1944 }
1945 tf.UnstructuredClient = &fake.RESTClient{
1946 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1947 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
1948 if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" {
1949 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
1950 }
1951 switch req.URL.Path {
1952 case "/namespaces/test/pods":
1953 if req.URL.Query().Get("watch") == "true" {
1954 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableWatchBody(codec, events[2:])}, nil
1955 }
1956 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, podList.Items...)}, nil
1957 default:
1958 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
1959 return nil, nil
1960 }
1961 }),
1962 }
1963
1964 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
1965 cmd := NewCmdGet("kubectl", tf, streams)
1966 cmd.SetOut(buf)
1967 cmd.SetErr(buf)
1968
1969 cmd.Flags().Set("watch", "true")
1970 cmd.Flags().Set("selector", "a=b")
1971 cmd.Run(cmd, []string{"pods"})
1972
1973 expected := `NAME READY STATUS RESTARTS AGE
1974 bar 0/0 0 <unknown>
1975 foo 0/0 0 <unknown>
1976 foo 0/0 0 <unknown>
1977 foo 0/0 0 <unknown>
1978 `
1979 if e, a := expected, buf.String(); e != a {
1980 t.Errorf("expected\n%v\ngot\n%v", e, a)
1981 }
1982 }
1983
1984 func TestWatchFieldSelector(t *testing.T) {
1985 pods, events := watchTestData()
1986
1987 tf := cmdtesting.NewTestFactory().WithNamespace("test")
1988 defer tf.Cleanup()
1989 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
1990
1991 podList := &corev1.PodList{
1992 Items: pods,
1993 ListMeta: metav1.ListMeta{
1994 ResourceVersion: "10",
1995 },
1996 }
1997 tf.UnstructuredClient = &fake.RESTClient{
1998 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
1999 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
2000 if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" {
2001 t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
2002 }
2003 switch req.URL.Path {
2004 case "/namespaces/test/pods":
2005 if req.URL.Query().Get("watch") == "true" {
2006 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[2:])}, nil
2007 }
2008 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, podList)}, nil
2009 default:
2010 t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
2011 return nil, nil
2012 }
2013 }),
2014 }
2015
2016 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
2017 cmd := NewCmdGet("kubectl", tf, streams)
2018 cmd.SetOut(buf)
2019 cmd.SetErr(buf)
2020
2021 cmd.Flags().Set("watch", "true")
2022 cmd.Flags().Set("field-selector", "a=b")
2023 cmd.Run(cmd, []string{"pods"})
2024
2025 expected := `NAME AGE
2026 bar <unknown>
2027 foo <unknown>
2028 foo <unknown>
2029 foo <unknown>
2030 `
2031 if e, a := expected, buf.String(); e != a {
2032 t.Errorf("expected\n%v\ngot\n%v", e, a)
2033 }
2034 }
2035
2036 func TestWatchTableFieldSelector(t *testing.T) {
2037 pods, events := watchTestData()
2038
2039 tf := cmdtesting.NewTestFactory().WithNamespace("test")
2040 defer tf.Cleanup()
2041 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2042
2043 podList := &corev1.PodList{
2044 Items: pods,
2045 ListMeta: metav1.ListMeta{
2046 ResourceVersion: "10",
2047 },
2048 }
2049 tf.UnstructuredClient = &fake.RESTClient{
2050 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
2051 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
2052 if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" {
2053 t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
2054 }
2055 switch req.URL.Path {
2056 case "/namespaces/test/pods":
2057 if req.URL.Query().Get("watch") == "true" {
2058 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableWatchBody(codec, events[2:])}, nil
2059 }
2060 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, podList.Items...)}, nil
2061 default:
2062 t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
2063 return nil, nil
2064 }
2065 }),
2066 }
2067
2068 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
2069 cmd := NewCmdGet("kubectl", tf, streams)
2070 cmd.SetOut(buf)
2071 cmd.SetErr(buf)
2072
2073 cmd.Flags().Set("watch", "true")
2074 cmd.Flags().Set("field-selector", "a=b")
2075 cmd.Run(cmd, []string{"pods"})
2076
2077 expected := `NAME READY STATUS RESTARTS AGE
2078 bar 0/0 0 <unknown>
2079 foo 0/0 0 <unknown>
2080 foo 0/0 0 <unknown>
2081 foo 0/0 0 <unknown>
2082 `
2083 if e, a := expected, buf.String(); e != a {
2084 t.Errorf("expected\n%v\ngot\n%v", e, a)
2085 }
2086 }
2087
2088 func TestWatchResource(t *testing.T) {
2089 pods, events := watchTestData()
2090
2091 tf := cmdtesting.NewTestFactory().WithNamespace("test")
2092 defer tf.Cleanup()
2093 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2094
2095 tf.UnstructuredClient = &fake.RESTClient{
2096 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
2097 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
2098 switch req.URL.Path {
2099 case "/namespaces/test/pods/foo":
2100 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods[1])}, nil
2101 case "/namespaces/test/pods":
2102 if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" {
2103 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[1:])}, nil
2104 }
2105 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2106 return nil, nil
2107 default:
2108 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2109 return nil, nil
2110 }
2111 }),
2112 }
2113
2114 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
2115 cmd := NewCmdGet("kubectl", tf, streams)
2116 cmd.SetOut(buf)
2117 cmd.SetErr(buf)
2118
2119 cmd.Flags().Set("watch", "true")
2120 cmd.Run(cmd, []string{"pods", "foo"})
2121
2122 expected := `NAME AGE
2123 foo <unknown>
2124 foo <unknown>
2125 foo <unknown>
2126 `
2127 if e, a := expected, buf.String(); e != a {
2128 t.Errorf("expected\n%v\ngot\n%v", e, a)
2129 }
2130 }
2131
2132 func TestWatchStatus(t *testing.T) {
2133 pods, events := watchTestData()
2134 events = append(events, watch.Event{Type: "ERROR", Object: &metav1.Status{Status: "Failure", Reason: "InternalServerError", Message: "Something happened"}})
2135
2136 tf := cmdtesting.NewTestFactory().WithNamespace("test")
2137 defer tf.Cleanup()
2138 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2139
2140 tf.UnstructuredClient = &fake.RESTClient{
2141 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
2142 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
2143 switch req.URL.Path {
2144 case "/namespaces/test/pods/foo":
2145 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods[1])}, nil
2146 case "/namespaces/test/pods":
2147 if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" {
2148 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[1:])}, nil
2149 }
2150 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2151 return nil, nil
2152 default:
2153 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2154 return nil, nil
2155 }
2156 }),
2157 }
2158
2159 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
2160 cmd := NewCmdGet("kubectl", tf, streams)
2161 cmd.SetOut(buf)
2162 cmd.SetErr(buf)
2163
2164 cmd.Flags().Set("watch", "true")
2165 cmd.Run(cmd, []string{"pods", "foo"})
2166
2167 expected := `NAME AGE
2168 foo <unknown>
2169 foo <unknown>
2170 foo <unknown>
2171
2172 STATUS REASON MESSAGE
2173 Failure InternalServerError Something happened
2174 `
2175 if e, a := expected, buf.String(); e != a {
2176 t.Errorf("expected\n%v\ngot\n%v", e, a)
2177 }
2178 }
2179
2180 func TestWatchTableResource(t *testing.T) {
2181 pods, events := watchTestData()
2182
2183 tf := cmdtesting.NewTestFactory().WithNamespace("test")
2184 defer tf.Cleanup()
2185 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2186
2187 tf.UnstructuredClient = &fake.RESTClient{
2188 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
2189 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
2190 switch req.URL.Path {
2191 case "/namespaces/test/pods/foo":
2192 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, pods[1])}, nil
2193 case "/namespaces/test/pods":
2194 if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" {
2195 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableWatchBody(codec, events[1:])}, nil
2196 }
2197 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2198 return nil, nil
2199 default:
2200 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2201 return nil, nil
2202 }
2203 }),
2204 }
2205
2206 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
2207 cmd := NewCmdGet("kubectl", tf, streams)
2208 cmd.SetOut(buf)
2209 cmd.SetErr(buf)
2210
2211 cmd.Flags().Set("watch", "true")
2212 cmd.Run(cmd, []string{"pods", "foo"})
2213
2214 expected := `NAME READY STATUS RESTARTS AGE
2215 foo 0/0 0 <unknown>
2216 foo 0/0 0 <unknown>
2217 foo 0/0 0 <unknown>
2218 `
2219 if e, a := expected, buf.String(); e != a {
2220 t.Errorf("expected\n%v\ngot\n%v", e, a)
2221 }
2222 }
2223
2224 func TestWatchResourceTable(t *testing.T) {
2225 columns := []metav1beta1.TableColumnDefinition{
2226 {Name: "Name", Type: "string", Format: "name", Description: "the name", Priority: 0},
2227 {Name: "Active", Type: "boolean", Description: "active", Priority: 0},
2228 }
2229
2230 listTable := &metav1beta1.Table{
2231 TypeMeta: metav1.TypeMeta{APIVersion: "meta.k8s.io/v1beta1", Kind: "Table"},
2232 ColumnDefinitions: columns,
2233 Rows: []metav1beta1.TableRow{
2234 {
2235 Cells: []interface{}{"a", true},
2236 Object: runtime.RawExtension{
2237 Object: &corev1.Pod{
2238 TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
2239 ObjectMeta: metav1.ObjectMeta{Name: "a", Namespace: "test", ResourceVersion: "10"},
2240 },
2241 },
2242 },
2243 {
2244 Cells: []interface{}{"b", true},
2245 Object: runtime.RawExtension{
2246 Object: &corev1.Pod{
2247 TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
2248 ObjectMeta: metav1.ObjectMeta{Name: "b", Namespace: "test", ResourceVersion: "20"},
2249 },
2250 },
2251 },
2252 },
2253 }
2254
2255 events := []watch.Event{
2256 {
2257 Type: watch.Added,
2258 Object: &metav1beta1.Table{
2259 TypeMeta: metav1.TypeMeta{APIVersion: "meta.k8s.io/v1beta1", Kind: "Table"},
2260 ColumnDefinitions: columns,
2261 Rows: []metav1beta1.TableRow{{
2262 Cells: []interface{}{"a", false},
2263 Object: runtime.RawExtension{
2264 Object: &corev1.Pod{
2265 TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
2266 ObjectMeta: metav1.ObjectMeta{Name: "a", Namespace: "test", ResourceVersion: "30"},
2267 },
2268 },
2269 }},
2270 },
2271 },
2272 {
2273 Type: watch.Deleted,
2274 Object: &metav1beta1.Table{
2275 ColumnDefinitions: []metav1beta1.TableColumnDefinition{},
2276 Rows: []metav1beta1.TableRow{{
2277 Cells: []interface{}{"b", false},
2278 Object: runtime.RawExtension{
2279 Object: &corev1.Pod{
2280 TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
2281 ObjectMeta: metav1.ObjectMeta{Name: "b", Namespace: "test", ResourceVersion: "40"},
2282 },
2283 },
2284 }},
2285 },
2286 },
2287 }
2288
2289 tf := cmdtesting.NewTestFactory().WithNamespace("test")
2290 defer tf.Cleanup()
2291 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2292
2293 tf.UnstructuredClient = &fake.RESTClient{
2294 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
2295 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
2296 switch req.URL.Path {
2297 case "/namespaces/test/pods":
2298 if req.URL.Query().Get("watch") != "true" && req.URL.Query().Get("fieldSelector") == "" {
2299 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, listTable)}, nil
2300 }
2301 if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "" {
2302 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events)}, nil
2303 }
2304 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2305 return nil, nil
2306 default:
2307 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2308 return nil, nil
2309 }
2310 }),
2311 }
2312
2313 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
2314 cmd := NewCmdGet("kubectl", tf, streams)
2315 cmd.SetOut(buf)
2316 cmd.SetErr(buf)
2317
2318 cmd.Flags().Set("watch", "true")
2319 cmd.Run(cmd, []string{"pods"})
2320
2321 expected := `NAME ACTIVE
2322 a true
2323 b true
2324 a false
2325 b false
2326 `
2327 if e, a := expected, buf.String(); e != a {
2328 t.Errorf("expected\n%v\ngot\n%v", e, a)
2329 }
2330 }
2331
2332 func TestWatchResourceWatchEvents(t *testing.T) {
2333
2334 testcases := []struct {
2335 format string
2336 table bool
2337 expected string
2338 }{
2339 {
2340 format: "",
2341 expected: `EVENT NAMESPACE NAME AGE
2342 ADDED test pod/bar <unknown>
2343 ADDED test pod/foo <unknown>
2344 MODIFIED test pod/foo <unknown>
2345 DELETED test pod/foo <unknown>
2346 `,
2347 },
2348 {
2349 format: "",
2350 table: true,
2351 expected: `EVENT NAMESPACE NAME READY STATUS RESTARTS AGE
2352 ADDED test pod/bar 0/0 0 <unknown>
2353 ADDED test pod/foo 0/0 0 <unknown>
2354 MODIFIED test pod/foo 0/0 0 <unknown>
2355 DELETED test pod/foo 0/0 0 <unknown>
2356 `,
2357 },
2358 {
2359 format: "wide",
2360 table: true,
2361 expected: `EVENT NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
2362 ADDED test pod/bar 0/0 0 <unknown> <none> <none> <none> <none>
2363 ADDED test pod/foo 0/0 0 <unknown> <none> <none> <none> <none>
2364 MODIFIED test pod/foo 0/0 0 <unknown> <none> <none> <none> <none>
2365 DELETED test pod/foo 0/0 0 <unknown> <none> <none> <none> <none>
2366 `,
2367 },
2368 {
2369 format: "json",
2370 expected: `{"type":"ADDED","object":{"apiVersion":"v1","kind":"Pod","metadata":{"creationTimestamp":null,"name":"bar","namespace":"test","resourceVersion":"9"},"spec":{"containers":null,"dnsPolicy":"ClusterFirst","enableServiceLinks":true,"restartPolicy":"Always","securityContext":{},"terminationGracePeriodSeconds":30},"status":{}}}
2371 {"type":"ADDED","object":{"apiVersion":"v1","kind":"Pod","metadata":{"creationTimestamp":null,"name":"foo","namespace":"test","resourceVersion":"10"},"spec":{"containers":null,"dnsPolicy":"ClusterFirst","enableServiceLinks":true,"restartPolicy":"Always","securityContext":{},"terminationGracePeriodSeconds":30},"status":{}}}
2372 {"type":"MODIFIED","object":{"apiVersion":"v1","kind":"Pod","metadata":{"creationTimestamp":null,"name":"foo","namespace":"test","resourceVersion":"11"},"spec":{"containers":null,"dnsPolicy":"ClusterFirst","enableServiceLinks":true,"restartPolicy":"Always","securityContext":{},"terminationGracePeriodSeconds":30},"status":{}}}
2373 {"type":"DELETED","object":{"apiVersion":"v1","kind":"Pod","metadata":{"creationTimestamp":null,"name":"foo","namespace":"test","resourceVersion":"12"},"spec":{"containers":null,"dnsPolicy":"ClusterFirst","enableServiceLinks":true,"restartPolicy":"Always","securityContext":{},"terminationGracePeriodSeconds":30},"status":{}}}
2374 `,
2375 },
2376 {
2377 format: "yaml",
2378 expected: `object:
2379 apiVersion: v1
2380 kind: Pod
2381 metadata:
2382 creationTimestamp: null
2383 name: bar
2384 namespace: test
2385 resourceVersion: "9"
2386 spec:
2387 containers: null
2388 dnsPolicy: ClusterFirst
2389 enableServiceLinks: true
2390 restartPolicy: Always
2391 securityContext: {}
2392 terminationGracePeriodSeconds: 30
2393 status: {}
2394 type: ADDED
2395 ---
2396 object:
2397 apiVersion: v1
2398 kind: Pod
2399 metadata:
2400 creationTimestamp: null
2401 name: foo
2402 namespace: test
2403 resourceVersion: "10"
2404 spec:
2405 containers: null
2406 dnsPolicy: ClusterFirst
2407 enableServiceLinks: true
2408 restartPolicy: Always
2409 securityContext: {}
2410 terminationGracePeriodSeconds: 30
2411 status: {}
2412 type: ADDED
2413 ---
2414 object:
2415 apiVersion: v1
2416 kind: Pod
2417 metadata:
2418 creationTimestamp: null
2419 name: foo
2420 namespace: test
2421 resourceVersion: "11"
2422 spec:
2423 containers: null
2424 dnsPolicy: ClusterFirst
2425 enableServiceLinks: true
2426 restartPolicy: Always
2427 securityContext: {}
2428 terminationGracePeriodSeconds: 30
2429 status: {}
2430 type: MODIFIED
2431 ---
2432 object:
2433 apiVersion: v1
2434 kind: Pod
2435 metadata:
2436 creationTimestamp: null
2437 name: foo
2438 namespace: test
2439 resourceVersion: "12"
2440 spec:
2441 containers: null
2442 dnsPolicy: ClusterFirst
2443 enableServiceLinks: true
2444 restartPolicy: Always
2445 securityContext: {}
2446 terminationGracePeriodSeconds: 30
2447 status: {}
2448 type: DELETED
2449 `,
2450 },
2451 {
2452 format: `jsonpath={.type},{.object.metadata.name},{.object.metadata.resourceVersion}{"\n"}`,
2453 expected: `ADDED,bar,9
2454 ADDED,foo,10
2455 MODIFIED,foo,11
2456 DELETED,foo,12
2457 `,
2458 },
2459 {
2460 format: `go-template={{.type}},{{.object.metadata.name}},{{.object.metadata.resourceVersion}}{{"\n"}}`,
2461 expected: `ADDED,bar,9
2462 ADDED,foo,10
2463 MODIFIED,foo,11
2464 DELETED,foo,12
2465 `,
2466 },
2467 {
2468 format: `custom-columns=TYPE:.type,NAME:.object.metadata.name,RSRC:.object.metadata.resourceVersion`,
2469 expected: `TYPE NAME RSRC
2470 ADDED bar 9
2471 ADDED foo 10
2472 MODIFIED foo 11
2473 DELETED foo 12
2474 `,
2475 },
2476 {
2477 format: `name`,
2478 expected: `pod/bar
2479 pod/foo
2480 pod/foo
2481 pod/foo
2482 `,
2483 },
2484 }
2485
2486 for _, tc := range testcases {
2487 t.Run(fmt.Sprintf("%s, table=%v", tc.format, tc.table), func(t *testing.T) {
2488 pods, events := watchTestData()
2489
2490 tf := cmdtesting.NewTestFactory().WithNamespace("test")
2491 defer tf.Cleanup()
2492 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2493
2494 podList := &corev1.PodList{
2495 Items: pods,
2496 ListMeta: metav1.ListMeta{
2497 ResourceVersion: "10",
2498 },
2499 }
2500
2501 tf.UnstructuredClient = &fake.RESTClient{
2502 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
2503 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
2504 switch req.URL.Path {
2505 case "/pods":
2506 if req.URL.Query().Get("watch") == "true" {
2507 if tc.table {
2508 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableWatchBody(codec, events[2:])}, nil
2509 } else {
2510 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[2:])}, nil
2511 }
2512 }
2513
2514 if tc.table {
2515 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, podList.Items...)}, nil
2516 } else {
2517 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, podList)}, nil
2518 }
2519 default:
2520 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2521 return nil, nil
2522 }
2523 }),
2524 }
2525
2526 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
2527 cmd := NewCmdGet("kubectl", tf, streams)
2528 cmd.SetOut(buf)
2529 cmd.SetErr(buf)
2530
2531 cmd.Flags().Set("watch", "true")
2532 cmd.Flags().Set("all-namespaces", "true")
2533 cmd.Flags().Set("show-kind", "true")
2534 cmd.Flags().Set("output-watch-events", "true")
2535 if len(tc.format) > 0 {
2536 cmd.Flags().Set("output", tc.format)
2537 }
2538
2539 cmd.Run(cmd, []string{"pods"})
2540 if e, a := tc.expected, buf.String(); e != a {
2541 t.Errorf("expected\n%v\ngot\n%v", e, a)
2542 }
2543 })
2544 }
2545 }
2546
2547 func TestWatchResourceIdentifiedByFile(t *testing.T) {
2548 pods, events := watchTestData()
2549
2550 tf := cmdtesting.NewTestFactory().WithNamespace("test")
2551 defer tf.Cleanup()
2552 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2553
2554 tf.UnstructuredClient = &fake.RESTClient{
2555 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
2556 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
2557 switch req.URL.Path {
2558 case "/namespaces/test/replicationcontrollers/cassandra":
2559 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods[1])}, nil
2560 case "/namespaces/test/replicationcontrollers":
2561 if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=cassandra" {
2562 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[1:])}, nil
2563 }
2564 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2565 return nil, nil
2566 default:
2567 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2568 return nil, nil
2569 }
2570 }),
2571 }
2572
2573 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
2574 cmd := NewCmdGet("kubectl", tf, streams)
2575 cmd.SetOut(buf)
2576 cmd.SetErr(buf)
2577
2578 cmd.Flags().Set("watch", "true")
2579 cmd.Flags().Set("filename", "../../../testdata/controller.yaml")
2580 cmd.Run(cmd, []string{})
2581
2582 expected := `NAME AGE
2583 foo <unknown>
2584 foo <unknown>
2585 foo <unknown>
2586 `
2587 if e, a := expected, buf.String(); e != a {
2588 t.Errorf("expected\n%v\ngot\n%v", e, a)
2589 }
2590 }
2591
2592 func TestWatchOnlyResource(t *testing.T) {
2593 pods, events := watchTestData()
2594
2595 tf := cmdtesting.NewTestFactory().WithNamespace("test")
2596 defer tf.Cleanup()
2597 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2598
2599 tf.UnstructuredClient = &fake.RESTClient{
2600 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
2601 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
2602 switch req.URL.Path {
2603 case "/namespaces/test/pods/foo":
2604 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods[1])}, nil
2605 case "/namespaces/test/pods":
2606 if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" {
2607 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[1:])}, nil
2608 }
2609 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2610 return nil, nil
2611 default:
2612 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2613 return nil, nil
2614 }
2615 }),
2616 }
2617
2618 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
2619 cmd := NewCmdGet("kubectl", tf, streams)
2620 cmd.SetOut(buf)
2621 cmd.SetErr(buf)
2622
2623 cmd.Flags().Set("watch-only", "true")
2624 cmd.Run(cmd, []string{"pods", "foo"})
2625
2626 expected := `NAME AGE
2627 foo <unknown>
2628 foo <unknown>
2629 `
2630 if e, a := expected, buf.String(); e != a {
2631 t.Errorf("expected\n%v\ngot\n%v", e, a)
2632 }
2633 }
2634
2635 func TestWatchOnlyTableResource(t *testing.T) {
2636 pods, events := watchTestData()
2637
2638 tf := cmdtesting.NewTestFactory().WithNamespace("test")
2639 defer tf.Cleanup()
2640 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2641
2642 tf.UnstructuredClient = &fake.RESTClient{
2643 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
2644 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
2645 switch req.URL.Path {
2646 case "/namespaces/test/pods/foo":
2647 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, pods[1])}, nil
2648 case "/namespaces/test/pods":
2649 if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" {
2650 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableWatchBody(codec, events[1:])}, nil
2651 }
2652 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2653 return nil, nil
2654 default:
2655 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2656 return nil, nil
2657 }
2658 }),
2659 }
2660
2661 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
2662 cmd := NewCmdGet("kubectl", tf, streams)
2663 cmd.SetOut(buf)
2664 cmd.SetErr(buf)
2665
2666 cmd.Flags().Set("watch-only", "true")
2667 cmd.Run(cmd, []string{"pods", "foo"})
2668
2669 expected := `NAME READY STATUS RESTARTS AGE
2670 foo 0/0 0 <unknown>
2671 foo 0/0 0 <unknown>
2672 `
2673 if e, a := expected, buf.String(); e != a {
2674 t.Errorf("expected\n%v\ngot\n%v", e, a)
2675 }
2676 }
2677
2678 func TestWatchOnlyList(t *testing.T) {
2679 pods, events := watchTestData()
2680
2681 tf := cmdtesting.NewTestFactory().WithNamespace("test")
2682 defer tf.Cleanup()
2683 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2684
2685 podList := &corev1.PodList{
2686 Items: pods,
2687 ListMeta: metav1.ListMeta{
2688 ResourceVersion: "10",
2689 },
2690 }
2691 tf.UnstructuredClient = &fake.RESTClient{
2692 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
2693 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
2694 switch req.URL.Path {
2695 case "/namespaces/test/pods":
2696 if req.URL.Query().Get("watch") == "true" {
2697 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[2:])}, nil
2698 }
2699 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, podList)}, nil
2700 default:
2701 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2702 return nil, nil
2703 }
2704 }),
2705 }
2706
2707 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
2708 cmd := NewCmdGet("kubectl", tf, streams)
2709 cmd.SetOut(buf)
2710 cmd.SetErr(buf)
2711
2712 cmd.Flags().Set("watch-only", "true")
2713 cmd.Run(cmd, []string{"pods"})
2714
2715 expected := `NAME AGE
2716 foo <unknown>
2717 foo <unknown>
2718 `
2719 if e, a := expected, buf.String(); e != a {
2720 t.Errorf("expected\n%v\ngot\n%v", e, a)
2721 }
2722 }
2723
2724 func TestWatchOnlyTableList(t *testing.T) {
2725 pods, events := watchTestData()
2726
2727 tf := cmdtesting.NewTestFactory().WithNamespace("test")
2728 defer tf.Cleanup()
2729 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2730
2731 podList := &corev1.PodList{
2732 Items: pods,
2733 ListMeta: metav1.ListMeta{
2734 ResourceVersion: "10",
2735 },
2736 }
2737 tf.UnstructuredClient = &fake.RESTClient{
2738 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
2739 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
2740 switch req.URL.Path {
2741 case "/namespaces/test/pods":
2742 if req.URL.Query().Get("watch") == "true" {
2743 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableWatchBody(codec, events[2:])}, nil
2744 }
2745 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podTableObjBody(codec, podList.Items...)}, nil
2746 default:
2747 t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2748 return nil, nil
2749 }
2750 }),
2751 }
2752
2753 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
2754 cmd := NewCmdGet("kubectl", tf, streams)
2755 cmd.SetOut(buf)
2756 cmd.SetErr(buf)
2757
2758 cmd.Flags().Set("watch-only", "true")
2759 cmd.Run(cmd, []string{"pods"})
2760
2761 expected := `NAME READY STATUS RESTARTS AGE
2762 foo 0/0 0 <unknown>
2763 foo 0/0 0 <unknown>
2764 `
2765 if e, a := expected, buf.String(); e != a {
2766 t.Errorf("expected\n%v\ngot\n%v", e, a)
2767 }
2768 }
2769
2770 func watchBody(codec runtime.Codec, events []watch.Event) io.ReadCloser {
2771 buf := bytes.NewBuffer([]byte{})
2772 enc := restclientwatch.NewEncoder(streaming.NewEncoder(buf, codec), codec)
2773 for i := range events {
2774 if err := enc.Encode(&events[i]); err != nil {
2775 panic(err)
2776 }
2777 }
2778 return io.NopCloser(buf)
2779 }
2780
2781 var podColumns = []metav1.TableColumnDefinition{
2782 {Name: "Name", Type: "string", Format: "name"},
2783 {Name: "Ready", Type: "string", Format: ""},
2784 {Name: "Status", Type: "string", Format: ""},
2785 {Name: "Restarts", Type: "integer", Format: ""},
2786 {Name: "Age", Type: "string", Format: ""},
2787 {Name: "IP", Type: "string", Format: "", Priority: 1},
2788 {Name: "Node", Type: "string", Format: "", Priority: 1},
2789 {Name: "Nominated Node", Type: "string", Format: "", Priority: 1},
2790 {Name: "Readiness Gates", Type: "string", Format: "", Priority: 1},
2791 }
2792
2793
2794 func podTableObjBody(codec runtime.Codec, pods ...corev1.Pod) io.ReadCloser {
2795 table := &metav1beta1.Table{
2796 TypeMeta: metav1.TypeMeta{APIVersion: "meta.k8s.io/v1beta1", Kind: "Table"},
2797 ColumnDefinitions: podColumns,
2798 }
2799 for i := range pods {
2800 b := bytes.NewBuffer(nil)
2801 codec.Encode(&pods[i], b)
2802 table.Rows = append(table.Rows, metav1beta1.TableRow{
2803 Object: runtime.RawExtension{Raw: b.Bytes()},
2804 Cells: []interface{}{pods[i].Name, "0/0", "", int64(0), "<unknown>", "<none>", "<none>", "<none>", "<none>"},
2805 })
2806 }
2807 data, err := json.Marshal(table)
2808 if err != nil {
2809 panic(err)
2810 }
2811 if !strings.Contains(string(data), `"meta.k8s.io/v1beta1"`) {
2812 panic("expected v1beta1, got " + string(data))
2813 }
2814 return cmdtesting.BytesBody(data)
2815 }
2816
2817
2818 func podV1TableObjBody(codec runtime.Codec, pods ...corev1.Pod) io.ReadCloser {
2819 table := &metav1.Table{
2820 TypeMeta: metav1.TypeMeta{APIVersion: "meta.k8s.io/v1", Kind: "Table"},
2821 ColumnDefinitions: podColumns,
2822 }
2823 for i := range pods {
2824 b := bytes.NewBuffer(nil)
2825 codec.Encode(&pods[i], b)
2826 table.Rows = append(table.Rows, metav1.TableRow{
2827 Object: runtime.RawExtension{Raw: b.Bytes()},
2828 Cells: []interface{}{pods[i].Name, "0/0", "", int64(0), "<unknown>", "<none>", "<none>", "<none>", "<none>"},
2829 })
2830 }
2831 data, err := json.Marshal(table)
2832 if err != nil {
2833 panic(err)
2834 }
2835 if !strings.Contains(string(data), `"meta.k8s.io/v1"`) {
2836 panic("expected v1, got " + string(data))
2837 }
2838 return cmdtesting.BytesBody(data)
2839 }
2840
2841
2842 func podTableWatchBody(codec runtime.Codec, events []watch.Event) io.ReadCloser {
2843 tableEvents := []watch.Event{}
2844 for i, e := range events {
2845 b := bytes.NewBuffer(nil)
2846 codec.Encode(e.Object, b)
2847 var columns []metav1.TableColumnDefinition
2848 if i == 0 {
2849 columns = podColumns
2850 }
2851 tableEvents = append(tableEvents, watch.Event{
2852 Type: e.Type,
2853 Object: &metav1.Table{
2854 ColumnDefinitions: columns,
2855 Rows: []metav1.TableRow{{
2856 Object: runtime.RawExtension{Raw: b.Bytes()},
2857 Cells: []interface{}{e.Object.(*corev1.Pod).Name, "0/0", "", int64(0), "<unknown>", "<none>", "<none>", "<none>", "<none>"},
2858 }}},
2859 })
2860 }
2861 return watchBody(codec, tableEvents)
2862 }
2863
2864
2865 func serviceTableObjBody(codec runtime.Codec, services ...corev1.Service) io.ReadCloser {
2866 table := &metav1.Table{
2867 ColumnDefinitions: []metav1.TableColumnDefinition{
2868 {Name: "Name", Type: "string", Format: "name"},
2869 {Name: "Type", Type: "string", Format: ""},
2870 {Name: "Cluster-IP", Type: "string", Format: ""},
2871 {Name: "External-IP", Type: "string", Format: ""},
2872 {Name: "Port(s)", Type: "string", Format: ""},
2873 {Name: "Age", Type: "string", Format: ""},
2874 },
2875 }
2876 for i := range services {
2877 b := bytes.NewBuffer(nil)
2878 codec.Encode(&services[i], b)
2879 table.Rows = append(table.Rows, metav1.TableRow{
2880 Object: runtime.RawExtension{Raw: b.Bytes()},
2881 Cells: []interface{}{services[i].Name, "ClusterIP", "<none>", "<none>", "<none>", "<unknown>"},
2882 })
2883 }
2884 return cmdtesting.ObjBody(codec, table)
2885 }
2886
2887
2888 func nodeTableObjBody(codec runtime.Codec, nodes ...corev1.Node) io.ReadCloser {
2889 table := &metav1.Table{
2890 ColumnDefinitions: []metav1.TableColumnDefinition{
2891 {Name: "Name", Type: "string", Format: "name"},
2892 {Name: "Status", Type: "string", Format: ""},
2893 {Name: "Roles", Type: "string", Format: ""},
2894 {Name: "Age", Type: "string", Format: ""},
2895 {Name: "Version", Type: "string", Format: ""},
2896 },
2897 }
2898 for i := range nodes {
2899 b := bytes.NewBuffer(nil)
2900 codec.Encode(&nodes[i], b)
2901 table.Rows = append(table.Rows, metav1.TableRow{
2902 Object: runtime.RawExtension{Raw: b.Bytes()},
2903 Cells: []interface{}{nodes[i].Name, "Unknown", "<none>", "<unknown>", ""},
2904 })
2905 }
2906 return cmdtesting.ObjBody(codec, table)
2907 }
2908
2909
2910 func componentStatusTableObjBody(codec runtime.Codec, componentStatuses ...corev1.ComponentStatus) io.ReadCloser {
2911 table := &metav1.Table{
2912 ColumnDefinitions: []metav1.TableColumnDefinition{
2913 {Name: "Name", Type: "string", Format: "name"},
2914 {Name: "Status", Type: "string", Format: ""},
2915 {Name: "Message", Type: "string", Format: ""},
2916 {Name: "Error", Type: "string", Format: ""},
2917 },
2918 }
2919 for _, v := range componentStatuses {
2920 b := bytes.NewBuffer(nil)
2921 codec.Encode(&v, b)
2922 var status string
2923 if v.Conditions[0].Status == corev1.ConditionTrue {
2924 status = "Healthy"
2925 } else {
2926 status = "Unhealthy"
2927 }
2928 table.Rows = append(table.Rows, metav1.TableRow{
2929 Object: runtime.RawExtension{Raw: b.Bytes()},
2930 Cells: []interface{}{v.Name, status, v.Conditions[0].Message, v.Conditions[0].Error},
2931 })
2932 }
2933 return cmdtesting.ObjBody(codec, table)
2934 }
2935
2936
2937 func emptyTableObjBody(codec runtime.Codec) io.ReadCloser {
2938 table := &metav1.Table{
2939 ColumnDefinitions: podColumns,
2940 }
2941 return cmdtesting.ObjBody(codec, table)
2942 }
2943
2944 func replicationControllersScaleSubresourceTableObjBody(codec runtime.Codec, replicationControllers ...corev1.ReplicationController) io.ReadCloser {
2945 table := &metav1.Table{
2946 ColumnDefinitions: []metav1.TableColumnDefinition{
2947 {Name: "Name", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
2948 {Name: "Desired", Type: "integer", Description: autoscalingv1.ScaleSpec{}.SwaggerDoc()["replicas"]},
2949 {Name: "Available", Type: "integer", Description: autoscalingv1.ScaleStatus{}.SwaggerDoc()["replicas"]},
2950 },
2951 }
2952
2953 for i := range replicationControllers {
2954 b := bytes.NewBuffer(nil)
2955 codec.Encode(&replicationControllers[i], b)
2956 table.Rows = append(table.Rows, metav1.TableRow{
2957 Object: runtime.RawExtension{Raw: b.Bytes()},
2958 Cells: []interface{}{replicationControllers[i].Name, replicationControllers[i].Spec.Replicas, replicationControllers[i].Status.Replicas},
2959 })
2960 }
2961 return cmdtesting.ObjBody(codec, table)
2962 }
2963
View as plain text