mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-30 21:30:16 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1654 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			1654 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
| Copyright 2014 The Kubernetes Authors.
 | |
| 
 | |
| Licensed under the Apache License, Version 2.0 (the "License");
 | |
| you may not use this file except in compliance with the License.
 | |
| You may obtain a copy of the License at
 | |
| 
 | |
|     http://www.apache.org/licenses/LICENSE-2.0
 | |
| 
 | |
| Unless required by applicable law or agreed to in writing, software
 | |
| distributed under the License is distributed on an "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| See the License for the specific language governing permissions and
 | |
| limitations under the License.
 | |
| */
 | |
| 
 | |
| package get
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	encjson "encoding/json"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"io/ioutil"
 | |
| 	"net/http"
 | |
| 	"path/filepath"
 | |
| 	"reflect"
 | |
| 	"strings"
 | |
| 	"testing"
 | |
| 
 | |
| 	appsv1 "k8s.io/api/apps/v1"
 | |
| 	autoscalingv1 "k8s.io/api/autoscaling/v1"
 | |
| 	batchv1 "k8s.io/api/batch/v1"
 | |
| 	batchv1beta1 "k8s.io/api/batch/v1beta1"
 | |
| 	corev1 "k8s.io/api/core/v1"
 | |
| 	extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
 | |
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | |
| 	metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
 | |
| 	"k8s.io/apimachinery/pkg/runtime"
 | |
| 	"k8s.io/apimachinery/pkg/runtime/schema"
 | |
| 	"k8s.io/apimachinery/pkg/runtime/serializer/json"
 | |
| 	"k8s.io/apimachinery/pkg/runtime/serializer/streaming"
 | |
| 	"k8s.io/apimachinery/pkg/util/diff"
 | |
| 	"k8s.io/apimachinery/pkg/watch"
 | |
| 	"k8s.io/cli-runtime/pkg/genericclioptions"
 | |
| 	"k8s.io/cli-runtime/pkg/resource"
 | |
| 	restclient "k8s.io/client-go/rest"
 | |
| 	"k8s.io/client-go/rest/fake"
 | |
| 	restclientwatch "k8s.io/client-go/rest/watch"
 | |
| 	"k8s.io/kube-openapi/pkg/util/proto"
 | |
| 	cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
 | |
| 	"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
 | |
| 	openapitesting "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing"
 | |
| 	"k8s.io/kubernetes/pkg/kubectl/scheme"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	openapiSchemaPath = filepath.Join("..", "..", "..", "..", "api", "openapi-spec", "swagger.json")
 | |
| 
 | |
| 	grace              = int64(30)
 | |
| 	enableServiceLinks = corev1.DefaultEnableServiceLinks
 | |
| )
 | |
| 
 | |
| func testComponentStatusData() *corev1.ComponentStatusList {
 | |
| 	good := corev1.ComponentStatus{
 | |
| 		Conditions: []corev1.ComponentCondition{
 | |
| 			{Type: corev1.ComponentHealthy, Status: corev1.ConditionTrue, Message: "ok"},
 | |
| 		},
 | |
| 		ObjectMeta: metav1.ObjectMeta{Name: "servergood"},
 | |
| 	}
 | |
| 
 | |
| 	bad := corev1.ComponentStatus{
 | |
| 		Conditions: []corev1.ComponentCondition{
 | |
| 			{Type: corev1.ComponentHealthy, Status: corev1.ConditionFalse, Message: "", Error: "bad status: 500"},
 | |
| 		},
 | |
| 		ObjectMeta: metav1.ObjectMeta{Name: "serverbad"},
 | |
| 	}
 | |
| 
 | |
| 	unknown := corev1.ComponentStatus{
 | |
| 		Conditions: []corev1.ComponentCondition{
 | |
| 			{Type: corev1.ComponentHealthy, Status: corev1.ConditionUnknown, Message: "", Error: "fizzbuzz error"},
 | |
| 		},
 | |
| 		ObjectMeta: metav1.ObjectMeta{Name: "serverunknown"},
 | |
| 	}
 | |
| 
 | |
| 	return &corev1.ComponentStatusList{
 | |
| 		Items: []corev1.ComponentStatus{good, bad, unknown},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get.
 | |
| func TestGetUnknownSchemaObject(t *testing.T) {
 | |
| 	t.Skip("This test is completely broken.  The first thing it does is add the object to the scheme!")
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	_, _, codec := cmdtesting.NewExternalScheme()
 | |
| 	tf.OpenAPISchemaFunc = openapitesting.CreateOpenAPISchemaFunc(openapiSchemaPath)
 | |
| 
 | |
| 	obj := &cmdtesting.ExternalType{
 | |
| 		Kind:       "Type",
 | |
| 		APIVersion: "apitest/unlikelyversion",
 | |
| 		Name:       "foo",
 | |
| 	}
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Resp: &http.Response{
 | |
| 			StatusCode: 200, Header: cmdtesting.DefaultHeader(),
 | |
| 			Body: cmdtesting.ObjBody(codec, obj),
 | |
| 		},
 | |
| 	}
 | |
| 	tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 	cmd.Run(cmd, []string{"type", "foo"})
 | |
| 
 | |
| 	expected := []runtime.Object{cmdtesting.NewInternalType("", "", "foo")}
 | |
| 	actual := []runtime.Object{}
 | |
| 	if len(actual) != len(expected) {
 | |
| 		t.Fatalf("expected: %#v, but actual: %#v", expected, actual)
 | |
| 	}
 | |
| 	t.Logf("actual: %#v", actual[0])
 | |
| 	for i, obj := range actual {
 | |
| 		expectedJSON := runtime.EncodeOrDie(codec, expected[i])
 | |
| 		expectedMap := map[string]interface{}{}
 | |
| 		if err := encjson.Unmarshal([]byte(expectedJSON), &expectedMap); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		actualJSON := runtime.EncodeOrDie(codec, obj)
 | |
| 		actualMap := map[string]interface{}{}
 | |
| 		if err := encjson.Unmarshal([]byte(actualJSON), &actualMap); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		if !reflect.DeepEqual(expectedMap, actualMap) {
 | |
| 			t.Errorf("expectedMap: %#v, but actualMap: %#v", expectedMap, actualMap)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get.
 | |
| func TestGetSchemaObject(t *testing.T) {
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(corev1.SchemeGroupVersion)
 | |
| 	t.Logf("%v", string(runtime.EncodeOrDie(codec, &corev1.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})))
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Resp:                 &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})},
 | |
| 	}
 | |
