...

Source file src/k8s.io/kubectl/pkg/cmd/get/get_test.go

Documentation: k8s.io/kubectl/pkg/cmd/get

     1  /*
     2  Copyright 2014 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package 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  // Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get.
    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  // Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get.
   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  	// The error out should be empty
   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  	// The error out should be empty
   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  		// The error out should be empty
   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  	// we're assuming that an empty file is being passed from stdin
   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  	// we're assuming that an empty file is being passed from stdin
   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  	// sorting with metadata.name
   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  	// t.Log(string(unstructuredBytes))
   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  	// sorting with metadata.name
   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  	// ensure that a runtime.Object without
  1265  	// an ObjectMeta field is handled properly
  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  		// current state events
  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  		// resource events
  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, // first event includes the 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  // build a meta table response from a pod list
  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  // build a meta table response from a pod list
  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  // build meta table watch events from pod watch events
  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  // build a meta table response from a service list
  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  // build a meta table response from a node list
  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  // build a meta table response from a componentStatus list
  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  // build an empty table response
  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