1
16
17 package set
18
19 import (
20 "fmt"
21 "io"
22 "net/http"
23 "strings"
24 "testing"
25
26 "github.com/stretchr/testify/assert"
27
28 appsv1 "k8s.io/api/apps/v1"
29 appsv1beta1 "k8s.io/api/apps/v1beta1"
30 appsv1beta2 "k8s.io/api/apps/v1beta2"
31 batchv1 "k8s.io/api/batch/v1"
32 corev1 "k8s.io/api/core/v1"
33 extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
34 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
35 "k8s.io/apimachinery/pkg/runtime"
36 "k8s.io/apimachinery/pkg/runtime/schema"
37 "k8s.io/cli-runtime/pkg/genericclioptions"
38 "k8s.io/cli-runtime/pkg/genericiooptions"
39 "k8s.io/cli-runtime/pkg/resource"
40 restclient "k8s.io/client-go/rest"
41 "k8s.io/client-go/rest/fake"
42 cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
43 "k8s.io/kubectl/pkg/scheme"
44 )
45
46 func TestImageLocal(t *testing.T) {
47 tf := cmdtesting.NewTestFactory().WithNamespace("test")
48 defer tf.Cleanup()
49
50 tf.Client = &fake.RESTClient{
51 GroupVersion: schema.GroupVersion{Version: ""},
52 NegotiatedSerializer: scheme.Codecs.WithoutConversion(),
53 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
54 t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req)
55 return nil, nil
56 }),
57 }
58 tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}}
59
60 outputFormat := "name"
61
62 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
63 cmd := NewCmdImage(tf, streams)
64 cmd.SetOut(buf)
65 cmd.SetErr(buf)
66 cmd.Flags().Set("output", outputFormat)
67 cmd.Flags().Set("local", "true")
68
69 opts := SetImageOptions{
70 PrintFlags: genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme),
71 FilenameOptions: resource.FilenameOptions{
72 Filenames: []string{"../../../testdata/controller.yaml"}},
73 Local: true,
74 IOStreams: streams,
75 }
76 err := opts.Complete(tf, cmd, []string{"cassandra=thingy"})
77 if err == nil {
78 err = opts.Validate()
79 }
80 if err == nil {
81 err = opts.Run()
82 }
83 if err != nil {
84 t.Fatalf("unexpected error: %v", err)
85 }
86 if !strings.Contains(buf.String(), "replicationcontroller/cassandra") {
87 t.Errorf("did not set image: %s", buf.String())
88 }
89 }
90
91 func TestSetImageValidation(t *testing.T) {
92 printFlags := genericclioptions.NewPrintFlags("").WithTypeSetter(scheme.Scheme)
93
94 testCases := []struct {
95 name string
96 imageOptions *SetImageOptions
97 expectErr string
98 }{
99 {
100 name: "test resource < 1 and filenames empty",
101 imageOptions: &SetImageOptions{PrintFlags: printFlags},
102 expectErr: "[one or more resources must be specified as <resource> <name> or <resource>/<name>, at least one image update is required]",
103 },
104 {
105 name: "test containerImages < 1",
106 imageOptions: &SetImageOptions{
107 PrintFlags: printFlags,
108 Resources: []string{"a", "b", "c"},
109
110 FilenameOptions: resource.FilenameOptions{
111 Filenames: []string{"testFile"},
112 },
113 },
114 expectErr: "at least one image update is required",
115 },
116 {
117 name: "test containerImages > 1 and all containers are already specified by *",
118 imageOptions: &SetImageOptions{
119 PrintFlags: printFlags,
120 Resources: []string{"a", "b", "c"},
121 FilenameOptions: resource.FilenameOptions{
122 Filenames: []string{"testFile"},
123 },
124 ContainerImages: map[string]string{
125 "test": "test",
126 "*": "test",
127 },
128 },
129 expectErr: "all containers are already specified by *, but saw more than one container_name=container_image pairs",
130 },
131 {
132 name: "success case",
133 imageOptions: &SetImageOptions{
134 PrintFlags: printFlags,
135 Resources: []string{"a", "b", "c"},
136 FilenameOptions: resource.FilenameOptions{
137 Filenames: []string{"testFile"},
138 },
139 ContainerImages: map[string]string{
140 "test": "test",
141 },
142 },
143 expectErr: "",
144 },
145 }
146 for _, testCase := range testCases {
147 err := testCase.imageOptions.Validate()
148 if err != nil {
149 if err.Error() != testCase.expectErr {
150 t.Errorf("[%s]:expect err:%s got err:%s", testCase.name, testCase.expectErr, err.Error())
151 }
152 }
153 if err == nil && (testCase.expectErr != "") {
154 t.Errorf("[%s]:expect err:%s got err:%v", testCase.name, testCase.expectErr, err)
155 }
156 }
157 }
158
159 func TestSetMultiResourcesImageLocal(t *testing.T) {
160 tf := cmdtesting.NewTestFactory().WithNamespace("test")
161 defer tf.Cleanup()
162
163 tf.Client = &fake.RESTClient{
164 GroupVersion: schema.GroupVersion{Version: ""},
165 NegotiatedSerializer: scheme.Codecs.WithoutConversion(),
166 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
167 t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req)
168 return nil, nil
169 }),
170 }
171 tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}}
172
173 outputFormat := "name"
174
175 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
176 cmd := NewCmdImage(tf, streams)
177 cmd.SetOut(buf)
178 cmd.SetErr(buf)
179 cmd.Flags().Set("output", outputFormat)
180 cmd.Flags().Set("local", "true")
181
182 opts := SetImageOptions{
183 PrintFlags: genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme),
184 FilenameOptions: resource.FilenameOptions{
185 Filenames: []string{"../../../testdata/set/multi-resource-yaml.yaml"}},
186 Local: true,
187 IOStreams: streams,
188 }
189 err := opts.Complete(tf, cmd, []string{"*=thingy"})
190 if err == nil {
191 err = opts.Validate()
192 }
193 if err == nil {
194 err = opts.Run()
195 }
196 if err != nil {
197 t.Fatalf("unexpected error: %v", err)
198 }
199 expectedOut := "replicationcontroller/first-rc\nreplicationcontroller/second-rc\n"
200 if buf.String() != expectedOut {
201 t.Errorf("expected out:\n%s\nbut got:\n%s", expectedOut, buf.String())
202 }
203 }
204
205 func TestSetImageRemote(t *testing.T) {
206 inputs := []struct {
207 name string
208 object runtime.Object
209 groupVersion schema.GroupVersion
210 path string
211 args []string
212 }{
213 {
214 name: "set image extensionsv1beta1 ReplicaSet",
215 object: &extensionsv1beta1.ReplicaSet{
216 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
217 Spec: extensionsv1beta1.ReplicaSetSpec{
218 Template: corev1.PodTemplateSpec{
219 Spec: corev1.PodSpec{
220 Containers: []corev1.Container{
221 {
222 Name: "nginx",
223 Image: "nginx",
224 },
225 },
226 InitContainers: []corev1.Container{
227 {
228 Name: "busybox",
229 Image: "busybox",
230 },
231 },
232 },
233 },
234 },
235 },
236 groupVersion: extensionsv1beta1.SchemeGroupVersion,
237 path: "/namespaces/test/replicasets/nginx",
238 args: []string{"replicaset", "nginx", "*=thingy"},
239 },
240 {
241 name: "set image appsv1beta2 ReplicaSet",
242 object: &appsv1beta2.ReplicaSet{
243 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
244 Spec: appsv1beta2.ReplicaSetSpec{
245 Template: corev1.PodTemplateSpec{
246 Spec: corev1.PodSpec{
247 Containers: []corev1.Container{
248 {
249 Name: "nginx",
250 Image: "nginx",
251 },
252 },
253 InitContainers: []corev1.Container{
254 {
255 Name: "busybox",
256 Image: "busybox",
257 },
258 },
259 },
260 },
261 },
262 },
263 groupVersion: appsv1beta2.SchemeGroupVersion,
264 path: "/namespaces/test/replicasets/nginx",
265 args: []string{"replicaset", "nginx", "*=thingy"},
266 },
267 {
268 name: "set image appsv1 ReplicaSet",
269 object: &appsv1.ReplicaSet{
270 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
271 Spec: appsv1.ReplicaSetSpec{
272 Template: corev1.PodTemplateSpec{
273 Spec: corev1.PodSpec{
274 Containers: []corev1.Container{
275 {
276 Name: "nginx",
277 Image: "nginx",
278 },
279 },
280 InitContainers: []corev1.Container{
281 {
282 Name: "busybox",
283 Image: "busybox",
284 },
285 },
286 },
287 },
288 },
289 },
290 groupVersion: appsv1.SchemeGroupVersion,
291 path: "/namespaces/test/replicasets/nginx",
292 args: []string{"replicaset", "nginx", "*=thingy"},
293 },
294 {
295 name: "set image extensionsv1beta1 DaemonSet",
296 object: &extensionsv1beta1.DaemonSet{
297 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
298 Spec: extensionsv1beta1.DaemonSetSpec{
299 Template: corev1.PodTemplateSpec{
300 Spec: corev1.PodSpec{
301 Containers: []corev1.Container{
302 {
303 Name: "nginx",
304 Image: "nginx",
305 },
306 },
307 InitContainers: []corev1.Container{
308 {
309 Name: "busybox",
310 Image: "busybox",
311 },
312 },
313 },
314 },
315 },
316 },
317 groupVersion: extensionsv1beta1.SchemeGroupVersion,
318 path: "/namespaces/test/daemonsets/nginx",
319 args: []string{"daemonset", "nginx", "*=thingy"},
320 },
321 {
322 name: "set image appsv1beta2 DaemonSet",
323 object: &appsv1beta2.DaemonSet{
324 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
325 Spec: appsv1beta2.DaemonSetSpec{
326 Template: corev1.PodTemplateSpec{
327 Spec: corev1.PodSpec{
328 Containers: []corev1.Container{
329 {
330 Name: "nginx",
331 Image: "nginx",
332 },
333 },
334 InitContainers: []corev1.Container{
335 {
336 Name: "busybox",
337 Image: "busybox",
338 },
339 },
340 },
341 },
342 },
343 },
344 groupVersion: appsv1beta2.SchemeGroupVersion,
345 path: "/namespaces/test/daemonsets/nginx",
346 args: []string{"daemonset", "nginx", "*=thingy"},
347 },
348 {
349 name: "set image appsv1 DaemonSet",
350 object: &appsv1.DaemonSet{
351 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
352 Spec: appsv1.DaemonSetSpec{
353 Template: corev1.PodTemplateSpec{
354 Spec: corev1.PodSpec{
355 Containers: []corev1.Container{
356 {
357 Name: "nginx",
358 Image: "nginx",
359 },
360 },
361 InitContainers: []corev1.Container{
362 {
363 Name: "busybox",
364 Image: "busybox",
365 },
366 },
367 },
368 },
369 },
370 },
371 groupVersion: appsv1.SchemeGroupVersion,
372 path: "/namespaces/test/daemonsets/nginx",
373 args: []string{"daemonset", "nginx", "*=thingy"},
374 },
375 {
376 name: "set image extensionsv1beta1 Deployment",
377 object: &extensionsv1beta1.Deployment{
378 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
379 Spec: extensionsv1beta1.DeploymentSpec{
380 Template: corev1.PodTemplateSpec{
381 Spec: corev1.PodSpec{
382 Containers: []corev1.Container{
383 {
384 Name: "nginx",
385 Image: "nginx",
386 },
387 },
388 InitContainers: []corev1.Container{
389 {
390 Name: "busybox",
391 Image: "busybox",
392 },
393 },
394 },
395 },
396 },
397 },
398 groupVersion: extensionsv1beta1.SchemeGroupVersion,
399 path: "/namespaces/test/deployments/nginx",
400 args: []string{"deployment", "nginx", "*=thingy"},
401 },
402 {
403 name: "set image appsv1beta1 Deployment",
404 object: &appsv1beta1.Deployment{
405 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
406 Spec: appsv1beta1.DeploymentSpec{
407 Template: corev1.PodTemplateSpec{
408 Spec: corev1.PodSpec{
409 Containers: []corev1.Container{
410 {
411 Name: "nginx",
412 Image: "nginx",
413 },
414 },
415 InitContainers: []corev1.Container{
416 {
417 Name: "busybox",
418 Image: "busybox",
419 },
420 },
421 },
422 },
423 },
424 },
425 groupVersion: appsv1beta1.SchemeGroupVersion,
426 path: "/namespaces/test/deployments/nginx",
427 args: []string{"deployment", "nginx", "*=thingy"},
428 },
429 {
430 name: "set image appsv1beta2 Deployment",
431 object: &appsv1beta2.Deployment{
432 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
433 Spec: appsv1beta2.DeploymentSpec{
434 Template: corev1.PodTemplateSpec{
435 Spec: corev1.PodSpec{
436 Containers: []corev1.Container{
437 {
438 Name: "nginx",
439 Image: "nginx",
440 },
441 },
442 InitContainers: []corev1.Container{
443 {
444 Name: "busybox",
445 Image: "busybox",
446 },
447 },
448 },
449 },
450 },
451 },
452 groupVersion: appsv1beta2.SchemeGroupVersion,
453 path: "/namespaces/test/deployments/nginx",
454 args: []string{"deployment", "nginx", "*=thingy"},
455 },
456 {
457 name: "set image appsv1 Deployment",
458 object: &appsv1.Deployment{
459 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
460 Spec: appsv1.DeploymentSpec{
461 Template: corev1.PodTemplateSpec{
462 Spec: corev1.PodSpec{
463 Containers: []corev1.Container{
464 {
465 Name: "nginx",
466 Image: "nginx",
467 },
468 },
469 InitContainers: []corev1.Container{
470 {
471 Name: "busybox",
472 Image: "busybox",
473 },
474 },
475 },
476 },
477 },
478 },
479 groupVersion: appsv1.SchemeGroupVersion,
480 path: "/namespaces/test/deployments/nginx",
481 args: []string{"deployment", "nginx", "*=thingy"},
482 },
483 {
484 name: "set image appsv1beta1 StatefulSet",
485 object: &appsv1beta1.StatefulSet{
486 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
487 Spec: appsv1beta1.StatefulSetSpec{
488 Template: corev1.PodTemplateSpec{
489 Spec: corev1.PodSpec{
490 Containers: []corev1.Container{
491 {
492 Name: "nginx",
493 Image: "nginx",
494 },
495 },
496 InitContainers: []corev1.Container{
497 {
498 Name: "busybox",
499 Image: "busybox",
500 },
501 },
502 },
503 },
504 },
505 },
506 groupVersion: appsv1beta1.SchemeGroupVersion,
507 path: "/namespaces/test/statefulsets/nginx",
508 args: []string{"statefulset", "nginx", "*=thingy"},
509 },
510 {
511 name: "set image appsv1beta2 StatefulSet",
512 object: &appsv1beta2.StatefulSet{
513 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
514 Spec: appsv1beta2.StatefulSetSpec{
515 Template: corev1.PodTemplateSpec{
516 Spec: corev1.PodSpec{
517 Containers: []corev1.Container{
518 {
519 Name: "nginx",
520 Image: "nginx",
521 },
522 },
523 InitContainers: []corev1.Container{
524 {
525 Name: "busybox",
526 Image: "busybox",
527 },
528 },
529 },
530 },
531 },
532 },
533 groupVersion: appsv1beta2.SchemeGroupVersion,
534 path: "/namespaces/test/statefulsets/nginx",
535 args: []string{"statefulset", "nginx", "*=thingy"},
536 },
537 {
538 name: "set image appsv1 StatefulSet",
539 object: &appsv1.StatefulSet{
540 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
541 Spec: appsv1.StatefulSetSpec{
542 Template: corev1.PodTemplateSpec{
543 Spec: corev1.PodSpec{
544 Containers: []corev1.Container{
545 {
546 Name: "nginx",
547 Image: "nginx",
548 },
549 },
550 InitContainers: []corev1.Container{
551 {
552 Name: "busybox",
553 Image: "busybox",
554 },
555 },
556 },
557 },
558 },
559 },
560 groupVersion: appsv1.SchemeGroupVersion,
561 path: "/namespaces/test/statefulsets/nginx",
562 args: []string{"statefulset", "nginx", "*=thingy"},
563 },
564 {
565 name: "set image batchv1 CronJob",
566 object: &batchv1.CronJob{
567 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
568 Spec: batchv1.CronJobSpec{
569 JobTemplate: batchv1.JobTemplateSpec{
570 Spec: batchv1.JobSpec{
571 Template: corev1.PodTemplateSpec{
572 Spec: corev1.PodSpec{
573 Containers: []corev1.Container{
574 {
575 Name: "nginx",
576 Image: "nginx",
577 },
578 },
579 InitContainers: []corev1.Container{
580 {
581 Name: "busybox",
582 Image: "busybox",
583 },
584 },
585 },
586 },
587 },
588 },
589 },
590 },
591 groupVersion: batchv1.SchemeGroupVersion,
592 path: "/namespaces/test/cronjobs/nginx",
593 args: []string{"cronjob", "nginx", "*=thingy"},
594 },
595 {
596 name: "set image corev1.ReplicationController",
597 object: &corev1.ReplicationController{
598 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
599 Spec: corev1.ReplicationControllerSpec{
600 Template: &corev1.PodTemplateSpec{
601 Spec: corev1.PodSpec{
602 Containers: []corev1.Container{
603 {
604 Name: "nginx",
605 Image: "nginx",
606 },
607 },
608 InitContainers: []corev1.Container{
609 {
610 Name: "busybox",
611 Image: "busybox",
612 },
613 },
614 },
615 },
616 },
617 },
618 groupVersion: corev1.SchemeGroupVersion,
619 path: "/namespaces/test/replicationcontrollers/nginx",
620 args: []string{"replicationcontroller", "nginx", "*=thingy"},
621 },
622 }
623 for _, input := range inputs {
624 t.Run(input.name, func(t *testing.T) {
625 tf := cmdtesting.NewTestFactory().WithNamespace("test")
626 defer tf.Cleanup()
627
628 tf.Client = &fake.RESTClient{
629 GroupVersion: input.groupVersion,
630 NegotiatedSerializer: scheme.Codecs.WithoutConversion(),
631 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
632 switch p, m := req.URL.Path, req.Method; {
633 case p == input.path && m == http.MethodGet:
634 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(input.object)}, nil
635 case p == input.path && m == http.MethodPatch:
636 stream, err := req.GetBody()
637 if err != nil {
638 return nil, err
639 }
640 bytes, err := io.ReadAll(stream)
641 if err != nil {
642 return nil, err
643 }
644 assert.Contains(t, string(bytes), `"image":`+`"`+"thingy"+`"`, fmt.Sprintf("image not updated for %#v", input.object))
645 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(input.object)}, nil
646 default:
647 t.Errorf("%s: unexpected request: %s %#v\n%#v", "image", req.Method, req.URL, req)
648 return nil, fmt.Errorf("unexpected request")
649 }
650 }),
651 }
652
653 outputFormat := "yaml"
654
655 streams := genericiooptions.NewTestIOStreamsDiscard()
656 cmd := NewCmdImage(tf, streams)
657 cmd.Flags().Set("output", outputFormat)
658 opts := SetImageOptions{
659 PrintFlags: genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme),
660
661 Local: false,
662 IOStreams: streams,
663 }
664 err := opts.Complete(tf, cmd, input.args)
665 assert.NoError(t, err)
666 err = opts.Run()
667 assert.NoError(t, err)
668 })
669 }
670 }
671
672 func TestSetImageRemoteWithSpecificContainers(t *testing.T) {
673 inputs := []struct {
674 name string
675 object runtime.Object
676 groupVersion schema.GroupVersion
677 path string
678 args []string
679 }{
680 {
681 name: "set container image only",
682 object: &extensionsv1beta1.ReplicaSet{
683 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
684 Spec: extensionsv1beta1.ReplicaSetSpec{
685 Template: corev1.PodTemplateSpec{
686 Spec: corev1.PodSpec{
687 Containers: []corev1.Container{
688 {
689 Name: "nginx",
690 Image: "nginx",
691 },
692 },
693 InitContainers: []corev1.Container{
694 {
695 Name: "busybox",
696 Image: "busybox",
697 },
698 },
699 },
700 },
701 },
702 },
703 groupVersion: extensionsv1beta1.SchemeGroupVersion,
704 path: "/namespaces/test/replicasets/nginx",
705 args: []string{"replicaset", "nginx", "nginx=thingy"},
706 },
707 {
708 name: "set initContainer image only",
709 object: &appsv1beta2.ReplicaSet{
710 ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
711 Spec: appsv1beta2.ReplicaSetSpec{
712 Template: corev1.PodTemplateSpec{
713 Spec: corev1.PodSpec{
714 Containers: []corev1.Container{
715 {
716 Name: "busybox",
717 Image: "busybox",
718 },
719 },
720 InitContainers: []corev1.Container{
721 {
722 Name: "nginx",
723 Image: "nginx",
724 },
725 },
726 },
727 },
728 },
729 },
730 groupVersion: appsv1beta2.SchemeGroupVersion,
731 path: "/namespaces/test/replicasets/nginx",
732 args: []string{"replicaset", "nginx", "nginx=thingy"},
733 },
734 }
735 for _, input := range inputs {
736 t.Run(input.name, func(t *testing.T) {
737 tf := cmdtesting.NewTestFactory().WithNamespace("test")
738 defer tf.Cleanup()
739
740 tf.Client = &fake.RESTClient{
741 GroupVersion: input.groupVersion,
742 NegotiatedSerializer: scheme.Codecs.WithoutConversion(),
743 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
744 switch p, m := req.URL.Path, req.Method; {
745 case p == input.path && m == http.MethodGet:
746 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(input.object)}, nil
747 case p == input.path && m == http.MethodPatch:
748 stream, err := req.GetBody()
749 if err != nil {
750 return nil, err
751 }
752 bytes, err := io.ReadAll(stream)
753 if err != nil {
754 return nil, err
755 }
756 assert.Contains(t, string(bytes), `"image":"`+"thingy"+`","name":`+`"nginx"`, fmt.Sprintf("image not updated for %#v", input.object))
757 assert.NotContains(t, string(bytes), `"image":"`+"thingy"+`","name":`+`"busybox"`, fmt.Sprintf("image updated for %#v", input.object))
758 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: objBody(input.object)}, nil
759 default:
760 t.Errorf("%s: unexpected request: %s %#v\n%#v", "image", req.Method, req.URL, req)
761 return nil, fmt.Errorf("unexpected request")
762 }
763 }),
764 }
765
766 outputFormat := "yaml"
767
768 streams := genericiooptions.NewTestIOStreamsDiscard()
769 cmd := NewCmdImage(tf, streams)
770 cmd.Flags().Set("output", outputFormat)
771 opts := SetImageOptions{
772 PrintFlags: genericclioptions.NewPrintFlags("").WithDefaultOutput(outputFormat).WithTypeSetter(scheme.Scheme),
773
774 Local: false,
775 IOStreams: streams,
776 }
777 err := opts.Complete(tf, cmd, input.args)
778 assert.NoError(t, err)
779 err = opts.Run()
780 assert.NoError(t, err)
781 })
782 }
783 }
784
785 func TestSetImageResolver(t *testing.T) {
786 f := func(in string) (string, error) {
787 return "custom", nil
788 }
789
790 ImageResolver = f
791
792 out, err := ImageResolver("my-image")
793 if err != nil {
794 t.Errorf("unexpected error from ImageResolver: %v", err)
795 } else if out != "custom" {
796 t.Errorf("expected: %s, found: %s", "custom", out)
797 }
798 }
799
View as plain text