| 	tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.Run(cmd, []string{"replicationcontrollers", "foo"})
 | |
| 
 | |
| 	if !strings.Contains(buf.String(), "foo") {
 | |
| 		t.Errorf("unexpected output: %s", buf.String())
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetObjectsWithOpenAPIOutputFormatPresent(t *testing.T) {
 | |
| 	pods, _, _ := cmdtesting.TestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	// overide the openAPISchema function to return custom output
 | |
| 	// for Pod type.
 | |
| 	tf.OpenAPISchemaFunc = testOpenAPISchemaData
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Resp:                 &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 	cmd.Flags().Set(useOpenAPIPrintColumnFlagLabel, "true")
 | |
| 	cmd.Run(cmd, []string{"pods", "foo"})
 | |
| 
 | |
| 	expected := `NAME   RSRC
 | |
| foo    10
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type FakeResources struct {
 | |
| 	resources map[schema.GroupVersionKind]proto.Schema
 | |
| }
 | |
| 
 | |
| func (f FakeResources) LookupResource(s schema.GroupVersionKind) proto.Schema {
 | |
| 	return f.resources[s]
 | |
| }
 | |
| 
 | |
| var _ openapi.Resources = &FakeResources{}
 | |
| 
 | |
| func testOpenAPISchemaData() (openapi.Resources, error) {
 | |
| 	return &FakeResources{
 | |
| 		resources: map[schema.GroupVersionKind]proto.Schema{
 | |
| 			{
 | |
| 				Version: "v1",
 | |
| 				Kind:    "Pod",
 | |
| 			}: &proto.Primitive{
 | |
| 				BaseSchema: proto.BaseSchema{
 | |
| 					Extensions: map[string]interface{}{
 | |
| 						"x-kubernetes-print-columns": "custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion",
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| func TestGetObjects(t *testing.T) {
 | |
| 	pods, _, _ := cmdtesting.TestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Resp:                 &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 	cmd.Run(cmd, []string{"pods", "foo"})
 | |
| 
 | |
| 	expected := `NAME   READY   STATUS   RESTARTS   AGE
 | |
| foo    0/0              0          <unknown>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetObjectsShowKind(t *testing.T) {
 | |
| 	pods, _, _ := cmdtesting.TestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Resp:                 &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 	cmd.Flags().Set("show-kind", "true")
 | |
| 	cmd.Run(cmd, []string{"pods", "foo"})
 | |
| 
 | |
| 	expected := `NAME      READY   STATUS   RESTARTS   AGE
 | |
| pod/foo   0/0              0          <unknown>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetMultipleResourceTypesShowKinds(t *testing.T) {
 | |
| 	pods, svcs, _ := cmdtesting.TestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
 | |
| 			switch p, m := req.URL.Path, req.Method; {
 | |
| 			case p == "/namespaces/test/pods" && m == "GET":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
 | |
| 			case p == "/namespaces/test/replicationcontrollers" && m == "GET":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.ReplicationControllerList{})}, nil
 | |
| 			case p == "/namespaces/test/services" && m == "GET":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svcs)}, nil
 | |
| 			case p == "/namespaces/test/statefulsets" && m == "GET":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &appsv1.StatefulSetList{})}, nil
 | |
| 			case p == "/namespaces/test/horizontalpodautoscalers" && m == "GET":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &autoscalingv1.HorizontalPodAutoscalerList{})}, nil
 | |
| 			case p == "/namespaces/test/jobs" && m == "GET":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &batchv1.JobList{})}, nil
 | |
| 			case p == "/namespaces/test/cronjobs" && m == "GET":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &batchv1beta1.CronJobList{})}, nil
 | |
| 			case p == "/namespaces/test/daemonsets" && m == "GET":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &appsv1.DaemonSetList{})}, nil
 | |
| 			case p == "/namespaces/test/deployments" && m == "GET":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &extensionsv1beta1.DeploymentList{})}, nil
 | |
| 			case p == "/namespaces/test/replicasets" && m == "GET":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &extensionsv1beta1.ReplicaSetList{})}, nil
 | |
| 
 | |
| 			default:
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			}
 | |
| 		}),
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 	cmd.Run(cmd, []string{"all"})
 | |
| 
 | |
| 	expected := `NAME      READY   STATUS   RESTARTS   AGE
 | |
| pod/foo   0/0              0          <unknown>
 | |
| pod/bar   0/0              0          <unknown>
 | |
| NAME          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
 | |
| service/baz   ClusterIP   <none>       <none>        <none>    <unknown>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetObjectsShowLabels(t *testing.T) {
 | |
| 	pods, _, _ := cmdtesting.TestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Resp:                 &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 	cmd.Flags().Set("show-labels", "true")
 | |
| 	cmd.Run(cmd, []string{"pods", "foo"})
 | |
| 
 | |
| 	expected := `NAME   READY   STATUS   RESTARTS   AGE         LABELS
 | |
| foo    0/0              0          <unknown>   <none>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetEmptyTable(t *testing.T) {
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 
 | |
| 	emptyTable := ioutil.NopCloser(bytes.NewBufferString(`{
 | |
| "kind":"Table",
 | |
| "apiVersion":"meta.k8s.io/v1beta1",
 | |
| "metadata":{
 | |
| 	"selfLink":"/api/v1/namespaces/default/pods",
 | |
| 	"resourceVersion":"346"
 | |
| },
 | |
| "columnDefinitions":[
 | |
| 	{"name":"Name","type":"string","format":"name","description":"the name","priority":0}
 | |
| ],
 | |
| "rows":[]
 | |
| }`))
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Resp:                 &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: emptyTable},
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, errbuf := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 	cmd.Run(cmd, []string{"pods"})
 | |
| 
 | |
| 	expected := ``
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| 	expectedErr := `No resources found.
 | |
| `
 | |
| 	if e, a := expectedErr, errbuf.String(); e != a {
 | |
| 		t.Errorf("expectedErr\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetObjectIgnoreNotFound(t *testing.T) {
 | |
| 	cmdtesting.InitTestErrorHandler(t)
 | |
| 
 | |
| 	ns := &corev1.NamespaceList{
 | |
| 		ListMeta: metav1.ListMeta{
 | |
| 			ResourceVersion: "1",
 | |
| 		},
 | |
| 		Items: []corev1.Namespace{
 | |
| 			{
 | |
| 				ObjectMeta: metav1.ObjectMeta{Name: "testns", Namespace: "test", ResourceVersion: "11"},
 | |
| 				Spec:       corev1.NamespaceSpec{},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
 | |
| 			switch p, m := req.URL.Path, req.Method; {
 | |
| 			case p == "/namespaces/test/pods/nonexistentpod" && m == "GET":
 | |
| 				return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.StringBody("")}, nil
 | |
| 			case p == "/api/v1/namespaces/test" && m == "GET":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &ns.Items[0])}, nil
 | |
| 			default:
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			}
 | |
| 		}),
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 	cmd.Flags().Set("ignore-not-found", "true")
 | |
| 	cmd.Flags().Set("output", "yaml")
 | |
| 	cmd.Run(cmd, []string{"pods", "nonexistentpod"})
 | |
| 
 | |
| 	if buf.String() != "" {
 | |
| 		t.Errorf("unexpected output: %s", buf.String())
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetSortedObjects(t *testing.T) {
 | |
| 	pods := &corev1.PodList{
 | |
| 		ListMeta: metav1.ListMeta{
 | |
| 			ResourceVersion: "15",
 | |
| 		},
 | |
| 		Items: []corev1.Pod{
 | |
| 			{
 | |
| 				ObjectMeta: metav1.ObjectMeta{Name: "c", Namespace: "test", ResourceVersion: "10"},
 | |
| 				Spec: corev1.PodSpec{
 | |
| 					RestartPolicy:                 corev1.RestartPolicyAlways,
 | |
| 					DNSPolicy:                     corev1.DNSClusterFirst,
 | |
| 					TerminationGracePeriodSeconds: &grace,
 | |
| 					SecurityContext:               &corev1.PodSecurityContext{},
 | |
| 					EnableServiceLinks:            &enableServiceLinks,
 | |
| 				},
 | |
| 			},
 | |
| 			{
 | |
| 				ObjectMeta: metav1.ObjectMeta{Name: "b", Namespace: "test", ResourceVersion: "11"},
 | |
| 				Spec: corev1.PodSpec{
 | |
| 					RestartPolicy:                 corev1.RestartPolicyAlways,
 | |
| 					DNSPolicy:                     corev1.DNSClusterFirst,
 | |
| 					TerminationGracePeriodSeconds: &grace,
 | |
| 					SecurityContext:               &corev1.PodSecurityContext{},
 | |
| 					EnableServiceLinks:            &enableServiceLinks,
 | |
| 				},
 | |
| 			},
 | |
| 			{
 | |
| 				ObjectMeta: metav1.ObjectMeta{Name: "a", Namespace: "test", ResourceVersion: "9"},
 | |
| 				Spec: corev1.PodSpec{
 | |
| 					RestartPolicy:                 corev1.RestartPolicyAlways,
 | |
| 					DNSPolicy:                     corev1.DNSClusterFirst,
 | |
| 					TerminationGracePeriodSeconds: &grace,
 | |
| 					SecurityContext:               &corev1.PodSecurityContext{},
 | |
| 					EnableServiceLinks:            &enableServiceLinks,
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Resp:                 &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)},
 | |
| 	}
 | |
| 	tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &corev1.SchemeGroupVersion}}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 
 | |
| 	// sorting with metedata.name
 | |
| 	cmd.Flags().Set("sort-by", ".metadata.name")
 | |
| 	cmd.Run(cmd, []string{"pods"})
 | |
| 
 | |
| 	expected := `NAME   READY   STATUS   RESTARTS   AGE
 | |
| a      0/0              0          <unknown>
 | |
| b      0/0              0          <unknown>
 | |
| c      0/0              0          <unknown>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetSortedObjectsUnstructuredTable(t *testing.T) {
 | |
| 	unstructuredMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(sortTestTableData()[0])
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	unstructuredBytes, err := encjson.MarshalIndent(unstructuredMap, "", "  ")
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	// t.Log(string(unstructuredBytes))
 | |
| 	body := ioutil.NopCloser(bytes.NewReader(unstructuredBytes))
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Resp:                 &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: body},
 | |
| 	}
 | |
| 	tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &corev1.SchemeGroupVersion}}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 
 | |
| 	// sorting with metedata.name
 | |
| 	cmd.Flags().Set("sort-by", ".metadata.name")
 | |
| 	cmd.Run(cmd, []string{"pods"})
 | |
| 
 | |
| 	expected := `NAME   CUSTOM
 | |
| a      custom-a
 | |
| b      custom-b
 | |
| c      custom-c
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func sortTestData() []runtime.Object {
 | |
| 	return []runtime.Object{
 | |
| 		&corev1.Pod{
 | |
| 			TypeMeta:   metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
 | |
| 			ObjectMeta: metav1.ObjectMeta{Name: "c", Namespace: "test", ResourceVersion: "10"},
 | |
| 			Spec: corev1.PodSpec{
 | |
| 				RestartPolicy:                 corev1.RestartPolicyAlways,
 | |
| 				DNSPolicy:                     corev1.DNSClusterFirst,
 | |
| 				TerminationGracePeriodSeconds: &grace,
 | |
| 				SecurityContext:               &corev1.PodSecurityContext{},
 | |
| 				EnableServiceLinks:            &enableServiceLinks,
 | |
| 			},
 | |
| 		},
 | |
| 		&corev1.Pod{
 | |
| 			TypeMeta:   metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
 | |
| 			ObjectMeta: metav1.ObjectMeta{Name: "b", Namespace: "test", ResourceVersion: "11"},
 | |
| 			Spec: corev1.PodSpec{
 | |
| 				RestartPolicy:                 corev1.RestartPolicyAlways,
 | |
| 				DNSPolicy:                     corev1.DNSClusterFirst,
 | |
| 				TerminationGracePeriodSeconds: &grace,
 | |
| 				SecurityContext:               &corev1.PodSecurityContext{},
 | |
| 				EnableServiceLinks:            &enableServiceLinks,
 | |
| 			},
 | |
| 		},
 | |
| 		&corev1.Pod{
 | |
| 			TypeMeta:   metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
 | |
| 			ObjectMeta: metav1.ObjectMeta{Name: "a", Namespace: "test", ResourceVersion: "9"},
 | |
| 			Spec: corev1.PodSpec{
 | |
| 				RestartPolicy:                 corev1.RestartPolicyAlways,
 | |
| 				DNSPolicy:                     corev1.DNSClusterFirst,
 | |
| 				TerminationGracePeriodSeconds: &grace,
 | |
| 				SecurityContext:               &corev1.PodSecurityContext{},
 | |
| 				EnableServiceLinks:            &enableServiceLinks,
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func sortTestTableData() []runtime.Object {
 | |
| 	return []runtime.Object{
 | |
| 		&metav1beta1.Table{
 | |
| 			TypeMeta: metav1.TypeMeta{APIVersion: "meta.k8s.io/v1beta1", Kind: "Table"},
 | |
| 			ColumnDefinitions: []metav1beta1.TableColumnDefinition{
 | |
| 				{Name: "NAME", Type: "string", Format: "name"},
 | |
| 				{Name: "CUSTOM", Type: "string", Format: ""},
 | |
| 			},
 | |
| 			Rows: []metav1beta1.TableRow{
 | |
| 				{
 | |
| 					Cells: []interface{}{"c", "custom-c"},
 | |
| 					Object: runtime.RawExtension{
 | |
| 						Object: &corev1.Pod{
 | |
| 							TypeMeta:   metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
 | |
| 							ObjectMeta: metav1.ObjectMeta{Name: "c", Namespace: "test", ResourceVersion: "10"},
 | |
| 							Spec: corev1.PodSpec{
 | |
| 								RestartPolicy:                 corev1.RestartPolicyAlways,
 | |
| 								DNSPolicy:                     corev1.DNSClusterFirst,
 | |
| 								TerminationGracePeriodSeconds: &grace,
 | |
| 								SecurityContext:               &corev1.PodSecurityContext{},
 | |
| 								EnableServiceLinks:            &enableServiceLinks,
 | |
| 							},
 | |
| 						},
 | |
| 					},
 | |
| 				},
 | |
| 				{
 | |
| 					Cells: []interface{}{"b", "custom-b"},
 | |
| 					Object: runtime.RawExtension{
 | |
| 						Object: &corev1.Pod{
 | |
| 							TypeMeta:   metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
 | |
| 							ObjectMeta: metav1.ObjectMeta{Name: "b", Namespace: "test", ResourceVersion: "11"},
 | |
| 							Spec: corev1.PodSpec{
 | |
| 								RestartPolicy:                 corev1.RestartPolicyAlways,
 | |
| 								DNSPolicy:                     corev1.DNSClusterFirst,
 | |
| 								TerminationGracePeriodSeconds: &grace,
 | |
| 								SecurityContext:               &corev1.PodSecurityContext{},
 | |
| 								EnableServiceLinks:            &enableServiceLinks,
 | |
| 							},
 | |
| 						},
 | |
| 					},
 | |
| 				},
 | |
| 				{
 | |
| 					Cells: []interface{}{"a", "custom-a"},
 | |
| 					Object: runtime.RawExtension{
 | |
| 						Object: &corev1.Pod{
 | |
| 							TypeMeta:   metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
 | |
| 							ObjectMeta: metav1.ObjectMeta{Name: "a", Namespace: "test", ResourceVersion: "9"},
 | |
| 							Spec: corev1.PodSpec{
 | |
| 								RestartPolicy:                 corev1.RestartPolicyAlways,
 | |
| 								DNSPolicy:                     corev1.DNSClusterFirst,
 | |
| 								TerminationGracePeriodSeconds: &grace,
 | |
| 								SecurityContext:               &corev1.PodSecurityContext{},
 | |
| 								EnableServiceLinks:            &enableServiceLinks,
 | |
| 							},
 | |
| 						},
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestRuntimeSorter(t *testing.T) {
 | |
| 	tests := []struct {
 | |
| 		name        string
 | |
| 		field       string
 | |
| 		objs        []runtime.Object
 | |
| 		op          func(sorter *RuntimeSorter, objs []runtime.Object, out io.Writer) error
 | |
| 		expect      string
 | |
| 		expectError string
 | |
| 	}{
 | |
| 		{
 | |
| 			name:  "ensure sorter works with an empty object list",
 | |
| 			field: "metadata.name",
 | |
| 			objs:  []runtime.Object{},
 | |
| 			op: func(sorter *RuntimeSorter, objs []runtime.Object, out io.Writer) error {
 | |
| 				return nil
 | |
| 			},
 | |
| 			expect: "",
 | |
| 		},
 | |
| 		{
 | |
| 			name:  "ensure sorter returns original position",
 | |
| 			field: "metadata.name",
 | |
| 			objs:  sortTestData(),
 | |
| 			op: func(sorter *RuntimeSorter, objs []runtime.Object, out io.Writer) error {
 | |
| 				for idx := range objs {
 | |
| 					p := sorter.OriginalPosition(idx)
 | |
| 					fmt.Fprintf(out, "%v,", p)
 | |
| 				}
 | |
| 				return nil
 | |
| 			},
 | |
| 			expect: "2,1,0,",
 | |
| 		},
 | |
| 		{
 | |
| 			name:  "ensure sorter handles table object position",
 | |
| 			field: "metadata.name",
 | |
| 			objs:  sortTestTableData(),
 | |
| 			op: func(sorter *RuntimeSorter, objs []runtime.Object, out io.Writer) error {
 | |
| 				for idx := range objs {
 | |
| 					p := sorter.OriginalPosition(idx)
 | |
| 					fmt.Fprintf(out, "%v,", p)
 | |
| 				}
 | |
| 				return nil
 | |
| 			},
 | |
| 			expect: "0,",
 | |
| 		},
 | |
| 		{
 | |
| 			name:  "ensure sorter sorts table objects",
 | |
| 			field: "metadata.name",
 | |
| 			objs:  sortTestData(),
 | |
| 			op: func(sorter *RuntimeSorter, objs []runtime.Object, out io.Writer) error {
 | |
| 				for _, o := range objs {
 | |
| 					fmt.Fprintf(out, "%s,", o.(*corev1.Pod).Name)
 | |
| 				}
 | |
| 				return nil
 | |
| 			},
 | |
| 			expect: "a,b,c,",
 | |
| 		},
 | |
| 		{
 | |
| 			name:        "ensure sorter rejects mixed Table + non-Table object lists",
 | |
| 			field:       "metadata.name",
 | |
| 			objs:        append(sortTestData(), sortTestTableData()...),
 | |
| 			op:          func(sorter *RuntimeSorter, objs []runtime.Object, out io.Writer) error { return nil },
 | |
| 			expectError: "sorting is not supported on mixed Table",
 | |
| 		},
 | |
| 		{
 | |
| 			name:        "ensure sorter errors out on invalid jsonpath",
 | |
| 			field:       "metadata.unknown",
 | |
| 			objs:        sortTestData(),
 | |
| 			op:          func(sorter *RuntimeSorter, objs []runtime.Object, out io.Writer) error { return nil },
 | |
| 			expectError: "couldn't find any field with path",
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, tc := range tests {
 | |
| 		t.Run(tc.name, func(t *testing.T) {
 | |
| 			sorter := NewRuntimeSorter(tc.objs, tc.field)
 | |
| 			if err := sorter.Sort(); err != nil {
 | |
| 				if len(tc.expectError) > 0 && strings.Contains(err.Error(), tc.expectError) {
 | |
| 					return
 | |
| 				}
 | |
| 
 | |
| 				if len(tc.expectError) > 0 {
 | |
| 					t.Fatalf("unexpected error: expecting %s, but got %s", tc.expectError, err)
 | |
| 				}
 | |
| 
 | |
| 				t.Fatalf("unexpected error: %v", err)
 | |
| 			}
 | |
| 
 | |
| 			out := bytes.NewBuffer([]byte{})
 | |
| 			err := tc.op(sorter, tc.objs, out)
 | |
| 			if err != nil {
 | |
| 				t.Fatalf("unexpected error: %v", err)
 | |
| 			}
 | |
| 
 | |
| 			if tc.expect != out.String() {
 | |
| 				t.Fatalf("unexpected output: expecting %s, but got %s", tc.expect, out.String())
 | |
| 			}
 | |
| 
 | |
| 		})
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 | |
| func TestGetObjectsIdentifiedByFile(t *testing.T) {
 | |
| 	pods, _, _ := cmdtesting.TestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Resp:                 &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 	cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml")
 | |
| 	cmd.Run(cmd, []string{})
 | |
| 
 | |
| 	expected := `NAME   READY   STATUS   RESTARTS   AGE
 | |
| foo    0/0              0          <unknown>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetListObjects(t *testing.T) {
 | |
| 	pods, _, _ := cmdtesting.TestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Resp:                 &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)},
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 	cmd.Run(cmd, []string{"pods"})
 | |
