From 8d35f94d518fc099d18f6bbb790784dec1a654de Mon Sep 17 00:00:00 2001 From: juanvallejo Date: Thu, 8 Mar 2018 17:23:55 -0500 Subject: [PATCH] use temp kubeconfig for fake factory --- pkg/kubectl/cmd/annotate_test.go | 54 +- pkg/kubectl/cmd/apply_test.go | 998 +++++++++--------- pkg/kubectl/cmd/attach_test.go | 318 +++--- pkg/kubectl/cmd/auth/cani_test.go | 108 +- pkg/kubectl/cmd/clusterinfo_dump_test.go | 4 + pkg/kubectl/cmd/cmd_test.go | 14 + pkg/kubectl/cmd/convert_test.go | 2 + pkg/kubectl/cmd/create_clusterrole_test.go | 4 + .../cmd/create_clusterrolebinding_test.go | 2 + pkg/kubectl/cmd/create_configmap_test.go | 2 + pkg/kubectl/cmd/create_deployment_test.go | 4 + pkg/kubectl/cmd/create_job_test.go | 2 + pkg/kubectl/cmd/create_namespace_test.go | 2 + pkg/kubectl/cmd/create_pdb_test.go | 2 + pkg/kubectl/cmd/create_priorityclass_test.go | 2 + pkg/kubectl/cmd/create_quota_test.go | 2 + pkg/kubectl/cmd/create_role_test.go | 6 + pkg/kubectl/cmd/create_rolebinding_test.go | 2 + pkg/kubectl/cmd/create_secret_test.go | 2 + pkg/kubectl/cmd/create_service_test.go | 6 + pkg/kubectl/cmd/create_serviceaccount_test.go | 2 + pkg/kubectl/cmd/create_test.go | 8 + pkg/kubectl/cmd/delete_test.go | 68 +- pkg/kubectl/cmd/describe_test.go | 7 + pkg/kubectl/cmd/drain_test.go | 494 ++++----- pkg/kubectl/cmd/edit_test.go | 2 + pkg/kubectl/cmd/exec_test.go | 188 ++-- pkg/kubectl/cmd/expose_test.go | 70 +- pkg/kubectl/cmd/label_test.go | 58 +- pkg/kubectl/cmd/logs_test.go | 66 +- pkg/kubectl/cmd/patch_test.go | 8 + pkg/kubectl/cmd/plugin_test.go | 52 +- pkg/kubectl/cmd/portforward_test.go | 116 +- pkg/kubectl/cmd/replace_test.go | 4 + pkg/kubectl/cmd/resource/get_test.go | 25 + pkg/kubectl/cmd/rollingupdate_test.go | 1 + pkg/kubectl/cmd/run_test.go | 246 +++-- pkg/kubectl/cmd/set/set_env_test.go | 106 +- pkg/kubectl/cmd/set/set_image_test.go | 108 +- pkg/kubectl/cmd/set/set_resources_test.go | 3 + pkg/kubectl/cmd/set/set_selector_test.go | 2 + .../cmd/set/set_serviceaccount_test.go | 131 +-- pkg/kubectl/cmd/set/set_subject_test.go | 2 + pkg/kubectl/cmd/taint_test.go | 174 +-- pkg/kubectl/cmd/testing/BUILD | 2 + pkg/kubectl/cmd/testing/fake.go | 46 +- pkg/kubectl/cmd/top_node_test.go | 14 + pkg/kubectl/cmd/top_pod_test.go | 338 +++--- pkg/kubectl/cmd/top_test.go | 2 + 49 files changed, 2156 insertions(+), 1723 deletions(-) diff --git a/pkg/kubectl/cmd/annotate_test.go b/pkg/kubectl/cmd/annotate_test.go index 7c9bdc62781..409070e26cd 100644 --- a/pkg/kubectl/cmd/annotate_test.go +++ b/pkg/kubectl/cmd/annotate_test.go @@ -417,29 +417,33 @@ func TestAnnotateErrors(t *testing.T) { } for k, testCase := range testCases { - tf := cmdtesting.NewTestFactory() - tf.Namespace = "test" - tf.ClientConfigVal = defaultClientConfig() + t.Run(k, func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdAnnotate(tf, buf) - cmd.SetOutput(buf) + tf.Namespace = "test" + tf.ClientConfigVal = defaultClientConfig() - for k, v := range testCase.flags { - cmd.Flags().Set(k, v) - } - options := &AnnotateOptions{} - err := options.Complete(buf, cmd, testCase.args) - if err == nil { - err = options.Validate() - } - if !testCase.errFn(err) { - t.Errorf("%s: unexpected error: %v", k, err) - continue - } - if buf.Len() > 0 { - t.Errorf("buffer should be empty: %s", string(buf.Bytes())) - } + buf := bytes.NewBuffer([]byte{}) + cmd := NewCmdAnnotate(tf, buf) + cmd.SetOutput(buf) + + for k, v := range testCase.flags { + cmd.Flags().Set(k, v) + } + options := &AnnotateOptions{} + err := options.Complete(buf, cmd, testCase.args) + if err == nil { + err = options.Validate() + } + if !testCase.errFn(err) { + t.Errorf("%s: unexpected error: %v", k, err) + return + } + if buf.Len() > 0 { + t.Errorf("buffer should be empty: %s", string(buf.Bytes())) + } + }) } } @@ -447,6 +451,8 @@ func TestAnnotateObject(t *testing.T) { pods, _, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -499,6 +505,8 @@ func TestAnnotateObjectFromFile(t *testing.T) { pods, _, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -550,6 +558,8 @@ func TestAnnotateObjectFromFile(t *testing.T) { func TestAnnotateLocal(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.UnstructuredClient = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Group: "testgroup", Version: "v1"}, NegotiatedSerializer: unstructuredSerializer, @@ -581,6 +591,8 @@ func TestAnnotateMultipleObjects(t *testing.T) { pods, _, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Group: "testgroup", Version: "v1"}, diff --git a/pkg/kubectl/cmd/apply_test.go b/pkg/kubectl/cmd/apply_test.go index 5397f8dc27f..aa4919769a3 100644 --- a/pkg/kubectl/cmd/apply_test.go +++ b/pkg/kubectl/cmd/apply_test.go @@ -69,6 +69,8 @@ func TestApplyExtraArgsFail(t *testing.T) { errBuf := bytes.NewBuffer([]byte{}) f := cmdtesting.NewTestFactory() + defer f.Cleanup() + c := NewCmdApply("kubectl", f, buf, errBuf) if validateApplyArgs(c, []string{"rc"}) == nil { t.Fatalf("unexpected non-error") @@ -332,55 +334,59 @@ func TestRunApplyViewLastApplied(t *testing.T) { }, } for _, test := range tests { - tf := cmdtesting.NewTestFactory() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + t.Run(test.name, func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - tf.UnstructuredClient = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Version: "v1"}, - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == pathRC && m == "GET": - bodyRC := ioutil.NopCloser(bytes.NewReader(test.respBytes)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil - case p == "/namespaces/test/replicationcontrollers" && m == "GET": - bodyRC := ioutil.NopCloser(bytes.NewReader(test.respBytes)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil - case p == "/namespaces/test/replicationcontrollers/no-match" && m == "GET": - return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: objBody(codec, &api.Pod{})}, nil - case p == "/api/v1/namespaces/test" && m == "GET": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &api.Namespace{})}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + + tf.UnstructuredClient = &fake.RESTClient{ + GroupVersion: schema.GroupVersion{Version: "v1"}, + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == pathRC && m == "GET": + bodyRC := ioutil.NopCloser(bytes.NewReader(test.respBytes)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil + case p == "/namespaces/test/replicationcontrollers" && m == "GET": + bodyRC := ioutil.NopCloser(bytes.NewReader(test.respBytes)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil + case p == "/namespaces/test/replicationcontrollers/no-match" && m == "GET": + return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: objBody(codec, &api.Pod{})}, nil + case p == "/api/v1/namespaces/test" && m == "GET": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &api.Namespace{})}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil + } + }), + } + tf.Namespace = "test" + tf.ClientConfigVal = defaultClientConfig() + buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) + + cmdutil.BehaviorOnFatal(func(str string, code int) { + if str != test.expectedErr { + t.Errorf("%s: unexpected error: %s\nexpected: %s", test.name, str, test.expectedErr) } - }), - } - tf.Namespace = "test" - tf.ClientConfigVal = defaultClientConfig() - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) + }) - cmdutil.BehaviorOnFatal(func(str string, code int) { - if str != test.expectedErr { - t.Errorf("%s: unexpected error: %s\nexpected: %s", test.name, str, test.expectedErr) + cmd := NewCmdApplyViewLastApplied(tf, buf, errBuf) + if test.filePath != "" { + cmd.Flags().Set("filename", test.filePath) + } + if test.outputFormat != "" { + cmd.Flags().Set("output", test.outputFormat) + } + if test.selector != "" { + cmd.Flags().Set("selector", test.selector) + } + + cmd.Run(cmd, test.args) + if buf.String() != test.expectedOut { + t.Fatalf("%s: unexpected output: %s\nexpected: %s", test.name, buf.String(), test.expectedOut) } }) - - cmd := NewCmdApplyViewLastApplied(tf, buf, errBuf) - if test.filePath != "" { - cmd.Flags().Set("filename", test.filePath) - } - if test.outputFormat != "" { - cmd.Flags().Set("output", test.outputFormat) - } - if test.selector != "" { - cmd.Flags().Set("selector", test.selector) - } - - cmd.Run(cmd, test.args) - if buf.String() != test.expectedOut { - t.Fatalf("%s: unexpected output: %s\nexpected: %s", test.name, buf.String(), test.expectedOut) - } } } @@ -390,6 +396,8 @@ func TestApplyObjectWithoutAnnotation(t *testing.T) { pathRC := "/namespaces/test/replicationcontrollers/" + nameRC tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { @@ -433,42 +441,46 @@ func TestApplyObject(t *testing.T) { pathRC := "/namespaces/test/replicationcontrollers/" + nameRC for _, fn := range testingOpenAPISchemaFns { - tf := cmdtesting.NewTestFactory() - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == pathRC && m == "GET": - bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil - case p == pathRC && m == "PATCH": - validatePatchApplication(t, req) - bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + t.Run("test apply when a local object is specified", func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - cmd := NewCmdApply("kubectl", tf, buf, errBuf) - cmd.Flags().Set("filename", filenameRC) - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == pathRC && m == "GET": + bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil + case p == pathRC && m == "PATCH": + validatePatchApplication(t, req) + bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil + } + }), + } + tf.OpenAPISchemaFunc = fn + tf.Namespace = "test" + buf := bytes.NewBuffer([]byte{}) + errBuf := bytes.NewBuffer([]byte{}) - // uses the name from the file, not the response - expectRC := "replicationcontroller/" + nameRC + "\n" - if buf.String() != expectRC { - t.Fatalf("unexpected output: %s\nexpected: %s", buf.String(), expectRC) - } - if errBuf.String() != "" { - t.Fatalf("unexpected error output: %s", errBuf.String()) - } + cmd := NewCmdApply("kubectl", tf, buf, errBuf) + cmd.Flags().Set("filename", filenameRC) + cmd.Flags().Set("output", "name") + cmd.Run(cmd, []string{}) + + // uses the name from the file, not the response + expectRC := "replicationcontroller/" + nameRC + "\n" + if buf.String() != expectRC { + t.Fatalf("unexpected output: %s\nexpected: %s", buf.String(), expectRC) + } + if errBuf.String() != "" { + t.Fatalf("unexpected error output: %s", errBuf.String()) + } + }) } } @@ -494,43 +506,47 @@ func TestApplyObjectOutput(t *testing.T) { } for _, fn := range testingOpenAPISchemaFns { - tf := cmdtesting.NewTestFactory() - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == pathRC && m == "GET": - bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil - case p == pathRC && m == "PATCH": - validatePatchApplication(t, req) - bodyRC := ioutil.NopCloser(bytes.NewReader(postPatchData)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + t.Run("test apply returns correct output", func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - cmd := NewCmdApply("kubectl", tf, buf, errBuf) - cmd.Flags().Set("filename", filenameRC) - cmd.Flags().Set("output", "yaml") - cmd.Run(cmd, []string{}) + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == pathRC && m == "GET": + bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil + case p == pathRC && m == "PATCH": + validatePatchApplication(t, req) + bodyRC := ioutil.NopCloser(bytes.NewReader(postPatchData)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil + } + }), + } + tf.OpenAPISchemaFunc = fn + tf.Namespace = "test" + buf := bytes.NewBuffer([]byte{}) + errBuf := bytes.NewBuffer([]byte{}) - if !strings.Contains(buf.String(), "test-rc") { - t.Fatalf("unexpected output: %s\nexpected to contain: %s", buf.String(), "test-rc") - } - if !strings.Contains(buf.String(), "post-patch: value") { - t.Fatalf("unexpected output: %s\nexpected to contain: %s", buf.String(), "post-patch: value") - } - if errBuf.String() != "" { - t.Fatalf("unexpected error output: %s", errBuf.String()) - } + cmd := NewCmdApply("kubectl", tf, buf, errBuf) + cmd.Flags().Set("filename", filenameRC) + cmd.Flags().Set("output", "yaml") + cmd.Run(cmd, []string{}) + + if !strings.Contains(buf.String(), "test-rc") { + t.Fatalf("unexpected output: %s\nexpected to contain: %s", buf.String(), "test-rc") + } + if !strings.Contains(buf.String(), "post-patch: value") { + t.Fatalf("unexpected output: %s\nexpected to contain: %s", buf.String(), "post-patch: value") + } + if errBuf.String() != "" { + t.Fatalf("unexpected error output: %s", errBuf.String()) + } + }) } } @@ -540,58 +556,62 @@ func TestApplyRetry(t *testing.T) { pathRC := "/namespaces/test/replicationcontrollers/" + nameRC for _, fn := range testingOpenAPISchemaFns { - firstPatch := true - retry := false - getCount := 0 - tf := cmdtesting.NewTestFactory() - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == pathRC && m == "GET": - getCount++ - bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil - case p == pathRC && m == "PATCH": - if firstPatch { - firstPatch = false - statusErr := kubeerr.NewConflict(schema.GroupResource{Group: "", Resource: "rc"}, "test-rc", fmt.Errorf("the object has been modified. Please apply at first.")) - bodyBytes, _ := json.Marshal(statusErr) - bodyErr := ioutil.NopCloser(bytes.NewReader(bodyBytes)) - return &http.Response{StatusCode: http.StatusConflict, Header: defaultHeader(), Body: bodyErr}, nil + t.Run("test apply retries on conflict error", func(t *testing.T) { + firstPatch := true + retry := false + getCount := 0 + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == pathRC && m == "GET": + getCount++ + bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil + case p == pathRC && m == "PATCH": + if firstPatch { + firstPatch = false + statusErr := kubeerr.NewConflict(schema.GroupResource{Group: "", Resource: "rc"}, "test-rc", fmt.Errorf("the object has been modified. Please apply at first.")) + bodyBytes, _ := json.Marshal(statusErr) + bodyErr := ioutil.NopCloser(bytes.NewReader(bodyBytes)) + return &http.Response{StatusCode: http.StatusConflict, Header: defaultHeader(), Body: bodyErr}, nil + } + retry = true + validatePatchApplication(t, req) + bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil } - retry = true - validatePatchApplication(t, req) - bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + }), + } + tf.OpenAPISchemaFunc = fn + tf.Namespace = "test" + buf := bytes.NewBuffer([]byte{}) + errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdApply("kubectl", tf, buf, errBuf) - cmd.Flags().Set("filename", filenameRC) - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) + cmd := NewCmdApply("kubectl", tf, buf, errBuf) + cmd.Flags().Set("filename", filenameRC) + cmd.Flags().Set("output", "name") + cmd.Run(cmd, []string{}) - if !retry || getCount != 2 { - t.Fatalf("apply didn't retry when get conflict error") - } + if !retry || getCount != 2 { + t.Fatalf("apply didn't retry when get conflict error") + } - // uses the name from the file, not the response - expectRC := "replicationcontroller/" + nameRC + "\n" - if buf.String() != expectRC { - t.Fatalf("unexpected output: %s\nexpected: %s", buf.String(), expectRC) - } - if errBuf.String() != "" { - t.Fatalf("unexpected error output: %s", errBuf.String()) - } + // uses the name from the file, not the response + expectRC := "replicationcontroller/" + nameRC + "\n" + if buf.String() != expectRC { + t.Fatalf("unexpected output: %s\nexpected: %s", buf.String(), expectRC) + } + if errBuf.String() != "" { + t.Fatalf("unexpected error output: %s", errBuf.String()) + } + }) } } @@ -601,6 +621,8 @@ func TestApplyNonExistObject(t *testing.T) { pathNameRC := pathRC + "/" + nameRC tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { @@ -645,6 +667,8 @@ func TestApplyEmptyPatch(t *testing.T) { var body []byte tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.UnstructuredClient = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Version: "v1"}, NegotiatedSerializer: unstructuredSerializer, @@ -718,59 +742,63 @@ func testApplyMultipleObjects(t *testing.T, asList bool) { pathSVC := "/namespaces/test/services/" + nameSVC for _, fn := range testingOpenAPISchemaFns { - tf := cmdtesting.NewTestFactory() - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == pathRC && m == "GET": - bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil - case p == pathRC && m == "PATCH": - validatePatchApplication(t, req) - bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil - case p == pathSVC && m == "GET": - bodySVC := ioutil.NopCloser(bytes.NewReader(currentSVC)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodySVC}, nil - case p == pathSVC && m == "PATCH": - validatePatchApplication(t, req) - bodySVC := ioutil.NopCloser(bytes.NewReader(currentSVC)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodySVC}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + t.Run("test apply on multiple objects", func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - cmd := NewCmdApply("kubectl", tf, buf, errBuf) - if asList { - cmd.Flags().Set("filename", filenameRCSVC) - } else { - cmd.Flags().Set("filename", filenameRC) - cmd.Flags().Set("filename", filenameSVC) - } - cmd.Flags().Set("output", "name") + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == pathRC && m == "GET": + bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil + case p == pathRC && m == "PATCH": + validatePatchApplication(t, req) + bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil + case p == pathSVC && m == "GET": + bodySVC := ioutil.NopCloser(bytes.NewReader(currentSVC)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodySVC}, nil + case p == pathSVC && m == "PATCH": + validatePatchApplication(t, req) + bodySVC := ioutil.NopCloser(bytes.NewReader(currentSVC)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodySVC}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil + } + }), + } + tf.OpenAPISchemaFunc = fn + tf.Namespace = "test" + buf := bytes.NewBuffer([]byte{}) + errBuf := bytes.NewBuffer([]byte{}) - cmd.Run(cmd, []string{}) + cmd := NewCmdApply("kubectl", tf, buf, errBuf) + if asList { + cmd.Flags().Set("filename", filenameRCSVC) + } else { + cmd.Flags().Set("filename", filenameRC) + cmd.Flags().Set("filename", filenameSVC) + } + cmd.Flags().Set("output", "name") - // Names should come from the REST response, NOT the files - expectRC := "replicationcontroller/" + nameRC + "\n" - expectSVC := "service/" + nameSVC + "\n" - // Test both possible orders since output is non-deterministic. - expectOne := expectRC + expectSVC - expectTwo := expectSVC + expectRC - if buf.String() != expectOne && buf.String() != expectTwo { - t.Fatalf("unexpected output: %s\nexpected: %s OR %s", buf.String(), expectOne, expectTwo) - } - if errBuf.String() != "" { - t.Fatalf("unexpected error output: %s", errBuf.String()) - } + cmd.Run(cmd, []string{}) + + // Names should come from the REST response, NOT the files + expectRC := "replicationcontroller/" + nameRC + "\n" + expectSVC := "service/" + nameSVC + "\n" + // Test both possible orders since output is non-deterministic. + expectOne := expectRC + expectSVC + expectTwo := expectSVC + expectRC + if buf.String() != expectOne && buf.String() != expectTwo { + t.Fatalf("unexpected output: %s\nexpected: %s OR %s", buf.String(), expectOne, expectTwo) + } + if errBuf.String() != "" { + t.Fatalf("unexpected error output: %s", errBuf.String()) + } + }) } } @@ -801,66 +829,70 @@ func TestApplyNULLPreservation(t *testing.T) { deploymentBytes := readDeploymentFromFile(t, filenameDeployObjServerside) for _, fn := range testingOpenAPISchemaFns { - tf := cmdtesting.NewTestFactory() - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == deploymentPath && m == "GET": - body := ioutil.NopCloser(bytes.NewReader(deploymentBytes)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil - case p == deploymentPath && m == "PATCH": - patch, err := ioutil.ReadAll(req.Body) - if err != nil { - t.Fatal(err) + t.Run("test apply preserves NULL fields", func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == deploymentPath && m == "GET": + body := ioutil.NopCloser(bytes.NewReader(deploymentBytes)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil + case p == deploymentPath && m == "PATCH": + patch, err := ioutil.ReadAll(req.Body) + if err != nil { + t.Fatal(err) + } + + patchMap := map[string]interface{}{} + if err := json.Unmarshal(patch, &patchMap); err != nil { + t.Fatal(err) + } + annotationMap := walkMapPath(t, patchMap, []string{"metadata", "annotations"}) + if _, ok := annotationMap[api.LastAppliedConfigAnnotation]; !ok { + t.Fatalf("patch does not contain annotation:\n%s\n", patch) + } + strategy := walkMapPath(t, patchMap, []string{"spec", "strategy"}) + if value, ok := strategy["rollingUpdate"]; !ok || value != nil { + t.Fatalf("patch did not retain null value in key: rollingUpdate:\n%s\n", patch) + } + verifiedPatch = true + + // The real API server would had returned the patched object but Kubectl + // is ignoring the actual return object. + // TODO: Make this match actual server behavior by returning the patched object. + body := ioutil.NopCloser(bytes.NewReader(deploymentBytes)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil } + }), + } + tf.OpenAPISchemaFunc = fn + tf.Namespace = "test" + buf := bytes.NewBuffer([]byte{}) + errBuf := bytes.NewBuffer([]byte{}) - patchMap := map[string]interface{}{} - if err := json.Unmarshal(patch, &patchMap); err != nil { - t.Fatal(err) - } - annotationMap := walkMapPath(t, patchMap, []string{"metadata", "annotations"}) - if _, ok := annotationMap[api.LastAppliedConfigAnnotation]; !ok { - t.Fatalf("patch does not contain annotation:\n%s\n", patch) - } - strategy := walkMapPath(t, patchMap, []string{"spec", "strategy"}) - if value, ok := strategy["rollingUpdate"]; !ok || value != nil { - t.Fatalf("patch did not retain null value in key: rollingUpdate:\n%s\n", patch) - } - verifiedPatch = true + cmd := NewCmdApply("kubectl", tf, buf, errBuf) + cmd.Flags().Set("filename", filenameDeployObjClientside) + cmd.Flags().Set("output", "name") - // The real API server would had returned the patched object but Kubectl - // is ignoring the actual return object. - // TODO: Make this match actual server behavior by returning the patched object. - body := ioutil.NopCloser(bytes.NewReader(deploymentBytes)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + cmd.Run(cmd, []string{}) - cmd := NewCmdApply("kubectl", tf, buf, errBuf) - cmd.Flags().Set("filename", filenameDeployObjClientside) - cmd.Flags().Set("output", "name") - - cmd.Run(cmd, []string{}) - - expected := "deployment.extensions/" + deploymentName + "\n" - if buf.String() != expected { - t.Fatalf("unexpected output: %s\nexpected: %s", buf.String(), expected) - } - if errBuf.String() != "" { - t.Fatalf("unexpected error output: %s", errBuf.String()) - } - if !verifiedPatch { - t.Fatal("No server-side patch call detected") - } + expected := "deployment.extensions/" + deploymentName + "\n" + if buf.String() != expected { + t.Fatalf("unexpected output: %s\nexpected: %s", buf.String(), expected) + } + if errBuf.String() != "" { + t.Fatalf("unexpected error output: %s", errBuf.String()) + } + if !verifiedPatch { + t.Fatal("No server-side patch call detected") + } + }) } } @@ -873,56 +905,60 @@ func TestUnstructuredApply(t *testing.T) { verifiedPatch := false for _, fn := range testingOpenAPISchemaFns { - tf := cmdtesting.NewTestFactory() - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == path && m == "GET": - body := ioutil.NopCloser(bytes.NewReader(curr)) - return &http.Response{ - StatusCode: 200, - Header: defaultHeader(), - Body: body}, nil - case p == path && m == "PATCH": - contentType := req.Header.Get("Content-Type") - if contentType != "application/merge-patch+json" { - t.Fatalf("Unexpected Content-Type: %s", contentType) + t.Run("test apply works correctly with unstructured objects", func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == path && m == "GET": + body := ioutil.NopCloser(bytes.NewReader(curr)) + return &http.Response{ + StatusCode: 200, + Header: defaultHeader(), + Body: body}, nil + case p == path && m == "PATCH": + contentType := req.Header.Get("Content-Type") + if contentType != "application/merge-patch+json" { + t.Fatalf("Unexpected Content-Type: %s", contentType) + } + validatePatchApplication(t, req) + verifiedPatch = true + + body := ioutil.NopCloser(bytes.NewReader(curr)) + return &http.Response{ + StatusCode: 200, + Header: defaultHeader(), + Body: body}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil } - validatePatchApplication(t, req) - verifiedPatch = true + }), + } + tf.OpenAPISchemaFunc = fn + tf.Namespace = "test" + buf := bytes.NewBuffer([]byte{}) + errBuf := bytes.NewBuffer([]byte{}) - body := ioutil.NopCloser(bytes.NewReader(curr)) - return &http.Response{ - StatusCode: 200, - Header: defaultHeader(), - Body: body}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + cmd := NewCmdApply("kubectl", tf, buf, errBuf) + cmd.Flags().Set("filename", filenameWidgetClientside) + cmd.Flags().Set("output", "name") + cmd.Run(cmd, []string{}) - cmd := NewCmdApply("kubectl", tf, buf, errBuf) - cmd.Flags().Set("filename", filenameWidgetClientside) - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - expected := "widget.unit-test.test.com/" + name + "\n" - if buf.String() != expected { - t.Fatalf("unexpected output: %s\nexpected: %s", buf.String(), expected) - } - if errBuf.String() != "" { - t.Fatalf("unexpected error output: %s", errBuf.String()) - } - if !verifiedPatch { - t.Fatal("No server-side patch call detected") - } + expected := "widget.unit-test.test.com/" + name + "\n" + if buf.String() != expected { + t.Fatalf("unexpected output: %s\nexpected: %s", buf.String(), expected) + } + if errBuf.String() != "" { + t.Fatalf("unexpected error output: %s", errBuf.String()) + } + if !verifiedPatch { + t.Fatal("No server-side patch call detected") + } + }) } } @@ -940,79 +976,83 @@ func TestUnstructuredIdempotentApply(t *testing.T) { verifiedPatch := false for _, fn := range testingOpenAPISchemaFns { - tf := cmdtesting.NewTestFactory() - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == path && m == "GET": - body := ioutil.NopCloser(bytes.NewReader(serversideData)) - return &http.Response{ - StatusCode: 200, - Header: defaultHeader(), - Body: body}, nil - case p == path && m == "PATCH": - // In idempotent updates, kubectl sends a logically empty - // request body with the PATCH request. - // Should look like this: - // Request Body: {"metadata":{"annotations":{}}} + t.Run("test repeated apply operations on an unstructured object", func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - patch, err := ioutil.ReadAll(req.Body) - if err != nil { - t.Fatal(err) + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == path && m == "GET": + body := ioutil.NopCloser(bytes.NewReader(serversideData)) + return &http.Response{ + StatusCode: 200, + Header: defaultHeader(), + Body: body}, nil + case p == path && m == "PATCH": + // In idempotent updates, kubectl sends a logically empty + // request body with the PATCH request. + // Should look like this: + // Request Body: {"metadata":{"annotations":{}}} + + patch, err := ioutil.ReadAll(req.Body) + if err != nil { + t.Fatal(err) + } + + contentType := req.Header.Get("Content-Type") + if contentType != "application/merge-patch+json" { + t.Fatalf("Unexpected Content-Type: %s", contentType) + } + + patchMap := map[string]interface{}{} + if err := json.Unmarshal(patch, &patchMap); err != nil { + t.Fatal(err) + } + if len(patchMap) != 1 { + t.Fatalf("Unexpected Patch. Has more than 1 entry. path: %s", patch) + } + + annotationsMap := walkMapPath(t, patchMap, []string{"metadata", "annotations"}) + if len(annotationsMap) != 0 { + t.Fatalf("Unexpected Patch. Found unexpected annotation: %s", patch) + } + + verifiedPatch = true + + body := ioutil.NopCloser(bytes.NewReader(serversideData)) + return &http.Response{ + StatusCode: 200, + Header: defaultHeader(), + Body: body}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil } + }), + } + tf.OpenAPISchemaFunc = fn + tf.Namespace = "test" + buf := bytes.NewBuffer([]byte{}) + errBuf := bytes.NewBuffer([]byte{}) - contentType := req.Header.Get("Content-Type") - if contentType != "application/merge-patch+json" { - t.Fatalf("Unexpected Content-Type: %s", contentType) - } + cmd := NewCmdApply("kubectl", tf, buf, errBuf) + cmd.Flags().Set("filename", filenameWidgetClientside) + cmd.Flags().Set("output", "name") + cmd.Run(cmd, []string{}) - patchMap := map[string]interface{}{} - if err := json.Unmarshal(patch, &patchMap); err != nil { - t.Fatal(err) - } - if len(patchMap) != 1 { - t.Fatalf("Unexpected Patch. Has more than 1 entry. path: %s", patch) - } - - annotationsMap := walkMapPath(t, patchMap, []string{"metadata", "annotations"}) - if len(annotationsMap) != 0 { - t.Fatalf("Unexpected Patch. Found unexpected annotation: %s", patch) - } - - verifiedPatch = true - - body := ioutil.NopCloser(bytes.NewReader(serversideData)) - return &http.Response{ - StatusCode: 200, - Header: defaultHeader(), - Body: body}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.OpenAPISchemaFunc = fn - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdApply("kubectl", tf, buf, errBuf) - cmd.Flags().Set("filename", filenameWidgetClientside) - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - expected := "widget.unit-test.test.com/widget\n" - if buf.String() != expected { - t.Fatalf("unexpected output: %s\nexpected: %s", buf.String(), expected) - } - if errBuf.String() != "" { - t.Fatalf("unexpected error output: %s", errBuf.String()) - } - if !verifiedPatch { - t.Fatal("No server-side patch call detected") - } + expected := "widget.unit-test.test.com/widget\n" + if buf.String() != expected { + t.Fatalf("unexpected output: %s\nexpected: %s", buf.String(), expected) + } + if errBuf.String() != "" { + t.Fatalf("unexpected error output: %s", errBuf.String()) + } + if !verifiedPatch { + t.Fatal("No server-side patch call detected") + } + }) } } @@ -1069,6 +1109,8 @@ func TestRunApplySetLastApplied(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -1158,104 +1200,108 @@ func TestForceApply(t *testing.T) { } for _, fn := range testingOpenAPISchemaFns { - deleted := false - isScaledDownToZero := false - counts := map[string]int{} - tf := cmdtesting.NewTestFactory() - tf.UnstructuredClient = &fake.RESTClient{ - NegotiatedSerializer: unstructuredSerializer, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case strings.HasSuffix(p, pathRC) && m == "GET": - if deleted { - counts["getNotFound"]++ - return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte{}))}, nil - } - counts["getOk"]++ - var bodyRC io.ReadCloser - if isScaledDownToZero { - rcObj := readReplicationControllerFromFile(t, filenameRC) - rcObj.Spec.Replicas = 0 - rcBytes, err := runtime.Encode(testapi.Default.Codec(), rcObj) + t.Run("test apply with --force", func(t *testing.T) { + deleted := false + isScaledDownToZero := false + counts := map[string]int{} + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + + tf.UnstructuredClient = &fake.RESTClient{ + NegotiatedSerializer: unstructuredSerializer, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case strings.HasSuffix(p, pathRC) && m == "GET": + if deleted { + counts["getNotFound"]++ + return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte{}))}, nil + } + counts["getOk"]++ + var bodyRC io.ReadCloser + if isScaledDownToZero { + rcObj := readReplicationControllerFromFile(t, filenameRC) + rcObj.Spec.Replicas = 0 + rcBytes, err := runtime.Encode(testapi.Default.Codec(), rcObj) + if err != nil { + t.Fatal(err) + } + bodyRC = ioutil.NopCloser(bytes.NewReader(rcBytes)) + } else { + bodyRC = ioutil.NopCloser(bytes.NewReader(currentRC)) + } + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil + case strings.HasSuffix(p, pathRCList) && m == "GET": + counts["getList"]++ + rcObj := readUnstructuredFromFile(t, filenameRC) + list := &unstructured.UnstructuredList{ + Object: map[string]interface{}{ + "apiVersion": "v1", + "kind": "ReplicationControllerList", + }, + Items: []unstructured.Unstructured{*rcObj}, + } + listBytes, err := runtime.Encode(testapi.Default.Codec(), list) if err != nil { t.Fatal(err) } - bodyRC = ioutil.NopCloser(bytes.NewReader(rcBytes)) - } else { - bodyRC = ioutil.NopCloser(bytes.NewReader(currentRC)) + bodyRCList := ioutil.NopCloser(bytes.NewReader(listBytes)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRCList}, nil + case strings.HasSuffix(p, pathRC) && m == "PATCH": + counts["patch"]++ + if counts["patch"] <= 6 { + statusErr := kubeerr.NewConflict(schema.GroupResource{Group: "", Resource: "rc"}, "test-rc", fmt.Errorf("the object has been modified. Please apply at first.")) + bodyBytes, _ := json.Marshal(statusErr) + bodyErr := ioutil.NopCloser(bytes.NewReader(bodyBytes)) + return &http.Response{StatusCode: http.StatusConflict, Header: defaultHeader(), Body: bodyErr}, nil + } + t.Fatalf("unexpected request: %#v after %v tries\n%#v", req.URL, counts["patch"], req) + return nil, nil + case strings.HasSuffix(p, pathRC) && m == "DELETE": + counts["delete"]++ + deleted = true + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte{}))}, nil + case strings.HasSuffix(p, pathRC) && m == "PUT": + counts["put"]++ + bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) + isScaledDownToZero = true + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil + case strings.HasSuffix(p, pathRCList) && m == "POST": + counts["post"]++ + deleted = false + isScaledDownToZero = false + bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil } - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil - case strings.HasSuffix(p, pathRCList) && m == "GET": - counts["getList"]++ - rcObj := readUnstructuredFromFile(t, filenameRC) - list := &unstructured.UnstructuredList{ - Object: map[string]interface{}{ - "apiVersion": "v1", - "kind": "ReplicationControllerList", - }, - Items: []unstructured.Unstructured{*rcObj}, - } - listBytes, err := runtime.Encode(testapi.Default.Codec(), list) - if err != nil { - t.Fatal(err) - } - bodyRCList := ioutil.NopCloser(bytes.NewReader(listBytes)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRCList}, nil - case strings.HasSuffix(p, pathRC) && m == "PATCH": - counts["patch"]++ - if counts["patch"] <= 6 { - statusErr := kubeerr.NewConflict(schema.GroupResource{Group: "", Resource: "rc"}, "test-rc", fmt.Errorf("the object has been modified. Please apply at first.")) - bodyBytes, _ := json.Marshal(statusErr) - bodyErr := ioutil.NopCloser(bytes.NewReader(bodyBytes)) - return &http.Response{StatusCode: http.StatusConflict, Header: defaultHeader(), Body: bodyErr}, nil - } - t.Fatalf("unexpected request: %#v after %v tries\n%#v", req.URL, counts["patch"], req) - return nil, nil - case strings.HasSuffix(p, pathRC) && m == "DELETE": - counts["delete"]++ - deleted = true - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte{}))}, nil - case strings.HasSuffix(p, pathRC) && m == "PUT": - counts["put"]++ - bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) - isScaledDownToZero = true - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil - case strings.HasSuffix(p, pathRCList) && m == "POST": - counts["post"]++ - deleted = false - isScaledDownToZero = false - bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: bodyRC}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.OpenAPISchemaFunc = fn - tf.Client = tf.UnstructuredClient - tf.ClientConfigVal = &restclient.Config{} - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdApply("kubectl", tf, buf, errBuf) - cmd.Flags().Set("filename", filenameRC) - cmd.Flags().Set("output", "name") - cmd.Flags().Set("force", "true") - cmd.Run(cmd, []string{}) - - for method, exp := range expected { - if exp != counts[method] { - t.Errorf("Unexpected amount of %q API calls, wanted %v got %v", method, exp, counts[method]) + }), } - } + tf.OpenAPISchemaFunc = fn + tf.Client = tf.UnstructuredClient + tf.ClientConfigVal = &restclient.Config{} + tf.Namespace = "test" + buf := bytes.NewBuffer([]byte{}) + errBuf := bytes.NewBuffer([]byte{}) - if expected := "replicationcontroller/" + nameRC + "\n"; buf.String() != expected { - t.Fatalf("unexpected output: %s\nexpected: %s", buf.String(), expected) - } - if errBuf.String() != "" { - t.Fatalf("unexpected error output: %s", errBuf.String()) - } + cmd := NewCmdApply("kubectl", tf, buf, errBuf) + cmd.Flags().Set("filename", filenameRC) + cmd.Flags().Set("output", "name") + cmd.Flags().Set("force", "true") + cmd.Run(cmd, []string{}) + + for method, exp := range expected { + if exp != counts[method] { + t.Errorf("Unexpected amount of %q API calls, wanted %v got %v", method, exp, counts[method]) + } + } + + if expected := "replicationcontroller/" + nameRC + "\n"; buf.String() != expected { + t.Fatalf("unexpected output: %s\nexpected: %s", buf.String(), expected) + } + if errBuf.String() != "" { + t.Fatalf("unexpected error output: %s", errBuf.String()) + } + }) } } diff --git a/pkg/kubectl/cmd/attach_test.go b/pkg/kubectl/cmd/attach_test.go index c1ef0e067d3..d5294ea2ea2 100644 --- a/pkg/kubectl/cmd/attach_test.go +++ b/pkg/kubectl/cmd/attach_test.go @@ -139,43 +139,47 @@ func TestPodAndContainerAttach(t *testing.T) { } for _, test := range tests { - tf := cmdtesting.NewTestFactory() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - ns := legacyscheme.Codecs + t.Run(test.name, func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - tf.Client = &fake.RESTClient{ - GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - if test.obj != nil { - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, test.obj)}, nil - } - return nil, nil - }), - } - tf.Namespace = "test" - tf.ClientConfigVal = defaultClientConfig() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + ns := legacyscheme.Codecs - cmd := &cobra.Command{} - options := test.p - cmdutil.AddPodRunningTimeoutFlag(cmd, test.timeout) + tf.Client = &fake.RESTClient{ + GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + if test.obj != nil { + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, test.obj)}, nil + } + return nil, nil + }), + } + tf.Namespace = "test" + tf.ClientConfigVal = defaultClientConfig() - err := options.Complete(tf, cmd, test.args) - if test.expectError && err == nil { - t.Errorf("%s: unexpected non-error", test.name) - } - if !test.expectError && err != nil { - t.Errorf("%s: unexpected error: %v", test.name, err) - } - if err != nil { - continue - } - if options.PodName != test.expectedPod { - t.Errorf("%s: expected: %s, got: %s", test.name, test.expectedPod, options.PodName) - } - if options.ContainerName != test.expectedContainer { - t.Errorf("%s: expected: %s, got: %s", test.name, test.expectedContainer, options.ContainerName) - } + cmd := &cobra.Command{} + options := test.p + cmdutil.AddPodRunningTimeoutFlag(cmd, test.timeout) + + err := options.Complete(tf, cmd, test.args) + if test.expectError && err == nil { + t.Errorf("%s: unexpected non-error", test.name) + } + if !test.expectError && err != nil { + t.Errorf("%s: unexpected error: %v", test.name, err) + } + if err != nil { + return + } + if options.PodName != test.expectedPod { + t.Errorf("%s: expected: %s, got: %s", test.name, test.expectedPod, options.PodName) + } + if options.ContainerName != test.expectedContainer { + t.Errorf("%s: expected: %s, got: %s", test.name, test.expectedContainer, options.ContainerName) + } + }) } } @@ -219,74 +223,78 @@ func TestAttach(t *testing.T) { }, } for _, test := range tests { - tf := cmdtesting.NewTestFactory() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - ns := legacyscheme.Codecs + t.Run(test.name, func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - tf.Client = &fake.RESTClient{ - GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == test.podPath && m == "GET": - body := objBody(codec, test.pod) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil - case p == test.fetchPodPath && m == "GET": - body := objBody(codec, test.pod) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil - default: - // Ensures no GET is performed when deleting by name - t.Errorf("%s: unexpected request: %s %#v\n%#v", p, req.Method, req.URL, req) - return nil, fmt.Errorf("unexpected request") - } - }), - } - tf.Namespace = "test" - tf.ClientConfigVal = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs, GroupVersion: &schema.GroupVersion{Version: test.version}}} - bufOut := bytes.NewBuffer([]byte{}) - bufErr := bytes.NewBuffer([]byte{}) - bufIn := bytes.NewBuffer([]byte{}) - remoteAttach := &fakeRemoteAttach{} - if test.remoteAttachErr { - remoteAttach.err = fmt.Errorf("attach error") - } - params := &AttachOptions{ - StreamOptions: StreamOptions{ - ContainerName: test.container, - In: bufIn, - Out: bufOut, - Err: bufErr, - }, - Attach: remoteAttach, - GetPodTimeout: 1000, - } - cmd := &cobra.Command{} - cmdutil.AddPodRunningTimeoutFlag(cmd, 1000) - if err := params.Complete(tf, cmd, []string{"foo"}); err != nil { - t.Fatal(err) - } - err := params.Run() - if test.exepctedErr != "" && err.Error() != test.exepctedErr { - t.Errorf("%s: Unexpected exec error: %v", test.name, err) - continue - } - if test.exepctedErr == "" && err != nil { - t.Errorf("%s: Unexpected error: %v", test.name, err) - continue - } - if test.exepctedErr != "" { - continue - } - if remoteAttach.url.Path != test.attachPath { - t.Errorf("%s: Did not get expected path for exec request: %q %q", test.name, test.attachPath, remoteAttach.url.Path) - continue - } - if remoteAttach.method != "POST" { - t.Errorf("%s: Did not get method for attach request: %s", test.name, remoteAttach.method) - } - if remoteAttach.url.Query().Get("container") != "bar" { - t.Errorf("%s: Did not have query parameters: %s", test.name, remoteAttach.url.Query()) - } + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + ns := legacyscheme.Codecs + + tf.Client = &fake.RESTClient{ + GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == test.podPath && m == "GET": + body := objBody(codec, test.pod) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil + case p == test.fetchPodPath && m == "GET": + body := objBody(codec, test.pod) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil + default: + // Ensures no GET is performed when deleting by name + t.Errorf("%s: unexpected request: %s %#v\n%#v", p, req.Method, req.URL, req) + return nil, fmt.Errorf("unexpected request") + } + }), + } + tf.Namespace = "test" + tf.ClientConfigVal = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs, GroupVersion: &schema.GroupVersion{Version: test.version}}} + bufOut := bytes.NewBuffer([]byte{}) + bufErr := bytes.NewBuffer([]byte{}) + bufIn := bytes.NewBuffer([]byte{}) + remoteAttach := &fakeRemoteAttach{} + if test.remoteAttachErr { + remoteAttach.err = fmt.Errorf("attach error") + } + params := &AttachOptions{ + StreamOptions: StreamOptions{ + ContainerName: test.container, + In: bufIn, + Out: bufOut, + Err: bufErr, + }, + Attach: remoteAttach, + GetPodTimeout: 1000, + } + cmd := &cobra.Command{} + cmdutil.AddPodRunningTimeoutFlag(cmd, 1000) + if err := params.Complete(tf, cmd, []string{"foo"}); err != nil { + t.Fatal(err) + } + err := params.Run() + if test.exepctedErr != "" && err.Error() != test.exepctedErr { + t.Errorf("%s: Unexpected exec error: %v", test.name, err) + return + } + if test.exepctedErr == "" && err != nil { + t.Errorf("%s: Unexpected error: %v", test.name, err) + return + } + if test.exepctedErr != "" { + return + } + if remoteAttach.url.Path != test.attachPath { + t.Errorf("%s: Did not get expected path for exec request: %q %q", test.name, test.attachPath, remoteAttach.url.Path) + return + } + if remoteAttach.method != "POST" { + t.Errorf("%s: Did not get method for attach request: %s", test.name, remoteAttach.method) + } + if remoteAttach.url.Query().Get("container") != "bar" { + t.Errorf("%s: Did not have query parameters: %s", test.name, remoteAttach.url.Query()) + } + }) } } @@ -309,62 +317,66 @@ func TestAttachWarnings(t *testing.T) { }, } for _, test := range tests { - tf := cmdtesting.NewTestFactory() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - ns := legacyscheme.Codecs + t.Run(test.name, func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - tf.Client = &fake.RESTClient{ - GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == test.podPath && m == "GET": - body := objBody(codec, test.pod) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil - case p == test.fetchPodPath && m == "GET": - body := objBody(codec, test.pod) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil - default: - t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) - return nil, fmt.Errorf("unexpected request") - } - }), - } - tf.Namespace = "test" - tf.ClientConfigVal = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs, GroupVersion: &schema.GroupVersion{Version: test.version}}} - bufOut := bytes.NewBuffer([]byte{}) - bufErr := bytes.NewBuffer([]byte{}) - bufIn := bytes.NewBuffer([]byte{}) - ex := &fakeRemoteAttach{} - params := &AttachOptions{ - StreamOptions: StreamOptions{ - ContainerName: test.container, - In: bufIn, - Out: bufOut, - Err: bufErr, - Stdin: test.stdin, - TTY: test.tty, - }, - Attach: ex, - GetPodTimeout: 1000, - } - cmd := &cobra.Command{} - cmdutil.AddPodRunningTimeoutFlag(cmd, 1000) - if err := params.Complete(tf, cmd, []string{"foo"}); err != nil { - t.Fatal(err) - } - if err := params.Run(); err != nil { - t.Fatal(err) - } + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + ns := legacyscheme.Codecs - if test.stdin && test.tty { - if !test.pod.Spec.Containers[0].TTY { - if !strings.Contains(bufErr.String(), test.expectedErr) { - t.Errorf("%s: Expected TTY fallback warning for attach request: %s", test.name, bufErr.String()) - continue + tf.Client = &fake.RESTClient{ + GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == test.podPath && m == "GET": + body := objBody(codec, test.pod) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil + case p == test.fetchPodPath && m == "GET": + body := objBody(codec, test.pod) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil + default: + t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) + return nil, fmt.Errorf("unexpected request") + } + }), + } + tf.Namespace = "test" + tf.ClientConfigVal = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs, GroupVersion: &schema.GroupVersion{Version: test.version}}} + bufOut := bytes.NewBuffer([]byte{}) + bufErr := bytes.NewBuffer([]byte{}) + bufIn := bytes.NewBuffer([]byte{}) + ex := &fakeRemoteAttach{} + params := &AttachOptions{ + StreamOptions: StreamOptions{ + ContainerName: test.container, + In: bufIn, + Out: bufOut, + Err: bufErr, + Stdin: test.stdin, + TTY: test.tty, + }, + Attach: ex, + GetPodTimeout: 1000, + } + cmd := &cobra.Command{} + cmdutil.AddPodRunningTimeoutFlag(cmd, 1000) + if err := params.Complete(tf, cmd, []string{"foo"}); err != nil { + t.Fatal(err) + } + if err := params.Run(); err != nil { + t.Fatal(err) + } + + if test.stdin && test.tty { + if !test.pod.Spec.Containers[0].TTY { + if !strings.Contains(bufErr.String(), test.expectedErr) { + t.Errorf("%s: Expected TTY fallback warning for attach request: %s", test.name, bufErr.String()) + return + } } } - } + }) } } diff --git a/pkg/kubectl/cmd/auth/cani_test.go b/pkg/kubectl/cmd/auth/cani_test.go index 0696bc05c69..eb3cf9c5d84 100644 --- a/pkg/kubectl/cmd/auth/cani_test.go +++ b/pkg/kubectl/cmd/auth/cani_test.go @@ -117,64 +117,68 @@ func TestRunAccessCheck(t *testing.T) { } for _, test := range tests { - test.o.Out = ioutil.Discard - test.o.Err = ioutil.Discard + t.Run(test.name, func(t *testing.T) { + test.o.Out = ioutil.Discard + test.o.Err = ioutil.Discard - tf := cmdtesting.NewTestFactory() - ns := legacyscheme.Codecs + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - tf.Client = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - expectPath := "/apis/authorization.k8s.io/v1/selfsubjectaccessreviews" - if req.URL.Path != expectPath { - t.Errorf("%s: expected %v, got %v", test.name, expectPath, req.URL.Path) - return nil, nil - } - bodyBits, err := ioutil.ReadAll(req.Body) - if err != nil { - t.Errorf("%s: %v", test.name, err) - return nil, nil - } - body := string(bodyBits) + ns := legacyscheme.Codecs - for _, expectedBody := range test.expectedBodyStrings { - if !strings.Contains(body, expectedBody) { - t.Errorf("%s expecting %s in %s", test.name, expectedBody, body) + tf.Client = &fake.RESTClient{ + GroupVersion: schema.GroupVersion{Group: "", Version: "v1"}, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + expectPath := "/apis/authorization.k8s.io/v1/selfsubjectaccessreviews" + if req.URL.Path != expectPath { + t.Errorf("%s: expected %v, got %v", test.name, expectPath, req.URL.Path) + return nil, nil } - } + bodyBits, err := ioutil.ReadAll(req.Body) + if err != nil { + t.Errorf("%s: %v", test.name, err) + return nil, nil + } + body := string(bodyBits) - return &http.Response{ - StatusCode: http.StatusOK, - Body: ioutil.NopCloser(bytes.NewBufferString( - fmt.Sprintf(`{"kind":"SelfSubjectAccessReview","apiVersion":"authorization.k8s.io/v1","status":{"allowed":%v}}`, test.allowed), - )), - }, - test.serverErr - }), - } - tf.Namespace = "test" - tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}} + for _, expectedBody := range test.expectedBodyStrings { + if !strings.Contains(body, expectedBody) { + t.Errorf("%s expecting %s in %s", test.name, expectedBody, body) + } + } - if err := test.o.Complete(tf, test.args); err != nil { - t.Errorf("%s: %v", test.name, err) - continue - } + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewBufferString( + fmt.Sprintf(`{"kind":"SelfSubjectAccessReview","apiVersion":"authorization.k8s.io/v1","status":{"allowed":%v}}`, test.allowed), + )), + }, + test.serverErr + }), + } + tf.Namespace = "test" + tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}} - actualAllowed, err := test.o.RunAccessCheck() - switch { - case test.serverErr == nil && err == nil: - // pass - case err != nil && test.serverErr != nil && strings.Contains(err.Error(), test.serverErr.Error()): - // pass - default: - t.Errorf("%s: expected %v, got %v", test.name, test.serverErr, err) - continue - } - if actualAllowed != test.allowed { - t.Errorf("%s: expected %v, got %v", test.name, test.allowed, actualAllowed) - continue - } + if err := test.o.Complete(tf, test.args); err != nil { + t.Errorf("%s: %v", test.name, err) + return + } + + actualAllowed, err := test.o.RunAccessCheck() + switch { + case test.serverErr == nil && err == nil: + // pass + case err != nil && test.serverErr != nil && strings.Contains(err.Error(), test.serverErr.Error()): + // pass + default: + t.Errorf("%s: expected %v, got %v", test.name, test.serverErr, err) + return + } + if actualAllowed != test.allowed { + t.Errorf("%s: expected %v, got %v", test.name, test.allowed, actualAllowed) + return + } + }) } } diff --git a/pkg/kubectl/cmd/clusterinfo_dump_test.go b/pkg/kubectl/cmd/clusterinfo_dump_test.go index 6d577baad85..f4a1a1145f6 100644 --- a/pkg/kubectl/cmd/clusterinfo_dump_test.go +++ b/pkg/kubectl/cmd/clusterinfo_dump_test.go @@ -31,6 +31,8 @@ func TestSetupOutputWriterNoOp(t *testing.T) { for _, test := range tests { out := &bytes.Buffer{} f := cmdtesting.NewTestFactory() + defer f.Cleanup() + cmd := NewCmdClusterInfoDump(f, os.Stdout) cmd.Flag("output-directory").Value.Set(test) writer := setupOutputWriter(cmd, out, "/some/file/that/should/be/ignored") @@ -51,6 +53,8 @@ func TestSetupOutputWriterFile(t *testing.T) { out := &bytes.Buffer{} f := cmdtesting.NewTestFactory() + defer f.Cleanup() + cmd := NewCmdClusterInfoDump(f, os.Stdout) cmd.Flag("output-directory").Value.Set(dir) writer := setupOutputWriter(cmd, out, file) diff --git a/pkg/kubectl/cmd/cmd_test.go b/pkg/kubectl/cmd/cmd_test.go index 42a2eaeb7d2..b694aa640fb 100644 --- a/pkg/kubectl/cmd/cmd_test.go +++ b/pkg/kubectl/cmd/cmd_test.go @@ -178,6 +178,8 @@ func stringBody(body string) io.ReadCloser { func Example_printMultiContainersReplicationControllerWithWide() { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -228,6 +230,8 @@ func Example_printMultiContainersReplicationControllerWithWide() { func Example_printReplicationController() { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -277,6 +281,8 @@ func Example_printReplicationController() { func Example_printPodWithWideFormat() { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -315,6 +321,8 @@ func Example_printPodWithWideFormat() { func Example_printPodWithShowLabels() { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -448,6 +456,8 @@ func newAllPhasePodList() *api.PodList { func Example_printPodShowTerminated() { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -484,6 +494,8 @@ func Example_printPodShowTerminated() { func Example_printPodShowAll() { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -507,6 +519,8 @@ func Example_printPodShowAll() { func Example_printServiceWithLabels() { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ diff --git a/pkg/kubectl/cmd/convert_test.go b/pkg/kubectl/cmd/convert_test.go index 19ee215881b..5b7474ef633 100644 --- a/pkg/kubectl/cmd/convert_test.go +++ b/pkg/kubectl/cmd/convert_test.go @@ -102,6 +102,8 @@ func TestConvertObject(t *testing.T) { for _, field := range tc.fields { t.Run(fmt.Sprintf("%s %s", tc.name, field), func(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.UnstructuredClient = &fake.RESTClient{ Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) diff --git a/pkg/kubectl/cmd/create_clusterrole_test.go b/pkg/kubectl/cmd/create_clusterrole_test.go index 1b246369d53..bf16b1cf270 100644 --- a/pkg/kubectl/cmd/create_clusterrole_test.go +++ b/pkg/kubectl/cmd/create_clusterrole_test.go @@ -33,6 +33,8 @@ func TestCreateClusterRole(t *testing.T) { clusterRoleName := "my-cluster-role" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.Namespace = "test" tf.Client = &fake.RESTClient{} tf.ClientConfigVal = defaultClientConfig() @@ -148,6 +150,8 @@ func TestCreateClusterRole(t *testing.T) { func TestClusterRoleValidate(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.Namespace = "test" tests := map[string]struct { diff --git a/pkg/kubectl/cmd/create_clusterrolebinding_test.go b/pkg/kubectl/cmd/create_clusterrolebinding_test.go index 00628a92ae0..762edac8245 100644 --- a/pkg/kubectl/cmd/create_clusterrolebinding_test.go +++ b/pkg/kubectl/cmd/create_clusterrolebinding_test.go @@ -68,6 +68,8 @@ func TestCreateClusterRoleBinding(t *testing.T) { } tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs info, _ := runtime.SerializerInfoForMediaType(ns.SupportedMediaTypes(), runtime.ContentTypeJSON) diff --git a/pkg/kubectl/cmd/create_configmap_test.go b/pkg/kubectl/cmd/create_configmap_test.go index 0ffa2696ce4..a0d5bdaecba 100644 --- a/pkg/kubectl/cmd/create_configmap_test.go +++ b/pkg/kubectl/cmd/create_configmap_test.go @@ -33,6 +33,8 @@ func TestCreateConfigMap(t *testing.T) { configMap := &v1.ConfigMap{} configMap.Name = "my-configmap" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) ns := legacyscheme.Codecs diff --git a/pkg/kubectl/cmd/create_deployment_test.go b/pkg/kubectl/cmd/create_deployment_test.go index bf94557220c..26b7c414c6e 100644 --- a/pkg/kubectl/cmd/create_deployment_test.go +++ b/pkg/kubectl/cmd/create_deployment_test.go @@ -75,6 +75,8 @@ func Test_generatorFromName(t *testing.T) { func TestCreateDeployment(t *testing.T) { depName := "jonny-dep" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -104,6 +106,8 @@ func TestCreateDeployment(t *testing.T) { func TestCreateDeploymentNoImage(t *testing.T) { depName := "jonny-dep" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ diff --git a/pkg/kubectl/cmd/create_job_test.go b/pkg/kubectl/cmd/create_job_test.go index e04cf9201ee..2e6989dc856 100644 --- a/pkg/kubectl/cmd/create_job_test.go +++ b/pkg/kubectl/cmd/create_job_test.go @@ -82,6 +82,8 @@ func TestCreateJobFromCronJob(t *testing.T) { return true, expectJob, nil }) f := cmdtesting.NewTestFactory() + defer f.Cleanup() + buf := bytes.NewBuffer([]byte{}) cmdOptions := &CreateJobOptions{ Name: testJobName, diff --git a/pkg/kubectl/cmd/create_namespace_test.go b/pkg/kubectl/cmd/create_namespace_test.go index 5b8d587d4fd..c743ce7cf3b 100644 --- a/pkg/kubectl/cmd/create_namespace_test.go +++ b/pkg/kubectl/cmd/create_namespace_test.go @@ -33,6 +33,8 @@ func TestCreateNamespace(t *testing.T) { namespaceObject := &v1.Namespace{} namespaceObject.Name = "my-namespace" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) ns := legacyscheme.Codecs diff --git a/pkg/kubectl/cmd/create_pdb_test.go b/pkg/kubectl/cmd/create_pdb_test.go index 76b82ebb1f4..2fb0956a4e5 100644 --- a/pkg/kubectl/cmd/create_pdb_test.go +++ b/pkg/kubectl/cmd/create_pdb_test.go @@ -32,6 +32,8 @@ import ( func TestCreatePdb(t *testing.T) { pdbName := "my-pdb" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ diff --git a/pkg/kubectl/cmd/create_priorityclass_test.go b/pkg/kubectl/cmd/create_priorityclass_test.go index 14b77ef2e45..92f51774af0 100644 --- a/pkg/kubectl/cmd/create_priorityclass_test.go +++ b/pkg/kubectl/cmd/create_priorityclass_test.go @@ -32,6 +32,8 @@ import ( func TestCreatePriorityClass(t *testing.T) { pcName := "my-pc" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ diff --git a/pkg/kubectl/cmd/create_quota_test.go b/pkg/kubectl/cmd/create_quota_test.go index cfcf1e4738c..618ff36176c 100644 --- a/pkg/kubectl/cmd/create_quota_test.go +++ b/pkg/kubectl/cmd/create_quota_test.go @@ -33,6 +33,8 @@ func TestCreateQuota(t *testing.T) { resourceQuotaObject := &v1.ResourceQuota{} resourceQuotaObject.Name = "my-quota" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) ns := legacyscheme.Codecs diff --git a/pkg/kubectl/cmd/create_role_test.go b/pkg/kubectl/cmd/create_role_test.go index 82c265b5dd9..30e5f81c29a 100644 --- a/pkg/kubectl/cmd/create_role_test.go +++ b/pkg/kubectl/cmd/create_role_test.go @@ -35,6 +35,8 @@ func TestCreateRole(t *testing.T) { roleName := "my-role" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.Namespace = "test" tf.Client = &fake.RESTClient{} tf.ClientConfigVal = defaultClientConfig() @@ -147,6 +149,8 @@ func TestCreateRole(t *testing.T) { func TestValidate(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.Namespace = "test" tests := map[string]struct { @@ -346,6 +350,8 @@ func TestComplete(t *testing.T) { roleName := "my-role" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.Namespace = "test" tf.Client = &fake.RESTClient{} tf.ClientConfigVal = defaultClientConfig() diff --git a/pkg/kubectl/cmd/create_rolebinding_test.go b/pkg/kubectl/cmd/create_rolebinding_test.go index b42faaa9db8..d227857eb15 100644 --- a/pkg/kubectl/cmd/create_rolebinding_test.go +++ b/pkg/kubectl/cmd/create_rolebinding_test.go @@ -70,6 +70,8 @@ func TestCreateRoleBinding(t *testing.T) { } tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs info, _ := runtime.SerializerInfoForMediaType(ns.SupportedMediaTypes(), runtime.ContentTypeJSON) diff --git a/pkg/kubectl/cmd/create_secret_test.go b/pkg/kubectl/cmd/create_secret_test.go index 86487976765..1e3f7397973 100644 --- a/pkg/kubectl/cmd/create_secret_test.go +++ b/pkg/kubectl/cmd/create_secret_test.go @@ -38,6 +38,8 @@ func TestCreateSecretGeneric(t *testing.T) { } secretObject.Name = "my-secret" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) ns := legacyscheme.Codecs diff --git a/pkg/kubectl/cmd/create_service_test.go b/pkg/kubectl/cmd/create_service_test.go index adf9679d962..9abd224dacf 100644 --- a/pkg/kubectl/cmd/create_service_test.go +++ b/pkg/kubectl/cmd/create_service_test.go @@ -33,6 +33,8 @@ func TestCreateService(t *testing.T) { service := &v1.Service{} service.Name = "my-service" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) negSer := legacyscheme.Codecs @@ -65,6 +67,8 @@ func TestCreateServiceNodePort(t *testing.T) { service := &v1.Service{} service.Name = "my-node-port-service" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) negSer := legacyscheme.Codecs @@ -97,6 +101,8 @@ func TestCreateServiceExternalName(t *testing.T) { service := &v1.Service{} service.Name = "my-external-name-service" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) negSer := legacyscheme.Codecs diff --git a/pkg/kubectl/cmd/create_serviceaccount_test.go b/pkg/kubectl/cmd/create_serviceaccount_test.go index 382f66dbe0f..7997ea72147 100644 --- a/pkg/kubectl/cmd/create_serviceaccount_test.go +++ b/pkg/kubectl/cmd/create_serviceaccount_test.go @@ -33,6 +33,8 @@ func TestCreateServiceAccount(t *testing.T) { serviceAccountObject := &v1.ServiceAccount{} serviceAccountObject.Name = "my-service-account" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) ns := legacyscheme.Codecs diff --git a/pkg/kubectl/cmd/create_test.go b/pkg/kubectl/cmd/create_test.go index c4f0019aa86..9b160374f06 100644 --- a/pkg/kubectl/cmd/create_test.go +++ b/pkg/kubectl/cmd/create_test.go @@ -34,6 +34,8 @@ func TestExtraArgsFail(t *testing.T) { errBuf := bytes.NewBuffer([]byte{}) f := cmdtesting.NewTestFactory() + defer f.Cleanup() + c := NewCmdCreate(f, buf, errBuf) options := CreateOptions{} if options.ValidateArgs(c, []string{"rc"}) == nil { @@ -47,6 +49,8 @@ func TestCreateObject(t *testing.T) { rc.Items[0].Name = "redis-master-controller" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -82,6 +86,8 @@ func TestCreateMultipleObject(t *testing.T) { _, svc, rc := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -121,6 +127,8 @@ func TestCreateDirectory(t *testing.T) { rc.Items[0].Name = "name" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ diff --git a/pkg/kubectl/cmd/delete_test.go b/pkg/kubectl/cmd/delete_test.go index fc0dd589d55..cd937864beb 100644 --- a/pkg/kubectl/cmd/delete_test.go +++ b/pkg/kubectl/cmd/delete_test.go @@ -57,6 +57,8 @@ func TestDeleteObjectByTuple(t *testing.T) { _, _, rc := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -121,6 +123,8 @@ func TestOrphanDependentsInDeleteObject(t *testing.T) { _, _, rc := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) var expectedOrphanDependents *bool @@ -171,6 +175,8 @@ func TestDeleteNamedObject(t *testing.T) { _, _, rc := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -222,6 +228,8 @@ func TestDeleteObject(t *testing.T) { _, _, rc := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -281,6 +289,8 @@ func TestDeleteObjectGraceZero(t *testing.T) { objectDeletionWaitInterval = time.Millisecond count := 0 tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -331,6 +341,8 @@ func TestDeleteObjectGraceZero(t *testing.T) { func TestDeleteObjectNotFound(t *testing.T) { initTestErrorHandler(t) tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { @@ -367,6 +379,8 @@ func TestDeleteObjectNotFound(t *testing.T) { func TestDeleteObjectIgnoreNotFound(t *testing.T) { initTestErrorHandler(t) tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { @@ -402,6 +416,8 @@ func TestDeleteAllNotFound(t *testing.T) { notFoundError := &errors.NewNotFound(api.Resource("services"), "foo").ErrStatus tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -447,6 +463,8 @@ func TestDeleteAllIgnoreNotFound(t *testing.T) { _, svc, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) // Add an item to the list which will result in a 404 on delete @@ -488,6 +506,8 @@ func TestDeleteMultipleObject(t *testing.T) { _, svc, rc := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -524,6 +544,8 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) { _, svc, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -569,6 +591,8 @@ func TestDeleteMultipleResourcesWithTheSameName(t *testing.T) { initTestErrorHandler(t) _, svc, rc := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -608,6 +632,8 @@ func TestDeleteDirectory(t *testing.T) { _, _, rc := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -641,6 +667,8 @@ func TestDeleteMultipleSelector(t *testing.T) { pods, svc, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -706,26 +734,30 @@ func TestResourceErrors(t *testing.T) { } for k, testCase := range testCases { - tf := cmdtesting.NewTestFactory() - tf.Namespace = "test" - tf.ClientConfigVal = defaultClientConfig() + t.Run(k, func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) + tf.Namespace = "test" + tf.ClientConfigVal = defaultClientConfig() - options := &DeleteOptions{ - FilenameOptions: resource.FilenameOptions{}, - GracePeriod: -1, - Cascade: false, - Output: "name", - } - err := options.Complete(tf, buf, errBuf, testCase.args, fakecmd) - if !testCase.errFn(err) { - t.Errorf("%s: unexpected error: %v", k, err) - continue - } + buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) - if buf.Len() > 0 { - t.Errorf("buffer should be empty: %s", string(buf.Bytes())) - } + options := &DeleteOptions{ + FilenameOptions: resource.FilenameOptions{}, + GracePeriod: -1, + Cascade: false, + Output: "name", + } + err := options.Complete(tf, buf, errBuf, testCase.args, fakecmd) + if !testCase.errFn(err) { + t.Errorf("%s: unexpected error: %v", k, err) + return + } + + if buf.Len() > 0 { + t.Errorf("buffer should be empty: %s", string(buf.Bytes())) + } + }) } } diff --git a/pkg/kubectl/cmd/describe_test.go b/pkg/kubectl/cmd/describe_test.go index 9e5b39a8ae2..6e029f3d684 100644 --- a/pkg/kubectl/cmd/describe_test.go +++ b/pkg/kubectl/cmd/describe_test.go @@ -33,6 +33,7 @@ import ( func TestDescribeUnknownSchemaObject(t *testing.T) { d := &testDescriber{Output: "test output"} tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() _, _, codec := cmdtesting.NewExternalScheme() tf.DescriberVal = d tf.UnstructuredClient = &fake.RESTClient{ @@ -58,6 +59,7 @@ func TestDescribeUnknownSchemaObject(t *testing.T) { func TestDescribeUnknownNamespacedSchemaObject(t *testing.T) { d := &testDescriber{Output: "test output"} tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() _, _, codec := cmdtesting.NewExternalScheme() tf.DescriberVal = d @@ -83,6 +85,7 @@ func TestDescribeUnknownNamespacedSchemaObject(t *testing.T) { func TestDescribeObject(t *testing.T) { _, _, rc := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) d := &testDescriber{Output: "test output"} @@ -118,6 +121,7 @@ func TestDescribeObject(t *testing.T) { func TestDescribeListObjects(t *testing.T) { pods, _, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) d := &testDescriber{Output: "test output"} @@ -140,6 +144,7 @@ func TestDescribeListObjects(t *testing.T) { func TestDescribeObjectShowEvents(t *testing.T) { pods, _, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) d := &testDescriber{Output: "test output"} @@ -163,6 +168,7 @@ func TestDescribeObjectShowEvents(t *testing.T) { func TestDescribeObjectSkipEvents(t *testing.T) { pods, _, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) d := &testDescriber{Output: "test output"} @@ -185,6 +191,7 @@ func TestDescribeObjectSkipEvents(t *testing.T) { func TestDescribeHelpMessage(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() buf := bytes.NewBuffer([]byte{}) buferr := bytes.NewBuffer([]byte{}) diff --git a/pkg/kubectl/cmd/drain_test.go b/pkg/kubectl/cmd/drain_test.go index deaaa867f27..f06a60053a4 100644 --- a/pkg/kubectl/cmd/drain_test.go +++ b/pkg/kubectl/cmd/drain_test.go @@ -150,86 +150,90 @@ func TestCordon(t *testing.T) { } for _, test := range tests { - tf := cmdtesting.NewTestFactory() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - ns := legacyscheme.Codecs + t.Run(test.description, func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - new_node := &corev1.Node{} - updated := false - tf.Client = &fake.RESTClient{ - GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - m := &MyReq{req} - switch { - case m.isFor("GET", "/nodes/node"): - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, test.node)}, nil - case m.isFor("GET", "/nodes/bar"): - return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: stringBody("nope")}, nil - case m.isFor("PATCH", "/nodes/node"): - data, err := ioutil.ReadAll(req.Body) - if err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - defer req.Body.Close() - oldJSON, err := runtime.Encode(codec, node) - if err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - appliedPatch, err := strategicpatch.StrategicMergePatch(oldJSON, data, &corev1.Node{}) - if err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - if err := runtime.DecodeInto(codec, appliedPatch, new_node); err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - if !reflect.DeepEqual(test.expected.Spec, new_node.Spec) { - t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, test.expected.Spec.Unschedulable, new_node.Spec.Unschedulable) - } - updated = true - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, new_node)}, nil - default: - t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req) - return nil, nil - } - }), - } - tf.ClientConfigVal = defaultClientConfig() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + ns := legacyscheme.Codecs - buf := bytes.NewBuffer([]byte{}) - cmd := test.cmd(tf, buf) + new_node := &corev1.Node{} + updated := false + tf.Client = &fake.RESTClient{ + GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + m := &MyReq{req} + switch { + case m.isFor("GET", "/nodes/node"): + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, test.node)}, nil + case m.isFor("GET", "/nodes/bar"): + return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: stringBody("nope")}, nil + case m.isFor("PATCH", "/nodes/node"): + data, err := ioutil.ReadAll(req.Body) + if err != nil { + t.Fatalf("%s: unexpected error: %v", test.description, err) + } + defer req.Body.Close() + oldJSON, err := runtime.Encode(codec, node) + if err != nil { + t.Fatalf("%s: unexpected error: %v", test.description, err) + } + appliedPatch, err := strategicpatch.StrategicMergePatch(oldJSON, data, &corev1.Node{}) + if err != nil { + t.Fatalf("%s: unexpected error: %v", test.description, err) + } + if err := runtime.DecodeInto(codec, appliedPatch, new_node); err != nil { + t.Fatalf("%s: unexpected error: %v", test.description, err) + } + if !reflect.DeepEqual(test.expected.Spec, new_node.Spec) { + t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, test.expected.Spec.Unschedulable, new_node.Spec.Unschedulable) + } + updated = true + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, new_node)}, nil + default: + t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req) + return nil, nil + } + }), + } + tf.ClientConfigVal = defaultClientConfig() - saw_fatal := false - func() { - defer func() { - // Recover from the panic below. - _ = recover() - // Restore cmdutil behavior - cmdutil.DefaultBehaviorOnFatal() + buf := bytes.NewBuffer([]byte{}) + cmd := test.cmd(tf, buf) + + saw_fatal := false + func() { + defer func() { + // Recover from the panic below. + _ = recover() + // Restore cmdutil behavior + cmdutil.DefaultBehaviorOnFatal() + }() + cmdutil.BehaviorOnFatal(func(e string, code int) { + saw_fatal = true + panic(e) + }) + cmd.SetArgs([]string{test.arg}) + cmd.Execute() }() - cmdutil.BehaviorOnFatal(func(e string, code int) { - saw_fatal = true - panic(e) - }) - cmd.SetArgs([]string{test.arg}) - cmd.Execute() - }() - if test.expectFatal { - if !saw_fatal { - t.Fatalf("%s: unexpected non-error", test.description) + if test.expectFatal { + if !saw_fatal { + t.Fatalf("%s: unexpected non-error", test.description) + } + if updated { + t.Fatalf("%s: unexpected update", test.description) + } } - if updated { - t.Fatalf("%s: unexpected update", test.description) - } - } - if !test.expectFatal && saw_fatal { - t.Fatalf("%s: unexpected error", test.description) - } - if !reflect.DeepEqual(test.expected.Spec, test.node.Spec) && !updated { - t.Fatalf("%s: node never updated", test.description) - } + if !test.expectFatal && saw_fatal { + t.Fatalf("%s: unexpected error", test.description) + } + if !reflect.DeepEqual(test.expected.Spec, test.node.Spec) && !updated { + t.Fatalf("%s: node never updated", test.description) + } + }) } } @@ -597,164 +601,168 @@ func TestDrain(t *testing.T) { currMethod = DeleteMethod } for _, test := range tests { - new_node := &corev1.Node{} - deleted := false - evicted := false - tf := cmdtesting.NewTestFactory() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - ns := legacyscheme.Codecs + t.Run(test.description, func(t *testing.T) { + new_node := &corev1.Node{} + deleted := false + evicted := false + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - tf.Client = &fake.RESTClient{ - GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - m := &MyReq{req} - switch { - case req.Method == "GET" && req.URL.Path == "/api": - apiVersions := metav1.APIVersions{ - Versions: []string{"v1"}, - } - return genResponseWithJsonEncodedBody(apiVersions) - case req.Method == "GET" && req.URL.Path == "/apis": - groupList := metav1.APIGroupList{ - Groups: []metav1.APIGroup{ - { - Name: "policy", - PreferredVersion: metav1.GroupVersionForDiscovery{ - GroupVersion: "policy/v1beta1", + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + ns := legacyscheme.Codecs + + tf.Client = &fake.RESTClient{ + GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + m := &MyReq{req} + switch { + case req.Method == "GET" && req.URL.Path == "/api": + apiVersions := metav1.APIVersions{ + Versions: []string{"v1"}, + } + return genResponseWithJsonEncodedBody(apiVersions) + case req.Method == "GET" && req.URL.Path == "/apis": + groupList := metav1.APIGroupList{ + Groups: []metav1.APIGroup{ + { + Name: "policy", + PreferredVersion: metav1.GroupVersionForDiscovery{ + GroupVersion: "policy/v1beta1", + }, }, }, - }, - } - return genResponseWithJsonEncodedBody(groupList) - case req.Method == "GET" && req.URL.Path == "/api/v1": - resourceList := metav1.APIResourceList{ - GroupVersion: "v1", - } - if testEviction { - resourceList.APIResources = []metav1.APIResource{ - { - Name: EvictionSubresource, - Kind: EvictionKind, - }, } + return genResponseWithJsonEncodedBody(groupList) + case req.Method == "GET" && req.URL.Path == "/api/v1": + resourceList := metav1.APIResourceList{ + GroupVersion: "v1", + } + if testEviction { + resourceList.APIResources = []metav1.APIResource{ + { + Name: EvictionSubresource, + Kind: EvictionKind, + }, + } + } + return genResponseWithJsonEncodedBody(resourceList) + case m.isFor("GET", "/nodes/node"): + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, test.node)}, nil + case m.isFor("GET", "/namespaces/default/replicationcontrollers/rc"): + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &test.rcs[0])}, nil + case m.isFor("GET", "/namespaces/default/daemonsets/ds"): + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(testapi.Extensions.Codec(), &ds)}, nil + case m.isFor("GET", "/namespaces/default/daemonsets/missing-ds"): + return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: objBody(testapi.Extensions.Codec(), &extensions.DaemonSet{})}, nil + case m.isFor("GET", "/namespaces/default/jobs/job"): + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(testapi.Batch.Codec(), &job)}, nil + case m.isFor("GET", "/namespaces/default/replicasets/rs"): + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(testapi.Extensions.Codec(), &test.replicaSets[0])}, nil + case m.isFor("GET", "/namespaces/default/pods/bar"): + return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: objBody(codec, &corev1.Pod{})}, nil + case m.isFor("GET", "/pods"): + values, err := url.ParseQuery(req.URL.RawQuery) + if err != nil { + t.Fatalf("%s: unexpected error: %v", test.description, err) + } + get_params := make(url.Values) + get_params["fieldSelector"] = []string{"spec.nodeName=node"} + if !reflect.DeepEqual(get_params, values) { + t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, get_params, values) + } + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &corev1.PodList{Items: test.pods})}, nil + case m.isFor("GET", "/replicationcontrollers"): + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &api.ReplicationControllerList{Items: test.rcs})}, nil + case m.isFor("PATCH", "/nodes/node"): + data, err := ioutil.ReadAll(req.Body) + if err != nil { + t.Fatalf("%s: unexpected error: %v", test.description, err) + } + defer req.Body.Close() + oldJSON, err := runtime.Encode(codec, node) + if err != nil { + t.Fatalf("%s: unexpected error: %v", test.description, err) + } + appliedPatch, err := strategicpatch.StrategicMergePatch(oldJSON, data, &corev1.Node{}) + if err != nil { + t.Fatalf("%s: unexpected error: %v", test.description, err) + } + if err := runtime.DecodeInto(codec, appliedPatch, new_node); err != nil { + t.Fatalf("%s: unexpected error: %v", test.description, err) + } + if !reflect.DeepEqual(test.expected.Spec, new_node.Spec) { + t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, test.expected.Spec, new_node.Spec) + } + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, new_node)}, nil + case m.isFor("DELETE", "/namespaces/default/pods/bar"): + deleted = true + return &http.Response{StatusCode: 204, Header: defaultHeader(), Body: objBody(codec, &test.pods[0])}, nil + case m.isFor("POST", "/namespaces/default/pods/bar/eviction"): + evicted = true + return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: policyObjBody(&policyv1beta1.Eviction{})}, nil + default: + t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req) + return nil, nil } - return genResponseWithJsonEncodedBody(resourceList) - case m.isFor("GET", "/nodes/node"): - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, test.node)}, nil - case m.isFor("GET", "/namespaces/default/replicationcontrollers/rc"): - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &test.rcs[0])}, nil - case m.isFor("GET", "/namespaces/default/daemonsets/ds"): - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(testapi.Extensions.Codec(), &ds)}, nil - case m.isFor("GET", "/namespaces/default/daemonsets/missing-ds"): - return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: objBody(testapi.Extensions.Codec(), &extensions.DaemonSet{})}, nil - case m.isFor("GET", "/namespaces/default/jobs/job"): - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(testapi.Batch.Codec(), &job)}, nil - case m.isFor("GET", "/namespaces/default/replicasets/rs"): - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(testapi.Extensions.Codec(), &test.replicaSets[0])}, nil - case m.isFor("GET", "/namespaces/default/pods/bar"): - return &http.Response{StatusCode: 404, Header: defaultHeader(), Body: objBody(codec, &corev1.Pod{})}, nil - case m.isFor("GET", "/pods"): - values, err := url.ParseQuery(req.URL.RawQuery) - if err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - get_params := make(url.Values) - get_params["fieldSelector"] = []string{"spec.nodeName=node"} - if !reflect.DeepEqual(get_params, values) { - t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, get_params, values) - } - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &corev1.PodList{Items: test.pods})}, nil - case m.isFor("GET", "/replicationcontrollers"): - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &api.ReplicationControllerList{Items: test.rcs})}, nil - case m.isFor("PATCH", "/nodes/node"): - data, err := ioutil.ReadAll(req.Body) - if err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - defer req.Body.Close() - oldJSON, err := runtime.Encode(codec, node) - if err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - appliedPatch, err := strategicpatch.StrategicMergePatch(oldJSON, data, &corev1.Node{}) - if err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - if err := runtime.DecodeInto(codec, appliedPatch, new_node); err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - if !reflect.DeepEqual(test.expected.Spec, new_node.Spec) { - t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, test.expected.Spec, new_node.Spec) - } - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, new_node)}, nil - case m.isFor("DELETE", "/namespaces/default/pods/bar"): - deleted = true - return &http.Response{StatusCode: 204, Header: defaultHeader(), Body: objBody(codec, &test.pods[0])}, nil - case m.isFor("POST", "/namespaces/default/pods/bar/eviction"): - evicted = true - return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: policyObjBody(&policyv1beta1.Eviction{})}, nil - default: - t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req) - return nil, nil - } - }), - } - tf.ClientConfigVal = defaultClientConfig() + }), + } + tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdDrain(tf, buf, errBuf) + buf := bytes.NewBuffer([]byte{}) + errBuf := bytes.NewBuffer([]byte{}) + cmd := NewCmdDrain(tf, buf, errBuf) - saw_fatal := false - fatal_msg := "" - func() { - defer func() { - // Recover from the panic below. - _ = recover() - // Restore cmdutil behavior - cmdutil.DefaultBehaviorOnFatal() + saw_fatal := false + fatal_msg := "" + func() { + defer func() { + // Recover from the panic below. + _ = recover() + // Restore cmdutil behavior + cmdutil.DefaultBehaviorOnFatal() + }() + cmdutil.BehaviorOnFatal(func(e string, code int) { saw_fatal = true; fatal_msg = e; panic(e) }) + cmd.SetArgs(test.args) + cmd.Execute() }() - cmdutil.BehaviorOnFatal(func(e string, code int) { saw_fatal = true; fatal_msg = e; panic(e) }) - cmd.SetArgs(test.args) - cmd.Execute() - }() - if test.expectFatal { - if !saw_fatal { - t.Fatalf("%s: unexpected non-error when using %s", test.description, currMethod) - } - } else { - if saw_fatal { - t.Fatalf("%s: unexpected error when using %s: %s", test.description, currMethod, fatal_msg) + if test.expectFatal { + if !saw_fatal { + t.Fatalf("%s: unexpected non-error when using %s", test.description, currMethod) + } + } else { + if saw_fatal { + t.Fatalf("%s: unexpected error when using %s: %s", test.description, currMethod, fatal_msg) - } - } - - if test.expectDelete { - // Test Delete - if !testEviction && !deleted { - t.Fatalf("%s: pod never deleted", test.description) - } - // Test Eviction - if testEviction && !evicted { - t.Fatalf("%s: pod never evicted", test.description) - } - } - if !test.expectDelete { - if deleted { - t.Fatalf("%s: unexpected delete when using %s", test.description, currMethod) - } - } - - if len(test.expectWarning) > 0 { - if len(errBuf.String()) == 0 { - t.Fatalf("%s: expected warning, but found no stderr output", test.description) + } } - if errBuf.String() != test.expectWarning { - t.Fatalf("%s: actual warning message did not match expected warning message.\n Expecting: %s\n Got: %s", test.description, test.expectWarning, errBuf.String()) + if test.expectDelete { + // Test Delete + if !testEviction && !deleted { + t.Fatalf("%s: pod never deleted", test.description) + } + // Test Eviction + if testEviction && !evicted { + t.Fatalf("%s: pod never evicted", test.description) + } } - } + if !test.expectDelete { + if deleted { + t.Fatalf("%s: unexpected delete when using %s", test.description, currMethod) + } + } + + if len(test.expectWarning) > 0 { + if len(errBuf.String()) == 0 { + t.Fatalf("%s: expected warning, but found no stderr output", test.description) + } + + if errBuf.String() != test.expectWarning { + t.Fatalf("%s: actual warning message did not match expected warning message.\n Expecting: %s\n Got: %s", test.description, test.expectWarning, errBuf.String()) + } + } + }) } } } @@ -824,31 +832,35 @@ func TestDeletePods(t *testing.T) { } for _, test := range tests { - tf := cmdtesting.NewTestFactory() - o := DrainOptions{Factory: tf} - o.mapper, _ = tf.Object() - o.Out = os.Stdout - _, pods := createPods(false) - pendingPods, err := o.waitForDelete(pods, test.interval, test.timeout, false, test.getPodFn) + t.Run(test.description, func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - if test.expectError { - if err == nil { - t.Fatalf("%s: unexpected non-error", test.description) - } else if test.expectedError != nil { - if *test.expectedError != err { - t.Fatalf("%s: the error does not match expected error", test.description) + o := DrainOptions{Factory: tf} + o.mapper, _ = tf.Object() + o.Out = os.Stdout + _, pods := createPods(false) + pendingPods, err := o.waitForDelete(pods, test.interval, test.timeout, false, test.getPodFn) + + if test.expectError { + if err == nil { + t.Fatalf("%s: unexpected non-error", test.description) + } else if test.expectedError != nil { + if *test.expectedError != err { + t.Fatalf("%s: the error does not match expected error", test.description) + } } } - } - if !test.expectError && err != nil { - t.Fatalf("%s: unexpected error", test.description) - } - if test.expectPendingPods && len(pendingPods) == 0 { - t.Fatalf("%s: unexpected empty pods", test.description) - } - if !test.expectPendingPods && len(pendingPods) > 0 { - t.Fatalf("%s: unexpected pending pods", test.description) - } + if !test.expectError && err != nil { + t.Fatalf("%s: unexpected error", test.description) + } + if test.expectPendingPods && len(pendingPods) == 0 { + t.Fatalf("%s: unexpected empty pods", test.description) + } + if !test.expectPendingPods && len(pendingPods) > 0 { + t.Fatalf("%s: unexpected pending pods", test.description) + } + }) } } diff --git a/pkg/kubectl/cmd/edit_test.go b/pkg/kubectl/cmd/edit_test.go index b01c3c4be27..fddc0c7e459 100644 --- a/pkg/kubectl/cmd/edit_test.go +++ b/pkg/kubectl/cmd/edit_test.go @@ -207,6 +207,8 @@ func TestEdit(t *testing.T) { } tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.UnstructuredClientForMappingFunc = func(mapping *meta.RESTMapping) (resource.RESTClient, error) { versionedAPIPath := "" if mapping.GroupVersionKind.Group == "" { diff --git a/pkg/kubectl/cmd/exec_test.go b/pkg/kubectl/cmd/exec_test.go index 58e3ccf9050..c80daabc086 100644 --- a/pkg/kubectl/cmd/exec_test.go +++ b/pkg/kubectl/cmd/exec_test.go @@ -130,38 +130,42 @@ func TestPodAndContainer(t *testing.T) { }, } for _, test := range tests { - tf := cmdtesting.NewTestFactory() - ns := legacyscheme.Codecs + t.Run(test.name, func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { return nil, nil }), - } - tf.Namespace = "test" - tf.ClientConfigVal = defaultClientConfig() + ns := legacyscheme.Codecs - cmd := &cobra.Command{} - options := test.p - options.Err = bytes.NewBuffer([]byte{}) - err := options.Complete(tf, cmd, test.args, test.argsLenAtDash) - if test.expectError && err == nil { - t.Errorf("%s: unexpected non-error", test.name) - } - if !test.expectError && err != nil { - t.Errorf("%s: unexpected error: %v", test.name, err) - } - if err != nil { - continue - } - if options.PodName != test.expectedPod { - t.Errorf("%s: expected: %s, got: %s", test.name, test.expectedPod, options.PodName) - } - if options.ContainerName != test.expectedContainer { - t.Errorf("%s: expected: %s, got: %s", test.name, test.expectedContainer, options.ContainerName) - } - if !reflect.DeepEqual(test.expectedArgs, options.Command) { - t.Errorf("%s: expected: %v, got %v", test.name, test.expectedArgs, options.Command) - } + tf.Client = &fake.RESTClient{ + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { return nil, nil }), + } + tf.Namespace = "test" + tf.ClientConfigVal = defaultClientConfig() + + cmd := &cobra.Command{} + options := test.p + options.Err = bytes.NewBuffer([]byte{}) + err := options.Complete(tf, cmd, test.args, test.argsLenAtDash) + if test.expectError && err == nil { + t.Errorf("%s: unexpected non-error", test.name) + } + if !test.expectError && err != nil { + t.Errorf("%s: unexpected error: %v", test.name, err) + } + if err != nil { + return + } + if options.PodName != test.expectedPod { + t.Errorf("%s: expected: %s, got: %s", test.name, test.expectedPod, options.PodName) + } + if options.ContainerName != test.expectedContainer { + t.Errorf("%s: expected: %s, got: %s", test.name, test.expectedContainer, options.ContainerName) + } + if !reflect.DeepEqual(test.expectedArgs, options.Command) { + t.Errorf("%s: expected: %v, got %v", test.name, test.expectedArgs, options.Command) + } + }) } } @@ -187,67 +191,71 @@ func TestExec(t *testing.T) { }, } for _, test := range tests { - tf := cmdtesting.NewTestFactory() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - ns := legacyscheme.Codecs + t.Run(test.name, func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == test.podPath && m == "GET": - body := objBody(codec, test.pod) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil - default: - // Ensures no GET is performed when deleting by name - t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) - return nil, fmt.Errorf("unexpected request") - } - }), - } - tf.Namespace = "test" - tf.ClientConfigVal = defaultClientConfig() - bufOut := bytes.NewBuffer([]byte{}) - bufErr := bytes.NewBuffer([]byte{}) - bufIn := bytes.NewBuffer([]byte{}) - ex := &fakeRemoteExecutor{} - if test.execErr { - ex.execErr = fmt.Errorf("exec error") - } - params := &ExecOptions{ - StreamOptions: StreamOptions{ - PodName: "foo", - ContainerName: "bar", - In: bufIn, - Out: bufOut, - Err: bufErr, - }, - Executor: ex, - } - cmd := &cobra.Command{} - args := []string{"test", "command"} - if err := params.Complete(tf, cmd, args, -1); err != nil { - t.Fatal(err) - } - err := params.Run() - if test.execErr && err != ex.execErr { - t.Errorf("%s: Unexpected exec error: %v", test.name, err) - continue - } - if !test.execErr && err != nil { - t.Errorf("%s: Unexpected error: %v", test.name, err) - continue - } - if test.execErr { - continue - } - if ex.url.Path != test.execPath { - t.Errorf("%s: Did not get expected path for exec request", test.name) - continue - } - if ex.method != "POST" { - t.Errorf("%s: Did not get method for exec request: %s", test.name, ex.method) - } + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + ns := legacyscheme.Codecs + + tf.Client = &fake.RESTClient{ + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == test.podPath && m == "GET": + body := objBody(codec, test.pod) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil + default: + // Ensures no GET is performed when deleting by name + t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) + return nil, fmt.Errorf("unexpected request") + } + }), + } + tf.Namespace = "test" + tf.ClientConfigVal = defaultClientConfig() + bufOut := bytes.NewBuffer([]byte{}) + bufErr := bytes.NewBuffer([]byte{}) + bufIn := bytes.NewBuffer([]byte{}) + ex := &fakeRemoteExecutor{} + if test.execErr { + ex.execErr = fmt.Errorf("exec error") + } + params := &ExecOptions{ + StreamOptions: StreamOptions{ + PodName: "foo", + ContainerName: "bar", + In: bufIn, + Out: bufOut, + Err: bufErr, + }, + Executor: ex, + } + cmd := &cobra.Command{} + args := []string{"test", "command"} + if err := params.Complete(tf, cmd, args, -1); err != nil { + t.Fatal(err) + } + err := params.Run() + if test.execErr && err != ex.execErr { + t.Errorf("%s: Unexpected exec error: %v", test.name, err) + return + } + if !test.execErr && err != nil { + t.Errorf("%s: Unexpected error: %v", test.name, err) + return + } + if test.execErr { + return + } + if ex.url.Path != test.execPath { + t.Errorf("%s: Did not get expected path for exec request", test.name) + return + } + if ex.method != "POST" { + t.Errorf("%s: Did not get method for exec request: %s", test.name, ex.method) + } + }) } } diff --git a/pkg/kubectl/cmd/expose_test.go b/pkg/kubectl/cmd/expose_test.go index 1239d4bcc72..7097d679407 100644 --- a/pkg/kubectl/cmd/expose_test.go +++ b/pkg/kubectl/cmd/expose_test.go @@ -466,42 +466,46 @@ func TestRunExposeService(t *testing.T) { } for _, test := range tests { - tf := cmdtesting.NewTestFactory() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - ns := legacyscheme.Codecs + t.Run(test.name, func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - tf.Client = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Version: "v1"}, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == test.calls[m] && m == "GET": - return &http.Response{StatusCode: test.status, Header: defaultHeader(), Body: objBody(codec, test.input)}, nil - case p == test.calls[m] && m == "POST": - return &http.Response{StatusCode: test.status, Header: defaultHeader(), Body: objBody(codec, test.output)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = test.ns - buf := bytes.NewBuffer([]byte{}) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + ns := legacyscheme.Codecs - cmd := NewCmdExposeService(tf, buf) - cmd.SetOutput(buf) - for flag, value := range test.flags { - cmd.Flags().Set(flag, value) - } - cmd.Run(cmd, test.args) + tf.Client = &fake.RESTClient{ + GroupVersion: schema.GroupVersion{Version: "v1"}, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == test.calls[m] && m == "GET": + return &http.Response{StatusCode: test.status, Header: defaultHeader(), Body: objBody(codec, test.input)}, nil + case p == test.calls[m] && m == "POST": + return &http.Response{StatusCode: test.status, Header: defaultHeader(), Body: objBody(codec, test.output)}, nil + default: + t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) + return nil, nil + } + }), + } + tf.Namespace = test.ns + buf := bytes.NewBuffer([]byte{}) - out := buf.String() - if _, ok := test.flags["dry-run"]; ok { - test.expected = fmt.Sprintf("service %q exposed (dry run)", test.flags["name"]) - } + cmd := NewCmdExposeService(tf, buf) + cmd.SetOutput(buf) + for flag, value := range test.flags { + cmd.Flags().Set(flag, value) + } + cmd.Run(cmd, test.args) - if !strings.Contains(out, test.expected) { - t.Errorf("%s: Unexpected output! Expected\n%s\ngot\n%s", test.name, test.expected, out) - } + out := buf.String() + if _, ok := test.flags["dry-run"]; ok { + test.expected = fmt.Sprintf("service %q exposed (dry run)", test.flags["name"]) + } + + if !strings.Contains(out, test.expected) { + t.Errorf("%s: Unexpected output! Expected\n%s\ngot\n%s", test.name, test.expected, out) + } + }) } } diff --git a/pkg/kubectl/cmd/label_test.go b/pkg/kubectl/cmd/label_test.go index cde525f2b17..96fe2ffd400 100644 --- a/pkg/kubectl/cmd/label_test.go +++ b/pkg/kubectl/cmd/label_test.go @@ -321,38 +321,44 @@ func TestLabelErrors(t *testing.T) { } for k, testCase := range testCases { - tf := cmdtesting.NewTestFactory() - tf.Namespace = "test" - tf.ClientConfigVal = defaultClientConfig() + t.Run(k, func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdLabel(tf, buf) - cmd.SetOutput(buf) + tf.Namespace = "test" + tf.ClientConfigVal = defaultClientConfig() - for k, v := range testCase.flags { - cmd.Flags().Set(k, v) - } - opts := LabelOptions{} - err := opts.Complete(buf, cmd, testCase.args) - if err == nil { - err = opts.Validate() - } - if err == nil { - err = opts.RunLabel(tf, cmd) - } - if !testCase.errFn(err) { - t.Errorf("%s: unexpected error: %v", k, err) - continue - } - if buf.Len() > 0 { - t.Errorf("buffer should be empty: %s", string(buf.Bytes())) - } + buf := bytes.NewBuffer([]byte{}) + cmd := NewCmdLabel(tf, buf) + cmd.SetOutput(buf) + + for k, v := range testCase.flags { + cmd.Flags().Set(k, v) + } + opts := LabelOptions{} + err := opts.Complete(buf, cmd, testCase.args) + if err == nil { + err = opts.Validate() + } + if err == nil { + err = opts.RunLabel(tf, cmd) + } + if !testCase.errFn(err) { + t.Errorf("%s: unexpected error: %v", k, err) + return + } + if buf.Len() > 0 { + t.Errorf("buffer should be empty: %s", string(buf.Bytes())) + } + }) } } func TestLabelForResourceFromFile(t *testing.T) { pods, _, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -405,6 +411,8 @@ func TestLabelForResourceFromFile(t *testing.T) { func TestLabelLocal(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { @@ -438,6 +446,8 @@ func TestLabelLocal(t *testing.T) { func TestLabelMultipleObjects(t *testing.T) { pods, _, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ diff --git a/pkg/kubectl/cmd/logs_test.go b/pkg/kubectl/cmd/logs_test.go index 8d5f0b9ec92..9476a76be6b 100644 --- a/pkg/kubectl/cmd/logs_test.go +++ b/pkg/kubectl/cmd/logs_test.go @@ -48,39 +48,43 @@ func TestLog(t *testing.T) { }, } for _, test := range tests { - logContent := "test log content" - tf := cmdtesting.NewTestFactory() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - ns := legacyscheme.Codecs + t.Run(test.name, func(t *testing.T) { + logContent := "test log content" + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == test.podPath && m == "GET": - body := objBody(codec, test.pod) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil - case p == test.logPath && m == "GET": - body := ioutil.NopCloser(bytes.NewBufferString(logContent)) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil - default: - // Ensures no GET is performed when deleting by name - t.Errorf("%s: unexpected request: %#v\n%#v", test.name, req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + ns := legacyscheme.Codecs - cmd := NewCmdLogs(tf, buf, buf) - cmd.Flags().Set("namespace", "test") - cmd.Run(cmd, []string{"foo"}) + tf.Client = &fake.RESTClient{ + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == test.podPath && m == "GET": + body := objBody(codec, test.pod) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil + case p == test.logPath && m == "GET": + body := ioutil.NopCloser(bytes.NewBufferString(logContent)) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil + default: + // Ensures no GET is performed when deleting by name + t.Errorf("%s: unexpected request: %#v\n%#v", test.name, req.URL, req) + return nil, nil + } + }), + } + tf.Namespace = "test" + tf.ClientConfigVal = defaultClientConfig() + buf := bytes.NewBuffer([]byte{}) - if buf.String() != logContent { - t.Errorf("%s: did not get expected log content. Got: %s", test.name, buf.String()) - } + cmd := NewCmdLogs(tf, buf, buf) + cmd.Flags().Set("namespace", "test") + cmd.Run(cmd, []string{"foo"}) + + if buf.String() != logContent { + t.Errorf("%s: did not get expected log content. Got: %s", test.name, buf.String()) + } + }) } } @@ -101,6 +105,7 @@ func testPod() *api.Pod { func TestValidateLogFlags(t *testing.T) { f := cmdtesting.NewTestFactory() + defer f.Cleanup() tests := []struct { name string @@ -152,6 +157,7 @@ func TestValidateLogFlags(t *testing.T) { func TestLogComplete(t *testing.T) { f := cmdtesting.NewTestFactory() + defer f.Cleanup() tests := []struct { name string diff --git a/pkg/kubectl/cmd/patch_test.go b/pkg/kubectl/cmd/patch_test.go index dc276b80acd..6d9757eb5c4 100644 --- a/pkg/kubectl/cmd/patch_test.go +++ b/pkg/kubectl/cmd/patch_test.go @@ -32,6 +32,8 @@ func TestPatchObject(t *testing.T) { _, svc, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -72,6 +74,8 @@ func TestPatchObjectFromFile(t *testing.T) { _, svc, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -108,6 +112,8 @@ func TestPatchNoop(t *testing.T) { patchObject := &svc.Items[0] tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -154,6 +160,8 @@ func TestPatchObjectFromFileOutput(t *testing.T) { svcCopy.Labels["post-patch"] = "post-patch-value" tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ diff --git a/pkg/kubectl/cmd/plugin_test.go b/pkg/kubectl/cmd/plugin_test.go index bfda32eb64f..205b266743f 100644 --- a/pkg/kubectl/cmd/plugin_test.go +++ b/pkg/kubectl/cmd/plugin_test.go @@ -80,34 +80,38 @@ func TestPluginCmd(t *testing.T) { } for _, test := range tests { - inBuf := bytes.NewBuffer([]byte{}) - outBuf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + t.Run(test.name, func(t *testing.T) { + inBuf := bytes.NewBuffer([]byte{}) + outBuf := bytes.NewBuffer([]byte{}) + errBuf := bytes.NewBuffer([]byte{}) - cmdutil.BehaviorOnFatal(func(str string, code int) { - errBuf.Write([]byte(str)) - }) + cmdutil.BehaviorOnFatal(func(str string, code int) { + errBuf.Write([]byte(str)) + }) - runner := &mockPluginRunner{ - success: test.expectedSuccess, - } - - f := cmdtesting.NewTestFactory() - cmd := NewCmdForPlugin(f, test.plugin, runner, inBuf, outBuf, errBuf) - if cmd == nil { - if !test.expectedNilCmd { - t.Fatalf("%s: command was unexpectedly not registered", test.name) + runner := &mockPluginRunner{ + success: test.expectedSuccess, } - continue - } - cmd.Run(cmd, []string{}) - if test.expectedSuccess && outBuf.String() != fmt.Sprintf("ok: %s", test.plugin.Name) { - t.Errorf("%s: unexpected output: %q", test.name, outBuf.String()) - } + f := cmdtesting.NewTestFactory() + defer f.Cleanup() - if !test.expectedSuccess && errBuf.String() != fmt.Sprintf("error: oops %s", test.plugin.Name) { - t.Errorf("%s: unexpected err output: %q", test.name, errBuf.String()) - } + cmd := NewCmdForPlugin(f, test.plugin, runner, inBuf, outBuf, errBuf) + if cmd == nil { + if !test.expectedNilCmd { + t.Fatalf("%s: command was unexpectedly not registered", test.name) + } + return + } + cmd.Run(cmd, []string{}) + + if test.expectedSuccess && outBuf.String() != fmt.Sprintf("ok: %s", test.plugin.Name) { + t.Errorf("%s: unexpected output: %q", test.name, outBuf.String()) + } + + if !test.expectedSuccess && errBuf.String() != fmt.Sprintf("error: oops %s", test.plugin.Name) { + t.Errorf("%s: unexpected err output: %q", test.name, errBuf.String()) + } + }) } } diff --git a/pkg/kubectl/cmd/portforward_test.go b/pkg/kubectl/cmd/portforward_test.go index 673df92c2c9..a4ba152e287 100644 --- a/pkg/kubectl/cmd/portforward_test.go +++ b/pkg/kubectl/cmd/portforward_test.go @@ -71,68 +71,72 @@ func testPortForward(t *testing.T, flags map[string]string, args []string) { }, } for _, test := range tests { - var err error - tf := cmdtesting.NewTestFactory() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - ns := legacyscheme.Codecs + t.Run(test.name, func(t *testing.T) { + var err error + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - tf.Client = &fake.RESTClient{ - VersionedAPIPath: "/api/v1", - GroupVersion: schema.GroupVersion{Group: ""}, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == test.podPath && m == "GET": - body := objBody(codec, test.pod) - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil - default: - // Ensures no GET is performed when deleting by name - t.Errorf("%s: unexpected request: %#v\n%#v", test.name, req.URL, req) - return nil, nil + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + ns := legacyscheme.Codecs + + tf.Client = &fake.RESTClient{ + VersionedAPIPath: "/api/v1", + GroupVersion: schema.GroupVersion{Group: ""}, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case p == test.podPath && m == "GET": + body := objBody(codec, test.pod) + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil + default: + // Ensures no GET is performed when deleting by name + t.Errorf("%s: unexpected request: %#v\n%#v", test.name, req.URL, req) + return nil, nil + } + }), + } + tf.Namespace = "test" + tf.ClientConfigVal = defaultClientConfig() + ff := &fakePortForwarder{} + if test.pfErr { + ff.pfErr = fmt.Errorf("pf error") + } + + opts := &PortForwardOptions{} + cmd := NewCmdPortForward(tf, os.Stdout, os.Stderr) + cmd.Run = func(cmd *cobra.Command, args []string) { + if err = opts.Complete(tf, cmd, args); err != nil { + return } - }), - } - tf.Namespace = "test" - tf.ClientConfigVal = defaultClientConfig() - ff := &fakePortForwarder{} - if test.pfErr { - ff.pfErr = fmt.Errorf("pf error") - } + opts.PortForwarder = ff + if err = opts.Validate(); err != nil { + return + } + err = opts.RunPortForward() + } - opts := &PortForwardOptions{} - cmd := NewCmdPortForward(tf, os.Stdout, os.Stderr) - cmd.Run = func(cmd *cobra.Command, args []string) { - if err = opts.Complete(tf, cmd, args); err != nil { + for name, value := range flags { + cmd.Flags().Set(name, value) + } + cmd.Run(cmd, args) + + if test.pfErr && err != ff.pfErr { + t.Errorf("%s: Unexpected port-forward error: %v", test.name, err) + } + if !test.pfErr && err != nil { + t.Errorf("%s: Unexpected error: %v", test.name, err) + } + if test.pfErr { return } - opts.PortForwarder = ff - if err = opts.Validate(); err != nil { - return + + if ff.url == nil || ff.url.Path != test.pfPath { + t.Errorf("%s: Did not get expected path for portforward request", test.name) } - err = opts.RunPortForward() - } - - for name, value := range flags { - cmd.Flags().Set(name, value) - } - cmd.Run(cmd, args) - - if test.pfErr && err != ff.pfErr { - t.Errorf("%s: Unexpected port-forward error: %v", test.name, err) - } - if !test.pfErr && err != nil { - t.Errorf("%s: Unexpected error: %v", test.name, err) - } - if test.pfErr { - continue - } - - if ff.url.Path != test.pfPath { - t.Errorf("%s: Did not get expected path for portforward request", test.name) - } - if ff.method != "POST" { - t.Errorf("%s: Did not get method for attach request: %s", test.name, ff.method) - } + if ff.method != "POST" { + t.Errorf("%s: Did not get method for attach request: %s", test.name, ff.method) + } + }) } } diff --git a/pkg/kubectl/cmd/replace_test.go b/pkg/kubectl/cmd/replace_test.go index 164c2ab0d20..e3604da0138 100644 --- a/pkg/kubectl/cmd/replace_test.go +++ b/pkg/kubectl/cmd/replace_test.go @@ -33,6 +33,7 @@ func TestReplaceObject(t *testing.T) { _, _, rc := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) deleted := false @@ -89,6 +90,7 @@ func TestReplaceMultipleObject(t *testing.T) { _, svc, rc := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) redisMasterDeleted := false @@ -159,6 +161,7 @@ func TestReplaceDirectory(t *testing.T) { _, _, rc := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) created := map[string]bool{} @@ -216,6 +219,7 @@ func TestForceReplaceObjectNotFound(t *testing.T) { _, _, rc := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ diff --git a/pkg/kubectl/cmd/resource/get_test.go b/pkg/kubectl/cmd/resource/get_test.go index 8f6a03cb0ad..162fa6392d8 100644 --- a/pkg/kubectl/cmd/resource/get_test.go +++ b/pkg/kubectl/cmd/resource/get_test.go @@ -198,6 +198,7 @@ func testComponentStatusData() *api.ComponentStatusList { 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() + defer tf.Cleanup() _, _, codec := cmdtesting.NewExternalScheme() tf.OpenAPISchemaFunc = openapitesting.CreateOpenAPISchemaFunc(openapiSchemaPath) @@ -272,6 +273,7 @@ func TestGetUnknownSchemaObject(t *testing.T) { // 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() + defer tf.Cleanup() codec := testapi.Default.Codec() tf.UnstructuredClient = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, @@ -294,6 +296,7 @@ func TestGetObjectsWithOpenAPIOutputFormatPresent(t *testing.T) { pods, _, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) // overide the openAPISchema function to return custom output @@ -351,6 +354,7 @@ func TestGetObjects(t *testing.T) { pods, _, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -417,6 +421,8 @@ func TestGetObjectsFiltered(t *testing.T) { for i, test := range testCases { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -458,6 +464,7 @@ func TestGetObjectIgnoreNotFound(t *testing.T) { } tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -511,6 +518,7 @@ func TestGetSortedObjects(t *testing.T) { } tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -544,6 +552,7 @@ func TestGetObjectsIdentifiedByFile(t *testing.T) { pods, _, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -571,6 +580,7 @@ func TestGetListObjects(t *testing.T) { pods, _, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -598,6 +608,7 @@ func TestGetAllListObjects(t *testing.T) { pods, _, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -626,6 +637,7 @@ func TestGetListComponentStatus(t *testing.T) { statuses := testComponentStatusData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -667,6 +679,7 @@ func TestGetMixedGenericObjects(t *testing.T) { } tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -717,6 +730,7 @@ func TestGetMultipleTypeObjects(t *testing.T) { pods, svc, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -756,6 +770,7 @@ func TestGetMultipleTypeObjectsAsList(t *testing.T) { pods, svc, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -858,6 +873,7 @@ func TestGetMultipleTypeObjectsWithLabelSelector(t *testing.T) { pods, svc, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -902,6 +918,7 @@ func TestGetMultipleTypeObjectsWithFieldSelector(t *testing.T) { pods, svc, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -954,6 +971,7 @@ func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) { } tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -993,6 +1011,7 @@ func TestGetByFormatForcesFlag(t *testing.T) { pods, _, _ := testData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -1089,6 +1108,7 @@ func TestWatchLabelSelector(t *testing.T) { pods, events := watchTestData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) podList := &api.PodList{ @@ -1141,6 +1161,7 @@ func TestWatchFieldSelector(t *testing.T) { pods, events := watchTestData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) podList := &api.PodList{ @@ -1193,6 +1214,7 @@ func TestWatchResource(t *testing.T) { pods, events := watchTestData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -1237,6 +1259,7 @@ func TestWatchResourceIdentifiedByFile(t *testing.T) { pods, events := watchTestData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -1282,6 +1305,7 @@ func TestWatchOnlyResource(t *testing.T) { pods, events := watchTestData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) tf.UnstructuredClient = &fake.RESTClient{ @@ -1325,6 +1349,7 @@ func TestWatchOnlyList(t *testing.T) { pods, events := watchTestData() tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) podList := &api.PodList{ diff --git a/pkg/kubectl/cmd/rollingupdate_test.go b/pkg/kubectl/cmd/rollingupdate_test.go index 553afb29a00..4e452dbb625 100644 --- a/pkg/kubectl/cmd/rollingupdate_test.go +++ b/pkg/kubectl/cmd/rollingupdate_test.go @@ -25,6 +25,7 @@ import ( func TestValidateArgs(t *testing.T) { f := cmdtesting.NewTestFactory() + defer f.Cleanup() tests := []struct { testName string diff --git a/pkg/kubectl/cmd/run_test.go b/pkg/kubectl/cmd/run_test.go index 5b47b087876..88d1dbbdc99 100644 --- a/pkg/kubectl/cmd/run_test.go +++ b/pkg/kubectl/cmd/run_test.go @@ -168,35 +168,39 @@ func TestRunArgsFollowDashRules(t *testing.T) { }, } for _, test := range tests { - tf := cmdtesting.NewTestFactory() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - ns := legacyscheme.Codecs + t.Run(test.name, func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - tf.Client = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Version: "v1"}, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - if req.URL.Path == "/namespaces/test/replicationcontrollers" { - return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: objBody(codec, rc)}, nil - } - return &http.Response{ - StatusCode: http.StatusOK, - Body: ioutil.NopCloser(bytes.NewBuffer([]byte("{}"))), - }, nil - }), - } - tf.Namespace = "test" - tf.ClientConfigVal = &restclient.Config{} - cmd := NewCmdRun(tf, os.Stdin, os.Stdout, os.Stderr) - cmd.Flags().Set("image", "nginx") - cmd.Flags().Set("generator", "run/v1") - err := RunRun(tf, os.Stdin, os.Stdout, os.Stderr, cmd, test.args, test.argsLenAtDash) - if test.expectError && err == nil { - t.Errorf("unexpected non-error (%s)", test.name) - } - if !test.expectError && err != nil { - t.Errorf("unexpected error: %v (%s)", err, test.name) - } + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + ns := legacyscheme.Codecs + + tf.Client = &fake.RESTClient{ + GroupVersion: schema.GroupVersion{Version: "v1"}, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + if req.URL.Path == "/namespaces/test/replicationcontrollers" { + return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: objBody(codec, rc)}, nil + } + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewBuffer([]byte("{}"))), + }, nil + }), + } + tf.Namespace = "test" + tf.ClientConfigVal = &restclient.Config{} + cmd := NewCmdRun(tf, os.Stdin, os.Stdout, os.Stderr) + cmd.Flags().Set("image", "nginx") + cmd.Flags().Set("generator", "run/v1") + err := RunRun(tf, os.Stdin, os.Stdout, os.Stderr, cmd, test.args, test.argsLenAtDash) + if test.expectError && err == nil { + t.Errorf("unexpected non-error (%s)", test.name) + } + if !test.expectError && err != nil { + t.Errorf("unexpected error: %v (%s)", err, test.name) + } + }) } } @@ -292,90 +296,98 @@ func TestGenerateService(t *testing.T) { }, } for _, test := range tests { - sawPOST := false - tf := cmdtesting.NewTestFactory() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - ns := legacyscheme.Codecs + t.Run(test.name, func(t *testing.T) { + sawPOST := false + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - tf.ClientConfigVal = defaultClientConfig() - tf.Client = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Version: "v1"}, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case test.expectPOST && m == "POST" && p == "/namespaces/namespace/services": - sawPOST = true - body := objBody(codec, &test.service) - data, err := ioutil.ReadAll(req.Body) - if err != nil { - t.Fatalf("unexpected error: %v", err) + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + ns := legacyscheme.Codecs + + tf.ClientConfigVal = defaultClientConfig() + tf.Client = &fake.RESTClient{ + GroupVersion: schema.GroupVersion{Version: "v1"}, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m := req.URL.Path, req.Method; { + case test.expectPOST && m == "POST" && p == "/namespaces/namespace/services": + sawPOST = true + body := objBody(codec, &test.service) + data, err := ioutil.ReadAll(req.Body) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + defer req.Body.Close() + svc := &api.Service{} + if err := runtime.DecodeInto(codec, data, svc); err != nil { + t.Fatalf("unexpected error: %v", err) + } + // Copy things that are defaulted by the system + test.service.Annotations = svc.Annotations + + if !reflect.DeepEqual(&test.service, svc) { + t.Errorf("expected:\n%v\nsaw:\n%v\n", &test.service, svc) + } + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil + default: + // Ensures no GET is performed when deleting by name + t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) + return nil, fmt.Errorf("unexpected request") } - defer req.Body.Close() - svc := &api.Service{} - if err := runtime.DecodeInto(codec, data, svc); err != nil { - t.Fatalf("unexpected error: %v", err) - } - // Copy things that are defaulted by the system - test.service.Annotations = svc.Annotations - - if !reflect.DeepEqual(&test.service, svc) { - t.Errorf("expected:\n%v\nsaw:\n%v\n", &test.service, svc) - } - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil - default: - // Ensures no GET is performed when deleting by name - t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) - return nil, fmt.Errorf("unexpected request") - } - }), - } - cmd := &cobra.Command{} - cmd.Flags().Bool(cmdutil.ApplyAnnotationsFlag, false, "") - cmd.Flags().Bool("record", false, "Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists.") - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - addRunFlags(cmd) - - if !test.expectPOST { - cmd.Flags().Set("dry-run", "true") - } - - if len(test.port) > 0 { - cmd.Flags().Set("port", test.port) - test.params["port"] = test.port - } - - buff := &bytes.Buffer{} - _, err := generateService(tf, cmd, test.args, test.serviceGenerator, test.params, "namespace", buff) - if test.expectErr { - if err == nil { - t.Error("unexpected non-error") + }), } - continue - } - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if test.expectPOST != sawPOST { - t.Errorf("expectPost: %v, sawPost: %v", test.expectPOST, sawPOST) - } + cmd := &cobra.Command{} + cmd.Flags().Bool(cmdutil.ApplyAnnotationsFlag, false, "") + cmd.Flags().Bool("record", false, "Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists.") + cmdutil.AddPrinterFlags(cmd) + cmdutil.AddInclude3rdPartyFlags(cmd) + addRunFlags(cmd) + + if !test.expectPOST { + cmd.Flags().Set("dry-run", "true") + } + + if len(test.port) > 0 { + cmd.Flags().Set("port", test.port) + test.params["port"] = test.port + } + + buff := &bytes.Buffer{} + _, err := generateService(tf, cmd, test.args, test.serviceGenerator, test.params, "namespace", buff) + if test.expectErr { + if err == nil { + t.Error("unexpected non-error") + } + return + } + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if test.expectPOST != sawPOST { + t.Errorf("expectPost: %v, sawPost: %v", test.expectPOST, sawPOST) + } + }) } } func TestRunValidations(t *testing.T) { tests := []struct { + name string args []string flags map[string]string expectedErr string }{ { + name: "test missing name error", expectedErr: "NAME is required", }, { + name: "test missing --image error", args: []string{"test"}, expectedErr: "--image is required", }, { + name: "test invalid image name error", args: []string{"test"}, flags: map[string]string{ "image": "#", @@ -383,6 +395,7 @@ func TestRunValidations(t *testing.T) { expectedErr: "Invalid image name", }, { + name: "test stdin replicas value", args: []string{"test"}, flags: map[string]string{ "image": "busybox", @@ -392,6 +405,7 @@ func TestRunValidations(t *testing.T) { expectedErr: "stdin requires that replicas is 1", }, { + name: "test rm errors when used on non-attached containers", args: []string{"test"}, flags: map[string]string{ "image": "busybox", @@ -400,6 +414,7 @@ func TestRunValidations(t *testing.T) { expectedErr: "rm should only be used for attached containers", }, { + name: "test error on attached containers options", args: []string{"test"}, flags: map[string]string{ "image": "busybox", @@ -409,6 +424,7 @@ func TestRunValidations(t *testing.T) { expectedErr: "can't be used with attached containers options", }, { + name: "test error on attached containers options, with value from stdin", args: []string{"test"}, flags: map[string]string{ "image": "busybox", @@ -418,6 +434,7 @@ func TestRunValidations(t *testing.T) { expectedErr: "can't be used with attached containers options", }, { + name: "test error on attached containers options, with value from stdin and tty", args: []string{"test"}, flags: map[string]string{ "image": "busybox", @@ -428,6 +445,7 @@ func TestRunValidations(t *testing.T) { expectedErr: "can't be used with attached containers options", }, { + name: "test error when tty=true and no stdin provided", args: []string{"test"}, flags: map[string]string{ "image": "busybox", @@ -437,28 +455,32 @@ func TestRunValidations(t *testing.T) { }, } for _, test := range tests { - tf := cmdtesting.NewTestFactory() - _, _, codec := cmdtesting.NewExternalScheme() - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: scheme.Codecs, - Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, cmdtesting.NewInternalType("", "", ""))}, - } - tf.Namespace = "test" - tf.ClientConfigVal = defaultClientConfig() - inBuf := bytes.NewReader([]byte{}) - outBuf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + t.Run(test.name, func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - cmd := NewCmdRun(tf, inBuf, outBuf, errBuf) - for flagName, flagValue := range test.flags { - cmd.Flags().Set(flagName, flagValue) - } - err := RunRun(tf, inBuf, outBuf, errBuf, cmd, test.args, cmd.ArgsLenAtDash()) - if err != nil && len(test.expectedErr) > 0 { - if !strings.Contains(err.Error(), test.expectedErr) { - t.Errorf("unexpected error: %v", err) + _, _, codec := cmdtesting.NewExternalScheme() + tf.Client = &fake.RESTClient{ + NegotiatedSerializer: scheme.Codecs, + Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, cmdtesting.NewInternalType("", "", ""))}, } - } + tf.Namespace = "test" + tf.ClientConfigVal = defaultClientConfig() + inBuf := bytes.NewReader([]byte{}) + outBuf := bytes.NewBuffer([]byte{}) + errBuf := bytes.NewBuffer([]byte{}) + + cmd := NewCmdRun(tf, inBuf, outBuf, errBuf) + for flagName, flagValue := range test.flags { + cmd.Flags().Set(flagName, flagValue) + } + err := RunRun(tf, inBuf, outBuf, errBuf, cmd, test.args, cmd.ArgsLenAtDash()) + if err != nil && len(test.expectedErr) > 0 { + if !strings.Contains(err.Error(), test.expectedErr) { + t.Errorf("unexpected error: %v", err) + } + } + }) } } diff --git a/pkg/kubectl/cmd/set/set_env_test.go b/pkg/kubectl/cmd/set/set_env_test.go index 44ed9887971..22c429a2734 100644 --- a/pkg/kubectl/cmd/set/set_env_test.go +++ b/pkg/kubectl/cmd/set/set_env_test.go @@ -47,6 +47,8 @@ import ( func TestSetEnvLocal(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Version: ""}, @@ -83,6 +85,8 @@ func TestSetEnvLocal(t *testing.T) { func TestSetMultiResourcesEnvLocal(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -122,12 +126,14 @@ func TestSetMultiResourcesEnvLocal(t *testing.T) { func TestSetEnvRemote(t *testing.T) { inputs := []struct { + name string object runtime.Object apiPrefix, apiGroup, apiVersion string testAPIGroup string args []string }{ { + name: "test extensions.v1beta1 replicaset", object: &extensionsv1beta1.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: extensionsv1beta1.ReplicaSetSpec{ @@ -148,6 +154,7 @@ func TestSetEnvRemote(t *testing.T) { args: []string{"replicaset", "nginx", "env=prod"}, }, { + name: "test apps.v1beta2 replicaset", object: &appsv1beta2.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1beta2.ReplicaSetSpec{ @@ -168,6 +175,7 @@ func TestSetEnvRemote(t *testing.T) { args: []string{"replicaset", "nginx", "env=prod"}, }, { + name: "test appsv1 replicaset", object: &appsv1.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1.ReplicaSetSpec{ @@ -188,6 +196,7 @@ func TestSetEnvRemote(t *testing.T) { args: []string{"replicaset", "nginx", "env=prod"}, }, { + name: "test extensions.v1beta1 daemonset", object: &extensionsv1beta1.DaemonSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: extensionsv1beta1.DaemonSetSpec{ @@ -208,6 +217,7 @@ func TestSetEnvRemote(t *testing.T) { args: []string{"daemonset", "nginx", "env=prod"}, }, { + name: "test appsv1beta2 daemonset", object: &appsv1beta2.DaemonSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1beta2.DaemonSetSpec{ @@ -228,6 +238,7 @@ func TestSetEnvRemote(t *testing.T) { args: []string{"daemonset", "nginx", "env=prod"}, }, { + name: "test appsv1 daemonset", object: &appsv1.DaemonSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1.DaemonSetSpec{ @@ -248,6 +259,7 @@ func TestSetEnvRemote(t *testing.T) { args: []string{"daemonset", "nginx", "env=prod"}, }, { + name: "test extensions.v1beta1 deployment", object: &extensionsv1beta1.Deployment{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: extensionsv1beta1.DeploymentSpec{ @@ -268,6 +280,7 @@ func TestSetEnvRemote(t *testing.T) { args: []string{"deployment", "nginx", "env=prod"}, }, { + name: "test appsv1bta1 deployment", object: &appsv1beta1.Deployment{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1beta1.DeploymentSpec{ @@ -288,6 +301,7 @@ func TestSetEnvRemote(t *testing.T) { args: []string{"deployment", "nginx", "env=prod"}, }, { + name: "test appsv1beta2n deployment", object: &appsv1beta2.Deployment{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1beta2.DeploymentSpec{ @@ -308,6 +322,7 @@ func TestSetEnvRemote(t *testing.T) { args: []string{"deployment", "nginx", "env=prod"}, }, { + name: "test appsv1 deployment", object: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1.DeploymentSpec{ @@ -328,6 +343,7 @@ func TestSetEnvRemote(t *testing.T) { args: []string{"deployment", "nginx", "env=prod"}, }, { + name: "test appsv1beta1 statefulset", object: &appsv1beta1.StatefulSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1beta1.StatefulSetSpec{ @@ -348,6 +364,7 @@ func TestSetEnvRemote(t *testing.T) { args: []string{"statefulset", "nginx", "env=prod"}, }, { + name: "test appsv1beta2 statefulset", object: &appsv1beta2.StatefulSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1beta2.StatefulSetSpec{ @@ -368,6 +385,7 @@ func TestSetEnvRemote(t *testing.T) { args: []string{"statefulset", "nginx", "env=prod"}, }, { + name: "test appsv1 statefulset", object: &appsv1.StatefulSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1.StatefulSetSpec{ @@ -429,48 +447,52 @@ func TestSetEnvRemote(t *testing.T) { }, } for _, input := range inputs { - groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion} - testapi.Default = testapi.Groups[input.testAPIGroup] - tf := cmdtesting.NewTestFactory() - codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion) - ns := legacyscheme.Codecs - tf.Namespace = "test" - tf.Client = &fake.RESTClient{ - GroupVersion: groupVersion, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", tf.Namespace, input.args[1]) - switch p, m := req.URL.Path, req.Method; { - case p == resourcePath && m == http.MethodGet: - return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil - case p == resourcePath && m == http.MethodPatch: - stream, err := req.GetBody() - if err != nil { - return nil, err + t.Run(input.name, func(t *testing.T) { + groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion} + testapi.Default = testapi.Groups[input.testAPIGroup] + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + + codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion) + ns := legacyscheme.Codecs + tf.Namespace = "test" + tf.Client = &fake.RESTClient{ + GroupVersion: groupVersion, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", tf.Namespace, input.args[1]) + switch p, m := req.URL.Path, req.Method; { + case p == resourcePath && m == http.MethodGet: + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil + case p == resourcePath && m == http.MethodPatch: + stream, err := req.GetBody() + if err != nil { + return nil, err + } + bytes, err := ioutil.ReadAll(stream) + if err != nil { + return nil, err + } + assert.Contains(t, string(bytes), `"value":`+`"`+"prod"+`"`, fmt.Sprintf("env not updated for %#v", input.object)) + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil + default: + t.Errorf("%s: unexpected request: %s %#v\n%#v", "image", req.Method, req.URL, req) + return nil, fmt.Errorf("unexpected request") } - bytes, err := ioutil.ReadAll(stream) - if err != nil { - return nil, err - } - assert.Contains(t, string(bytes), `"value":`+`"`+"prod"+`"`, fmt.Sprintf("env not updated for %#v", input.object)) - return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil - default: - t.Errorf("%s: unexpected request: %s %#v\n%#v", "image", req.Method, req.URL, req) - return nil, fmt.Errorf("unexpected request") - } - }), - VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()), - } - out := new(bytes.Buffer) - cmd := NewCmdEnv(tf, out, out, out) - cmd.SetOutput(out) - cmd.Flags().Set("output", "yaml") - opts := EnvOptions{ - Out: out, - Local: false} - err := opts.Complete(tf, cmd, input.args) - assert.NoError(t, err) - err = opts.RunEnv(tf) - assert.NoError(t, err) + }), + VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()), + } + out := new(bytes.Buffer) + cmd := NewCmdEnv(tf, out, out, out) + cmd.SetOutput(out) + cmd.Flags().Set("output", "yaml") + opts := EnvOptions{ + Out: out, + Local: false} + err := opts.Complete(tf, cmd, input.args) + assert.NoError(t, err) + err = opts.RunEnv(tf) + assert.NoError(t, err) + }) } } diff --git a/pkg/kubectl/cmd/set/set_image_test.go b/pkg/kubectl/cmd/set/set_image_test.go index 71de566d19c..5c5cf358857 100644 --- a/pkg/kubectl/cmd/set/set_image_test.go +++ b/pkg/kubectl/cmd/set/set_image_test.go @@ -46,6 +46,8 @@ import ( func TestImageLocal(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -149,6 +151,8 @@ func TestSetImageValidation(t *testing.T) { func TestSetMultiResourcesImageLocal(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -190,12 +194,14 @@ func TestSetMultiResourcesImageLocal(t *testing.T) { func TestSetImageRemote(t *testing.T) { inputs := []struct { + name string object runtime.Object apiPrefix, apiGroup, apiVersion string testAPIGroup string args []string }{ { + name: "set image extensionsv1beta1 ReplicaSet", object: &extensionsv1beta1.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: extensionsv1beta1.ReplicaSetSpec{ @@ -216,6 +222,7 @@ func TestSetImageRemote(t *testing.T) { args: []string{"replicaset", "nginx", "*=thingy"}, }, { + name: "set image appsv1beta2 ReplicaSet", object: &appsv1beta2.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1beta2.ReplicaSetSpec{ @@ -236,6 +243,7 @@ func TestSetImageRemote(t *testing.T) { args: []string{"replicaset", "nginx", "*=thingy"}, }, { + name: "set image appsv1 ReplicaSet", object: &appsv1.ReplicaSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1.ReplicaSetSpec{ @@ -256,6 +264,7 @@ func TestSetImageRemote(t *testing.T) { args: []string{"replicaset", "nginx", "*=thingy"}, }, { + name: "set image extensionsv1beta1 DaemonSet", object: &extensionsv1beta1.DaemonSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: extensionsv1beta1.DaemonSetSpec{ @@ -276,6 +285,7 @@ func TestSetImageRemote(t *testing.T) { args: []string{"daemonset", "nginx", "*=thingy"}, }, { + name: "set image appsv1beta2 DaemonSet", object: &appsv1beta2.DaemonSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1beta2.DaemonSetSpec{ @@ -296,6 +306,7 @@ func TestSetImageRemote(t *testing.T) { args: []string{"daemonset", "nginx", "*=thingy"}, }, { + name: "set image appsv1 DaemonSet", object: &appsv1.DaemonSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1.DaemonSetSpec{ @@ -316,6 +327,7 @@ func TestSetImageRemote(t *testing.T) { args: []string{"daemonset", "nginx", "*=thingy"}, }, { + name: "set image extensionsv1beta1 Deployment", object: &extensionsv1beta1.Deployment{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: extensionsv1beta1.DeploymentSpec{ @@ -336,6 +348,7 @@ func TestSetImageRemote(t *testing.T) { args: []string{"deployment", "nginx", "*=thingy"}, }, { + name: "set image appsv1beta1 Deployment", object: &appsv1beta1.Deployment{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1beta1.DeploymentSpec{ @@ -356,6 +369,7 @@ func TestSetImageRemote(t *testing.T) { args: []string{"deployment", "nginx", "*=thingy"}, }, { + name: "set image appsv1beta2 Deployment", object: &appsv1beta2.Deployment{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1beta2.DeploymentSpec{ @@ -376,6 +390,7 @@ func TestSetImageRemote(t *testing.T) { args: []string{"deployment", "nginx", "*=thingy"}, }, { + name: "set image appsv1 Deployment", object: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1.DeploymentSpec{ @@ -396,6 +411,7 @@ func TestSetImageRemote(t *testing.T) { args: []string{"deployment", "nginx", "*=thingy"}, }, { + name: "set image appsv1beta1 StatefulSet", object: &appsv1beta1.StatefulSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1beta1.StatefulSetSpec{ @@ -416,6 +432,7 @@ func TestSetImageRemote(t *testing.T) { args: []string{"statefulset", "nginx", "*=thingy"}, }, { + name: "set image appsv1beta2 StatefulSet", object: &appsv1beta2.StatefulSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1beta2.StatefulSetSpec{ @@ -436,6 +453,7 @@ func TestSetImageRemote(t *testing.T) { args: []string{"statefulset", "nginx", "*=thingy"}, }, { + name: "set image appsv1 StatefulSet", object: &appsv1.StatefulSet{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: appsv1.StatefulSetSpec{ @@ -456,6 +474,7 @@ func TestSetImageRemote(t *testing.T) { args: []string{"statefulset", "nginx", "*=thingy"}, }, { + name: "set image batchv1 Job", object: &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: batchv1.JobSpec{ @@ -476,6 +495,7 @@ func TestSetImageRemote(t *testing.T) { args: []string{"job", "nginx", "*=thingy"}, }, { + name: "set image v1.ReplicationController", object: &v1.ReplicationController{ ObjectMeta: metav1.ObjectMeta{Name: "nginx"}, Spec: v1.ReplicationControllerSpec{ @@ -497,48 +517,52 @@ func TestSetImageRemote(t *testing.T) { }, } for _, input := range inputs { - groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion} - testapi.Default = testapi.Groups[input.testAPIGroup] - tf := cmdtesting.NewTestFactory() - codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion) - ns := legacyscheme.Codecs - tf.Namespace = "test" - tf.Client = &fake.RESTClient{ - GroupVersion: groupVersion, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", tf.Namespace, input.args[1]) - switch p, m := req.URL.Path, req.Method; { - case p == resourcePath && m == http.MethodGet: - return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil - case p == resourcePath && m == http.MethodPatch: - stream, err := req.GetBody() - if err != nil { - return nil, err + t.Run(input.name, func(t *testing.T) { + groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion} + testapi.Default = testapi.Groups[input.testAPIGroup] + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + + codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion) + ns := legacyscheme.Codecs + tf.Namespace = "test" + tf.Client = &fake.RESTClient{ + GroupVersion: groupVersion, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", tf.Namespace, input.args[1]) + switch p, m := req.URL.Path, req.Method; { + case p == resourcePath && m == http.MethodGet: + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil + case p == resourcePath && m == http.MethodPatch: + stream, err := req.GetBody() + if err != nil { + return nil, err + } + bytes, err := ioutil.ReadAll(stream) + if err != nil { + return nil, err + } + assert.Contains(t, string(bytes), `"image":`+`"`+"thingy"+`"`, fmt.Sprintf("image not updated for %#v", input.object)) + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil + default: + t.Errorf("%s: unexpected request: %s %#v\n%#v", "image", req.Method, req.URL, req) + return nil, fmt.Errorf("unexpected request") } - bytes, err := ioutil.ReadAll(stream) - if err != nil { - return nil, err - } - assert.Contains(t, string(bytes), `"image":`+`"`+"thingy"+`"`, fmt.Sprintf("image not updated for %#v", input.object)) - return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil - default: - t.Errorf("%s: unexpected request: %s %#v\n%#v", "image", req.Method, req.URL, req) - return nil, fmt.Errorf("unexpected request") - } - }), - VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()), - } - out := new(bytes.Buffer) - cmd := NewCmdImage(tf, out, out) - cmd.SetOutput(out) - cmd.Flags().Set("output", "yaml") - opts := ImageOptions{ - Out: out, - Local: false} - err := opts.Complete(tf, cmd, input.args) - assert.NoError(t, err) - err = opts.Run() - assert.NoError(t, err) + }), + VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()), + } + out := new(bytes.Buffer) + cmd := NewCmdImage(tf, out, out) + cmd.SetOutput(out) + cmd.Flags().Set("output", "yaml") + opts := ImageOptions{ + Out: out, + Local: false} + err := opts.Complete(tf, cmd, input.args) + assert.NoError(t, err) + err = opts.Run() + assert.NoError(t, err) + }) } } diff --git a/pkg/kubectl/cmd/set/set_resources_test.go b/pkg/kubectl/cmd/set/set_resources_test.go index e2a6525766b..2685fb0a3a2 100644 --- a/pkg/kubectl/cmd/set/set_resources_test.go +++ b/pkg/kubectl/cmd/set/set_resources_test.go @@ -46,6 +46,7 @@ import ( func TestResourcesLocal(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -90,6 +91,7 @@ func TestResourcesLocal(t *testing.T) { func TestSetMultiResourcesLimitsLocal(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -446,6 +448,7 @@ func TestSetResourcesRemote(t *testing.T) { groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion} testapi.Default = testapi.Groups[input.testAPIGroup] tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion) ns := legacyscheme.Codecs tf.Namespace = "test" diff --git a/pkg/kubectl/cmd/set/set_selector_test.go b/pkg/kubectl/cmd/set/set_selector_test.go index 8b8aca5a672..15dba1a947c 100644 --- a/pkg/kubectl/cmd/set/set_selector_test.go +++ b/pkg/kubectl/cmd/set/set_selector_test.go @@ -317,6 +317,8 @@ func TestGetResourcesAndSelector(t *testing.T) { func TestSelectorTest(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Version: ""}, diff --git a/pkg/kubectl/cmd/set/set_serviceaccount_test.go b/pkg/kubectl/cmd/set/set_serviceaccount_test.go index 381b7c7ee8b..90bf81b87f8 100644 --- a/pkg/kubectl/cmd/set/set_serviceaccount_test.go +++ b/pkg/kubectl/cmd/set/set_serviceaccount_test.go @@ -68,6 +68,8 @@ func TestSetServiceAccountLocal(t *testing.T) { for i, input := range inputs { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.Client = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Version: "v1"}, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { @@ -98,6 +100,8 @@ func TestSetServiceAccountLocal(t *testing.T) { func TestSetServiceAccountMultiLocal(t *testing.T) { testapi.Default = testapi.Groups[""] tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ GroupVersion: schema.GroupVersion{Version: ""}, @@ -310,77 +314,86 @@ func TestSetServiceAccountRemote(t *testing.T) { }, } for _, input := range inputs { - groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion} - testapi.Default = testapi.Groups[input.testAPIGroup] - tf := cmdtesting.NewTestFactory() - codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion) - ns := legacyscheme.Codecs - tf.Namespace = "test" - tf.Client = &fake.RESTClient{ - GroupVersion: groupVersion, - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", tf.Namespace, input.args[1]) - switch p, m := req.URL.Path, req.Method; { - case p == resourcePath && m == http.MethodGet: - return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil - case p == resourcePath && m == http.MethodPatch: - stream, err := req.GetBody() - if err != nil { - return nil, err + t.Run(input.apiPrefix, func(t *testing.T) { + groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion} + testapi.Default = testapi.Groups[input.testAPIGroup] + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + + codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion) + ns := legacyscheme.Codecs + tf.Namespace = "test" + tf.Client = &fake.RESTClient{ + GroupVersion: groupVersion, + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", tf.Namespace, input.args[1]) + switch p, m := req.URL.Path, req.Method; { + case p == resourcePath && m == http.MethodGet: + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil + case p == resourcePath && m == http.MethodPatch: + stream, err := req.GetBody() + if err != nil { + return nil, err + } + bytes, err := ioutil.ReadAll(stream) + if err != nil { + return nil, err + } + assert.Contains(t, string(bytes), `"serviceAccountName":`+`"`+serviceAccount+`"`, fmt.Sprintf("serviceaccount not updated for %#v", input.object)) + return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil + default: + t.Errorf("%s: unexpected request: %s %#v\n%#v", "serviceaccount", req.Method, req.URL, req) + return nil, fmt.Errorf("unexpected request") } - bytes, err := ioutil.ReadAll(stream) - if err != nil { - return nil, err - } - assert.Contains(t, string(bytes), `"serviceAccountName":`+`"`+serviceAccount+`"`, fmt.Sprintf("serviceaccount not updated for %#v", input.object)) - return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil - default: - t.Errorf("%s: unexpected request: %s %#v\n%#v", "serviceaccount", req.Method, req.URL, req) - return nil, fmt.Errorf("unexpected request") - } - }), - VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()), - } - out := new(bytes.Buffer) - cmd := NewCmdServiceAccount(tf, out, out) - cmd.SetOutput(out) - cmd.Flags().Set("output", "yaml") - saConfig := serviceAccountConfig{ - out: out, - local: false} - err := saConfig.Complete(tf, cmd, input.args) - assert.NoError(t, err) - err = saConfig.Run() - assert.NoError(t, err) + }), + VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()), + } + out := new(bytes.Buffer) + cmd := NewCmdServiceAccount(tf, out, out) + cmd.SetOutput(out) + cmd.Flags().Set("output", "yaml") + saConfig := serviceAccountConfig{ + out: out, + local: false} + err := saConfig.Complete(tf, cmd, input.args) + assert.NoError(t, err) + err = saConfig.Run() + assert.NoError(t, err) + }) } } func TestServiceAccountValidation(t *testing.T) { inputs := []struct { + name string args []string errorString string }{ - {args: []string{}, errorString: serviceAccountMissingErrString}, - {args: []string{serviceAccount}, errorString: resourceMissingErrString}, + {name: "test service account missing", args: []string{}, errorString: serviceAccountMissingErrString}, + {name: "test service account resource missing", args: []string{serviceAccount}, errorString: resourceMissingErrString}, } for _, input := range inputs { - tf := cmdtesting.NewTestFactory() - tf.Client = &fake.RESTClient{ - GroupVersion: schema.GroupVersion{Version: "v1"}, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) - return nil, nil - }), - } - tf.Namespace = "test" - out := bytes.NewBuffer([]byte{}) - cmd := NewCmdServiceAccount(tf, out, out) - cmd.SetOutput(out) + t.Run(input.name, func(t *testing.T) { + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - saConfig := &serviceAccountConfig{} - err := saConfig.Complete(tf, cmd, input.args) - assert.EqualError(t, err, input.errorString) + tf.Client = &fake.RESTClient{ + GroupVersion: schema.GroupVersion{Version: "v1"}, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) + return nil, nil + }), + } + tf.Namespace = "test" + out := bytes.NewBuffer([]byte{}) + cmd := NewCmdServiceAccount(tf, out, out) + cmd.SetOutput(out) + + saConfig := &serviceAccountConfig{} + err := saConfig.Complete(tf, cmd, input.args) + assert.EqualError(t, err, input.errorString) + }) } } diff --git a/pkg/kubectl/cmd/set/set_subject_test.go b/pkg/kubectl/cmd/set/set_subject_test.go index 27658d33766..8b205095e72 100644 --- a/pkg/kubectl/cmd/set/set_subject_test.go +++ b/pkg/kubectl/cmd/set/set_subject_test.go @@ -29,6 +29,8 @@ import ( func TestValidate(t *testing.T) { tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + tf.Namespace = "test" tests := map[string]struct { diff --git a/pkg/kubectl/cmd/taint_test.go b/pkg/kubectl/cmd/taint_test.go index fc6f9fa4e0b..5fb814edbdc 100644 --- a/pkg/kubectl/cmd/taint_test.go +++ b/pkg/kubectl/cmd/taint_test.go @@ -236,102 +236,106 @@ func TestTaint(t *testing.T) { } for _, test := range tests { - oldNode, expectNewNode := generateNodeAndTaintedNode(test.oldTaints, test.newTaints) - new_node := &v1.Node{} - tainted := false - tf := cmdtesting.NewTestFactory() - codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) - ns := legacyscheme.Codecs + t.Run(test.description, func(t *testing.T) { + oldNode, expectNewNode := generateNodeAndTaintedNode(test.oldTaints, test.newTaints) + new_node := &v1.Node{} + tainted := false + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - m := &MyReq{req} - switch { - case m.isFor("GET", "/nodes"): - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, oldNode)}, nil - case m.isFor("GET", "/nodes/node-name"): - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, oldNode)}, nil - case m.isFor("PATCH", "/nodes/node-name"): - tainted = true - data, err := ioutil.ReadAll(req.Body) - if err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - defer req.Body.Close() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) + ns := legacyscheme.Codecs - // apply the patch - oldJSON, err := runtime.Encode(codec, oldNode) - if err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - appliedPatch, err := strategicpatch.StrategicMergePatch(oldJSON, data, &v1.Node{}) - if err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } + tf.Client = &fake.RESTClient{ + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + m := &MyReq{req} + switch { + case m.isFor("GET", "/nodes"): + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, oldNode)}, nil + case m.isFor("GET", "/nodes/node-name"): + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, oldNode)}, nil + case m.isFor("PATCH", "/nodes/node-name"): + tainted = true + data, err := ioutil.ReadAll(req.Body) + if err != nil { + t.Fatalf("%s: unexpected error: %v", test.description, err) + } + defer req.Body.Close() - // decode the patch - if err := runtime.DecodeInto(codec, appliedPatch, new_node); err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - if !equalTaints(expectNewNode.Spec.Taints, new_node.Spec.Taints) { - t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, expectNewNode.Spec.Taints, new_node.Spec.Taints) - } - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, new_node)}, nil - case m.isFor("PUT", "/nodes/node-name"): - tainted = true - data, err := ioutil.ReadAll(req.Body) - if err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - defer req.Body.Close() - if err := runtime.DecodeInto(codec, data, new_node); err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - if !equalTaints(expectNewNode.Spec.Taints, new_node.Spec.Taints) { - t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, expectNewNode.Spec.Taints, new_node.Spec.Taints) - } - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, new_node)}, nil - default: - t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req) - return nil, nil - } - }), - } - tf.ClientConfigVal = defaultClientConfig() + // apply the patch + oldJSON, err := runtime.Encode(codec, oldNode) + if err != nil { + t.Fatalf("%s: unexpected error: %v", test.description, err) + } + appliedPatch, err := strategicpatch.StrategicMergePatch(oldJSON, data, &v1.Node{}) + if err != nil { + t.Fatalf("%s: unexpected error: %v", test.description, err) + } - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdTaint(tf, buf) + // decode the patch + if err := runtime.DecodeInto(codec, appliedPatch, new_node); err != nil { + t.Fatalf("%s: unexpected error: %v", test.description, err) + } + if !equalTaints(expectNewNode.Spec.Taints, new_node.Spec.Taints) { + t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, expectNewNode.Spec.Taints, new_node.Spec.Taints) + } + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, new_node)}, nil + case m.isFor("PUT", "/nodes/node-name"): + tainted = true + data, err := ioutil.ReadAll(req.Body) + if err != nil { + t.Fatalf("%s: unexpected error: %v", test.description, err) + } + defer req.Body.Close() + if err := runtime.DecodeInto(codec, data, new_node); err != nil { + t.Fatalf("%s: unexpected error: %v", test.description, err) + } + if !equalTaints(expectNewNode.Spec.Taints, new_node.Spec.Taints) { + t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, expectNewNode.Spec.Taints, new_node.Spec.Taints) + } + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, new_node)}, nil + default: + t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req) + return nil, nil + } + }), + } + tf.ClientConfigVal = defaultClientConfig() - saw_fatal := false - func() { - defer func() { - // Recover from the panic below. - _ = recover() - // Restore cmdutil behavior - cmdutil.DefaultBehaviorOnFatal() + buf := bytes.NewBuffer([]byte{}) + cmd := NewCmdTaint(tf, buf) + + saw_fatal := false + func() { + defer func() { + // Recover from the panic below. + _ = recover() + // Restore cmdutil behavior + cmdutil.DefaultBehaviorOnFatal() + }() + cmdutil.BehaviorOnFatal(func(e string, code int) { saw_fatal = true; panic(e) }) + cmd.SetArgs(test.args) + cmd.Execute() }() - cmdutil.BehaviorOnFatal(func(e string, code int) { saw_fatal = true; panic(e) }) - cmd.SetArgs(test.args) - cmd.Execute() - }() - if test.expectFatal { - if !saw_fatal { - t.Fatalf("%s: unexpected non-error", test.description) + if test.expectFatal { + if !saw_fatal { + t.Fatalf("%s: unexpected non-error", test.description) + } } - } - if test.expectTaint { - if !tainted { - t.Fatalf("%s: node not tainted", test.description) + if test.expectTaint { + if !tainted { + t.Fatalf("%s: node not tainted", test.description) + } } - } - if !test.expectTaint { - if tainted { - t.Fatalf("%s: unexpected taint", test.description) + if !test.expectTaint { + if tainted { + t.Fatalf("%s: unexpected taint", test.description) + } } - } + }) } } diff --git a/pkg/kubectl/cmd/testing/BUILD b/pkg/kubectl/cmd/testing/BUILD index 0046490faba..23f686de7b5 100644 --- a/pkg/kubectl/cmd/testing/BUILD +++ b/pkg/kubectl/cmd/testing/BUILD @@ -37,6 +37,8 @@ go_library( "//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/rest/fake:go_default_library", + "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", + "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", ], ) diff --git a/pkg/kubectl/cmd/testing/fake.go b/pkg/kubectl/cmd/testing/fake.go index 0098607e019..751165d2e73 100644 --- a/pkg/kubectl/cmd/testing/fake.go +++ b/pkg/kubectl/cmd/testing/fake.go @@ -17,8 +17,11 @@ limitations under the License. package testing import ( + "bytes" "errors" "fmt" + "io/ioutil" + "os" "path/filepath" "time" @@ -34,6 +37,8 @@ import ( "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" "k8s.io/client-go/rest/fake" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" @@ -240,16 +245,55 @@ type TestFactory struct { ClientConfigVal *restclient.Config CommandVal string + tempConfigFile *os.File + UnstructuredClientForMappingFunc func(mapping *meta.RESTMapping) (resource.RESTClient, error) OpenAPISchemaFunc func() (openapi.Resources, error) } func NewTestFactory() *TestFactory { + // specify an optionalClientConfig to explicitly use in testing + // to avoid polluting an existing user config. + config, configFile := defaultFakeClientConfig() return &TestFactory{ - Factory: cmdutil.NewFactory(nil), + Factory: cmdutil.NewFactory(config), + tempConfigFile: configFile, } } +func (f *TestFactory) Cleanup() { + if f.tempConfigFile == nil { + return + } + + os.Remove(f.tempConfigFile.Name()) +} + +func defaultFakeClientConfig() (clientcmd.ClientConfig, *os.File) { + loadingRules, tmpFile, err := newDefaultFakeClientConfigLoadingRules() + if err != nil { + panic(fmt.Sprintf("unable to create a fake client config: %v", err)) + } + + overrides := &clientcmd.ConfigOverrides{ClusterDefaults: clientcmdapi.Cluster{Server: "http://localhost:8080"}} + fallbackReader := bytes.NewBuffer([]byte{}) + + clientConfig := clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, fallbackReader) + return clientConfig, tmpFile +} + +func newDefaultFakeClientConfigLoadingRules() (*clientcmd.ClientConfigLoadingRules, *os.File, error) { + tmpFile, err := ioutil.TempFile("", "cmdtests_temp") + if err != nil { + return nil, nil, err + } + + return &clientcmd.ClientConfigLoadingRules{ + Precedence: []string{tmpFile.Name()}, + MigrationRules: map[string]string{}, + }, tmpFile, nil +} + func (f *TestFactory) CategoryExpander() categories.CategoryExpander { return categories.LegacyCategoryExpander } diff --git a/pkg/kubectl/cmd/top_node_test.go b/pkg/kubectl/cmd/top_node_test.go index 2780ea3b96c..13c7af7f871 100644 --- a/pkg/kubectl/cmd/top_node_test.go +++ b/pkg/kubectl/cmd/top_node_test.go @@ -50,6 +50,8 @@ func TestTopNodeAllMetrics(t *testing.T) { expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) ns := legacyscheme.Codecs @@ -101,6 +103,8 @@ func TestTopNodeAllMetricsCustomDefaults(t *testing.T) { expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) ns := legacyscheme.Codecs @@ -162,6 +166,8 @@ func TestTopNodeWithNameMetrics(t *testing.T) { expectedNodePath := fmt.Sprintf("/%s/%s/nodes/%s", apiPrefix, apiVersion, expectedMetrics.Name) tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) ns := legacyscheme.Codecs @@ -227,6 +233,8 @@ func TestTopNodeWithLabelSelectorMetrics(t *testing.T) { expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) ns := legacyscheme.Codecs @@ -280,6 +288,8 @@ func TestTopNodeAllMetricsFromMetricsServer(t *testing.T) { expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) ns := legacyscheme.Codecs @@ -344,6 +354,8 @@ func TestTopNodeWithNameMetricsFromMetricsServer(t *testing.T) { expectedNodePath := fmt.Sprintf("/%s/%s/nodes/%s", apiPrefix, apiVersion, expectedMetrics.Name) tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) ns := legacyscheme.Codecs @@ -418,6 +430,8 @@ func TestTopNodeWithLabelSelectorMetricsFromMetricsServer(t *testing.T) { expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion) tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...) ns := legacyscheme.Codecs diff --git a/pkg/kubectl/cmd/top_pod_test.go b/pkg/kubectl/cmd/top_pod_test.go index 86b95936dd4..ac5f78aa3d9 100644 --- a/pkg/kubectl/cmd/top_pod_test.go +++ b/pkg/kubectl/cmd/top_pod_test.go @@ -134,90 +134,94 @@ func TestTopPod(t *testing.T) { } initTestErrorHandler(t) for _, testCase := range testCases { - t.Logf("Running test case: %s", testCase.name) - metricsList := testPodMetricsData() - var expectedMetrics []metricsv1alpha1api.PodMetrics - var expectedContainerNames, nonExpectedMetricsNames []string - for n, m := range metricsList { - if n < len(testCase.namespaces) { - m.Namespace = testCase.namespaces[n] - expectedMetrics = append(expectedMetrics, m) - for _, c := range m.Containers { - expectedContainerNames = append(expectedContainerNames, c.Name) - } - } else { - nonExpectedMetricsNames = append(nonExpectedMetricsNames, m.Name) - } - } - - var response interface{} - if len(expectedMetrics) == 1 { - response = expectedMetrics[0] - } else { - response = metricsv1alpha1api.PodMetricsList{ - ListMeta: metav1.ListMeta{ - ResourceVersion: "2", - }, - Items: expectedMetrics, - } - } - - tf := cmdtesting.NewTestFactory() - ns := legacyscheme.Codecs - - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m, q := req.URL.Path, req.Method, req.URL.RawQuery; { - case p == "/api": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil - case p == "/apis": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil - case p == testCase.expectedPath && m == "GET" && (testCase.expectedQuery == "" || q == testCase.expectedQuery): - body, err := marshallBody(response) - if err != nil { - t.Errorf("%s: unexpected error: %v", testCase.name, err) + t.Run(testCase.name, func(t *testing.T) { + t.Logf("Running test case: %s", testCase.name) + metricsList := testPodMetricsData() + var expectedMetrics []metricsv1alpha1api.PodMetrics + var expectedContainerNames, nonExpectedMetricsNames []string + for n, m := range metricsList { + if n < len(testCase.namespaces) { + m.Namespace = testCase.namespaces[n] + expectedMetrics = append(expectedMetrics, m) + for _, c := range m.Containers { + expectedContainerNames = append(expectedContainerNames, c.Name) } - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil - default: - t.Fatalf("%s: unexpected request: %#v\nGot URL: %#v\nExpected path: %#v\nExpected query: %#v", - testCase.name, req, req.URL, testCase.expectedPath, testCase.expectedQuery) - return nil, nil - } - }), - } - tf.Namespace = testNS - tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdTopPod(tf, nil, buf) - for name, value := range testCase.flags { - cmd.Flags().Set(name, value) - } - cmd.Run(cmd, testCase.args) - - // Check the presence of pod names&namespaces/container names in the output. - result := buf.String() - if testCase.containers { - for _, containerName := range expectedContainerNames { - if !strings.Contains(result, containerName) { - t.Errorf("%s: missing metrics for container %s: \n%s", testCase.name, containerName, result) + } else { + nonExpectedMetricsNames = append(nonExpectedMetricsNames, m.Name) } } - } - for _, m := range expectedMetrics { - if !strings.Contains(result, m.Name) { - t.Errorf("%s: missing metrics for %s: \n%s", testCase.name, m.Name, result) + + var response interface{} + if len(expectedMetrics) == 1 { + response = expectedMetrics[0] + } else { + response = metricsv1alpha1api.PodMetricsList{ + ListMeta: metav1.ListMeta{ + ResourceVersion: "2", + }, + Items: expectedMetrics, + } } - if testCase.listsNamespaces && !strings.Contains(result, m.Namespace) { - t.Errorf("%s: missing metrics for %s/%s: \n%s", testCase.name, m.Namespace, m.Name, result) + + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + + ns := legacyscheme.Codecs + + tf.Client = &fake.RESTClient{ + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m, q := req.URL.Path, req.Method, req.URL.RawQuery; { + case p == "/api": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil + case p == "/apis": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil + case p == testCase.expectedPath && m == "GET" && (testCase.expectedQuery == "" || q == testCase.expectedQuery): + body, err := marshallBody(response) + if err != nil { + t.Errorf("%s: unexpected error: %v", testCase.name, err) + } + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil + default: + t.Fatalf("%s: unexpected request: %#v\nGot URL: %#v\nExpected path: %#v\nExpected query: %#v", + testCase.name, req, req.URL, testCase.expectedPath, testCase.expectedQuery) + return nil, nil + } + }), } - } - for _, name := range nonExpectedMetricsNames { - if strings.Contains(result, name) { - t.Errorf("%s: unexpected metrics for %s: \n%s", testCase.name, name, result) + tf.Namespace = testNS + tf.ClientConfigVal = defaultClientConfig() + buf := bytes.NewBuffer([]byte{}) + + cmd := NewCmdTopPod(tf, nil, buf) + for name, value := range testCase.flags { + cmd.Flags().Set(name, value) } - } + cmd.Run(cmd, testCase.args) + + // Check the presence of pod names&namespaces/container names in the output. + result := buf.String() + if testCase.containers { + for _, containerName := range expectedContainerNames { + if !strings.Contains(result, containerName) { + t.Errorf("%s: missing metrics for container %s: \n%s", testCase.name, containerName, result) + } + } + } + for _, m := range expectedMetrics { + if !strings.Contains(result, m.Name) { + t.Errorf("%s: missing metrics for %s: \n%s", testCase.name, m.Name, result) + } + if testCase.listsNamespaces && !strings.Contains(result, m.Namespace) { + t.Errorf("%s: missing metrics for %s/%s: \n%s", testCase.name, m.Namespace, m.Name, result) + } + } + for _, name := range nonExpectedMetricsNames { + if strings.Contains(result, name) { + t.Errorf("%s: unexpected metrics for %s: \n%s", testCase.name, name, result) + } + } + }) } } @@ -305,6 +309,8 @@ func TestTopPodWithMetricsServer(t *testing.T) { } tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + ns := legacyscheme.Codecs tf.Client = &fake.RESTClient{ @@ -471,98 +477,102 @@ func TestTopPodCustomDefaults(t *testing.T) { } initTestErrorHandler(t) for _, testCase := range testCases { - t.Logf("Running test case: %s", testCase.name) - metricsList := testPodMetricsData() - var expectedMetrics []metricsv1alpha1api.PodMetrics - var expectedContainerNames, nonExpectedMetricsNames []string - for n, m := range metricsList { - if n < len(testCase.namespaces) { - m.Namespace = testCase.namespaces[n] - expectedMetrics = append(expectedMetrics, m) - for _, c := range m.Containers { - expectedContainerNames = append(expectedContainerNames, c.Name) - } - } else { - nonExpectedMetricsNames = append(nonExpectedMetricsNames, m.Name) - } - } - - var response interface{} - if len(expectedMetrics) == 1 { - response = expectedMetrics[0] - } else { - response = metricsv1alpha1api.PodMetricsList{ - ListMeta: metav1.ListMeta{ - ResourceVersion: "2", - }, - Items: expectedMetrics, - } - } - - tf := cmdtesting.NewTestFactory() - ns := legacyscheme.Codecs - - tf.Client = &fake.RESTClient{ - NegotiatedSerializer: ns, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m, q := req.URL.Path, req.Method, req.URL.RawQuery; { - case p == "/api": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil - case p == "/apis": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil - case p == testCase.expectedPath && m == "GET" && (testCase.expectedQuery == "" || q == testCase.expectedQuery): - body, err := marshallBody(response) - if err != nil { - t.Errorf("%s: unexpected error: %v", testCase.name, err) + t.Run(testCase.name, func(t *testing.T) { + t.Logf("Running test case: %s", testCase.name) + metricsList := testPodMetricsData() + var expectedMetrics []metricsv1alpha1api.PodMetrics + var expectedContainerNames, nonExpectedMetricsNames []string + for n, m := range metricsList { + if n < len(testCase.namespaces) { + m.Namespace = testCase.namespaces[n] + expectedMetrics = append(expectedMetrics, m) + for _, c := range m.Containers { + expectedContainerNames = append(expectedContainerNames, c.Name) } - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil - default: - t.Fatalf("%s: unexpected request: %#v\nGot URL: %#v\nExpected path: %#v\nExpected query: %#v", - testCase.name, req, req.URL, testCase.expectedPath, testCase.expectedQuery) - return nil, nil - } - }), - } - tf.Namespace = testNS - tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - - opts := &TopPodOptions{ - HeapsterOptions: HeapsterTopOptions{ - Namespace: "custom-namespace", - Scheme: "https", - Service: "custom-heapster-service", - }, - DiscoveryClient: &fakeDiscovery{}, - } - cmd := NewCmdTopPod(tf, opts, buf) - for name, value := range testCase.flags { - cmd.Flags().Set(name, value) - } - cmd.Run(cmd, testCase.args) - - // Check the presence of pod names&namespaces/container names in the output. - result := buf.String() - if testCase.containers { - for _, containerName := range expectedContainerNames { - if !strings.Contains(result, containerName) { - t.Errorf("%s: missing metrics for container %s: \n%s", testCase.name, containerName, result) + } else { + nonExpectedMetricsNames = append(nonExpectedMetricsNames, m.Name) } } - } - for _, m := range expectedMetrics { - if !strings.Contains(result, m.Name) { - t.Errorf("%s: missing metrics for %s: \n%s", testCase.name, m.Name, result) + + var response interface{} + if len(expectedMetrics) == 1 { + response = expectedMetrics[0] + } else { + response = metricsv1alpha1api.PodMetricsList{ + ListMeta: metav1.ListMeta{ + ResourceVersion: "2", + }, + Items: expectedMetrics, + } } - if testCase.listsNamespaces && !strings.Contains(result, m.Namespace) { - t.Errorf("%s: missing metrics for %s/%s: \n%s", testCase.name, m.Namespace, m.Name, result) + + tf := cmdtesting.NewTestFactory() + defer tf.Cleanup() + + ns := legacyscheme.Codecs + + tf.Client = &fake.RESTClient{ + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + switch p, m, q := req.URL.Path, req.Method, req.URL.RawQuery; { + case p == "/api": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil + case p == "/apis": + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil + case p == testCase.expectedPath && m == "GET" && (testCase.expectedQuery == "" || q == testCase.expectedQuery): + body, err := marshallBody(response) + if err != nil { + t.Errorf("%s: unexpected error: %v", testCase.name, err) + } + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil + default: + t.Fatalf("%s: unexpected request: %#v\nGot URL: %#v\nExpected path: %#v\nExpected query: %#v", + testCase.name, req, req.URL, testCase.expectedPath, testCase.expectedQuery) + return nil, nil + } + }), } - } - for _, name := range nonExpectedMetricsNames { - if strings.Contains(result, name) { - t.Errorf("%s: unexpected metrics for %s: \n%s", testCase.name, name, result) + tf.Namespace = testNS + tf.ClientConfigVal = defaultClientConfig() + buf := bytes.NewBuffer([]byte{}) + + opts := &TopPodOptions{ + HeapsterOptions: HeapsterTopOptions{ + Namespace: "custom-namespace", + Scheme: "https", + Service: "custom-heapster-service", + }, + DiscoveryClient: &fakeDiscovery{}, } - } + cmd := NewCmdTopPod(tf, opts, buf) + for name, value := range testCase.flags { + cmd.Flags().Set(name, value) + } + cmd.Run(cmd, testCase.args) + + // Check the presence of pod names&namespaces/container names in the output. + result := buf.String() + if testCase.containers { + for _, containerName := range expectedContainerNames { + if !strings.Contains(result, containerName) { + t.Errorf("%s: missing metrics for container %s: \n%s", testCase.name, containerName, result) + } + } + } + for _, m := range expectedMetrics { + if !strings.Contains(result, m.Name) { + t.Errorf("%s: missing metrics for %s: \n%s", testCase.name, m.Name, result) + } + if testCase.listsNamespaces && !strings.Contains(result, m.Namespace) { + t.Errorf("%s: missing metrics for %s/%s: \n%s", testCase.name, m.Namespace, m.Name, result) + } + } + for _, name := range nonExpectedMetricsNames { + if strings.Contains(result, name) { + t.Errorf("%s: unexpected metrics for %s: \n%s", testCase.name, name, result) + } + } + }) } } diff --git a/pkg/kubectl/cmd/top_test.go b/pkg/kubectl/cmd/top_test.go index f8a49115e4b..0090782fcd8 100644 --- a/pkg/kubectl/cmd/top_test.go +++ b/pkg/kubectl/cmd/top_test.go @@ -44,6 +44,8 @@ func TestTopSubcommandsExist(t *testing.T) { initTestErrorHandler(t) f := cmdtesting.NewTestFactory() + defer f.Cleanup() + buf := bytes.NewBuffer([]byte{}) cmd := NewCmdTop(f, buf, buf)