1
16
17 package describe
18
19 import (
20 "fmt"
21 "net/http"
22 "strings"
23 "testing"
24
25 "k8s.io/apimachinery/pkg/api/meta"
26 "k8s.io/cli-runtime/pkg/genericclioptions"
27 "k8s.io/cli-runtime/pkg/genericiooptions"
28 "k8s.io/cli-runtime/pkg/resource"
29 "k8s.io/client-go/rest/fake"
30 cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
31 "k8s.io/kubectl/pkg/describe"
32 "k8s.io/kubectl/pkg/scheme"
33 )
34
35
36 func TestDescribeUnknownSchemaObject(t *testing.T) {
37 d := &testDescriber{Output: "test output"}
38 oldFn := describe.DescriberFn
39 defer func() {
40 describe.DescriberFn = oldFn
41 }()
42 describe.DescriberFn = d.describerFor
43
44 tf := cmdtesting.NewTestFactory().WithNamespace("non-default")
45 defer tf.Cleanup()
46 _, _, codec := cmdtesting.NewExternalScheme()
47
48 tf.UnstructuredClient = &fake.RESTClient{
49 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
50 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, cmdtesting.NewInternalType("", "", "foo"))},
51 }
52
53 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
54
55 cmd := NewCmdDescribe("kubectl", tf, streams)
56 cmd.Run(cmd, []string{"type", "foo"})
57
58 if d.Name != "foo" || d.Namespace != "" {
59 t.Errorf("unexpected describer: %#v", d)
60 }
61
62 if buf.String() != d.Output {
63 t.Errorf("unexpected output: %s", buf.String())
64 }
65 }
66
67
68 func TestDescribeUnknownNamespacedSchemaObject(t *testing.T) {
69 d := &testDescriber{Output: "test output"}
70 oldFn := describe.DescriberFn
71 defer func() {
72 describe.DescriberFn = oldFn
73 }()
74 describe.DescriberFn = d.describerFor
75
76 tf := cmdtesting.NewTestFactory()
77 defer tf.Cleanup()
78 _, _, codec := cmdtesting.NewExternalScheme()
79
80 tf.UnstructuredClient = &fake.RESTClient{
81 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
82 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, cmdtesting.NewInternalNamespacedType("", "", "foo", "non-default"))},
83 }
84 tf.WithNamespace("non-default")
85
86 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
87
88 cmd := NewCmdDescribe("kubectl", tf, streams)
89 cmd.Run(cmd, []string{"namespacedtype", "foo"})
90
91 if d.Name != "foo" || d.Namespace != "non-default" {
92 t.Errorf("unexpected describer: %#v", d)
93 }
94
95 if buf.String() != d.Output {
96 t.Errorf("unexpected output: %s", buf.String())
97 }
98 }
99
100 func TestDescribeObject(t *testing.T) {
101 d := &testDescriber{Output: "test output"}
102 oldFn := describe.DescriberFn
103 defer func() {
104 describe.DescriberFn = oldFn
105 }()
106 describe.DescriberFn = d.describerFor
107
108 _, _, rc := cmdtesting.TestData()
109 tf := cmdtesting.NewTestFactory().WithNamespace("test")
110 defer tf.Cleanup()
111 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
112
113 tf.UnstructuredClient = &fake.RESTClient{
114 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
115 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
116 switch p, m := req.URL.Path, req.Method; {
117 case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "GET":
118 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
119 default:
120 t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
121 return nil, nil
122 }
123 }),
124 }
125
126 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
127
128 cmd := NewCmdDescribe("kubectl", tf, streams)
129 cmd.Flags().Set("filename", "../../../testdata/redis-master-controller.yaml")
130 cmd.Run(cmd, []string{})
131
132 if d.Name != "redis-master" || d.Namespace != "test" {
133 t.Errorf("unexpected describer: %#v", d)
134 }
135
136 if buf.String() != d.Output {
137 t.Errorf("unexpected output: %s", buf.String())
138 }
139 }
140
141 func TestDescribeListObjects(t *testing.T) {
142 d := &testDescriber{Output: "test output"}
143 oldFn := describe.DescriberFn
144 defer func() {
145 describe.DescriberFn = oldFn
146 }()
147 describe.DescriberFn = d.describerFor
148
149 pods, _, _ := cmdtesting.TestData()
150 tf := cmdtesting.NewTestFactory().WithNamespace("test")
151 defer tf.Cleanup()
152 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
153
154 tf.UnstructuredClient = &fake.RESTClient{
155 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
156 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)},
157 }
158
159 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
160
161 cmd := NewCmdDescribe("kubectl", tf, streams)
162 cmd.Run(cmd, []string{"pods"})
163 if buf.String() != fmt.Sprintf("%s\n\n%s", d.Output, d.Output) {
164 t.Errorf("unexpected output: %s", buf.String())
165 }
166 }
167
168 func TestDescribeObjectShowEvents(t *testing.T) {
169 d := &testDescriber{Output: "test output"}
170 oldFn := describe.DescriberFn
171 defer func() {
172 describe.DescriberFn = oldFn
173 }()
174 describe.DescriberFn = d.describerFor
175
176 pods, _, _ := cmdtesting.TestData()
177 tf := cmdtesting.NewTestFactory().WithNamespace("test")
178 defer tf.Cleanup()
179 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
180
181 tf.UnstructuredClient = &fake.RESTClient{
182 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
183 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)},
184 }
185
186 cmd := NewCmdDescribe("kubectl", tf, genericiooptions.NewTestIOStreamsDiscard())
187 cmd.Flags().Set("show-events", "true")
188 cmd.Run(cmd, []string{"pods"})
189 if d.Settings.ShowEvents != true {
190 t.Errorf("ShowEvents = true expected, got ShowEvents = %v", d.Settings.ShowEvents)
191 }
192 }
193
194 func TestDescribeObjectSkipEvents(t *testing.T) {
195 d := &testDescriber{Output: "test output"}
196 oldFn := describe.DescriberFn
197 defer func() {
198 describe.DescriberFn = oldFn
199 }()
200 describe.DescriberFn = d.describerFor
201
202 pods, _, _ := cmdtesting.TestData()
203 tf := cmdtesting.NewTestFactory().WithNamespace("test")
204 defer tf.Cleanup()
205 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
206
207 tf.UnstructuredClient = &fake.RESTClient{
208 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
209 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)},
210 }
211
212 cmd := NewCmdDescribe("kubectl", tf, genericiooptions.NewTestIOStreamsDiscard())
213 cmd.Flags().Set("show-events", "false")
214 cmd.Run(cmd, []string{"pods"})
215 if d.Settings.ShowEvents != false {
216 t.Errorf("ShowEvents = false expected, got ShowEvents = %v", d.Settings.ShowEvents)
217 }
218 }
219
220 func TestDescribeObjectChunkSize(t *testing.T) {
221 d := &testDescriber{Output: "test output"}
222 oldFn := describe.DescriberFn
223 defer func() {
224 describe.DescriberFn = oldFn
225 }()
226 describe.DescriberFn = d.describerFor
227
228 pods, _, _ := cmdtesting.TestData()
229 tf := cmdtesting.NewTestFactory().WithNamespace("test")
230 defer tf.Cleanup()
231 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
232
233 tf.UnstructuredClient = &fake.RESTClient{
234 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
235 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)},
236 }
237
238 cmd := NewCmdDescribe("kubectl", tf, genericiooptions.NewTestIOStreamsDiscard())
239 cmd.Flags().Set("chunk-size", "100")
240 cmd.Run(cmd, []string{"pods"})
241 if d.Settings.ChunkSize != 100 {
242 t.Errorf("ChunkSize = 100 expected, got ChunkSize = %v", d.Settings.ChunkSize)
243 }
244 }
245
246 func TestDescribeHelpMessage(t *testing.T) {
247 tf := cmdtesting.NewTestFactory()
248 defer tf.Cleanup()
249
250 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
251
252 cmd := NewCmdDescribe("kubectl", tf, streams)
253 cmd.SetArgs([]string{"-h"})
254 cmd.SetOut(buf)
255 cmd.SetErr(buf)
256 _, err := cmd.ExecuteC()
257
258 if err != nil {
259 t.Fatalf("Unexpected error: %v", err)
260 }
261
262 got := buf.String()
263
264 expected := `describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME)`
265 if !strings.Contains(got, expected) {
266 t.Errorf("Expected to contain: \n %v\nGot:\n %v\n", expected, got)
267 }
268
269 unexpected := `describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME) [flags]`
270 if strings.Contains(got, unexpected) {
271 t.Errorf("Expected not to contain: \n %v\nGot:\n %v\n", unexpected, got)
272 }
273 }
274
275 func TestDescribeNoResourcesFound(t *testing.T) {
276 testNS := "testns"
277 testCases := []struct {
278 name string
279 flags map[string]string
280 namespace string
281 expectedOutput string
282 expectedErr string
283 }{
284 {
285 name: "all namespaces",
286 flags: map[string]string{"all-namespaces": "true"},
287 expectedOutput: "",
288 expectedErr: "No resources found\n",
289 },
290 {
291 name: "all in namespace",
292 namespace: testNS,
293 expectedOutput: "",
294 expectedErr: "No resources found in " + testNS + " namespace.\n",
295 },
296 }
297 cmdtesting.InitTestErrorHandler(t)
298 for _, testCase := range testCases {
299 t.Run(testCase.name, func(t *testing.T) {
300 pods, _, _ := cmdtesting.EmptyTestData()
301 tf := cmdtesting.NewTestFactory().WithNamespace(testNS)
302 defer tf.Cleanup()
303 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
304
305 tf.UnstructuredClient = &fake.RESTClient{
306 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
307 Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, pods)},
308 }
309
310 streams, _, buf, errbuf := genericiooptions.NewTestIOStreams()
311
312 cmd := NewCmdDescribe("kubectl", tf, streams)
313 for name, value := range testCase.flags {
314 _ = cmd.Flags().Set(name, value)
315 }
316 cmd.Run(cmd, []string{"pods"})
317
318 if e, a := testCase.expectedOutput, buf.String(); e != a {
319 t.Errorf("Unexpected output:\nExpected:\n%v\nActual:\n%v", e, a)
320 }
321 if e, a := testCase.expectedErr, errbuf.String(); e != a {
322 t.Errorf("Unexpected error:\nExpected:\n%v\nActual:\n%v", e, a)
323 }
324 })
325 }
326 }
327
328 type testDescriber struct {
329 Name, Namespace string
330 Settings describe.DescriberSettings
331 Output string
332 Err error
333 }
334
335 func (t *testDescriber) Describe(namespace, name string, describerSettings describe.DescriberSettings) (output string, err error) {
336 t.Namespace, t.Name = namespace, name
337 t.Settings = describerSettings
338 return t.Output, t.Err
339 }
340 func (t *testDescriber) describerFor(restClientGetter genericclioptions.RESTClientGetter, mapping *meta.RESTMapping) (describe.ResourceDescriber, error) {
341 return t, nil
342 }
343
View as plain text