| 
 | |
| 	expected := `NAME   READY   STATUS   RESTARTS   AGE
 | |
| foo    0/0              0          <unknown>
 | |
| bar    0/0              0          <unknown>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetListComponentStatus(t *testing.T) {
 | |
| 	statuses := testComponentStatusData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Resp:                 &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, statuses)},
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 	cmd.Run(cmd, []string{"componentstatuses"})
 | |
| 
 | |
| 	expected := `NAME            STATUS      MESSAGE   ERROR
 | |
| servergood      Healthy     ok        
 | |
| serverbad       Unhealthy             bad status: 500
 | |
| serverunknown   Unhealthy             fizzbuzz error
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetMixedGenericObjects(t *testing.T) {
 | |
| 	cmdtesting.InitTestErrorHandler(t)
 | |
| 
 | |
| 	// ensure that a runtime.Object without
 | |
| 	// an ObjectMeta field is handled properly
 | |
| 	structuredObj := &metav1.Status{
 | |
| 		TypeMeta: metav1.TypeMeta{
 | |
| 			Kind:       "Status",
 | |
| 			APIVersion: "v1",
 | |
| 		},
 | |
| 		Status:  "Success",
 | |
| 		Message: "",
 | |
| 		Reason:  "",
 | |
| 		Code:    0,
 | |
| 	}
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
 | |
| 			switch req.URL.Path {
 | |
| 			case "/namespaces/test/pods":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, structuredObj)}, nil
 | |
