1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654 |
- /*
- 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))
- }
|