1
16
17 package polymorphichelpers
18
19 import (
20 "fmt"
21 "reflect"
22 "testing"
23 "time"
24
25 "github.com/google/go-cmp/cmp"
26 appsv1 "k8s.io/api/apps/v1"
27 batchv1 "k8s.io/api/batch/v1"
28 corev1 "k8s.io/api/core/v1"
29 extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
30 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31 "k8s.io/apimachinery/pkg/runtime"
32 "k8s.io/apimachinery/pkg/runtime/schema"
33 fakeexternal "k8s.io/client-go/kubernetes/fake"
34 testclient "k8s.io/client-go/testing"
35 "k8s.io/kubectl/pkg/cmd/util/podcmd"
36 )
37
38 var (
39 podsResource = schema.GroupVersionResource{Version: "v1", Resource: "pods"}
40 podsKind = schema.GroupVersionKind{Version: "v1", Kind: "Pod"}
41 )
42
43 func TestLogsForObject(t *testing.T) {
44 tests := []struct {
45 name string
46 obj runtime.Object
47 opts *corev1.PodLogOptions
48 allContainers bool
49 clientsetPods []runtime.Object
50 actions []testclient.Action
51
52 expectedErr string
53 expectedSources []corev1.ObjectReference
54 }{
55 {
56 name: "pod logs",
57 obj: testPodWithOneContainers(),
58 actions: []testclient.Action{
59 getLogsAction("test", &corev1.PodLogOptions{Container: "c1"}),
60 },
61 expectedSources: []corev1.ObjectReference{
62 {
63 Kind: testPodWithOneContainers().Kind,
64 APIVersion: testPodWithOneContainers().APIVersion,
65 Name: testPodWithOneContainers().Name,
66 Namespace: testPodWithOneContainers().Namespace,
67 FieldPath: fmt.Sprintf("spec.containers{%s}", testPodWithOneContainers().Spec.Containers[0].Name),
68 },
69 },
70 },
71 {
72 name: "pod logs: all containers",
73 obj: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers(),
74 opts: &corev1.PodLogOptions{},
75 allContainers: true,
76 actions: []testclient.Action{
77 getLogsAction("test", &corev1.PodLogOptions{Container: "foo-2-and-2-and-1-initc1"}),
78 getLogsAction("test", &corev1.PodLogOptions{Container: "foo-2-and-2-and-1-initc2"}),
79 getLogsAction("test", &corev1.PodLogOptions{Container: "foo-2-and-2-and-1-c1"}),
80 getLogsAction("test", &corev1.PodLogOptions{Container: "foo-2-and-2-and-1-c2"}),
81 getLogsAction("test", &corev1.PodLogOptions{Container: "foo-2-and-2-and-1-e1"}),
82 },
83 expectedSources: []corev1.ObjectReference{
84 {
85 Kind: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Kind,
86 APIVersion: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().APIVersion,
87 Name: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Name,
88 Namespace: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Namespace,
89 FieldPath: fmt.Sprintf("spec.initContainers{%s}", testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Spec.InitContainers[0].Name),
90 },
91 {
92 Kind: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Kind,
93 APIVersion: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().APIVersion,
94 Name: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Name,
95 Namespace: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Namespace,
96 FieldPath: fmt.Sprintf("spec.initContainers{%s}", testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Spec.InitContainers[1].Name),
97 },
98 {
99 Kind: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Kind,
100 APIVersion: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().APIVersion,
101 Name: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Name,
102 Namespace: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Namespace,
103 FieldPath: fmt.Sprintf("spec.containers{%s}", testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Spec.Containers[0].Name),
104 },
105 {
106 Kind: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Kind,
107 APIVersion: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().APIVersion,
108 Name: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Name,
109 Namespace: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Namespace,
110 FieldPath: fmt.Sprintf("spec.containers{%s}", testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Spec.Containers[1].Name),
111 },
112 {
113 Kind: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Kind,
114 APIVersion: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().APIVersion,
115 Name: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Name,
116 Namespace: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Namespace,
117 FieldPath: fmt.Sprintf("spec.ephemeralContainers{%s}", testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Spec.EphemeralContainers[0].Name),
118 },
119 },
120 },
121 {
122 name: "pod logs: default to first container",
123 obj: testPodWithTwoContainers(),
124 actions: []testclient.Action{
125 getLogsAction("test", &corev1.PodLogOptions{Container: "foo-2-c1"}),
126 },
127 expectedSources: []corev1.ObjectReference{
128 {
129 Kind: testPodWithTwoContainers().Kind,
130 APIVersion: testPodWithTwoContainers().APIVersion,
131 Name: testPodWithTwoContainers().Name,
132 Namespace: testPodWithTwoContainers().Namespace,
133 FieldPath: fmt.Sprintf("spec.containers{%s}", testPodWithTwoContainers().Spec.Containers[0].Name),
134 },
135 },
136 },
137 {
138 name: "pods list logs",
139 obj: &corev1.PodList{
140 Items: []corev1.Pod{*testPodWithOneContainers()},
141 },
142 actions: []testclient.Action{
143 getLogsAction("test", &corev1.PodLogOptions{Container: "c1"}),
144 },
145 expectedSources: []corev1.ObjectReference{{
146 Kind: testPodWithOneContainers().Kind,
147 APIVersion: testPodWithOneContainers().APIVersion,
148 Name: testPodWithOneContainers().Name,
149 Namespace: testPodWithOneContainers().Namespace,
150 FieldPath: fmt.Sprintf("spec.containers{%s}", testPodWithOneContainers().Spec.Containers[0].Name),
151 }},
152 },
153 {
154 name: "pods list logs: default container should not leak across pods",
155 obj: &corev1.PodList{
156 Items: []corev1.Pod{
157 {
158 TypeMeta: metav1.TypeMeta{
159 Kind: "pod",
160 APIVersion: "v1",
161 },
162 ObjectMeta: metav1.ObjectMeta{
163 Name: "foo",
164 Namespace: "test",
165 Labels: map[string]string{"test": "logs"},
166 Annotations: map[string]string{
167 "kubectl.kubernetes.io/default-container": "c1",
168 },
169 },
170 Spec: corev1.PodSpec{
171 RestartPolicy: corev1.RestartPolicyAlways,
172 DNSPolicy: corev1.DNSClusterFirst,
173 Containers: []corev1.Container{
174 {Name: "c1"},
175 {Name: "c2"},
176 },
177 },
178 },
179 {
180 TypeMeta: metav1.TypeMeta{
181 Kind: "pod",
182 APIVersion: "v1",
183 },
184 ObjectMeta: metav1.ObjectMeta{
185 Name: "bar",
186 Namespace: "test",
187 Labels: map[string]string{"test": "logs"},
188 },
189 Spec: corev1.PodSpec{
190 RestartPolicy: corev1.RestartPolicyAlways,
191 DNSPolicy: corev1.DNSClusterFirst,
192 Containers: []corev1.Container{
193 {Name: "c2"},
194 },
195 },
196 },
197 },
198 },
199 actions: []testclient.Action{
200 getLogsAction("test", &corev1.PodLogOptions{Container: "c1"}),
201 getLogsAction("test", &corev1.PodLogOptions{Container: "c2"}),
202 },
203 expectedSources: []corev1.ObjectReference{{
204 Kind: "pod",
205 APIVersion: "v1",
206 Name: "foo",
207 Namespace: "test",
208 FieldPath: fmt.Sprintf("spec.containers{%s}", "c1"),
209 }, {
210 Kind: "pod",
211 APIVersion: "v1",
212 Name: "bar",
213 Namespace: "test",
214 FieldPath: fmt.Sprintf("spec.containers{%s}", "c2"),
215 }},
216 },
217 {
218 name: "pods list logs: all containers",
219 obj: &corev1.PodList{
220 Items: []corev1.Pod{*testPodWithTwoContainersAndTwoInitContainers()},
221 },
222 opts: &corev1.PodLogOptions{},
223 allContainers: true,
224 actions: []testclient.Action{
225 getLogsAction("test", &corev1.PodLogOptions{Container: "foo-2-and-2-initc1"}),
226 getLogsAction("test", &corev1.PodLogOptions{Container: "foo-2-and-2-initc2"}),
227 getLogsAction("test", &corev1.PodLogOptions{Container: "foo-2-and-2-c1"}),
228 getLogsAction("test", &corev1.PodLogOptions{Container: "foo-2-and-2-c2"}),
229 },
230 expectedSources: []corev1.ObjectReference{
231 {
232 Kind: testPodWithTwoContainersAndTwoInitContainers().Kind,
233 APIVersion: testPodWithTwoContainersAndTwoInitContainers().APIVersion,
234 Name: testPodWithTwoContainersAndTwoInitContainers().Name,
235 Namespace: testPodWithTwoContainersAndTwoInitContainers().Namespace,
236 FieldPath: fmt.Sprintf("spec.initContainers{%s}", testPodWithTwoContainersAndTwoInitContainers().Spec.InitContainers[0].Name),
237 },
238 {
239 Kind: testPodWithTwoContainersAndTwoInitContainers().Kind,
240 APIVersion: testPodWithTwoContainersAndTwoInitContainers().APIVersion,
241 Name: testPodWithTwoContainersAndTwoInitContainers().Name,
242 Namespace: testPodWithTwoContainersAndTwoInitContainers().Namespace,
243 FieldPath: fmt.Sprintf("spec.initContainers{%s}", testPodWithTwoContainersAndTwoInitContainers().Spec.InitContainers[1].Name),
244 },
245 {
246 Kind: testPodWithTwoContainersAndTwoInitContainers().Kind,
247 APIVersion: testPodWithTwoContainersAndTwoInitContainers().APIVersion,
248 Name: testPodWithTwoContainersAndTwoInitContainers().Name,
249 Namespace: testPodWithTwoContainersAndTwoInitContainers().Namespace,
250 FieldPath: fmt.Sprintf("spec.containers{%s}", testPodWithTwoContainersAndTwoInitContainers().Spec.Containers[0].Name),
251 },
252 {
253 Kind: testPodWithTwoContainersAndTwoInitContainers().Kind,
254 APIVersion: testPodWithTwoContainersAndTwoInitContainers().APIVersion,
255 Name: testPodWithTwoContainersAndTwoInitContainers().Name,
256 Namespace: testPodWithTwoContainersAndTwoInitContainers().Namespace,
257 FieldPath: fmt.Sprintf("spec.containers{%s}", testPodWithTwoContainersAndTwoInitContainers().Spec.Containers[1].Name),
258 },
259 },
260 },
261 {
262 name: "pods list logs: default to first container",
263 obj: &corev1.PodList{
264 Items: []corev1.Pod{*testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers()},
265 },
266 actions: []testclient.Action{
267 getLogsAction("test", &corev1.PodLogOptions{Container: "foo-2-and-2-and-1-c1"}),
268 },
269 expectedSources: []corev1.ObjectReference{
270 {
271 Kind: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Kind,
272 APIVersion: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().APIVersion,
273 Name: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Name,
274 Namespace: testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Namespace,
275 FieldPath: fmt.Sprintf("spec.containers{%s}", testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers().Spec.Containers[0].Name),
276 },
277 },
278 },
279 {
280 name: "replication controller logs",
281 obj: &corev1.ReplicationController{
282 ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"},
283 Spec: corev1.ReplicationControllerSpec{
284 Selector: map[string]string{"foo": "bar"},
285 },
286 },
287 clientsetPods: []runtime.Object{testPodWithOneContainers()},
288 actions: []testclient.Action{
289 testclient.NewListAction(podsResource, podsKind, "test", metav1.ListOptions{LabelSelector: "foo=bar"}),
290 getLogsAction("test", &corev1.PodLogOptions{Container: "c1"}),
291 },
292 expectedSources: []corev1.ObjectReference{{
293 Kind: testPodWithOneContainers().Kind,
294 APIVersion: testPodWithOneContainers().APIVersion,
295 Name: testPodWithOneContainers().Name,
296 Namespace: testPodWithOneContainers().Namespace,
297 FieldPath: fmt.Sprintf("spec.containers{%s}", testPodWithOneContainers().Spec.Containers[0].Name),
298 }},
299 },
300 {
301 name: "replica set logs",
302 obj: &extensionsv1beta1.ReplicaSet{
303 ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"},
304 Spec: extensionsv1beta1.ReplicaSetSpec{
305 Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
306 },
307 },
308 clientsetPods: []runtime.Object{testPodWithOneContainers()},
309 actions: []testclient.Action{
310 testclient.NewListAction(podsResource, podsKind, "test", metav1.ListOptions{LabelSelector: "foo=bar"}),
311 getLogsAction("test", &corev1.PodLogOptions{Container: "c1"}),
312 },
313 expectedSources: []corev1.ObjectReference{{
314 Kind: testPodWithOneContainers().Kind,
315 APIVersion: testPodWithOneContainers().APIVersion,
316 Name: testPodWithOneContainers().Name,
317 Namespace: testPodWithOneContainers().Namespace,
318 FieldPath: fmt.Sprintf("spec.containers{%s}", testPodWithOneContainers().Spec.Containers[0].Name),
319 }},
320 },
321 {
322 name: "deployment logs",
323 obj: &extensionsv1beta1.Deployment{
324 ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"},
325 Spec: extensionsv1beta1.DeploymentSpec{
326 Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
327 },
328 },
329 clientsetPods: []runtime.Object{testPodWithOneContainers()},
330 actions: []testclient.Action{
331 testclient.NewListAction(podsResource, podsKind, "test", metav1.ListOptions{LabelSelector: "foo=bar"}),
332 getLogsAction("test", &corev1.PodLogOptions{Container: "c1"}),
333 },
334 expectedSources: []corev1.ObjectReference{{
335 Kind: testPodWithOneContainers().Kind,
336 APIVersion: testPodWithOneContainers().APIVersion,
337 Name: testPodWithOneContainers().Name,
338 Namespace: testPodWithOneContainers().Namespace,
339 FieldPath: fmt.Sprintf("spec.containers{%s}", testPodWithOneContainers().Spec.Containers[0].Name),
340 }},
341 },
342 {
343 name: "job logs",
344 obj: &batchv1.Job{
345 ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"},
346 Spec: batchv1.JobSpec{
347 Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
348 },
349 },
350 clientsetPods: []runtime.Object{testPodWithOneContainers()},
351 actions: []testclient.Action{
352 testclient.NewListAction(podsResource, podsKind, "test", metav1.ListOptions{LabelSelector: "foo=bar"}),
353 getLogsAction("test", &corev1.PodLogOptions{Container: "c1"}),
354 },
355 expectedSources: []corev1.ObjectReference{{
356 Kind: testPodWithOneContainers().Kind,
357 APIVersion: testPodWithOneContainers().APIVersion,
358 Name: testPodWithOneContainers().Name,
359 Namespace: testPodWithOneContainers().Namespace,
360 FieldPath: fmt.Sprintf("spec.containers{%s}", testPodWithOneContainers().Spec.Containers[0].Name),
361 }},
362 },
363 {
364 name: "stateful set logs",
365 obj: &appsv1.StatefulSet{
366 ObjectMeta: metav1.ObjectMeta{Name: "hello", Namespace: "test"},
367 Spec: appsv1.StatefulSetSpec{
368 Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
369 },
370 },
371 clientsetPods: []runtime.Object{testPodWithOneContainers()},
372 actions: []testclient.Action{
373 testclient.NewListAction(podsResource, podsKind, "test", metav1.ListOptions{LabelSelector: "foo=bar"}),
374 getLogsAction("test", &corev1.PodLogOptions{Container: "c1"}),
375 },
376 expectedSources: []corev1.ObjectReference{{
377 Kind: testPodWithOneContainers().Kind,
378 APIVersion: testPodWithOneContainers().APIVersion,
379 Name: testPodWithOneContainers().Name,
380 Namespace: testPodWithOneContainers().Namespace,
381 FieldPath: fmt.Sprintf("spec.containers{%s}", testPodWithOneContainers().Spec.Containers[0].Name),
382 }},
383 },
384 }
385
386 for _, test := range tests {
387 fakeClientset := fakeexternal.NewSimpleClientset(test.clientsetPods...)
388 responses, err := logsForObjectWithClient(fakeClientset.CoreV1(), test.obj, test.opts, 20*time.Second, test.allContainers)
389 if test.expectedErr == "" && err != nil {
390 t.Errorf("%s: unexpected error: %v", test.name, err)
391 continue
392 }
393
394 if err != nil && test.expectedErr != err.Error() {
395 t.Errorf("%s: expected error: %v, got: %v", test.name, test.expectedErr, err)
396 continue
397 }
398
399 if len(test.expectedSources) != len(responses) {
400 t.Errorf(
401 "%s: the number of expected sources doesn't match the number of responses: %v, got: %v",
402 test.name,
403 len(test.expectedSources),
404 len(responses),
405 )
406 continue
407 }
408
409 for _, ref := range test.expectedSources {
410 if _, ok := responses[ref]; !ok {
411 t.Errorf("%s: didn't find expected log source object reference: %#v", test.name, ref)
412 }
413 }
414
415 var i int
416 for i = range test.actions {
417 if len(fakeClientset.Actions()) < i {
418 t.Errorf("%s: expected action %d does not exists in actual actions: %#v",
419 test.name, i, fakeClientset.Actions())
420 continue
421 }
422 got := fakeClientset.Actions()[i]
423 want := test.actions[i]
424 if !reflect.DeepEqual(got, want) {
425 t.Errorf("%s: unexpected diff for action: %s", test.name, cmp.Diff(got, want))
426 }
427 }
428 for i++; i < len(fakeClientset.Actions()); i++ {
429 t.Errorf("%s: actual action %d does not exist in expected: %v", test.name, i, fakeClientset.Actions()[i])
430 }
431 }
432 }
433
434 func testPodWithOneContainers() *corev1.Pod {
435 return &corev1.Pod{
436 TypeMeta: metav1.TypeMeta{
437 Kind: "pod",
438 APIVersion: "v1",
439 },
440 ObjectMeta: metav1.ObjectMeta{
441 Name: "foo",
442 Namespace: "test",
443 Labels: map[string]string{"foo": "bar"},
444 },
445 Spec: corev1.PodSpec{
446 RestartPolicy: corev1.RestartPolicyAlways,
447 DNSPolicy: corev1.DNSClusterFirst,
448 Containers: []corev1.Container{
449 {Name: "c1"},
450 },
451 },
452 }
453 }
454
455 func testPodWithTwoContainers() *corev1.Pod {
456 return &corev1.Pod{
457 TypeMeta: metav1.TypeMeta{
458 Kind: "pod",
459 APIVersion: "v1",
460 },
461 ObjectMeta: metav1.ObjectMeta{
462 Name: "foo-two-containers",
463 Namespace: "test",
464 Labels: map[string]string{"foo": "bar"},
465 },
466 Spec: corev1.PodSpec{
467 RestartPolicy: corev1.RestartPolicyAlways,
468 DNSPolicy: corev1.DNSClusterFirst,
469 Containers: []corev1.Container{
470 {Name: "foo-2-c1"},
471 {Name: "foo-2-c2"},
472 },
473 },
474 }
475 }
476
477 func testPodWithTwoContainersAndTwoInitContainers() *corev1.Pod {
478 return &corev1.Pod{
479 TypeMeta: metav1.TypeMeta{
480 Kind: "pod",
481 APIVersion: "v1",
482 },
483 ObjectMeta: metav1.ObjectMeta{
484 Name: "foo-two-containers-and-two-init-containers",
485 Namespace: "test",
486 },
487 Spec: corev1.PodSpec{
488 InitContainers: []corev1.Container{
489 {Name: "foo-2-and-2-initc1"},
490 {Name: "foo-2-and-2-initc2"},
491 },
492 Containers: []corev1.Container{
493 {Name: "foo-2-and-2-c1"},
494 {Name: "foo-2-and-2-c2"},
495 },
496 },
497 }
498 }
499
500 func TestLogsForObjectWithClient(t *testing.T) {
501 cases := []struct {
502 name string
503 podFn func() *corev1.Pod
504 podLogOptions *corev1.PodLogOptions
505 expectedFieldPath string
506 allContainers bool
507 expectedError string
508 }{
509 {
510 name: "two container pod without default container selected should default to the first one",
511 podFn: testPodWithTwoContainers,
512 podLogOptions: &corev1.PodLogOptions{},
513 expectedFieldPath: `spec.containers{foo-2-c1}`,
514 },
515 {
516 name: "two container pod with default container selected",
517 podFn: func() *corev1.Pod {
518 pod := testPodWithTwoContainers()
519 pod.Annotations = map[string]string{podcmd.DefaultContainerAnnotationName: "foo-2-c1"}
520 return pod
521 },
522 podLogOptions: &corev1.PodLogOptions{},
523 expectedFieldPath: `spec.containers{foo-2-c1}`,
524 },
525 {
526 name: "two container pod with default container selected but also container set explicitly",
527 podFn: func() *corev1.Pod {
528 pod := testPodWithTwoContainers()
529 pod.Annotations = map[string]string{podcmd.DefaultContainerAnnotationName: "foo-2-c1"}
530 return pod
531 },
532 podLogOptions: &corev1.PodLogOptions{
533 Container: "foo-2-c2",
534 },
535 expectedFieldPath: `spec.containers{foo-2-c2}`,
536 },
537 {
538 name: "two container pod with non-existing default container selected should default to the first container",
539 podFn: func() *corev1.Pod {
540 pod := testPodWithTwoContainers()
541 pod.Annotations = map[string]string{podcmd.DefaultContainerAnnotationName: "non-existing"}
542 return pod
543 },
544 podLogOptions: &corev1.PodLogOptions{},
545 expectedFieldPath: `spec.containers{foo-2-c1}`,
546 },
547 {
548 name: "two container pod with default container set, but allContainers also set",
549 podFn: func() *corev1.Pod {
550 pod := testPodWithTwoContainers()
551 pod.Annotations = map[string]string{podcmd.DefaultContainerAnnotationName: "foo-2-c1"}
552 return pod
553 },
554 allContainers: true,
555 podLogOptions: &corev1.PodLogOptions{},
556 expectedFieldPath: `spec.containers{foo-2-c2}`,
557 },
558 }
559
560 for _, tc := range cases {
561 t.Run(tc.name, func(t *testing.T) {
562 pod := tc.podFn()
563 fakeClientset := fakeexternal.NewSimpleClientset(pod)
564 responses, err := logsForObjectWithClient(fakeClientset.CoreV1(), pod, tc.podLogOptions, 20*time.Second, tc.allContainers)
565 if err != nil {
566 if len(tc.expectedError) > 0 {
567 if err.Error() == tc.expectedError {
568 return
569 }
570 }
571 t.Errorf("unexpected error: %v", err)
572 return
573 }
574 if len(tc.expectedError) > 0 {
575 t.Errorf("expected error %q, got none", tc.expectedError)
576 return
577 }
578 if !tc.allContainers && len(responses) != 1 {
579 t.Errorf("expected one response, got %d", len(responses))
580 return
581 }
582 if tc.allContainers && len(responses) != 2 {
583 t.Errorf("expected 2 responses for allContainers, got %d", len(responses))
584 return
585 }
586
587
588 if tc.allContainers {
589 return
590 }
591 for r := range responses {
592 if r.FieldPath != tc.expectedFieldPath {
593 t.Errorf("expected %q container to be preselected, got %q", tc.expectedFieldPath, r.FieldPath)
594 }
595 }
596 })
597 }
598
599 }
600
601 func testPodWithTwoContainersAndTwoInitAndOneEphemeralContainers() *corev1.Pod {
602 return &corev1.Pod{
603 TypeMeta: metav1.TypeMeta{
604 Kind: "pod",
605 APIVersion: "v1",
606 },
607 ObjectMeta: metav1.ObjectMeta{
608 Name: "foo-two-containers-and-two-init-containers",
609 Namespace: "test",
610 },
611 Spec: corev1.PodSpec{
612 InitContainers: []corev1.Container{
613 {Name: "foo-2-and-2-and-1-initc1"},
614 {Name: "foo-2-and-2-and-1-initc2"},
615 },
616 Containers: []corev1.Container{
617 {Name: "foo-2-and-2-and-1-c1"},
618 {Name: "foo-2-and-2-and-1-c2"},
619 },
620 EphemeralContainers: []corev1.EphemeralContainer{
621 {
622 EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "foo-2-and-2-and-1-e1"},
623 },
624 },
625 },
626 }
627 }
628
629 func getLogsAction(namespace string, opts *corev1.PodLogOptions) testclient.Action {
630 action := testclient.GenericActionImpl{}
631 action.Verb = "get"
632 action.Namespace = namespace
633 action.Resource = podsResource
634 action.Subresource = "log"
635 action.Value = opts
636 return action
637 }
638
View as plain text