| 			default:
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			}
 | |
| 		}),
 | |
| 	}
 | |
| 	tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 	cmd.Flags().Set("output", "json")
 | |
| 	cmd.Run(cmd, []string{"pods"})
 | |
| 
 | |
| 	expected := `{
 | |
|     "apiVersion": "v1",
 | |
|     "items": [
 | |
|         {
 | |
|             "apiVersion": "v1",
 | |
|             "kind": "Status",
 | |
|             "metadata": {},
 | |
|             "status": "Success"
 | |
|         }
 | |
|     ],
 | |
|     "kind": "List",
 | |
|     "metadata": {
 | |
|         "resourceVersion": "",
 | |
|         "selfLink": ""
 | |
|     }
 | |
| }
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetMultipleTypeObjects(t *testing.T) {
 | |
| 	pods, svc, _ := cmdtesting.TestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
 | |
| 			switch req.URL.Path {
 | |
| 			case "/namespaces/test/pods":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
 | |
| 			case "/namespaces/test/services":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
 | |
| 			default:
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			}
 | |
| 		}),
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 	cmd.Run(cmd, []string{"pods,services"})
 | |
| 
 | |
| 	expected := `NAME      READY   STATUS   RESTARTS   AGE
 | |
| pod/foo   0/0              0          <unknown>
 | |
