k3s/pkg/kubectl/cmd/get/get_test.go

1455 lines
50 KiB
Go
Raw Normal View History

/*
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.
*/
2018-04-19 21:57:09 +00:00
package get
import (
"bytes"
encjson "encoding/json"
2018-05-30 19:24:55 +00:00
"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"
2017-01-11 14:09:48 +00:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2018-05-30 19:24:55 +00:00
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
2017-01-11 14:09:48 +00:00
"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"
2018-08-02 17:29:16 +00:00
"k8s.io/apimachinery/pkg/util/diff"
2017-01-11 14:09:48 +00:00
"k8s.io/apimachinery/pkg/watch"
2018-08-21 10:46:39 +00:00
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericclioptions/resource"
2017-01-19 18:27:59 +00:00
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake"
2017-01-18 21:01:15 +00:00
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"
)
2018-10-05 12:38:38 +00:00
var (
openapiSchemaPath = filepath.Join("..", "..", "..", "..", "api", "openapi-spec", "swagger.json")
2018-10-05 12:38:38 +00:00
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) {
2018-02-21 01:14:21 +00:00
t.Skip("This test is completely broken. The first thing it does is add the object to the scheme!")
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-02-21 17:10:38 +00:00
_, _, codec := cmdtesting.NewExternalScheme()
tf.OpenAPISchemaFunc = openapitesting.CreateOpenAPISchemaFunc(openapiSchemaPath)
obj := &cmdtesting.ExternalType{
Kind: "Type",
APIVersion: "apitest/unlikelyversion",
Name: "foo",
}
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{
2018-10-05 12:38:38 +00:00
StatusCode: 200, Header: cmdtesting.DefaultHeader(),
Body: cmdtesting.ObjBody(codec, obj),
},
}
2018-10-05 12:38:38 +00:00
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
cmd := NewCmdGet("kubectl", tf, streams)
cmd.SetOutput(buf)
cmd.Run(cmd, []string{"type", "foo"})
expected := []runtime.Object{cmdtesting.NewInternalType("", "", "foo")}
2018-02-21 01:14:21 +00:00
actual := []runtime.Object{}
if len(actual) != len(expected) {
2017-07-22 17:59:53 +00:00
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) {
2017-07-22 17:59:53 +00:00
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")
2018-03-08 22:23:55 +00:00
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{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})},
}
2018-10-05 12:38:38 +00:00
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
cmd := NewCmdGet("kubectl", tf, streams)
cmd.Run(cmd, []string{"replicationcontrollers", "foo"})
2018-02-21 01:14:21 +00:00
if !strings.Contains(buf.String(), "foo") {
t.Errorf("unexpected output: %s", buf.String())
}
}
func TestGetObjectsWithOpenAPIOutputFormatPresent(t *testing.T) {
2018-10-05 12:38:38 +00:00
pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
// overide the openAPISchema function to return custom output
// for Pod type.
tf.OpenAPISchemaFunc = testOpenAPISchemaData
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
cmd := NewCmdGet("kubectl", tf, streams)
cmd.SetOutput(buf)
cmd.Flags().Set(useOpenAPIPrintColumnFlagLabel, "true")
cmd.Run(cmd, []string{"pods", "foo"})
expected := `NAME RSRC
foo 10
2018-02-21 01:14:21 +00:00
`
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) {
2018-10-05 12:38:38 +00:00
pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
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>
2018-02-21 01:14:21 +00:00
`
if e, a := expected, buf.String(); e != a {
t.Errorf("expected\n%v\ngot\n%v", e, a)
}
}
2018-05-20 05:26:53 +00:00
func TestGetObjectsShowKind(t *testing.T) {
2018-10-05 12:38:38 +00:00
pods, _, _ := cmdtesting.TestData()
2018-05-20 05:26:53 +00:00
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-05-20 05:26:53 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-05-20 05:26:53 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
2018-05-20 05:26:53 +00:00
}
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>
2018-05-20 05:26:53 +00:00
`
if e, a := expected, buf.String(); e != a {
t.Errorf("expected\n%v\ngot\n%v", e, a)
2018-05-20 05:26:53 +00:00
}
}
func TestGetMultipleResourceTypesShowKinds(t *testing.T) {
2018-10-05 12:38:38 +00:00
pods, svcs, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
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":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
case p == "/namespaces/test/replicationcontrollers" && m == "GET":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.ReplicationControllerList{})}, nil
case p == "/namespaces/test/services" && m == "GET":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svcs)}, nil
case p == "/namespaces/test/statefulsets" && m == "GET":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &appsv1.StatefulSetList{})}, nil
case p == "/namespaces/test/horizontalpodautoscalers" && m == "GET":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &autoscalingv1.HorizontalPodAutoscalerList{})}, nil
case p == "/namespaces/test/jobs" && m == "GET":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &batchv1.JobList{})}, nil
case p == "/namespaces/test/cronjobs" && m == "GET":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &batchv1beta1.CronJobList{})}, nil
case p == "/namespaces/test/daemonsets" && m == "GET":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &appsv1.DaemonSetList{})}, nil
case p == "/namespaces/test/deployments" && m == "GET":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &extensionsv1beta1.DeploymentList{})}, nil
case p == "/namespaces/test/replicasets" && m == "GET":
2018-10-05 12:38:38 +00:00
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)
}
}
2018-05-20 05:26:53 +00:00
func TestGetObjectsShowLabels(t *testing.T) {
2018-10-05 12:38:38 +00:00
pods, _, _ := cmdtesting.TestData()
2018-05-20 05:26:53 +00:00
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-05-20 05:26:53 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-05-20 05:26:53 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
2018-05-20 05:26:53 +00:00
}
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>
2018-02-21 01:14:21 +00:00
`
if e, a := expected, buf.String(); e != a {
t.Errorf("expected\n%v\ngot\n%v", e, a)
}
}
2017-02-14 19:48:07 +00:00
func TestGetObjectIgnoreNotFound(t *testing.T) {
2018-10-05 12:38:38 +00:00
cmdtesting.InitTestErrorHandler(t)
2017-02-14 19:48:07 +00:00
ns := &corev1.NamespaceList{
2017-02-14 19:48:07 +00:00
ListMeta: metav1.ListMeta{
ResourceVersion: "1",
},
Items: []corev1.Namespace{
2017-02-14 19:48:07 +00:00
{
ObjectMeta: metav1.ObjectMeta{Name: "testns", Namespace: "test", ResourceVersion: "11"},
Spec: corev1.NamespaceSpec{},
2017-02-14 19:48:07 +00:00
},
},
}
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
2017-02-14 19:48:07 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
2017-02-14 19:48:07 +00:00
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":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 404, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.StringBody("")}, nil
2017-02-14 19:48:07 +00:00
case p == "/api/v1/namespaces/test" && m == "GET":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &ns.Items[0])}, nil
2017-02-14 19:48:07 +00:00
default:
2017-08-11 02:50:06 +00:00
t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2017-02-14 19:48:07 +00:00
return nil, nil
}
}),
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
cmd := NewCmdGet("kubectl", tf, streams)
2017-02-14 19:48:07 +00:00
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{
2016-12-03 18:57:26 +00:00
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")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
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}}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
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>
2018-02-21 01:14:21 +00:00
`
if e, a := expected, buf.String(); e != a {
t.Errorf("expected\n%v\ngot\n%v", e, a)
}
}
2018-05-30 19:24:55 +00:00
func sortTestData() []runtime.Object {
return []runtime.Object{
&corev1.Pod{
2018-05-30 19:24:55 +00:00
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,
},
2018-05-30 19:24:55 +00:00
},
&corev1.Pod{
2018-05-30 19:24:55 +00:00
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,
},
2018-05-30 19:24:55 +00:00
},
&corev1.Pod{
2018-05-30 19:24:55 +00:00
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,
},
2018-05-30 19:24:55 +00:00
},
}
}
func sortTestTableData() []runtime.Object {
return []runtime.Object{
&metav1beta1.Table{
TypeMeta: metav1.TypeMeta{Kind: "Table"},
Rows: []metav1beta1.TableRow{
{
Object: runtime.RawExtension{
Object: &corev1.Pod{
2018-05-30 19:24:55 +00:00
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,
},
2018-05-30 19:24:55 +00:00
},
},
},
{
Object: runtime.RawExtension{
Object: &corev1.Pod{
2018-05-30 19:24:55 +00:00
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,
},
2018-05-30 19:24:55 +00:00
},
},
},
{
Object: runtime.RawExtension{
Object: &corev1.Pod{
2018-05-30 19:24:55 +00:00
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,
},
2018-05-30 19:24:55 +00:00
},
},
},
},
},
}
}
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
}{
2018-11-08 17:35:52 +00:00
{
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: "",
},
2018-05-30 19:24:55 +00:00
{
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)
2018-05-30 19:24:55 +00:00
}
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) {
2018-10-05 12:38:38 +00:00
pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods.Items[0])},
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
cmd := NewCmdGet("kubectl", tf, streams)
cmd.SetOutput(buf)
2018-02-26 22:20:51 +00:00
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>
2018-02-21 01:14:21 +00:00
`
if e, a := expected, buf.String(); e != a {
t.Errorf("expected\n%v\ngot\n%v", e, a)
}
}
func TestGetListObjects(t *testing.T) {
2018-10-05 12:38:38 +00:00
pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)},
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
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>
2018-02-21 01:14:21 +00:00
`
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")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, statuses)},
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
cmd := NewCmdGet("kubectl", tf, streams)
cmd.SetOutput(buf)
cmd.Run(cmd, []string{"componentstatuses"})
2018-02-21 01:14:21 +00:00
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) {
2018-10-05 12:38:38 +00:00
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")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path {
case "/namespaces/test/pods":
2018-10-05 12:38:38 +00:00
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
}
}),
}
2018-10-05 12:38:38 +00:00
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
cmd := NewCmdGet("kubectl", tf, streams)
cmd.SetOutput(buf)
cmd.Flags().Set("output", "json")
cmd.Run(cmd, []string{"pods"})
2018-02-21 01:14:21 +00:00
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) {
2018-10-05 12:38:38 +00:00
pods, svc, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path {
case "/namespaces/test/pods":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
case "/namespaces/test/services":
2018-10-05 12:38:38 +00:00
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
}
}),
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
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>
2018-02-21 01:14:21 +00:00
`
if e, a := expected, buf.String(); e != a {
t.Errorf("expected\n%v\ngot\n%v", e, a)
}
}
func TestGetMultipleTypeObjectsAsList(t *testing.T) {
2018-10-05 12:38:38 +00:00
pods, svc, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path {
case "/namespaces/test/pods":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
case "/namespaces/test/services":
2018-10-05 12:38:38 +00:00
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
}
}),
}
2018-10-05 12:38:38 +00:00
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
cmd := NewCmdGet("kubectl", tf, streams)
cmd.SetOutput(buf)
cmd.Flags().Set("output", "json")
cmd.Run(cmd, []string{"pods,services"})
2018-02-21 01:14:21 +00:00
expected := `{
"apiVersion": "v1",
"items": [
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"creationTimestamp": null,
"name": "foo",
"namespace": "test",
"resourceVersion": "10"
},
"spec": {
"containers": null,
"dnsPolicy": "ClusterFirst",
"enableServiceLinks": true,
2018-02-21 01:14:21 +00:00
"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,
2018-02-21 01:14:21 +00:00
"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))
}
}
2017-08-05 05:25:53 +00:00
func TestGetMultipleTypeObjectsWithLabelSelector(t *testing.T) {
2018-10-05 12:38:38 +00:00
pods, svc, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
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":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
case "/namespaces/test/services":
2018-10-05 12:38:38 +00:00
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
}
}),
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
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>
2018-02-21 01:14:21 +00:00
`
if e, a := expected, buf.String(); e != a {
t.Errorf("expected\n%v\ngot\n%v", e, a)
}
}
2017-08-05 05:25:53 +00:00
func TestGetMultipleTypeObjectsWithFieldSelector(t *testing.T) {
2018-10-05 12:38:38 +00:00
pods, svc, _ := cmdtesting.TestData()
2017-08-05 05:25:53 +00:00
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
2017-08-05 05:25:53 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
2017-08-05 05:25:53 +00:00
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":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)}, nil
2017-08-05 05:25:53 +00:00
case "/namespaces/test/services":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, svc)}, nil
2017-08-05 05:25:53 +00:00
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
}
}),
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
cmd := NewCmdGet("kubectl", tf, streams)
2017-08-05 05:25:53 +00:00
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>
2018-02-21 01:14:21 +00:00
`
if e, a := expected, buf.String(); e != a {
t.Errorf("expected\n%v\ngot\n%v", e, a)
2017-08-05 05:25:53 +00:00
}
}
func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) {
2018-10-05 12:38:38 +00:00
_, svc, _ := cmdtesting.TestData()
node := &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
}
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path {
case "/nodes/foo":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, node)}, nil
case "/namespaces/test/services/bar":
2018-10-05 12:38:38 +00:00
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
}
}),
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
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>
2018-02-21 01:14:21 +00:00
`
if e, a := expected, buf.String(); e != a {
t.Errorf("expected\n%v\ngot\n%v", e, a)
}
}
2015-12-03 19:32:22 +00:00
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
}
2017-08-05 05:25:53 +00:00
func TestWatchLabelSelector(t *testing.T) {
pods, events := watchTestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
podList := &corev1.PodList{
Items: pods,
2016-12-03 18:57:26 +00:00
ListMeta: metav1.ListMeta{
ResourceVersion: "10",
},
}
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
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":
2017-01-09 21:21:23 +00:00
if req.URL.Query().Get("watch") == "true" {
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[2:])}, nil
2017-01-09 21:21:23 +00:00
}
2018-10-05 12:38:38 +00:00
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
}
}),
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
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>
2018-02-21 01:14:21 +00:00
`
if e, a := expected, buf.String(); e != a {
t.Errorf("expected\n%v\ngot\n%v", e, a)
}
}
2017-08-05 05:25:53 +00:00
func TestWatchFieldSelector(t *testing.T) {
pods, events := watchTestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
podList := &corev1.PodList{
2017-08-05 05:25:53 +00:00
Items: pods,
ListMeta: metav1.ListMeta{
ResourceVersion: "10",
},
}
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
2017-08-05 05:25:53 +00:00
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" {
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[2:])}, nil
2017-08-05 05:25:53 +00:00
}
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, podList)}, nil
2017-08-05 05:25:53 +00:00
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
}
}),
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
cmd := NewCmdGet("kubectl", tf, streams)
2017-08-05 05:25:53 +00:00
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>
2018-02-21 01:14:21 +00:00
`
if e, a := expected, buf.String(); e != a {
t.Errorf("expected\n%v\ngot\n%v", e, a)
2017-08-05 05:25:53 +00:00
}
}
func TestWatchResource(t *testing.T) {
pods, events := watchTestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path {
case "/namespaces/test/pods/foo":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods[1])}, nil
2017-01-09 21:21:23 +00:00
case "/namespaces/test/pods":
if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" {
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[1:])}, nil
2017-01-09 21:21:23 +00:00
}
t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2017-01-09 21:21:23 +00:00
return nil, nil
default:
t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
return nil, nil
}
}),
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
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>
2018-02-21 01:14:21 +00:00
`
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")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path {
2016-03-10 17:26:39 +00:00
case "/namespaces/test/replicationcontrollers/cassandra":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods[1])}, nil
2017-01-09 21:21:23 +00:00
case "/namespaces/test/replicationcontrollers":
if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=cassandra" {
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[1:])}, nil
2017-01-09 21:21:23 +00:00
}
t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2017-01-09 21:21:23 +00:00
return nil, nil
default:
t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
return nil, nil
}
}),
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
cmd := NewCmdGet("kubectl", tf, streams)
cmd.SetOutput(buf)
cmd.Flags().Set("watch", "true")
2018-02-26 22:20:51 +00:00
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>
2018-02-21 01:14:21 +00:00
`
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")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path {
case "/namespaces/test/pods/foo":
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &pods[1])}, nil
2017-01-09 21:21:23 +00:00
case "/namespaces/test/pods":
if req.URL.Query().Get("watch") == "true" && req.URL.Query().Get("fieldSelector") == "metadata.name=foo" {
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[1:])}, nil
2017-01-09 21:21:23 +00:00
}
t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
2017-01-09 21:21:23 +00:00
return nil, nil
default:
t.Fatalf("request url: %#v,and request: %#v", req.URL, req)
return nil, nil
}
}),
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
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>
2018-02-21 01:14:21 +00:00
`
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")
2018-03-08 22:23:55 +00:00
defer tf.Cleanup()
2018-08-02 17:29:16 +00:00
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
2018-02-21 17:10:38 +00:00
podList := &corev1.PodList{
Items: pods,
2016-12-03 18:57:26 +00:00
ListMeta: metav1.ListMeta{
ResourceVersion: "10",
},
}
tf.UnstructuredClient = &fake.RESTClient{
2018-10-05 12:38:38 +00:00
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
switch req.URL.Path {
case "/namespaces/test/pods":
2017-01-09 21:21:23 +00:00
if req.URL.Query().Get("watch") == "true" {
2018-10-05 12:38:38 +00:00
return &http.Response{StatusCode: 200, Header: cmdtesting.DefaultHeader(), Body: watchBody(codec, events[2:])}, nil
2017-01-09 21:21:23 +00:00
}
2018-10-05 12:38:38 +00:00
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
}
}),
}
2018-04-25 12:32:08 +00:00
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
2018-04-25 23:55:26 +00:00
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>
2018-02-21 01:14:21 +00:00
`
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 {
enc.Encode(&events[i])
}
2016-04-26 07:05:40 +00:00
return json.Framer.NewFrameReader(ioutil.NopCloser(buf))
}