diff --git a/pkg/kubectl/cmd/annotate.go b/pkg/kubectl/cmd/annotate.go index 5d6c466d6f9..8e50c0c9184 100644 --- a/pkg/kubectl/cmd/annotate.go +++ b/pkg/kubectl/cmd/annotate.go @@ -19,7 +19,6 @@ package cmd import ( "bytes" "fmt" - "io" jsonpatch "github.com/evanphx/json-patch" "github.com/golang/glog" @@ -60,8 +59,7 @@ type AnnotateOptions struct { removeAnnotations []string Recorder genericclioptions.Recorder - // Common share fields - out io.Writer + genericclioptions.IOStreams } var ( @@ -99,17 +97,17 @@ var ( kubectl annotate pods foo description-`)) ) -func NewAnnotateOptions(out io.Writer) *AnnotateOptions { +func NewAnnotateOptions(ioStreams genericclioptions.IOStreams) *AnnotateOptions { return &AnnotateOptions{ - out: out, RecordFlags: genericclioptions.NewRecordFlags(), - Recorder: genericclioptions.NoopRecorder{}, + Recorder: genericclioptions.NoopRecorder{}, + IOStreams: ioStreams, } } -func NewCmdAnnotate(f cmdutil.Factory, out io.Writer) *cobra.Command { - o := NewAnnotateOptions(out) +func NewCmdAnnotate(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewAnnotateOptions(ioStreams) validArgs := cmdutil.ValidArgList(f) cmd := &cobra.Command{ @@ -283,9 +281,9 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro } if len(o.outputFormat) > 0 { - return cmdutil.PrintObject(cmd, outputObj, o.out) + return cmdutil.PrintObject(cmd, outputObj, o.Out) } - cmdutil.PrintSuccess(false, o.out, info.Object, o.dryrun, "annotated") + cmdutil.PrintSuccess(false, o.Out, info.Object, o.dryrun, "annotated") return nil }) } diff --git a/pkg/kubectl/cmd/annotate_test.go b/pkg/kubectl/cmd/annotate_test.go index 7eedc2188ff..ec30bbd47a7 100644 --- a/pkg/kubectl/cmd/annotate_test.go +++ b/pkg/kubectl/cmd/annotate_test.go @@ -17,7 +17,6 @@ limitations under the License. package cmd import ( - "bytes" "net/http" "reflect" "strings" @@ -30,6 +29,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -424,14 +424,14 @@ func TestAnnotateErrors(t *testing.T) { tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdAnnotate(tf, buf) - cmd.SetOutput(buf) + iostreams, _, bufOut, bufErr := genericclioptions.NewTestIOStreams() + cmd := NewCmdAnnotate(tf, iostreams) + cmd.SetOutput(bufOut) for k, v := range testCase.flags { cmd.Flags().Set(k, v) } - options := NewAnnotateOptions(buf) + options := NewAnnotateOptions(iostreams) err := options.Complete(tf, cmd, testCase.args) if err == nil { err = options.Validate() @@ -440,8 +440,11 @@ func TestAnnotateErrors(t *testing.T) { t.Errorf("%s: unexpected error: %v", k, err) return } - if buf.Len() > 0 { - t.Errorf("buffer should be empty: %s", string(buf.Bytes())) + if bufOut.Len() > 0 { + t.Errorf("buffer should be empty: %s", string(bufOut.Bytes())) + } + if bufErr.Len() > 0 { + t.Errorf("buffer should be empty: %s", string(bufErr.Bytes())) } }) } @@ -485,10 +488,10 @@ func TestAnnotateObject(t *testing.T) { tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdAnnotate(tf, buf) - cmd.SetOutput(buf) - options := NewAnnotateOptions(buf) + iostreams, _, bufOut, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdAnnotate(tf, iostreams) + cmd.SetOutput(bufOut) + options := NewAnnotateOptions(iostreams) args := []string{"pods/foo", "a=b", "c-"} if err := options.Complete(tf, cmd, args); err != nil { t.Fatalf("unexpected error: %v", err) @@ -539,10 +542,10 @@ func TestAnnotateObjectFromFile(t *testing.T) { tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdAnnotate(tf, buf) - cmd.SetOutput(buf) - options := NewAnnotateOptions(buf) + iostreams, _, bufOut, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdAnnotate(tf, iostreams) + cmd.SetOutput(bufOut) + options := NewAnnotateOptions(iostreams) options.Filenames = []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"} args := []string{"a=b", "c-"} if err := options.Complete(tf, cmd, args); err != nil { @@ -571,9 +574,9 @@ func TestAnnotateLocal(t *testing.T) { tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdAnnotate(tf, buf) - options := NewAnnotateOptions(buf) + iostreams, _, _, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdAnnotate(tf, iostreams) + options := NewAnnotateOptions(iostreams) options.local = true options.Filenames = []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"} args := []string{"a=b"} @@ -627,10 +630,10 @@ func TestAnnotateMultipleObjects(t *testing.T) { tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdAnnotate(tf, buf) - cmd.SetOutput(buf) - options := NewAnnotateOptions(buf) + iostreams, _, _, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdAnnotate(tf, iostreams) + cmd.SetOutput(iostreams.Out) + options := NewAnnotateOptions(iostreams) options.all = true args := []string{"pods", "a=b", "c-"} if err := options.Complete(tf, cmd, args); err != nil { diff --git a/pkg/kubectl/cmd/apiresources.go b/pkg/kubectl/cmd/apiresources.go index 75d825f21c8..cb94ad8bbd7 100644 --- a/pkg/kubectl/cmd/apiresources.go +++ b/pkg/kubectl/cmd/apiresources.go @@ -29,6 +29,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/printers" ) @@ -53,12 +54,12 @@ var ( // ApiResourcesOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // referencing the cmd.Flags() type ApiResourcesOptions struct { - out io.Writer - Output string APIGroup string Namespaced bool NoHeaders bool + + genericclioptions.IOStreams } // groupResource contains the APIGroup and APIResource @@ -67,10 +68,14 @@ type groupResource struct { APIResource metav1.APIResource } -func NewCmdApiResources(f cmdutil.Factory, out io.Writer) *cobra.Command { - options := &ApiResourcesOptions{ - out: out, +func NewAPIResourceOptions(ioStreams genericclioptions.IOStreams) *ApiResourcesOptions { + return &ApiResourcesOptions{ + IOStreams: ioStreams, } +} + +func NewCmdApiResources(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewAPIResourceOptions(ioStreams) cmd := &cobra.Command{ Use: "api-resources", @@ -78,15 +83,15 @@ func NewCmdApiResources(f cmdutil.Factory, out io.Writer) *cobra.Command { Long: "Print the supported API resources on the server", Example: apiresources_example, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(cmd)) - cmdutil.CheckErr(options.Validate(cmd)) - cmdutil.CheckErr(options.RunApiResources(cmd, f)) + cmdutil.CheckErr(o.Complete(cmd)) + cmdutil.CheckErr(o.Validate(cmd)) + cmdutil.CheckErr(o.RunApiResources(cmd, f)) }, } cmdutil.AddOutputFlags(cmd) cmdutil.AddNoHeadersFlags(cmd) - cmd.Flags().StringVar(&options.APIGroup, "api-group", "", "The API group to use when talking to the server.") - cmd.Flags().BoolVar(&options.Namespaced, "namespaced", true, "Namespaced indicates if a resource is namespaced or not.") + cmd.Flags().StringVar(&o.APIGroup, "api-group", "", "The API group to use when talking to the server.") + cmd.Flags().BoolVar(&o.Namespaced, "namespaced", true, "Namespaced indicates if a resource is namespaced or not.") return cmd } @@ -110,7 +115,7 @@ func (o *ApiResourcesOptions) Validate(cmd *cobra.Command) error { } func (o *ApiResourcesOptions) RunApiResources(cmd *cobra.Command, f cmdutil.Factory) error { - w := printers.GetNewTabWriter(o.out) + w := printers.GetNewTabWriter(o.Out) defer w.Flush() discoveryclient, err := f.DiscoveryClient() diff --git a/pkg/kubectl/cmd/apply.go b/pkg/kubectl/cmd/apply.go index 9eba52acdc1..de24503d17a 100644 --- a/pkg/kubectl/cmd/apply.go +++ b/pkg/kubectl/cmd/apply.go @@ -73,8 +73,7 @@ type ApplyOptions struct { OpenApiPatch bool PruneWhitelist []string - Out io.Writer - ErrOut io.Writer + genericclioptions.IOStreams } const ( @@ -113,7 +112,7 @@ var ( warningNoLastAppliedConfigAnnotation = "Warning: %[1]s apply should be used on resource created by either %[1]s create --save-config or %[1]s apply\n" ) -func NewApplyOptions(out, errout io.Writer) *ApplyOptions { +func NewApplyOptions(ioStreams genericclioptions.IOStreams) *ApplyOptions { return &ApplyOptions{ RecordFlags: genericclioptions.NewRecordFlags(), DeleteFlags: NewDeleteFlags("that contains the configuration to apply"), @@ -124,13 +123,12 @@ func NewApplyOptions(out, errout io.Writer) *ApplyOptions { Recorder: genericclioptions.NoopRecorder{}, - Out: out, - ErrOut: errout, + IOStreams: ioStreams, } } -func NewCmdApply(baseName string, f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - o := NewApplyOptions(out, errOut) +func NewCmdApply(baseName string, f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewApplyOptions(ioStreams) // Store baseName for use in printing warnings / messages involving the base command name. // This is useful for downstream command that wrap this one. @@ -167,9 +165,9 @@ func NewCmdApply(baseName string, f cmdutil.Factory, out, errOut io.Writer) *cob cmdutil.AddIncludeUninitializedFlag(cmd) // apply subcommands - cmd.AddCommand(NewCmdApplyViewLastApplied(f, out, errOut)) - cmd.AddCommand(NewCmdApplySetLastApplied(f, out, errOut)) - cmd.AddCommand(NewCmdApplyEditLastApplied(f, out, errOut)) + cmd.AddCommand(NewCmdApplyViewLastApplied(f, ioStreams)) + cmd.AddCommand(NewCmdApplySetLastApplied(f, ioStreams)) + cmd.AddCommand(NewCmdApplyEditLastApplied(f, ioStreams)) return cmd } diff --git a/pkg/kubectl/cmd/apply_edit_last_applied.go b/pkg/kubectl/cmd/apply_edit_last_applied.go index 9a2319ee741..c3008861f7b 100644 --- a/pkg/kubectl/cmd/apply_edit_last_applied.go +++ b/pkg/kubectl/cmd/apply_edit_last_applied.go @@ -17,14 +17,13 @@ limitations under the License. package cmd import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) var ( @@ -57,8 +56,8 @@ var ( kubectl apply edit-last-applied -f deploy.yaml -o json`) ) -func NewCmdApplyEditLastApplied(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - o := editor.NewEditOptions(editor.ApplyEditMode, out, errOut) +func NewCmdApplyEditLastApplied(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := editor.NewEditOptions(editor.ApplyEditMode, ioStreams) validArgs := cmdutil.ValidArgList(f) diff --git a/pkg/kubectl/cmd/apply_set_last_applied.go b/pkg/kubectl/cmd/apply_set_last_applied.go index fb74479640d..3dbe44b2757 100644 --- a/pkg/kubectl/cmd/apply_set_last_applied.go +++ b/pkg/kubectl/cmd/apply_set_last_applied.go @@ -35,6 +35,7 @@ import ( "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" @@ -55,8 +56,7 @@ type SetLastAppliedOptions struct { PatchBufferList []PatchBuffer Factory cmdutil.Factory - Out io.Writer - ErrOut io.Writer + genericclioptions.IOStreams } type PatchBuffer struct { @@ -82,15 +82,14 @@ var ( `)) ) -func NewSetLastAppliedOptions(out, errout io.Writer) *SetLastAppliedOptions { +func NewSetLastAppliedOptions(ioStreams genericclioptions.IOStreams) *SetLastAppliedOptions { return &SetLastAppliedOptions{ - Out: out, - ErrOut: errout, + IOStreams: ioStreams, } } -func NewCmdApplySetLastApplied(f cmdutil.Factory, out, errout io.Writer) *cobra.Command { - options := NewSetLastAppliedOptions(out, errout) +func NewCmdApplySetLastApplied(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := NewSetLastAppliedOptions(ioStreams) cmd := &cobra.Command{ Use: "set-last-applied -f FILENAME", DisableFlagsInUseLine: true, diff --git a/pkg/kubectl/cmd/apply_test.go b/pkg/kubectl/cmd/apply_test.go index d6064939153..3644cbf101d 100644 --- a/pkg/kubectl/cmd/apply_test.go +++ b/pkg/kubectl/cmd/apply_test.go @@ -51,6 +51,7 @@ import ( cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -70,13 +71,10 @@ var ( ) func TestApplyExtraArgsFail(t *testing.T) { - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - f := cmdtesting.NewTestFactory() defer f.Cleanup() - c := NewCmdApply("kubectl", f, buf, errBuf) + c := NewCmdApply("kubectl", f, genericclioptions.NewTestIOStreamsDiscard()) if validateApplyArgs(c, []string{"rc"}) == nil { t.Fatalf("unexpected non-error") } @@ -298,10 +296,9 @@ func TestRunApplyPrintsValidObjectList(t *testing.T) { } tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameCM) cmd.Flags().Set("output", "json") cmd.Flags().Set("dry-run", "true") @@ -426,7 +423,6 @@ func TestRunApplyViewLastApplied(t *testing.T) { } 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 { @@ -434,7 +430,8 @@ func TestRunApplyViewLastApplied(t *testing.T) { } }) - cmd := NewCmdApplyViewLastApplied(tf, buf, errBuf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdApplyViewLastApplied(tf, ioStreams) if test.filePath != "" { cmd.Flags().Set("filename", test.filePath) } @@ -479,10 +476,9 @@ func TestApplyObjectWithoutAnnotation(t *testing.T) { } tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -527,10 +523,9 @@ func TestApplyObject(t *testing.T) { } tf.OpenAPISchemaFunc = fn tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -592,10 +587,9 @@ func TestApplyObjectOutput(t *testing.T) { } tf.OpenAPISchemaFunc = fn tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "yaml") cmd.Run(cmd, []string{}) @@ -654,10 +648,9 @@ func TestApplyRetry(t *testing.T) { } tf.OpenAPISchemaFunc = fn tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -704,10 +697,9 @@ func TestApplyNonExistObject(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -759,10 +751,8 @@ func TestApplyEmptyPatch(t *testing.T) { tf.Namespace = "test" // 1. apply non exist object - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -776,10 +766,8 @@ func TestApplyEmptyPatch(t *testing.T) { } // 2. test apply already exist object, will not send empty patch request - buf = bytes.NewBuffer([]byte{}) - errBuf = bytes.NewBuffer([]byte{}) - - cmd = NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, _ = genericclioptions.NewTestIOStreams() + cmd = NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -835,10 +823,9 @@ func testApplyMultipleObjects(t *testing.T, asList bool) { } tf.OpenAPISchemaFunc = fn tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) if asList { cmd.Flags().Set("filename", filenameRCSVC) } else { @@ -936,10 +923,9 @@ func TestApplyNULLPreservation(t *testing.T) { } tf.OpenAPISchemaFunc = fn tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameDeployObjClientside) cmd.Flags().Set("output", "name") @@ -1003,10 +989,9 @@ func TestUnstructuredApply(t *testing.T) { } tf.OpenAPISchemaFunc = fn tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameWidgetClientside) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -1097,10 +1082,9 @@ func TestUnstructuredIdempotentApply(t *testing.T) { } tf.OpenAPISchemaFunc = fn tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameWidgetClientside) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -1203,7 +1187,6 @@ func TestRunApplySetLastApplied(t *testing.T) { } 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 { @@ -1211,7 +1194,8 @@ func TestRunApplySetLastApplied(t *testing.T) { } }) - cmd := NewCmdApplySetLastApplied(tf, buf, errBuf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdApplySetLastApplied(tf, ioStreams) cmd.Flags().Set("filename", test.filePath) cmd.Flags().Set("output", test.output) cmd.Run(cmd, []string{}) @@ -1382,10 +1366,8 @@ func TestForceApply(t *testing.T) { tf.ClientConfigVal = &restclient.Config{} tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdApply("kubectl", tf, buf, errBuf) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() + cmd := NewCmdApply("kubectl", tf, ioStreams) cmd.Flags().Set("filename", filenameRC) cmd.Flags().Set("output", "name") cmd.Flags().Set("force", "true") diff --git a/pkg/kubectl/cmd/apply_view_last_applied.go b/pkg/kubectl/cmd/apply_view_last_applied.go index bc0650cee3e..24f49b660cf 100644 --- a/pkg/kubectl/cmd/apply_view_last_applied.go +++ b/pkg/kubectl/cmd/apply_view_last_applied.go @@ -20,13 +20,13 @@ import ( "bytes" "encoding/json" "fmt" - "io" "github.com/ghodss/yaml" "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -38,8 +38,8 @@ type ViewLastAppliedOptions struct { OutputFormat string All bool Factory cmdutil.Factory - Out io.Writer - ErrOut io.Writer + + genericclioptions.IOStreams } var ( @@ -57,16 +57,16 @@ var ( kubectl apply view-last-applied -f deploy.yaml -o json`)) ) -func NewViewLastAppliedOptions(out, err io.Writer) *ViewLastAppliedOptions { +func NewViewLastAppliedOptions(ioStreams genericclioptions.IOStreams) *ViewLastAppliedOptions { return &ViewLastAppliedOptions{ - Out: out, - ErrOut: err, OutputFormat: "yaml", + + IOStreams: ioStreams, } } -func NewCmdApplyViewLastApplied(f cmdutil.Factory, out, err io.Writer) *cobra.Command { - options := NewViewLastAppliedOptions(out, err) +func NewCmdApplyViewLastApplied(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + options := NewViewLastAppliedOptions(ioStreams) validArgs := cmdutil.ValidArgList(f) cmd := &cobra.Command{ diff --git a/pkg/kubectl/cmd/cmd.go b/pkg/kubectl/cmd/cmd.go index 3b9b0585acb..f7f15eb9889 100644 --- a/pkg/kubectl/cmd/cmd.go +++ b/pkg/kubectl/cmd/cmd.go @@ -34,6 +34,7 @@ import ( "k8s.io/kubernetes/pkg/kubectl/util/i18n" "github.com/spf13/cobra" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) const ( @@ -246,11 +247,13 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob // From this point and forward we get warnings on flags that contain "_" separators cmds.SetGlobalNormalizationFunc(flag.WarnWordSepNormalizeFunc) + ioStreams := genericclioptions.IOStreams{In: in, Out: out, ErrOut: err} + groups := templates.CommandGroups{ { Message: "Basic Commands (Beginner):", Commands: []*cobra.Command{ - create.NewCmdCreate(f, out, err), + create.NewCmdCreate(f, ioStreams), NewCmdExposeService(f, out), NewCmdRun(f, in, out, err), set.NewCmdSet(f, in, out, err), @@ -262,7 +265,7 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob Commands: []*cobra.Command{ resource.NewCmdGet(f, out, err), NewCmdExplain(f, out, err), - NewCmdEdit(f, out, err), + NewCmdEdit(f, ioStreams), NewCmdDelete(f, out, err), }, }, @@ -303,7 +306,7 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob { Message: "Advanced Commands:", Commands: []*cobra.Command{ - NewCmdApply("kubectl", f, out, err), + NewCmdApply("kubectl", f, ioStreams), NewCmdPatch(f, out), NewCmdReplace(f, out, err), NewCmdConvert(f, out), @@ -313,7 +316,7 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob Message: "Settings Commands:", Commands: []*cobra.Command{ NewCmdLabel(f, out, err), - NewCmdAnnotate(f, out), + NewCmdAnnotate(f, ioStreams), NewCmdCompletion(out, ""), }, }, @@ -347,7 +350,7 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob cmds.AddCommand(NewCmdPlugin(f, in, out, err)) cmds.AddCommand(NewCmdVersion(f, out)) cmds.AddCommand(NewCmdApiVersions(f, out)) - cmds.AddCommand(NewCmdApiResources(f, out)) + cmds.AddCommand(NewCmdApiResources(f, ioStreams)) cmds.AddCommand(NewCmdOptions(out)) return cmds diff --git a/pkg/kubectl/cmd/create/BUILD b/pkg/kubectl/cmd/create/BUILD index 877344edf5e..27a4928ab72 100644 --- a/pkg/kubectl/cmd/create/BUILD +++ b/pkg/kubectl/cmd/create/BUILD @@ -77,6 +77,7 @@ go_test( "//pkg/kubectl:go_default_library", "//pkg/kubectl/cmd/testing:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", "//pkg/kubectl/scheme:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", diff --git a/pkg/kubectl/cmd/create/create.go b/pkg/kubectl/cmd/create/create.go index f50ebf1e43d..396a0e3da9e 100644 --- a/pkg/kubectl/cmd/create/create.go +++ b/pkg/kubectl/cmd/create/create.go @@ -50,11 +50,11 @@ type CreateOptions struct { Selector string EditBeforeCreate bool Raw string - Out io.Writer - ErrOut io.Writer Recorder genericclioptions.Recorder PrintObj func(obj kruntime.Object) error + + genericclioptions.IOStreams } var ( @@ -74,20 +74,19 @@ var ( kubectl create -f docker-registry.yaml --edit -o json`)) ) -func NewCreateOptions(out, errOut io.Writer) *CreateOptions { +func NewCreateOptions(ioStreams genericclioptions.IOStreams) *CreateOptions { return &CreateOptions{ PrintFlags: NewPrintFlags("created"), RecordFlags: genericclioptions.NewRecordFlags(), Recorder: genericclioptions.NoopRecorder{}, - Out: out, - ErrOut: errOut, + IOStreams: ioStreams, } } -func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - o := NewCreateOptions(out, errOut) +func NewCmdCreate(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewCreateOptions(ioStreams) cmd := &cobra.Command{ Use: "create -f FILENAME", @@ -97,7 +96,7 @@ func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { Example: createExample, Run: func(cmd *cobra.Command, args []string) { if cmdutil.IsFilenameSliceEmpty(o.FilenameOptions.Filenames) { - defaultRunFunc := cmdutil.DefaultSubCommandRun(errOut) + defaultRunFunc := cmdutil.DefaultSubCommandRun(ioStreams.ErrOut) defaultRunFunc(cmd, args) return } @@ -125,20 +124,20 @@ func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { o.PrintFlags.AddFlags(cmd) // create subcommands - cmd.AddCommand(NewCmdCreateNamespace(f, out)) - cmd.AddCommand(NewCmdCreateQuota(f, out)) - cmd.AddCommand(NewCmdCreateSecret(f, out, errOut)) - cmd.AddCommand(NewCmdCreateConfigMap(f, out)) - cmd.AddCommand(NewCmdCreateServiceAccount(f, out)) - cmd.AddCommand(NewCmdCreateService(f, out, errOut)) - cmd.AddCommand(NewCmdCreateDeployment(f, out, errOut)) - cmd.AddCommand(NewCmdCreateClusterRole(f, out)) - cmd.AddCommand(NewCmdCreateClusterRoleBinding(f, out)) - cmd.AddCommand(NewCmdCreateRole(f, out)) - cmd.AddCommand(NewCmdCreateRoleBinding(f, out)) - cmd.AddCommand(NewCmdCreatePodDisruptionBudget(f, out)) - cmd.AddCommand(NewCmdCreatePriorityClass(f, out)) - cmd.AddCommand(NewCmdCreateJob(f, out)) + cmd.AddCommand(NewCmdCreateNamespace(f, ioStreams)) + cmd.AddCommand(NewCmdCreateQuota(f, ioStreams)) + cmd.AddCommand(NewCmdCreateSecret(f, ioStreams)) + cmd.AddCommand(NewCmdCreateConfigMap(f, ioStreams)) + cmd.AddCommand(NewCmdCreateServiceAccount(f, ioStreams)) + cmd.AddCommand(NewCmdCreateService(f, ioStreams)) + cmd.AddCommand(NewCmdCreateDeployment(f, ioStreams)) + cmd.AddCommand(NewCmdCreateClusterRole(f, ioStreams)) + cmd.AddCommand(NewCmdCreateClusterRoleBinding(f, ioStreams)) + cmd.AddCommand(NewCmdCreateRole(f, ioStreams)) + cmd.AddCommand(NewCmdCreateRoleBinding(f, ioStreams)) + cmd.AddCommand(NewCmdCreatePodDisruptionBudget(f, ioStreams)) + cmd.AddCommand(NewCmdCreatePriorityClass(f, ioStreams)) + cmd.AddCommand(NewCmdCreateJob(f, ioStreams)) return cmd } @@ -207,7 +206,7 @@ func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error { } if o.EditBeforeCreate { - return RunEditOnCreate(f, o.RecordFlags, o.Out, o.ErrOut, cmd, &o.FilenameOptions) + return RunEditOnCreate(f, o.RecordFlags, o.IOStreams, cmd, &o.FilenameOptions) } schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate")) if err != nil { @@ -292,8 +291,8 @@ func (o *CreateOptions) raw(f cmdutil.Factory) error { return nil } -func RunEditOnCreate(f cmdutil.Factory, recordFlags *genericclioptions.RecordFlags, out, errOut io.Writer, cmd *cobra.Command, options *resource.FilenameOptions) error { - editOptions := editor.NewEditOptions(editor.EditBeforeCreateMode, out, errOut) +func RunEditOnCreate(f cmdutil.Factory, recordFlags *genericclioptions.RecordFlags, ioStreams genericclioptions.IOStreams, cmd *cobra.Command, options *resource.FilenameOptions) error { + editOptions := editor.NewEditOptions(editor.EditBeforeCreateMode, ioStreams) editOptions.FilenameOptions = *options editOptions.ValidateOptions = cmdutil.ValidateOptions{ EnableValidation: cmdutil.GetFlagBool(cmd, "validate"), @@ -341,8 +340,14 @@ type CreateSubcommandOptions struct { PrintObj func(obj kruntime.Object) error - CmdOut io.Writer - CmdErr io.Writer + genericclioptions.IOStreams +} + +func NewCreateSubcommandOptions(ioStreams genericclioptions.IOStreams) *CreateSubcommandOptions { + return &CreateSubcommandOptions{ + PrintFlags: NewPrintFlags("created"), + IOStreams: ioStreams, + } } func (o *CreateSubcommandOptions) Complete(cmd *cobra.Command, args []string, generator kubectl.StructuredGenerator) error { @@ -365,7 +370,7 @@ func (o *CreateSubcommandOptions) Complete(cmd *cobra.Command, args []string, ge } o.PrintObj = func(obj kruntime.Object) error { - return printer.PrintObj(obj, o.CmdOut) + return printer.PrintObj(obj, o.Out) } return nil diff --git a/pkg/kubectl/cmd/create/create_clusterrole.go b/pkg/kubectl/cmd/create/create_clusterrole.go index 015902f9576..b4a860092c9 100644 --- a/pkg/kubectl/cmd/create/create_clusterrole.go +++ b/pkg/kubectl/cmd/create/create_clusterrole.go @@ -18,7 +18,6 @@ package create import ( "fmt" - "io" "strings" "github.com/spf13/cobra" @@ -26,6 +25,7 @@ import ( rbacv1 "k8s.io/api/rbac/v1" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -59,12 +59,9 @@ type CreateClusterRoleOptions struct { } // ClusterRole is a command to ease creating ClusterRoles. -func NewCmdCreateClusterRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateClusterRole(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { c := &CreateClusterRoleOptions{ - CreateRoleOptions: &CreateRoleOptions{ - PrintFlags: NewPrintFlags("created"), - Out: cmdOut, - }, + CreateRoleOptions: NewCreateRoleOptions(ioStreams), } cmd := &cobra.Command{ Use: "clusterrole NAME --verb=verb --resource=resource.group [--resource-name=resourcename] [--dry-run]", diff --git a/pkg/kubectl/cmd/create/create_clusterrole_test.go b/pkg/kubectl/cmd/create/create_clusterrole_test.go index 61e32ab5f36..69ea254e755 100644 --- a/pkg/kubectl/cmd/create/create_clusterrole_test.go +++ b/pkg/kubectl/cmd/create/create_clusterrole_test.go @@ -17,7 +17,6 @@ limitations under the License. package create import ( - "bytes" "testing" rbac "k8s.io/api/rbac/v1" @@ -29,6 +28,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -133,8 +133,8 @@ func TestCreateClusterRole(t *testing.T) { } for name, test := range tests { - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateClusterRole(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateClusterRole(tf, ioStreams) cmd.Flags().Set("dry-run", "true") cmd.Flags().Set("output", "yaml") cmd.Flags().Set("verb", test.verbs) diff --git a/pkg/kubectl/cmd/create/create_clusterrolebinding.go b/pkg/kubectl/cmd/create/create_clusterrolebinding.go index 9be08b9a963..2098457b40f 100644 --- a/pkg/kubectl/cmd/create/create_clusterrolebinding.go +++ b/pkg/kubectl/cmd/create/create_clusterrolebinding.go @@ -17,13 +17,12 @@ limitations under the License. package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -41,12 +40,9 @@ type ClusterRoleBindingOpts struct { } // ClusterRoleBinding is a command to ease creating ClusterRoleBindings. -func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &ClusterRoleBindingOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ diff --git a/pkg/kubectl/cmd/create/create_clusterrolebinding_test.go b/pkg/kubectl/cmd/create/create_clusterrolebinding_test.go index c08e1dc8946..206d6da73b2 100644 --- a/pkg/kubectl/cmd/create/create_clusterrolebinding_test.go +++ b/pkg/kubectl/cmd/create/create_clusterrolebinding_test.go @@ -32,6 +32,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func TestCreateClusterRoleBinding(t *testing.T) { @@ -111,8 +112,8 @@ func TestCreateClusterRoleBinding(t *testing.T) { } expectedOutput := "clusterrolebinding.rbac.authorization.k8s.io/" + expectBinding.Name + "\n" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateClusterRoleBinding(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateClusterRoleBinding(tf, ioStreams) cmd.Flags().Set("clusterrole", "fake-clusterrole") cmd.Flags().Set("user", "fake-user") cmd.Flags().Set("group", "fake-group") diff --git a/pkg/kubectl/cmd/create/create_configmap.go b/pkg/kubectl/cmd/create/create_configmap.go index b3b9fa785ea..b99b143f738 100644 --- a/pkg/kubectl/cmd/create/create_configmap.go +++ b/pkg/kubectl/cmd/create/create_configmap.go @@ -17,13 +17,12 @@ limitations under the License. package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -62,12 +61,9 @@ type ConfigMapOpts struct { } // ConfigMap is a command to ease creating ConfigMaps. -func NewCmdCreateConfigMap(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateConfigMap(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &ConfigMapOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ diff --git a/pkg/kubectl/cmd/create/create_configmap_test.go b/pkg/kubectl/cmd/create/create_configmap_test.go index fd0c995000f..36884e0a1ca 100644 --- a/pkg/kubectl/cmd/create/create_configmap_test.go +++ b/pkg/kubectl/cmd/create/create_configmap_test.go @@ -29,6 +29,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -55,8 +56,8 @@ func TestCreateConfigMap(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateConfigMap(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateConfigMap(tf, ioStreams) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{configMap.Name}) expectedOutput := "configmap/" + configMap.Name + "\n" diff --git a/pkg/kubectl/cmd/create/create_deployment.go b/pkg/kubectl/cmd/create/create_deployment.go index 8461ab40584..08c1dc01e36 100644 --- a/pkg/kubectl/cmd/create/create_deployment.go +++ b/pkg/kubectl/cmd/create/create_deployment.go @@ -17,13 +17,12 @@ limitations under the License. package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -43,13 +42,9 @@ type DeploymentOpts struct { // NewCmdCreateDeployment is a macro command to create a new deployment. // This command is better known to users as `kubectl create deployment`. // Note that this command overlaps significantly with the `kubectl run` command. -func NewCmdCreateDeployment(f cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.Command { +func NewCmdCreateDeployment(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &DeploymentOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - CmdErr: cmdErr, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ @@ -131,12 +126,12 @@ func (o *DeploymentOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args [] if len(generatorName) == 0 { generatorName = cmdutil.DeploymentBasicAppsV1GeneratorName - generatorNameTemp, err := cmdutil.FallbackGeneratorNameIfNecessary(generatorName, clientset.Discovery(), o.CreateSubcommandOptions.CmdErr) + generatorNameTemp, err := cmdutil.FallbackGeneratorNameIfNecessary(generatorName, clientset.Discovery(), o.CreateSubcommandOptions.ErrOut) if err != nil { return err } if generatorNameTemp != generatorName { - cmdutil.Warning(o.CreateSubcommandOptions.CmdErr, generatorName, generatorNameTemp) + cmdutil.Warning(o.CreateSubcommandOptions.ErrOut, generatorName, generatorNameTemp) } else { generatorName = generatorNameTemp } diff --git a/pkg/kubectl/cmd/create/create_deployment_test.go b/pkg/kubectl/cmd/create/create_deployment_test.go index 679870d59b7..1c56a299021 100644 --- a/pkg/kubectl/cmd/create/create_deployment_test.go +++ b/pkg/kubectl/cmd/create/create_deployment_test.go @@ -30,6 +30,7 @@ import ( "k8s.io/kubernetes/pkg/kubectl" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func Test_generatorFromName(t *testing.T) { @@ -104,9 +105,9 @@ func TestCreateDeployment(t *testing.T) { } tf.ClientConfigVal = &restclient.Config{} tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateDeployment(tf, buf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateDeployment(tf, ioStreams) cmd.Flags().Set("dry-run", "true") cmd.Flags().Set("output", "name") cmd.Flags().Set("image", "hollywood/jonny.depp:v2") @@ -136,16 +137,14 @@ func TestCreateDeploymentNoImage(t *testing.T) { tf.ClientConfigVal = &restclient.Config{} tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuff := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateDeployment(tf, buf, errBuff) + ioStreams := genericclioptions.NewTestIOStreamsDiscard() + cmd := NewCmdCreateDeployment(tf, ioStreams) cmd.Flags().Set("output", "name") options := &DeploymentOpts{ CreateSubcommandOptions: &CreateSubcommandOptions{ PrintFlags: NewPrintFlags("created"), - CmdOut: buf, - CmdErr: errBuff, DryRun: true, + IOStreams: ioStreams, }, } diff --git a/pkg/kubectl/cmd/create/create_job.go b/pkg/kubectl/cmd/create/create_job.go index b77212f5c4e..e52b6b52f42 100644 --- a/pkg/kubectl/cmd/create/create_job.go +++ b/pkg/kubectl/cmd/create/create_job.go @@ -18,7 +18,6 @@ package create import ( "fmt" - "io" "github.com/spf13/cobra" @@ -29,6 +28,7 @@ import ( clientbatchv1 "k8s.io/client-go/kubernetes/typed/batch/v1" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -53,30 +53,36 @@ type CreateJobOptions struct { Namespace string OutputFormat string Client clientbatchv1.BatchV1Interface - Out io.Writer DryRun bool Builder *resource.Builder Cmd *cobra.Command + + genericclioptions.IOStreams +} + +func NewCreateJobOptions(ioStreams genericclioptions.IOStreams) *CreateJobOptions { + return &CreateJobOptions{ + PrintFlags: NewPrintFlags("created"), + IOStreams: ioStreams, + } } // NewCmdCreateJob is a command to ease creating Jobs from CronJobs. -func NewCmdCreateJob(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - c := &CreateJobOptions{ - PrintFlags: NewPrintFlags("created"), - Out: cmdOut, - } +func NewCmdCreateJob(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewCreateJobOptions(ioStreams) + cmd := &cobra.Command{ Use: "job NAME [--from=CRONJOB]", Short: jobLong, Long: jobLong, Example: jobExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(c.Complete(f, cmd, args)) - cmdutil.CheckErr(c.RunCreateJob()) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.RunCreateJob()) }, } - c.PrintFlags.AddFlags(cmd) + o.PrintFlags.AddFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddValidateFlags(cmd) @@ -86,14 +92,14 @@ func NewCmdCreateJob(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { return cmd } -func (c *CreateJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) (err error) { +func (o *CreateJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) (err error) { if len(args) == 0 { return cmdutil.UsageErrorf(cmd, "NAME is required") } - c.Name = args[0] + o.Name = args[0] - c.From = cmdutil.GetFlagString(cmd, "from") - c.Namespace, _, err = f.DefaultNamespace() + o.From = cmdutil.GetFlagString(cmd, "from") + o.Namespace, _, err = f.DefaultNamespace() if err != nil { return err } @@ -102,32 +108,32 @@ func (c *CreateJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args if err != nil { return err } - c.Client = clientset.BatchV1() - c.Builder = f.NewBuilder() - c.DryRun = cmdutil.GetDryRunFlag(cmd) - c.Cmd = cmd - c.OutputFormat = cmdutil.GetFlagString(cmd, "output") + o.Client = clientset.BatchV1() + o.Builder = f.NewBuilder() + o.DryRun = cmdutil.GetDryRunFlag(cmd) + o.Cmd = cmd + o.OutputFormat = cmdutil.GetFlagString(cmd, "output") - if c.DryRun { - c.PrintFlags.Complete("%s (dry run)") + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") } - printer, err := c.PrintFlags.ToPrinter() + printer, err := o.PrintFlags.ToPrinter() if err != nil { return err } - c.PrintObj = func(obj runtime.Object) error { - return printer.PrintObj(obj, c.Out) + o.PrintObj = func(obj runtime.Object) error { + return printer.PrintObj(obj, o.Out) } return nil } -func (c *CreateJobOptions) RunCreateJob() error { - infos, err := c.Builder. +func (o *CreateJobOptions) RunCreateJob() error { + infos, err := o.Builder. Unstructured(). - NamespaceParam(c.Namespace).DefaultNamespace(). - ResourceTypeOrNameArgs(false, c.From). + NamespaceParam(o.Namespace).DefaultNamespace(). + ResourceTypeOrNameArgs(false, o.From). Flatten(). Latest(). Do(). @@ -143,10 +149,10 @@ func (c *CreateJobOptions) RunCreateJob() error { return fmt.Errorf("from must be an existing cronjob") } - return c.createJob(cronJob) + return o.createJob(cronJob) } -func (c *CreateJobOptions) createJob(cronJob *batchv1beta1.CronJob) error { +func (o *CreateJobOptions) createJob(cronJob *batchv1beta1.CronJob) error { annotations := make(map[string]string) annotations["cronjob.kubernetes.io/instantiate"] = "manual" for k, v := range cronJob.Spec.JobTemplate.Annotations { @@ -154,21 +160,21 @@ func (c *CreateJobOptions) createJob(cronJob *batchv1beta1.CronJob) error { } job := &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{ - Name: c.Name, - Namespace: c.Namespace, + Name: o.Name, + Namespace: o.Namespace, Annotations: annotations, Labels: cronJob.Spec.JobTemplate.Labels, }, Spec: cronJob.Spec.JobTemplate.Spec, } - if !c.DryRun { + if !o.DryRun { var err error - job, err = c.Client.Jobs(c.Namespace).Create(job) + job, err = o.Client.Jobs(o.Namespace).Create(job) if err != nil { return fmt.Errorf("failed to create job: %v", err) } } - return c.PrintObj(job) + return o.PrintObj(job) } diff --git a/pkg/kubectl/cmd/create/create_job_test.go b/pkg/kubectl/cmd/create/create_job_test.go index f1da73dca59..af6fbcfa5f2 100644 --- a/pkg/kubectl/cmd/create/create_job_test.go +++ b/pkg/kubectl/cmd/create/create_job_test.go @@ -17,7 +17,6 @@ limitations under the License. package create import ( - "bytes" "testing" batchv1 "k8s.io/api/batch/v1" @@ -28,6 +27,7 @@ import ( fake "k8s.io/client-go/kubernetes/fake" clienttesting "k8s.io/client-go/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func TestCreateJobFromCronJob(t *testing.T) { @@ -86,14 +86,13 @@ func TestCreateJobFromCronJob(t *testing.T) { printFlags := NewPrintFlags("created") - buf := bytes.NewBuffer([]byte{}) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() cmdOptions := &CreateJobOptions{ PrintFlags: printFlags, Name: testJobName, Namespace: testNamespaceName, Client: clientset.BatchV1(), - Out: buf, - Cmd: NewCmdCreateJob(f, buf), + Cmd: NewCmdCreateJob(f, ioStreams), PrintObj: func(obj runtime.Object) error { p, err := printFlags.ToPrinter() if err != nil { @@ -102,6 +101,7 @@ func TestCreateJobFromCronJob(t *testing.T) { return p.PrintObj(obj, buf) }, + IOStreams: ioStreams, } err := cmdOptions.createJob(cronJob) diff --git a/pkg/kubectl/cmd/create/create_namespace.go b/pkg/kubectl/cmd/create/create_namespace.go index cfbf8ec7059..ddcd56116ec 100644 --- a/pkg/kubectl/cmd/create/create_namespace.go +++ b/pkg/kubectl/cmd/create/create_namespace.go @@ -17,13 +17,12 @@ limitations under the License. package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -41,12 +40,9 @@ type NamespaceOpts struct { } // NewCmdCreateNamespace is a macro command to create a new namespace -func NewCmdCreateNamespace(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateNamespace(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &NamespaceOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ diff --git a/pkg/kubectl/cmd/create/create_namespace_test.go b/pkg/kubectl/cmd/create/create_namespace_test.go index 21e5021a1cd..785f6bda7a2 100644 --- a/pkg/kubectl/cmd/create/create_namespace_test.go +++ b/pkg/kubectl/cmd/create/create_namespace_test.go @@ -17,7 +17,6 @@ limitations under the License. package create import ( - "bytes" "net/http" "testing" @@ -26,6 +25,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -51,8 +51,8 @@ func TestCreateNamespace(t *testing.T) { } }), } - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateNamespace(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateNamespace(tf, ioStreams) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{namespaceObject.Name}) expectedOutput := "namespace/" + namespaceObject.Name + "\n" diff --git a/pkg/kubectl/cmd/create/create_pdb.go b/pkg/kubectl/cmd/create/create_pdb.go index 0d64695e26c..e830aaca2c2 100644 --- a/pkg/kubectl/cmd/create/create_pdb.go +++ b/pkg/kubectl/cmd/create/create_pdb.go @@ -17,13 +17,12 @@ limitations under the License. package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -46,12 +45,9 @@ type PodDisruptionBudgetOpts struct { } // NewCmdCreatePodDisruptionBudget is a macro command to create a new pod disruption budget. -func NewCmdCreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreatePodDisruptionBudget(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &PodDisruptionBudgetOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ diff --git a/pkg/kubectl/cmd/create/create_pdb_test.go b/pkg/kubectl/cmd/create/create_pdb_test.go index 86d9c1db875..93eb4cfad30 100644 --- a/pkg/kubectl/cmd/create/create_pdb_test.go +++ b/pkg/kubectl/cmd/create/create_pdb_test.go @@ -27,6 +27,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func TestCreatePdb(t *testing.T) { @@ -48,11 +49,11 @@ func TestCreatePdb(t *testing.T) { } tf.ClientConfigVal = &restclient.Config{} tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) outputFormat := "name" - cmd := NewCmdCreatePodDisruptionBudget(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreatePodDisruptionBudget(tf, ioStreams) cmd.Flags().Set("min-available", "1") cmd.Flags().Set("selector", "app=rails") cmd.Flags().Set("dry-run", "true") @@ -64,8 +65,8 @@ func TestCreatePdb(t *testing.T) { options := &PodDisruptionBudgetOpts{ CreateSubcommandOptions: &CreateSubcommandOptions{ PrintFlags: printFlags, - CmdOut: buf, Name: pdbName, + IOStreams: ioStreams, }, } err := options.Complete(cmd, []string{pdbName}) diff --git a/pkg/kubectl/cmd/create/create_priorityclass.go b/pkg/kubectl/cmd/create/create_priorityclass.go index 18e41d2a661..b1c217f1e0e 100644 --- a/pkg/kubectl/cmd/create/create_priorityclass.go +++ b/pkg/kubectl/cmd/create/create_priorityclass.go @@ -17,13 +17,12 @@ limitations under the License. package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -44,12 +43,9 @@ type PriorityClassOpts struct { } // NewCmdCreatePriorityClass is a macro command to create a new priorityClass. -func NewCmdCreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreatePriorityClass(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &PriorityClassOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ diff --git a/pkg/kubectl/cmd/create/create_priorityclass_test.go b/pkg/kubectl/cmd/create/create_priorityclass_test.go index 8738a968f31..44d30218278 100644 --- a/pkg/kubectl/cmd/create/create_priorityclass_test.go +++ b/pkg/kubectl/cmd/create/create_priorityclass_test.go @@ -27,6 +27,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func TestCreatePriorityClass(t *testing.T) { @@ -47,11 +48,11 @@ func TestCreatePriorityClass(t *testing.T) { }), } tf.ClientConfigVal = &restclient.Config{} - buf := bytes.NewBuffer([]byte{}) outputFormat := "name" - cmd := NewCmdCreatePriorityClass(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreatePriorityClass(tf, ioStreams) cmd.Flags().Set("value", "1000") cmd.Flags().Set("global-default", "true") cmd.Flags().Set("description", "my priority") @@ -64,8 +65,8 @@ func TestCreatePriorityClass(t *testing.T) { options := &PriorityClassOpts{ CreateSubcommandOptions: &CreateSubcommandOptions{ PrintFlags: printFlags, - CmdOut: buf, Name: pcName, + IOStreams: ioStreams, }, } err := options.Complete(cmd, []string{pcName}) diff --git a/pkg/kubectl/cmd/create/create_quota.go b/pkg/kubectl/cmd/create/create_quota.go index d46c41e1bfd..2806e66d6a0 100644 --- a/pkg/kubectl/cmd/create/create_quota.go +++ b/pkg/kubectl/cmd/create/create_quota.go @@ -17,13 +17,12 @@ limitations under the License. package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -44,12 +43,9 @@ type QuotaOpts struct { } // NewCmdCreateQuota is a macro command to create a new quota -func NewCmdCreateQuota(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateQuota(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &QuotaOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ diff --git a/pkg/kubectl/cmd/create/create_quota_test.go b/pkg/kubectl/cmd/create/create_quota_test.go index a3c27b788df..f0b3b1619d4 100644 --- a/pkg/kubectl/cmd/create/create_quota_test.go +++ b/pkg/kubectl/cmd/create/create_quota_test.go @@ -17,7 +17,6 @@ limitations under the License. package create import ( - "bytes" "net/http" "testing" @@ -26,6 +25,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -75,8 +75,8 @@ func TestCreateQuota(t *testing.T) { }, } for name, test := range tests { - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateQuota(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateQuota(tf, ioStreams) cmd.Flags().Parse(test.flags) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{resourceQuotaObject.Name}) diff --git a/pkg/kubectl/cmd/create/create_role.go b/pkg/kubectl/cmd/create/create_role.go index b2256b31d96..f3271e4c5fc 100644 --- a/pkg/kubectl/cmd/create/create_role.go +++ b/pkg/kubectl/cmd/create/create_role.go @@ -18,7 +18,6 @@ package create import ( "fmt" - "io" "strings" "github.com/spf13/cobra" @@ -31,6 +30,7 @@ import ( clientgorbacv1 "k8s.io/client-go/kubernetes/typed/rbac/v1" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -112,17 +112,23 @@ type CreateRoleOptions struct { Namespace string Client clientgorbacv1.RbacV1Interface Mapper meta.RESTMapper - Out io.Writer PrintObj func(obj runtime.Object) error + + genericclioptions.IOStreams +} + +func NewCreateRoleOptions(ioStreams genericclioptions.IOStreams) *CreateRoleOptions { + return &CreateRoleOptions{ + PrintFlags: NewPrintFlags("created"), + + IOStreams: ioStreams, + } } // Role is a command to ease creating Roles. -func NewCmdCreateRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - c := &CreateRoleOptions{ - PrintFlags: NewPrintFlags("created"), +func NewCmdCreateRole(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := NewCreateRoleOptions(ioStreams) - Out: cmdOut, - } cmd := &cobra.Command{ Use: "role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename] [--dry-run]", DisableFlagsInUseLine: true, @@ -130,34 +136,34 @@ func NewCmdCreateRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { Long: roleLong, Example: roleExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(c.Complete(f, cmd, args)) - cmdutil.CheckErr(c.Validate()) - cmdutil.CheckErr(c.RunCreateRole()) + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.RunCreateRole()) }, } - c.PrintFlags.AddFlags(cmd) + o.PrintFlags.AddFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddValidateFlags(cmd) cmdutil.AddDryRunFlag(cmd) - cmd.Flags().StringSliceVar(&c.Verbs, "verb", c.Verbs, "Verb that applies to the resources contained in the rule") + cmd.Flags().StringSliceVar(&o.Verbs, "verb", o.Verbs, "Verb that applies to the resources contained in the rule") cmd.Flags().StringSlice("resource", []string{}, "Resource that the rule applies to") - cmd.Flags().StringArrayVar(&c.ResourceNames, "resource-name", c.ResourceNames, "Resource in the white list that the rule applies to, repeat this flag for multiple items") + cmd.Flags().StringArrayVar(&o.ResourceNames, "resource-name", o.ResourceNames, "Resource in the white list that the rule applies to, repeat this flag for multiple items") return cmd } -func (c *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { +func (o *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { name, err := NameFromCommandArgs(cmd, args) if err != nil { return err } - c.Name = name + o.Name = name // Remove duplicate verbs. verbs := []string{} - for _, v := range c.Verbs { + for _, v := range o.Verbs { // VerbAll respresents all kinds of verbs. if v == "*" { verbs = []string{"*"} @@ -167,7 +173,7 @@ func (c *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args verbs = append(verbs, v) } } - c.Verbs = verbs + o.Verbs = verbs // Support resource.group pattern. If no API Group specified, use "" as core API Group. // e.g. --resource=pods,deployments.extensions @@ -186,36 +192,36 @@ func (c *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args } resource.Resource = parts[0] - c.Resources = append(c.Resources, *resource) + o.Resources = append(o.Resources, *resource) } // Remove duplicate resource names. resourceNames := []string{} - for _, n := range c.ResourceNames { + for _, n := range o.ResourceNames { if !arrayContains(resourceNames, n) { resourceNames = append(resourceNames, n) } } - c.ResourceNames = resourceNames + o.ResourceNames = resourceNames // Complete other options for Run. - c.Mapper, _ = f.Object() + o.Mapper, _ = f.Object() - c.DryRun = cmdutil.GetDryRunFlag(cmd) - c.OutputFormat = cmdutil.GetFlagString(cmd, "output") + o.DryRun = cmdutil.GetDryRunFlag(cmd) + o.OutputFormat = cmdutil.GetFlagString(cmd, "output") - if c.DryRun { - c.PrintFlags.Complete("%s (dry run)") + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") } - printer, err := c.PrintFlags.ToPrinter() + printer, err := o.PrintFlags.ToPrinter() if err != nil { return err } - c.PrintObj = func(obj runtime.Object) error { - return printer.PrintObj(obj, c.Out) + o.PrintObj = func(obj runtime.Object) error { + return printer.PrintObj(obj, o.Out) } - c.Namespace, _, err = f.DefaultNamespace() + o.Namespace, _, err = f.DefaultNamespace() if err != nil { return err } @@ -224,48 +230,48 @@ func (c *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args if err != nil { return err } - c.Client = clientset.RbacV1() + o.Client = clientset.RbacV1() return nil } -func (c *CreateRoleOptions) Validate() error { - if c.Name == "" { +func (o *CreateRoleOptions) Validate() error { + if o.Name == "" { return fmt.Errorf("name must be specified") } // validate verbs. - if len(c.Verbs) == 0 { + if len(o.Verbs) == 0 { return fmt.Errorf("at least one verb must be specified") } - for _, v := range c.Verbs { + for _, v := range o.Verbs { if !arrayContains(validResourceVerbs, v) { return fmt.Errorf("invalid verb: '%s'", v) } } // validate resources. - if len(c.Resources) == 0 { + if len(o.Resources) == 0 { return fmt.Errorf("at least one resource must be specified") } - return c.validateResource() + return o.validateResource() } -func (c *CreateRoleOptions) validateResource() error { - for _, r := range c.Resources { +func (o *CreateRoleOptions) validateResource() error { + for _, r := range o.Resources { if len(r.Resource) == 0 { return fmt.Errorf("resource must be specified if apiGroup/subresource specified") } resource := schema.GroupVersionResource{Resource: r.Resource, Group: r.Group} - groupVersionResource, err := c.Mapper.ResourceFor(schema.GroupVersionResource{Resource: r.Resource, Group: r.Group}) + groupVersionResource, err := o.Mapper.ResourceFor(schema.GroupVersionResource{Resource: r.Resource, Group: r.Group}) if err == nil { resource = groupVersionResource } - for _, v := range c.Verbs { + for _, v := range o.Verbs { if groupResources, ok := specialVerbs[v]; ok { match := false for _, extra := range groupResources { @@ -288,24 +294,24 @@ func (c *CreateRoleOptions) validateResource() error { return nil } -func (c *CreateRoleOptions) RunCreateRole() error { +func (o *CreateRoleOptions) RunCreateRole() error { role := &rbacv1.Role{} - role.Name = c.Name - rules, err := generateResourcePolicyRules(c.Mapper, c.Verbs, c.Resources, c.ResourceNames, []string{}) + role.Name = o.Name + rules, err := generateResourcePolicyRules(o.Mapper, o.Verbs, o.Resources, o.ResourceNames, []string{}) if err != nil { return err } role.Rules = rules // Create role. - if !c.DryRun { - role, err = c.Client.Roles(c.Namespace).Create(role) + if !o.DryRun { + role, err = o.Client.Roles(o.Namespace).Create(role) if err != nil { return err } } - return c.PrintObj(role) + return o.PrintObj(role) } func arrayContains(s []string, e string) bool { diff --git a/pkg/kubectl/cmd/create/create_role_test.go b/pkg/kubectl/cmd/create/create_role_test.go index f04063b454c..e7937197f96 100644 --- a/pkg/kubectl/cmd/create/create_role_test.go +++ b/pkg/kubectl/cmd/create/create_role_test.go @@ -17,7 +17,6 @@ limitations under the License. package create import ( - "bytes" "reflect" "testing" @@ -29,6 +28,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func TestCreateRole(t *testing.T) { @@ -129,8 +129,8 @@ func TestCreateRole(t *testing.T) { for name, test := range tests { t.Run(name, func(t *testing.T) { - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateRole(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateRole(tf, ioStreams) cmd.Flags().Set("dry-run", "true") cmd.Flags().Set("output", "yaml") cmd.Flags().Set("verb", test.verbs) @@ -360,8 +360,7 @@ func TestComplete(t *testing.T) { tf.Client = &fake.RESTClient{} tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateRole(tf, buf) + cmd := NewCmdCreateRole(tf, genericclioptions.NewTestIOStreamsDiscard()) cmd.Flags().Set("resource", "pods,deployments.extensions") tests := map[string]struct { diff --git a/pkg/kubectl/cmd/create/create_rolebinding.go b/pkg/kubectl/cmd/create/create_rolebinding.go index 6bed1adad13..e6210285ef1 100644 --- a/pkg/kubectl/cmd/create/create_rolebinding.go +++ b/pkg/kubectl/cmd/create/create_rolebinding.go @@ -17,13 +17,12 @@ limitations under the License. package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -41,12 +40,9 @@ type RoleBindingOpts struct { } // RoleBinding is a command to ease creating RoleBindings. -func NewCmdCreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateRoleBinding(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &RoleBindingOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ diff --git a/pkg/kubectl/cmd/create/create_rolebinding_test.go b/pkg/kubectl/cmd/create/create_rolebinding_test.go index 5e5db16406f..f57b2351204 100644 --- a/pkg/kubectl/cmd/create/create_rolebinding_test.go +++ b/pkg/kubectl/cmd/create/create_rolebinding_test.go @@ -32,6 +32,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) var groupVersion = schema.GroupVersion{Group: "rbac.authorization.k8s.io", Version: "v1"} @@ -112,8 +113,7 @@ func TestCreateRoleBinding(t *testing.T) { }, } - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateRoleBinding(tf, buf) + cmd := NewCmdCreateRoleBinding(tf, genericclioptions.NewTestIOStreamsDiscard()) cmd.Flags().Set("role", "fake-role") cmd.Flags().Set("user", "fake-user") cmd.Flags().Set("group", "fake-group") diff --git a/pkg/kubectl/cmd/create/create_secret.go b/pkg/kubectl/cmd/create/create_secret.go index 7e7ed51f73b..a1749d49eff 100644 --- a/pkg/kubectl/cmd/create/create_secret.go +++ b/pkg/kubectl/cmd/create/create_secret.go @@ -17,27 +17,26 @@ limitations under the License. package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) // NewCmdCreateSecret groups subcommands to create various types of secrets -func NewCmdCreateSecret(f cmdutil.Factory, cmdOut, errOut io.Writer) *cobra.Command { +func NewCmdCreateSecret(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "secret", Short: i18n.T("Create a secret using specified subcommand"), Long: "Create a secret using specified subcommand.", - Run: cmdutil.DefaultSubCommandRun(errOut), + Run: cmdutil.DefaultSubCommandRun(ioStreams.ErrOut), } - cmd.AddCommand(NewCmdCreateSecretDockerRegistry(f, cmdOut)) - cmd.AddCommand(NewCmdCreateSecretTLS(f, cmdOut)) - cmd.AddCommand(NewCmdCreateSecretGeneric(f, cmdOut)) + cmd.AddCommand(NewCmdCreateSecretDockerRegistry(f, ioStreams)) + cmd.AddCommand(NewCmdCreateSecretTLS(f, ioStreams)) + cmd.AddCommand(NewCmdCreateSecretGeneric(f, ioStreams)) return cmd } @@ -78,12 +77,9 @@ type SecretGenericOpts struct { } // NewCmdCreateSecretGeneric is a command to create generic secrets from files, directories, or literal values -func NewCmdCreateSecretGeneric(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateSecretGeneric(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &SecretGenericOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ @@ -166,12 +162,9 @@ type SecretDockerRegistryOpts struct { } // NewCmdCreateSecretDockerRegistry is a macro command for creating secrets to work with Docker registries -func NewCmdCreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateSecretDockerRegistry(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &SecretDockerRegistryOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ @@ -260,12 +253,9 @@ type SecretTLSOpts struct { } // NewCmdCreateSecretTLS is a macro command for creating secrets to work with Docker registries -func NewCmdCreateSecretTLS(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateSecretTLS(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &SecretTLSOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ diff --git a/pkg/kubectl/cmd/create/create_secret_test.go b/pkg/kubectl/cmd/create/create_secret_test.go index b4b80f5d0ce..a563ef540b2 100644 --- a/pkg/kubectl/cmd/create/create_secret_test.go +++ b/pkg/kubectl/cmd/create/create_secret_test.go @@ -17,7 +17,6 @@ limitations under the License. package create import ( - "bytes" "net/http" "testing" @@ -26,6 +25,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -57,8 +57,8 @@ func TestCreateSecretGeneric(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateSecretGeneric(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateSecretGeneric(tf, ioStreams) cmd.Flags().Set("output", "name") cmd.Flags().Set("from-literal", "password=includes,comma") cmd.Flags().Set("from-literal", "username=test_user") @@ -90,8 +90,8 @@ func TestCreateSecretDockerRegistry(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateSecretDockerRegistry(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateSecretDockerRegistry(tf, ioStreams) cmd.Flags().Set("docker-username", "test-user") cmd.Flags().Set("docker-password", "test-pass") cmd.Flags().Set("docker-email", "test-email") diff --git a/pkg/kubectl/cmd/create/create_service.go b/pkg/kubectl/cmd/create/create_service.go index 891bd766471..3afce7207db 100644 --- a/pkg/kubectl/cmd/create/create_service.go +++ b/pkg/kubectl/cmd/create/create_service.go @@ -17,30 +17,29 @@ limitations under the License. package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/api/core/v1" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) // NewCmdCreateService is a macro command to create a new service -func NewCmdCreateService(f cmdutil.Factory, cmdOut, errOut io.Writer) *cobra.Command { +func NewCmdCreateService(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "service", Aliases: []string{"svc"}, Short: i18n.T("Create a service using specified subcommand."), Long: "Create a service using specified subcommand.", - Run: cmdutil.DefaultSubCommandRun(errOut), + Run: cmdutil.DefaultSubCommandRun(ioStreams.ErrOut), } - cmd.AddCommand(NewCmdCreateServiceClusterIP(f, cmdOut)) - cmd.AddCommand(NewCmdCreateServiceNodePort(f, cmdOut)) - cmd.AddCommand(NewCmdCreateServiceLoadBalancer(f, cmdOut)) - cmd.AddCommand(NewCmdCreateServiceExternalName(f, cmdOut)) + cmd.AddCommand(NewCmdCreateServiceClusterIP(f, ioStreams)) + cmd.AddCommand(NewCmdCreateServiceNodePort(f, ioStreams)) + cmd.AddCommand(NewCmdCreateServiceLoadBalancer(f, ioStreams)) + cmd.AddCommand(NewCmdCreateServiceExternalName(f, ioStreams)) return cmd } @@ -66,12 +65,9 @@ type ServiceClusterIPOpts struct { } // NewCmdCreateServiceClusterIP is a command to create a ClusterIP service -func NewCmdCreateServiceClusterIP(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateServiceClusterIP(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &ServiceClusterIPOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ @@ -141,12 +137,9 @@ type ServiceNodePortOpts struct { } // NewCmdCreateServiceNodePort is a macro command for creating a NodePort service -func NewCmdCreateServiceNodePort(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateServiceNodePort(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &ServiceNodePortOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ @@ -213,12 +206,9 @@ type ServiceLoadBalancerOpts struct { } // NewCmdCreateServiceLoadBalancer is a macro command for creating a LoadBalancer service -func NewCmdCreateServiceLoadBalancer(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateServiceLoadBalancer(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &ServiceLoadBalancerOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ @@ -287,12 +277,9 @@ type ServiceExternalNameOpts struct { } // NewCmdCreateServiceExternalName is a macro command for creating an ExternalName service -func NewCmdCreateServiceExternalName(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateServiceExternalName(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &ServiceExternalNameOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ diff --git a/pkg/kubectl/cmd/create/create_service_test.go b/pkg/kubectl/cmd/create/create_service_test.go index 2c204725ae2..059c5c0fcc3 100644 --- a/pkg/kubectl/cmd/create/create_service_test.go +++ b/pkg/kubectl/cmd/create/create_service_test.go @@ -17,7 +17,6 @@ limitations under the License. package create import ( - "bytes" "net/http" "testing" @@ -26,6 +25,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -52,8 +52,8 @@ func TestCreateService(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateServiceClusterIP(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateServiceClusterIP(tf, ioStreams) cmd.Flags().Set("output", "name") cmd.Flags().Set("tcp", "8080:8000") cmd.Run(cmd, []string{service.Name}) @@ -86,8 +86,8 @@ func TestCreateServiceNodePort(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateServiceNodePort(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateServiceNodePort(tf, ioStreams) cmd.Flags().Set("output", "name") cmd.Flags().Set("tcp", "30000:8000") cmd.Run(cmd, []string{service.Name}) @@ -120,8 +120,8 @@ func TestCreateServiceExternalName(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateServiceExternalName(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateServiceExternalName(tf, ioStreams) cmd.Flags().Set("output", "name") cmd.Flags().Set("external-name", "name") cmd.Run(cmd, []string{service.Name}) diff --git a/pkg/kubectl/cmd/create/create_serviceaccount.go b/pkg/kubectl/cmd/create/create_serviceaccount.go index 4ac7b97d29f..3489376ef73 100644 --- a/pkg/kubectl/cmd/create/create_serviceaccount.go +++ b/pkg/kubectl/cmd/create/create_serviceaccount.go @@ -17,13 +17,12 @@ limitations under the License. package create import ( - "io" - "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -41,12 +40,9 @@ type ServiceAccountOpts struct { } // NewCmdCreateServiceAccount is a macro command to create a new service account -func NewCmdCreateServiceAccount(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { +func NewCmdCreateServiceAccount(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { options := &ServiceAccountOpts{ - CreateSubcommandOptions: &CreateSubcommandOptions{ - PrintFlags: NewPrintFlags("created"), - CmdOut: cmdOut, - }, + CreateSubcommandOptions: NewCreateSubcommandOptions(ioStreams), } cmd := &cobra.Command{ diff --git a/pkg/kubectl/cmd/create/create_serviceaccount_test.go b/pkg/kubectl/cmd/create/create_serviceaccount_test.go index 42d216a945a..6fcba4e02f2 100644 --- a/pkg/kubectl/cmd/create/create_serviceaccount_test.go +++ b/pkg/kubectl/cmd/create/create_serviceaccount_test.go @@ -17,7 +17,6 @@ limitations under the License. package create import ( - "bytes" "net/http" "testing" @@ -26,6 +25,7 @@ import ( "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -52,8 +52,8 @@ func TestCreateServiceAccount(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateServiceAccount(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreateServiceAccount(tf, ioStreams) cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{serviceAccountObject.Name}) expectedOutput := "serviceaccount/" + serviceAccountObject.Name + "\n" diff --git a/pkg/kubectl/cmd/create/create_test.go b/pkg/kubectl/cmd/create/create_test.go index a70247e1e95..91ff4f840b7 100644 --- a/pkg/kubectl/cmd/create/create_test.go +++ b/pkg/kubectl/cmd/create/create_test.go @@ -17,7 +17,6 @@ limitations under the License. package create import ( - "bytes" "net/http" "testing" @@ -30,18 +29,17 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) func TestExtraArgsFail(t *testing.T) { initTestErrorHandler(t) - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) f := cmdtesting.NewTestFactory() defer f.Cleanup() - c := NewCmdCreate(f, buf, errBuf) + c := NewCmdCreate(f, genericclioptions.NewTestIOStreamsDiscard()) options := CreateOptions{} if options.ValidateArgs(c, []string{"rc"}) == nil { t.Errorf("unexpected non-error") @@ -72,10 +70,9 @@ func TestCreateObject(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreate(tf, buf, errBuf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreate(tf, ioStreams) cmd.Flags().Set("filename", "../../../../examples/guestbook/legacy/redis-master-controller.yaml") cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) @@ -111,10 +108,9 @@ func TestCreateMultipleObject(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreate(tf, buf, errBuf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreate(tf, ioStreams) cmd.Flags().Set("filename", "../../../../examples/guestbook/legacy/redis-master-controller.yaml") cmd.Flags().Set("filename", "../../../../examples/guestbook/frontend-service.yaml") cmd.Flags().Set("output", "name") @@ -150,10 +146,9 @@ func TestCreateDirectory(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreate(tf, buf, errBuf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdCreate(tf, ioStreams) cmd.Flags().Set("filename", "../../../../examples/guestbook/legacy") cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{}) diff --git a/pkg/kubectl/cmd/edit.go b/pkg/kubectl/cmd/edit.go index f2915d9a0f0..f9ad0fdea5a 100644 --- a/pkg/kubectl/cmd/edit.go +++ b/pkg/kubectl/cmd/edit.go @@ -18,7 +18,6 @@ package cmd import ( "fmt" - "io" "github.com/spf13/cobra" @@ -26,6 +25,7 @@ import ( "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -68,8 +68,8 @@ var ( kubectl edit deployment/mydeployment -o yaml --save-config`)) ) -func NewCmdEdit(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - o := editor.NewEditOptions(editor.NormalEditMode, out, errOut) +func NewCmdEdit(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { + o := editor.NewEditOptions(editor.NormalEditMode, ioStreams) o.ValidateOptions = cmdutil.ValidateOptions{EnableValidation: true} validArgs := cmdutil.ValidArgList(f) diff --git a/pkg/kubectl/cmd/edit_test.go b/pkg/kubectl/cmd/edit_test.go index 30fced8102c..78fda659ad3 100644 --- a/pkg/kubectl/cmd/edit_test.go +++ b/pkg/kubectl/cmd/edit_test.go @@ -39,6 +39,7 @@ import ( "k8s.io/kubernetes/pkg/kubectl/cmd/create" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/resource" ) @@ -229,18 +230,17 @@ func TestEdit(t *testing.T) { } tf.ClientConfigVal = defaultClientConfig() tf.CommandVal = "edit test cmd invocation" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) + ioStreams, _, buf, errBuf := genericclioptions.NewTestIOStreams() var cmd *cobra.Command switch testcase.Mode { case "edit": - cmd = NewCmdEdit(tf, buf, errBuf) + cmd = NewCmdEdit(tf, ioStreams) case "create": - cmd = create.NewCmdCreate(tf, buf, errBuf) + cmd = create.NewCmdCreate(tf, ioStreams) cmd.Flags().Set("edit", "true") case "edit-last-applied": - cmd = NewCmdApplyEditLastApplied(tf, buf, errBuf) + cmd = NewCmdApplyEditLastApplied(tf, ioStreams) default: t.Fatalf("%s: unexpected mode %s", name, testcase.Mode) } diff --git a/pkg/kubectl/cmd/util/editor/editoptions.go b/pkg/kubectl/cmd/util/editor/editoptions.go index 48e1d95da1b..946b3c7b84b 100644 --- a/pkg/kubectl/cmd/util/editor/editoptions.go +++ b/pkg/kubectl/cmd/util/editor/editoptions.go @@ -72,8 +72,7 @@ type EditOptions struct { ApplyAnnotation bool ChangeCause string - Out io.Writer - ErrOut io.Writer + genericclioptions.IOStreams Recorder genericclioptions.Recorder f cmdutil.Factory @@ -81,7 +80,7 @@ type EditOptions struct { updatedResultGetter func(data []byte) *resource.Result } -func NewEditOptions(editMode EditMode, out, errOut io.Writer) *EditOptions { +func NewEditOptions(editMode EditMode, ioStreams genericclioptions.IOStreams) *EditOptions { return &EditOptions{ RecordFlags: genericclioptions.NewRecordFlags(), @@ -92,8 +91,7 @@ func NewEditOptions(editMode EditMode, out, errOut io.Writer) *EditOptions { Recorder: genericclioptions.NoopRecorder{}, - Out: out, - ErrOut: errOut, + IOStreams: ioStreams, } } diff --git a/pkg/kubectl/genericclioptions/BUILD b/pkg/kubectl/genericclioptions/BUILD index f2af80dd683..0dabfc5309a 100644 --- a/pkg/kubectl/genericclioptions/BUILD +++ b/pkg/kubectl/genericclioptions/BUILD @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "doc.go", + "io_options.go", "record_flags.go", ], importpath = "k8s.io/kubernetes/pkg/kubectl/genericclioptions", diff --git a/pkg/kubectl/genericclioptions/io_options.go b/pkg/kubectl/genericclioptions/io_options.go new file mode 100644 index 00000000000..4fc3a77b0cd --- /dev/null +++ b/pkg/kubectl/genericclioptions/io_options.go @@ -0,0 +1,57 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genericclioptions + +import ( + "bytes" + "io" + "io/ioutil" +) + +// IOStreams provides the standard names for iostreams. This is useful for embedding and for unit testing. +// Inconsistent and different names make it hard to read and review code +type IOStreams struct { + // In think, os.Stdin + In io.Reader + // Out think, os.Stdout + Out io.Writer + // ErrOut think, os.Stderr + ErrOut io.Writer +} + +// NewTestIOStreams returns a valid IOStreams and in, out, errout buffers for unit tests +func NewTestIOStreams() (IOStreams, *bytes.Buffer, *bytes.Buffer, *bytes.Buffer) { + in := &bytes.Buffer{} + out := &bytes.Buffer{} + errOut := &bytes.Buffer{} + + return IOStreams{ + In: in, + Out: out, + ErrOut: errOut, + }, in, out, errOut +} + +// NewTestIOStreamsDiscard returns a valid IOStreams that just discards +func NewTestIOStreamsDiscard() IOStreams { + in := &bytes.Buffer{} + return IOStreams{ + In: in, + Out: ioutil.Discard, + ErrOut: ioutil.Discard, + } +}