| pod/bar   0/0              0          <unknown>
 | |
| NAME          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
 | |
| service/baz   ClusterIP   <none>       <none>        <none>    <unknown>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetMultipleTypeObjectsAsList(t *testing.T) {
 | |
| 	pods, svc, _ := cmdtesting.TestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
 | |
| 			switch req.URL.Path {
 | |
| 			case "/namespaces/test/pods":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
 | |
| 			case "/namespaces/test/services":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
 | |
| 			default:
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			}
 | |
| 		}),
 | |
| 	}
 | |
| 	tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 
 | |
| 	cmd.Flags().Set("output", "json")
 | |
| 	cmd.Run(cmd, []string{"pods,services"})
 | |
| 
 | |
| 	expected := `{
 | |
|     "apiVersion": "v1",
 | |
|     "items": [
 | |
|         {
 | |
|             "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": {}
 | |
|         },
 | |
|         {
 | |
|             "apiVersion": "v1",
 | |
|             "kind": "Pod",
 | |
|             "metadata": {
 | |
|                 "creationTimestamp": null,
 | |
|                 "name": "bar",
 | |
|                 "namespace": "test",
 | |
|                 "resourceVersion": "11"
 | |
|             },
 | |
|             "spec": {
 | |
|                 "containers": null,
 | |
|                 "dnsPolicy": "ClusterFirst",
 | |
|                 "enableServiceLinks": true,
 | |
|                 "restartPolicy": "Always",
 | |
|                 "securityContext": {},
 | |
|                 "terminationGracePeriodSeconds": 30
 | |
|             },
 | |
|             "status": {}
 | |
|         },
 | |
|         {
 | |
|             "apiVersion": "v1",
 | |
|             "kind": "Service",
 | |
|             "metadata": {
 | |
|                 "creationTimestamp": null,
 | |
|                 "name": "baz",
 | |
|                 "namespace": "test",
 | |
|                 "resourceVersion": "12"
 | |
|             },
 | |
|             "spec": {
 | |
|                 "sessionAffinity": "None",
 | |
|                 "type": "ClusterIP"
 | |
|             },
 | |
|             "status": {
 | |
|                 "loadBalancer": {}
 | |
|             }
 | |
|         }
 | |
|     ],
 | |
|     "kind": "List",
 | |
|     "metadata": {
 | |
|         "resourceVersion": "",
 | |
|         "selfLink": ""
 | |
|     }
 | |
| }
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("did not match: %v", diff.StringDiff(e, a))
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetMultipleTypeObjectsWithLabelSelector(t *testing.T) {
 | |
| 	pods, svc, _ := cmdtesting.TestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
 | |
| 			if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" {
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 			}
 | |
| 			switch req.URL.Path {
 | |
| 			case "/namespaces/test/pods":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
 | |
| 			case "/namespaces/test/services":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
 | |
| 			default:
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			}
 | |
| 		}),
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 
 | |
| 	cmd.Flags().Set("selector", "a=b")
 | |
| 	cmd.Run(cmd, []string{"pods,services"})
 | |
| 
 | |
| 	expected := `NAME      READY   STATUS   RESTARTS   AGE
 | |
| pod/foo   0/0              0          <unknown>
 | |
| pod/bar   0/0              0          <unknown>
 | |
| NAME          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
 | |
| service/baz   ClusterIP   <none>       <none>        <none>    <unknown>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetMultipleTypeObjectsWithFieldSelector(t *testing.T) {
 | |
| 	pods, svc, _ := cmdtesting.TestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
 | |
| 			if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" {
 | |
| 				t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
 | |
| 			}
 | |
| 			switch req.URL.Path {
 | |
| 			case "/namespaces/test/pods":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
 | |
| 			case "/namespaces/test/services":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
 | |
| 			default:
 | |
| 				t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			}
 | |
| 		}),
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 
 | |
| 	cmd.Flags().Set("field-selector", "a=b")
 | |
| 	cmd.Run(cmd, []string{"pods,services"})
 | |
| 
 | |
| 	expected := `NAME      READY   STATUS   RESTARTS   AGE
 | |
| pod/foo   0/0              0          <unknown>
 | |
| pod/bar   0/0              0          <unknown>
 | |
| NAME          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
 | |
| service/baz   ClusterIP   <none>       <none>        <none>    <unknown>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) {
 | |
| 	_, svc, _ := cmdtesting.TestData()
 | |
| 	node := &corev1.Node{
 | |
| 		ObjectMeta: metav1.ObjectMeta{
 | |
| 			Name: "foo",
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
 | |
| 			switch req.URL.Path {
 | |
| 			case "/nodes/foo":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, node)}, nil
 | |
| 			case "/namespaces/test/services/bar":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
 | |
| 			default:
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			}
 | |
| 		}),
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 
 | |
| 	cmd.Run(cmd, []string{"services/bar", "node/foo"})
 | |
| 
 | |
| 	expected := `NAME          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
 | |
| service/baz   ClusterIP   <none>       <none>        <none>    <unknown>
 | |
| NAME       STATUS    ROLES    AGE         VERSION
 | |
| node/foo   Unknown   <none>   <unknown>   
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func watchTestData() ([]corev1.Pod, []watch.Event) {
 | |
| 	pods := []corev1.Pod{
 | |
| 		{
 | |
| 			ObjectMeta: metav1.ObjectMeta{
 | |
| 				Name:            "bar",
 | |
| 				Namespace:       "test",
 | |
| 				ResourceVersion: "9",
 | |
| 			},
 | |
| 			Spec: corev1.PodSpec{
 | |
| 				RestartPolicy:                 corev1.RestartPolicyAlways,
 | |
| 				DNSPolicy:                     corev1.DNSClusterFirst,
 | |
| 				TerminationGracePeriodSeconds: &grace,
 | |
| 				SecurityContext:               &corev1.PodSecurityContext{},
 | |
| 				EnableServiceLinks:            &enableServiceLinks,
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			ObjectMeta: metav1.ObjectMeta{
 | |
| 				Name:            "foo",
 | |
| 				Namespace:       "test",
 | |
| 				ResourceVersion: "10",
 | |
| 			},
 | |
| 			Spec: corev1.PodSpec{
 | |
| 				RestartPolicy:                 corev1.RestartPolicyAlways,
 | |
| 				DNSPolicy:                     corev1.DNSClusterFirst,
 | |
| 				TerminationGracePeriodSeconds: &grace,
 | |
| 				SecurityContext:               &corev1.PodSecurityContext{},
 | |
| 				EnableServiceLinks:            &enableServiceLinks,
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 	events := []watch.Event{
 | |
| 		// current state events
 | |
| 		{
 | |
| 			Type: watch.Added,
 | |
| 			Object: &corev1.Pod{
 | |
| 				ObjectMeta: metav1.ObjectMeta{
 | |
| 					Name:            "bar",
 | |
| 					Namespace:       "test",
 | |
| 					ResourceVersion: "9",
 | |
| 				},
 | |
| 				Spec: corev1.PodSpec{
 | |
| 					RestartPolicy:                 corev1.RestartPolicyAlways,
 | |
| 					DNSPolicy:                     corev1.DNSClusterFirst,
 | |
| 					TerminationGracePeriodSeconds: &grace,
 | |
| 					SecurityContext:               &corev1.PodSecurityContext{},
 | |
| 					EnableServiceLinks:            &enableServiceLinks,
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			Type: watch.Added,
 | |
| 			Object: &corev1.Pod{
 | |
| 				ObjectMeta: metav1.ObjectMeta{
 | |
| 					Name:            "foo",
 | |
| 					Namespace:       "test",
 | |
| 					ResourceVersion: "10",
 | |
| 				},
 | |
| 				Spec: corev1.PodSpec{
 | |
| 					RestartPolicy:                 corev1.RestartPolicyAlways,
 | |
| 					DNSPolicy:                     corev1.DNSClusterFirst,
 | |
| 					TerminationGracePeriodSeconds: &grace,
 | |
| 					SecurityContext:               &corev1.PodSecurityContext{},
 | |
| 					EnableServiceLinks:            &enableServiceLinks,
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		// resource events
 | |
| 		{
 | |
| 			Type: watch.Modified,
 | |
| 			Object: &corev1.Pod{
 | |
| 				ObjectMeta: metav1.ObjectMeta{
 | |
| 					Name:            "foo",
 | |
| 					Namespace:       "test",
 | |
| 					ResourceVersion: "11",
 | |
| 				},
 | |
| 				Spec: corev1.PodSpec{
 | |
| 					RestartPolicy:                 corev1.RestartPolicyAlways,
 | |
| 					DNSPolicy:                     corev1.DNSClusterFirst,
 | |
| 					TerminationGracePeriodSeconds: &grace,
 | |
| 					SecurityContext:               &corev1.PodSecurityContext{},
 | |
| 					EnableServiceLinks:            &enableServiceLinks,
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			Type: watch.Deleted,
 | |
| 			Object: &corev1.Pod{
 | |
| 				ObjectMeta: metav1.ObjectMeta{
 | |
| 					Name:            "foo",
 | |
| 					Namespace:       "test",
 | |
| 					ResourceVersion: "12",
 | |
| 				},
 | |
| 				Spec: corev1.PodSpec{
 | |
| 					RestartPolicy:                 corev1.RestartPolicyAlways,
 | |
| 					DNSPolicy:                     corev1.DNSClusterFirst,
 | |
| 					TerminationGracePeriodSeconds: &grace,
 | |
| 					SecurityContext:               &corev1.PodSecurityContext{},
 | |
| 					EnableServiceLinks:            &enableServiceLinks,
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 	return pods, events
 | |
| }
 | |
| 
 | |
| func TestWatchLabelSelector(t *testing.T) {
 | |
| 	pods, events := watchTestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	podList := &corev1.PodList{
 | |
| 		Items: pods,
 | |
| 		ListMeta: metav1.ListMeta{
 | |
| 			ResourceVersion: "10",
 | |
| 		},
 | |
| 	}
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
 | |
| 			if req.URL.Query().Get(metav1.LabelSelectorQueryParam("v1")) != "a=b" {
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 			}
 | |
| 			switch req.URL.Path {
 | |
| 			case "/namespaces/test/pods":
 | |
| 				if req.URL.Query().Get("watch") == "true" {
 | |
| 					return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[2:])}, nil
 | |
| 				}
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, podList)}, nil
 | |
| 			default:
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			}
 | |
| 		}),
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 
 | |
| 	cmd.Flags().Set("watch", "true")
 | |
| 	cmd.Flags().Set("selector", "a=b")
 | |
| 	cmd.Run(cmd, []string{"pods"})
 | |
| 
 | |
| 	expected := `NAME   READY   STATUS   RESTARTS   AGE
 | |
| bar    0/0              0          <unknown>
 | |
| foo    0/0              0          <unknown>
 | |
| foo    0/0              0          <unknown>
 | |
| foo    0/0              0          <unknown>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestWatchFieldSelector(t *testing.T) {
 | |
| 	pods, events := watchTestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	podList := &corev1.PodList{
 | |
| 		Items: pods,
 | |
| 		ListMeta: metav1.ListMeta{
 | |
| 			ResourceVersion: "10",
 | |
| 		},
 | |
| 	}
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
 | |
| 			if req.URL.Query().Get(metav1.FieldSelectorQueryParam("v1")) != "a=b" {
 | |
| 				t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
 | |
| 			}
 | |
| 			switch req.URL.Path {
 | |
| 			case "/namespaces/test/pods":
 | |
| 				if req.URL.Query().Get("watch") == "true" {
 | |
| 					return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[2:])}, nil
 | |
| 				}
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, podList)}, nil
 | |
| 			default:
 | |
| 				t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			}
 | |
| 		}),
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 
 | |
| 	cmd.Flags().Set("watch", "true")
 | |
| 	cmd.Flags().Set("field-selector", "a=b")
 | |
| 	cmd.Run(cmd, []string{"pods"})
 | |
| 
 | |
| 	expected := `NAME   READY   STATUS   RESTARTS   AGE
 | |
| bar    0/0              0          <unknown>
 | |
| foo    0/0              0          <unknown>
 | |
| foo    0/0              0          <unknown>
 | |
| foo    0/0              0          <unknown>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestWatchResource(t *testing.T) {
 | |
| 	pods, events := watchTestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
 | |
| 			switch req.URL.Path {
 | |
| 			case "/namespaces/test/pods/foo":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods[1])}, nil
 | |
| 			case "/namespaces/test/pods":
 | |
| 				if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" {
 | |
| 					return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[1:])}, nil
 | |
| 				}
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			default:
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			}
 | |
| 		}),
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 
 | |
| 	cmd.Flags().Set("watch", "true")
 | |
| 	cmd.Run(cmd, []string{"pods", "foo"})
 | |
| 
 | |
| 	expected := `NAME   READY   STATUS   RESTARTS   AGE
 | |
| foo    0/0              0          <unknown>
 | |
| foo    0/0              0          <unknown>
 | |
| foo    0/0              0          <unknown>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestWatchResourceTable(t *testing.T) {
 | |
| 	columns := []metav1beta1.TableColumnDefinition{
 | |
| 		{Name: "Name", Type: "string", Format: "name", Description: "the name", Priority: 0},
 | |
| 		{Name: "Active", Type: "boolean", Description: "active", Priority: 0},
 | |
| 	}
 | |
| 
 | |
| 	listTable := &metav1beta1.Table{
 | |
| 		TypeMeta:          metav1.TypeMeta{APIVersion: "meta.k8s.io/v1beta1", Kind: "Table"},
 | |
| 		ColumnDefinitions: columns,
 | |
| 		Rows: []metav1beta1.TableRow{
 | |
| 			{
 | |
| 				Cells: []interface{}{"a", true},
 | |
| 				Object: runtime.RawExtension{
 | |
| 					Object: &corev1.Pod{
 | |
| 						TypeMeta:   metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
 | |
| 						ObjectMeta: metav1.ObjectMeta{Name: "a", Namespace: "test", ResourceVersion: "10"},
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 			{
 | |
| 				Cells: []interface{}{"b", true},
 | |
| 				Object: runtime.RawExtension{
 | |
| 					Object: &corev1.Pod{
 | |
| 						TypeMeta:   metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
 | |
| 						ObjectMeta: metav1.ObjectMeta{Name: "b", Namespace: "test", ResourceVersion: "20"},
 | |
| 					},
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	events := []watch.Event{
 | |
| 		{
 | |
| 			Type: watch.Added,
 | |
| 			Object: &metav1beta1.Table{
 | |
| 				TypeMeta:          metav1.TypeMeta{APIVersion: "meta.k8s.io/v1beta1", Kind: "Table"},
 | |
| 				ColumnDefinitions: columns, // first event includes the columns
 | |
| 				Rows: []metav1beta1.TableRow{{
 | |
| 					Cells: []interface{}{"a", false},
 | |
| 					Object: runtime.RawExtension{
 | |
| 						Object: &corev1.Pod{
 | |
| 							TypeMeta:   metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
 | |
| 							ObjectMeta: metav1.ObjectMeta{Name: "a", Namespace: "test", ResourceVersion: "30"},
 | |
| 						},
 | |
| 					},
 | |
| 				}},
 | |
| 			},
 | |
| 		},
 | |
| 		{
 | |
| 			Type: watch.Deleted,
 | |
| 			Object: &metav1beta1.Table{
 | |
| 				ColumnDefinitions: []metav1beta1.TableColumnDefinition{},
 | |
| 				Rows: []metav1beta1.TableRow{{
 | |
| 					Cells: []interface{}{"b", false},
 | |
| 					Object: runtime.RawExtension{
 | |
| 						Object: &corev1.Pod{
 | |
| 							TypeMeta:   metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
 | |
| 							ObjectMeta: metav1.ObjectMeta{Name: "b", Namespace: "test", ResourceVersion: "40"},
 | |
| 						},
 | |
| 					},
 | |
| 				}},
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
 | |
| 			switch req.URL.Path {
 | |
| 			case "/namespaces/test/pods":
 | |
| 				if req.URL.Query().Get("watch") != "true" && req.URL.Query().Get("fieldSelector") == "" {
 | |
| 					return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, listTable)}, nil
 | |
| 				}
 | |
| 				if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "" {
 | |
| 					return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events)}, nil
 | |
| 				}
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			default:
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			}
 | |
| 		}),
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 
 | |
| 	cmd.Flags().Set("watch", "true")
 | |
| 	cmd.Run(cmd, []string{"pods"})
 | |
| 
 | |
| 	expected := `NAME   ACTIVE
 | |
| a      true
 | |
| b      true
 | |
| a      false
 | |
| b      false
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestWatchResourceIdentifiedByFile(t *testing.T) {
 | |
| 	pods, events := watchTestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
 | |
| 			switch req.URL.Path {
 | |
| 			case "/namespaces/test/replicationcontrollers/cassandra":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods[1])}, nil
 | |
| 			case "/namespaces/test/replicationcontrollers":
 | |
| 				if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=cassandra" {
 | |
| 					return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[1:])}, nil
 | |
| 				}
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			default:
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			}
 | |
| 		}),
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 
 | |
| 	cmd.Flags().Set("watch", "true")
 | |
| 	cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml")
 | |
| 	cmd.Run(cmd, []string{})
 | |
| 
 | |
| 	expected := `NAME   READY   STATUS   RESTARTS   AGE
 | |
| foo    0/0              0          <unknown>
 | |
| foo    0/0              0          <unknown>
 | |
| foo    0/0              0          <unknown>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestWatchOnlyResource(t *testing.T) {
 | |
| 	pods, events := watchTestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
 | |
| 			switch req.URL.Path {
 | |
| 			case "/namespaces/test/pods/foo":
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods[1])}, nil
 | |
| 			case "/namespaces/test/pods":
 | |
| 				if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" {
 | |
| 					return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[1:])}, nil
 | |
| 				}
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			default:
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			}
 | |
| 		}),
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 
 | |
| 	cmd.Flags().Set("watch-only", "true")
 | |
| 	cmd.Run(cmd, []string{"pods", "foo"})
 | |
| 
 | |
| 	expected := `NAME   READY   STATUS   RESTARTS   AGE
 | |
| foo    0/0              0          <unknown>
 | |
| foo    0/0              0          <unknown>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestWatchOnlyList(t *testing.T) {
 | |
| 	pods, events := watchTestData()
 | |
| 
 | |
| 	tf := cmdtesting.NewTestFactory().WithNamespace("test")
 | |
| 	defer tf.Cleanup()
 | |
| 	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
 | |
| 
 | |
| 	podList := &corev1.PodList{
 | |
| 		Items: pods,
 | |
| 		ListMeta: metav1.ListMeta{
 | |
| 			ResourceVersion: "10",
 | |
| 		},
 | |
| 	}
 | |
| 	tf.UnstructuredClient = &fake.RESTClient{
 | |
| 		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
 | |
| 		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
 | |
| 			switch req.URL.Path {
 | |
| 			case "/namespaces/test/pods":
 | |
| 				if req.URL.Query().Get("watch") == "true" {
 | |
| 					return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[2:])}, nil
 | |
| 				}
 | |
| 				return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, podList)}, nil
 | |
| 			default:
 | |
| 				t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
 | |
| 				return nil, nil
 | |
| 			}
 | |
| 		}),
 | |
| 	}
 | |
| 
 | |
| 	streams, _, buf, _ := genericclioptions.NewTestIOStreams()
 | |
| 	cmd := NewCmdGet("kubectl", tf, streams)
 | |
| 	cmd.SetOutput(buf)
 | |
| 
 | |
| 	cmd.Flags().Set("watch-only", "true")
 | |
| 	cmd.Run(cmd, []string{"pods"})
 | |
| 
 | |
| 	expected := `NAME   READY   STATUS   RESTARTS   AGE
 | |
| foo    0/0              0          <unknown>
 | |
| foo    0/0              0          <unknown>
 | |
| `
 | |
| 	if e, a := expected, buf.String(); e != a {
 | |
| 		t.Errorf("expected\n%v\ngot\n%v", e, a)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func watchBody(codec runtime.Codec, events []watch.Event) io.ReadCloser {
 | |
| 	buf := bytes.NewBuffer([]byte{})
 | |
| 	enc := restclientwatch.NewEncoder(streaming.NewEncoder(buf, codec), codec)
 | |
| 	for i := range events {
 | |
| 		if err := enc.Encode(&events[i]); err != nil {
 | |
| 			panic(err)
 | |
| 		}
 | |
| 	}
 | |
| 	return json.Framer.NewFrameReader(ioutil.NopCloser(buf))
 | |
| }
 |