diff --git a/pkg/kubectl/cmd/cmd.go b/pkg/kubectl/cmd/cmd.go index 130d22d3c34..62094582f47 100644 --- a/pkg/kubectl/cmd/cmd.go +++ b/pkg/kubectl/cmd/cmd.go @@ -255,17 +255,17 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob Message: "Basic Commands (Beginner):", Commands: []*cobra.Command{ create.NewCmdCreate(f, ioStreams), - NewCmdExposeService(f, out), - NewCmdRun(f, in, out, err), - set.NewCmdSet(f, in, out, err), - deprecatedAlias("run-container", NewCmdRun(f, in, out, err)), + NewCmdExposeService(f, ioStreams), + NewCmdRun(f, ioStreams), + set.NewCmdSet(f, ioStreams), + deprecatedAlias("run-container", NewCmdRun(f, ioStreams)), }, }, { Message: "Basic Commands (Intermediate):", Commands: []*cobra.Command{ - resource.NewCmdGet(f, out, err), - NewCmdExplain(f, out, err), + resource.NewCmdGet(f, ioStreams), + NewCmdExplain(f, ioStreams), NewCmdEdit(f, ioStreams), NewCmdDelete(f, out, err), }, diff --git a/pkg/kubectl/cmd/cmd_test.go b/pkg/kubectl/cmd/cmd_test.go index 53ab46225f1..74312869c43 100644 --- a/pkg/kubectl/cmd/cmd_test.go +++ b/pkg/kubectl/cmd/cmd_test.go @@ -43,6 +43,7 @@ import ( "k8s.io/kubernetes/pkg/kubectl/cmd/resource" 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" "k8s.io/kubernetes/pkg/printers" "k8s.io/kubernetes/pkg/util/strings" @@ -253,7 +254,7 @@ func Example_printServiceWithLabels() { NegotiatedSerializer: ns, Client: nil, } - cmd := resource.NewCmdGet(tf, os.Stdout, os.Stderr) + cmd := resource.NewCmdGet(tf, genericclioptions.NewTestIOStreamsDiscard()) svc := &api.ServiceList{ Items: []api.Service{ { diff --git a/pkg/kubectl/cmd/explain.go b/pkg/kubectl/cmd/explain.go index d391988e5d2..61ef8fa3f52 100644 --- a/pkg/kubectl/cmd/explain.go +++ b/pkg/kubectl/cmd/explain.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/explain" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/util/i18n" ) @@ -49,8 +49,20 @@ var ( kubectl explain pods.spec.containers`)) ) +type ExplainOptions struct { + genericclioptions.IOStreams +} + +func NewExplainOptions(streams genericclioptions.IOStreams) *ExplainOptions { + return &ExplainOptions{ + IOStreams: streams, + } +} + // NewCmdExplain returns a cobra command for swagger docs -func NewCmdExplain(f cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command { +func NewCmdExplain(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewExplainOptions(streams) + cmd := &cobra.Command{ Use: "explain RESOURCE", DisableFlagsInUseLine: true, @@ -58,7 +70,7 @@ func NewCmdExplain(f cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command { Long: explainLong + "\n\n" + cmdutil.ValidResourceTypeList(f), Example: explainExamples, Run: func(cmd *cobra.Command, args []string) { - err := RunExplain(f, out, cmdErr, cmd, args) + err := o.RunExplain(f, cmd, args) cmdutil.CheckErr(err) }, } @@ -68,9 +80,9 @@ func NewCmdExplain(f cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command { } // RunExplain executes the appropriate steps to print a model's documentation -func RunExplain(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, args []string) error { +func (o *ExplainOptions) RunExplain(f cmdutil.Factory, cmd *cobra.Command, args []string) error { if len(args) == 0 { - fmt.Fprintf(cmdErr, "You must specify the type of resource to explain. %s\n\n", cmdutil.ValidResourceTypeList(f)) + fmt.Fprintf(o.ErrOut, "You must specify the type of resource to explain. %s\n\n", cmdutil.ValidResourceTypeList(f)) return cmdutil.UsageErrorf(cmd, "Required resource not specified.") } if len(args) > 1 { @@ -120,5 +132,5 @@ func RunExplain(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, ar return fmt.Errorf("Couldn't find resource for %q", gvk) } - return explain.PrintModelDescription(fieldsPath, out, schema, gvk, recursive) + return explain.PrintModelDescription(fieldsPath, o.Out, schema, gvk, recursive) } diff --git a/pkg/kubectl/cmd/expose.go b/pkg/kubectl/cmd/expose.go index 4ed649cdb08..0cdeab70f3a 100644 --- a/pkg/kubectl/cmd/expose.go +++ b/pkg/kubectl/cmd/expose.go @@ -17,7 +17,6 @@ limitations under the License. package cmd import ( - "io" "regexp" "strings" @@ -79,18 +78,20 @@ type ExposeServiceOptions struct { RecordFlags *genericclioptions.RecordFlags Recorder genericclioptions.Recorder + genericclioptions.IOStreams } -func NewExposeServiceOptions() *ExposeServiceOptions { +func NewExposeServiceOptions(streams genericclioptions.IOStreams) *ExposeServiceOptions { return &ExposeServiceOptions{ RecordFlags: genericclioptions.NewRecordFlags(), - Recorder: genericclioptions.NoopRecorder{}, + Recorder: genericclioptions.NoopRecorder{}, + IOStreams: streams, } } -func NewCmdExposeService(f cmdutil.Factory, out io.Writer) *cobra.Command { - o := NewExposeServiceOptions() +func NewCmdExposeService(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewExposeServiceOptions(streams) validArgs := []string{} resources := regexp.MustCompile(`\s*,`).Split(exposeResources, -1) @@ -106,7 +107,7 @@ func NewCmdExposeService(f cmdutil.Factory, out io.Writer) *cobra.Command { Example: exposeExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd)) - cmdutil.CheckErr(o.RunExpose(f, out, cmd, args)) + cmdutil.CheckErr(o.RunExpose(f, cmd, args)) }, ValidArgs: validArgs, ArgAliases: kubectl.ResourceAliases(validArgs), @@ -150,7 +151,7 @@ func (o *ExposeServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) e return err } -func (o *ExposeServiceOptions) RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error { +func (o *ExposeServiceOptions) RunExpose(f cmdutil.Factory, cmd *cobra.Command, args []string) error { namespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err @@ -284,9 +285,9 @@ func (o *ExposeServiceOptions) RunExpose(f cmdutil.Factory, out io.Writer, cmd * info.Refresh(object, true) if cmdutil.GetDryRunFlag(cmd) { if len(cmdutil.GetFlagString(cmd, "output")) > 0 { - return cmdutil.PrintObject(cmd, object, out) + return cmdutil.PrintObject(cmd, object, o.Out) } - cmdutil.PrintSuccess(false, out, info.Object, true, "exposed") + cmdutil.PrintSuccess(false, o.Out, info.Object, true, "exposed") return nil } if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info.Object, cmdutil.InternalVersionJSONEncoder()); err != nil { @@ -300,10 +301,10 @@ func (o *ExposeServiceOptions) RunExpose(f cmdutil.Factory, out io.Writer, cmd * } if len(cmdutil.GetFlagString(cmd, "output")) > 0 { - return cmdutil.PrintObject(cmd, object, out) + return cmdutil.PrintObject(cmd, object, o.Out) } - cmdutil.PrintSuccess(false, out, info.Object, false, "exposed") + cmdutil.PrintSuccess(false, o.Out, info.Object, false, "exposed") return nil }) if err != nil { diff --git a/pkg/kubectl/cmd/expose_test.go b/pkg/kubectl/cmd/expose_test.go index 6cfe5f6085b..212efb7aac9 100644 --- a/pkg/kubectl/cmd/expose_test.go +++ b/pkg/kubectl/cmd/expose_test.go @@ -17,7 +17,6 @@ limitations under the License. package cmd import ( - "bytes" "fmt" "net/http" "strings" @@ -31,6 +30,7 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -489,9 +489,9 @@ func TestRunExposeService(t *testing.T) { }), } tf.Namespace = test.ns - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdExposeService(tf, buf) + ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdExposeService(tf, ioStreams) cmd.SetOutput(buf) for flag, value := range test.flags { cmd.Flags().Set(flag, value) diff --git a/pkg/kubectl/cmd/resource/BUILD b/pkg/kubectl/cmd/resource/BUILD index 78ac12bae5e..927fd5f2783 100644 --- a/pkg/kubectl/cmd/resource/BUILD +++ b/pkg/kubectl/cmd/resource/BUILD @@ -11,6 +11,7 @@ go_library( "//pkg/kubectl/cmd/templates:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/cmd/util/openapi:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", "//pkg/kubectl/resource:go_default_library", "//pkg/kubectl/util/i18n:go_default_library", "//pkg/printers:go_default_library", @@ -50,6 +51,7 @@ go_test( "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/cmd/util/openapi:go_default_library", "//pkg/kubectl/cmd/util/openapi/testing:go_default_library", + "//pkg/kubectl/genericclioptions:go_default_library", "//pkg/kubectl/scheme:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", diff --git a/pkg/kubectl/cmd/resource/get.go b/pkg/kubectl/cmd/resource/get.go index 832a68a7535..d488e24b7f1 100644 --- a/pkg/kubectl/cmd/resource/get.go +++ b/pkg/kubectl/cmd/resource/get.go @@ -43,6 +43,7 @@ import ( "k8s.io/kubernetes/pkg/kubectl/cmd/templates" 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/resource" "k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/printers" @@ -51,8 +52,6 @@ import ( // GetOptions contains the input to the get command. type GetOptions struct { - Out, ErrOut io.Writer - resource.FilenameOptions Raw string @@ -75,6 +74,8 @@ type GetOptions struct { Export bool IncludeUninitialized bool + + genericclioptions.IOStreams } var ( @@ -126,18 +127,18 @@ const ( ) // NewGetOptions returns a GetOptions with default chunk size 500. -func NewGetOptions(out io.Writer, errOut io.Writer) *GetOptions { +func NewGetOptions(streams genericclioptions.IOStreams) *GetOptions { return &GetOptions{ - Out: out, - ErrOut: errOut, ChunkSize: 500, + + IOStreams: streams, } } // NewCmdGet creates a command object for the generic "get" action, which // retrieves one or more resources from a server. -func NewCmdGet(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command { - options := NewGetOptions(out, errOut) +func NewCmdGet(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + options := NewGetOptions(streams) validArgs := cmdutil.ValidArgList(f) cmd := &cobra.Command{ diff --git a/pkg/kubectl/cmd/resource/get_test.go b/pkg/kubectl/cmd/resource/get_test.go index 656536ca361..7a4f0fc71a8 100644 --- a/pkg/kubectl/cmd/resource/get_test.go +++ b/pkg/kubectl/cmd/resource/get_test.go @@ -50,6 +50,7 @@ import ( cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" openapitesting "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -211,10 +212,8 @@ func TestGetUnknownSchemaObject(t *testing.T) { t.Fatalf("unexpected conversion of unstructured object to structured: %s", diff.ObjectReflectDiff(convertedObj, obj)) } - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Run(cmd, []string{"type", "foo"}) @@ -254,10 +253,9 @@ func TestGetSchemaObject(t *testing.T) { } tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.Run(cmd, []string{"replicationcontrollers", "foo"}) if !strings.Contains(buf.String(), "foo") { @@ -280,10 +278,9 @@ func TestGetObjectsWithOpenAPIOutputFormatPresent(t *testing.T) { Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set(useOpenAPIPrintColumnFlagLabel, "true") cmd.Run(cmd, []string{"pods", "foo"}) @@ -335,10 +332,9 @@ func TestGetObjects(t *testing.T) { Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Run(cmd, []string{"pods", "foo"}) @@ -384,10 +380,9 @@ func TestGetObjectIgnoreNotFound(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("ignore-not-found", "true") cmd.Flags().Set("output", "yaml") @@ -430,10 +425,8 @@ func TestGetSortedObjects(t *testing.T) { tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: "v1"}}} - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) // sorting with metedata.name @@ -462,10 +455,9 @@ func TestGetObjectsIdentifiedByFile(t *testing.T) { Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml") cmd.Run(cmd, []string{}) @@ -490,10 +482,9 @@ func TestGetListObjects(t *testing.T) { Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Run(cmd, []string{"pods"}) @@ -518,10 +509,9 @@ func TestGetAllListObjects(t *testing.T) { Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("show-all", "true") cmd.Run(cmd, []string{"pods"}) @@ -547,10 +537,9 @@ func TestGetListComponentStatus(t *testing.T) { Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, statuses)}, } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Run(cmd, []string{"componentstatuses"}) @@ -598,10 +587,9 @@ func TestGetMixedGenericObjects(t *testing.T) { } tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("output", "json") cmd.Run(cmd, []string{"pods"}) @@ -650,10 +638,9 @@ func TestGetMultipleTypeObjects(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Run(cmd, []string{"pods,services"}) @@ -691,10 +678,9 @@ func TestGetMultipleTypeObjectsAsList(t *testing.T) { } tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("output", "json") @@ -796,10 +782,9 @@ func TestGetMultipleTypeObjectsWithLabelSelector(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("selector", "a=b") @@ -841,10 +826,9 @@ func TestGetMultipleTypeObjectsWithFieldSelector(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("field-selector", "a=b") @@ -888,10 +872,9 @@ func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Run(cmd, []string{"services/bar", "node/foo"}) @@ -918,10 +901,9 @@ func TestGetByFormatForcesFlag(t *testing.T) { Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Flags().Lookup("output").Value.Set("yaml") cmd.Flags().Set("show-all", "false") @@ -1035,10 +1017,9 @@ func TestWatchLabelSelector(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("watch", "true") @@ -1088,10 +1069,9 @@ func TestWatchFieldSelector(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("watch", "true") @@ -1135,10 +1115,9 @@ func TestWatchResource(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("watch", "true") @@ -1180,10 +1159,9 @@ func TestWatchResourceIdentifiedByFile(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("watch", "true") @@ -1226,10 +1204,9 @@ func TestWatchOnlyResource(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("watch-only", "true") @@ -1273,10 +1250,9 @@ func TestWatchOnlyList(t *testing.T) { }), } tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(tf, buf, errBuf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdGet(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("watch-only", "true") diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index 55ad213a74c..95a0a42e7ab 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -118,12 +118,10 @@ type RunOptions struct { Schedule string TTY bool - In io.Reader - Out io.Writer - ErrOut io.Writer + genericclioptions.IOStreams } -func NewRunOptions(in io.Reader, out, errOut io.Writer) *RunOptions { +func NewRunOptions(streams genericclioptions.IOStreams) *RunOptions { return &RunOptions{ PrintFlags: printers.NewPrintFlags("created"), DeleteFlags: NewDeleteFlags("to use to replace the resource."), @@ -131,14 +129,12 @@ func NewRunOptions(in io.Reader, out, errOut io.Writer) *RunOptions { Recorder: genericclioptions.NoopRecorder{}, - In: in, - Out: out, - ErrOut: errOut, + IOStreams: streams, } } -func NewCmdRun(f cmdutil.Factory, in io.Reader, out, errOut io.Writer) *cobra.Command { - o := NewRunOptions(in, out, errOut) +func NewCmdRun(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewRunOptions(streams) cmd := &cobra.Command{ Use: "run NAME --image=image [--env=\"key=value\"] [--port=port] [--replicas=replicas] [--dry-run=bool] [--overrides=inline-json] [--command] -- [COMMAND] [args...]", diff --git a/pkg/kubectl/cmd/run_test.go b/pkg/kubectl/cmd/run_test.go index 91760139913..6d65d0d5d07 100644 --- a/pkg/kubectl/cmd/run_test.go +++ b/pkg/kubectl/cmd/run_test.go @@ -194,7 +194,7 @@ func TestRunArgsFollowDashRules(t *testing.T) { tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{} - cmd := NewCmdRun(tf, os.Stdin, os.Stdout, os.Stderr) + cmd := NewCmdRun(tf, genericclioptions.NewTestIOStreamsDiscard()) cmd.Flags().Set("image", "nginx") cmd.Flags().Set("generator", "run/v1") @@ -210,9 +210,7 @@ func TestRunArgsFollowDashRules(t *testing.T) { PrintFlags: printFlags, DeleteOptions: deleteFlags.ToOptions(os.Stdout, os.Stderr), - In: os.Stdin, - Out: os.Stdout, - ErrOut: os.Stderr, + IOStreams: genericclioptions.NewTestIOStreamsDiscard(), Image: "nginx", Generator: "run/v1", @@ -375,14 +373,13 @@ func TestGenerateService(t *testing.T) { return } + ioStreams, _, buff, _ := genericclioptions.NewTestIOStreams() deleteFlags := NewDeleteFlags("to use to replace the resource.") - buff := &bytes.Buffer{} opts := &RunOptions{ PrintFlags: printFlags, DeleteOptions: deleteFlags.ToOptions(os.Stdout, os.Stderr), - Out: buff, - ErrOut: buff, + IOStreams: ioStreams, Port: test.port, Recorder: genericclioptions.NoopRecorder{}, @@ -519,19 +516,17 @@ func TestRunValidations(t *testing.T) { } tf.Namespace = "test" tf.ClientConfigVal = defaultClientConfig() - inBuf := bytes.NewReader([]byte{}) - outBuf := bytes.NewBuffer([]byte{}) - errBuf := bytes.NewBuffer([]byte{}) - cmd := NewCmdRun(tf, inBuf, outBuf, errBuf) + streams, _, _, bufErr := genericclioptions.NewTestIOStreams() + cmd := NewCmdRun(tf, streams) for flagName, flagValue := range test.flags { cmd.Flags().Set(flagName, flagValue) } cmd.Run(cmd, test.args) var err error - if errBuf.Len() > 0 { - err = fmt.Errorf("%v", errBuf.String()) + if bufErr.Len() > 0 { + err = fmt.Errorf("%v", bufErr.String()) } if err != nil && len(test.expectedErr) > 0 { if !strings.Contains(err.Error(), test.expectedErr) { diff --git a/pkg/kubectl/cmd/set/BUILD b/pkg/kubectl/cmd/set/BUILD index 0181e2d0f58..bdde3d4ce8b 100644 --- a/pkg/kubectl/cmd/set/BUILD +++ b/pkg/kubectl/cmd/set/BUILD @@ -66,6 +66,7 @@ go_test( "//pkg/apis/rbac: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/resource:go_default_library", "//pkg/kubectl/scheme:go_default_library", "//pkg/printers:go_default_library", diff --git a/pkg/kubectl/cmd/set/set.go b/pkg/kubectl/cmd/set/set.go index dfc69c1049d..f0864fc334d 100644 --- a/pkg/kubectl/cmd/set/set.go +++ b/pkg/kubectl/cmd/set/set.go @@ -17,11 +17,10 @@ limitations under the License. package set import ( - "io" - "github.com/spf13/cobra" "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" ) @@ -32,22 +31,22 @@ var ( These commands help you make changes to existing application resources.`) ) -func NewCmdSet(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command { +func NewCmdSet(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "set SUBCOMMAND", DisableFlagsInUseLine: true, Short: i18n.T("Set specific features on objects"), Long: set_long, - Run: cmdutil.DefaultSubCommandRun(err), + Run: cmdutil.DefaultSubCommandRun(streams.ErrOut), } // add subcommands - cmd.AddCommand(NewCmdImage(f, out, err)) - cmd.AddCommand(NewCmdResources(f, out, err)) - cmd.AddCommand(NewCmdSelector(f, out)) - cmd.AddCommand(NewCmdSubject(f, out, err)) - cmd.AddCommand(NewCmdServiceAccount(f, out, err)) - cmd.AddCommand(NewCmdEnv(f, in, out, err)) + cmd.AddCommand(NewCmdImage(f, streams)) + cmd.AddCommand(NewCmdResources(f, streams)) + cmd.AddCommand(NewCmdSelector(f, streams)) + cmd.AddCommand(NewCmdSubject(f, streams)) + cmd.AddCommand(NewCmdServiceAccount(f, streams)) + cmd.AddCommand(NewCmdEnv(f, streams)) return cmd } diff --git a/pkg/kubectl/cmd/set/set_env.go b/pkg/kubectl/cmd/set/set_env.go index b4e0e507104..837ba77e388 100644 --- a/pkg/kubectl/cmd/set/set_env.go +++ b/pkg/kubectl/cmd/set/set_env.go @@ -19,7 +19,6 @@ package set import ( "errors" "fmt" - "io" "regexp" "sort" "strings" @@ -36,6 +35,7 @@ import ( "k8s.io/kubernetes/pkg/printers" utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) var ( @@ -94,10 +94,6 @@ var ( type EnvOptions struct { PrintFlags *printers.PrintFlags - Out io.Writer - Err io.Writer - In io.Reader - resource.FilenameOptions EnvParams []string EnvArgs []string @@ -123,25 +119,26 @@ type EnvOptions struct { Infos []*resource.Info UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) + + genericclioptions.IOStreams } // NewEnvOptions returns an EnvOptions indicating all containers in the selected // pod templates are selected by default and allowing environment to be overwritten -func NewEnvOptions(in io.Reader, out, errout io.Writer) *EnvOptions { +func NewEnvOptions(streams genericclioptions.IOStreams) *EnvOptions { return &EnvOptions{ PrintFlags: printers.NewPrintFlags("env updated"), - Out: out, - Err: errout, - In: in, ContainerSelector: "*", Overwrite: true, + + IOStreams: streams, } } // NewCmdEnv implements the OpenShift cli env command -func NewCmdEnv(f cmdutil.Factory, in io.Reader, out, errout io.Writer) *cobra.Command { - options := NewEnvOptions(in, out, errout) +func NewCmdEnv(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + options := NewEnvOptions(streams) cmd := &cobra.Command{ Use: "env RESOURCE/NAME KEY_1=VAL_1 ... KEY_N=VAL_N", DisableFlagsInUseLine: true, @@ -346,7 +343,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error { resolutionErrorsEncountered := false containers, _ := selectContainers(spec.Containers, o.ContainerSelector) if len(containers) == 0 { - fmt.Fprintf(o.Err, "warning: %s/%s does not have any containers matching %q\n", info.Mapping.Resource, info.Name, o.ContainerSelector) + fmt.Fprintf(o.ErrOut, "warning: %s/%s does not have any containers matching %q\n", info.Mapping.Resource, info.Name, o.ContainerSelector) return nil } for _, c := range containers { @@ -397,7 +394,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error { } sort.Strings(errs) for _, err := range errs { - fmt.Fprintln(o.Err, err) + fmt.Fprintln(o.ErrOut, err) } } } diff --git a/pkg/kubectl/cmd/set/set_env_test.go b/pkg/kubectl/cmd/set/set_env_test.go index 2495f6394fa..8dbfa0efa16 100644 --- a/pkg/kubectl/cmd/set/set_env_test.go +++ b/pkg/kubectl/cmd/set/set_env_test.go @@ -17,11 +17,9 @@ limitations under the License. package set import ( - "bytes" "fmt" "io/ioutil" "net/http" - "os" "path" "strings" "testing" @@ -43,6 +41,7 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -65,8 +64,8 @@ func TestSetEnvLocal(t *testing.T) { outputFormat := "name" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdEnv(tf, os.Stdin, buf, buf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdEnv(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("output", outputFormat) cmd.Flags().Set("local", "true") @@ -80,8 +79,8 @@ func TestSetEnvLocal(t *testing.T) { }, FilenameOptions: resource.FilenameOptions{ Filenames: []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}}, - Out: buf, - Local: true, + Local: true, + IOStreams: streams, } err := opts.Complete(tf, cmd, []string{"env=prod"}) if err == nil { @@ -114,8 +113,8 @@ func TestSetMultiResourcesEnvLocal(t *testing.T) { outputFormat := "name" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdEnv(tf, os.Stdin, buf, buf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdEnv(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("output", outputFormat) cmd.Flags().Set("local", "true") @@ -129,8 +128,8 @@ func TestSetMultiResourcesEnvLocal(t *testing.T) { }, FilenameOptions: resource.FilenameOptions{ Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}}, - Out: buf, - Local: true, + Local: true, + IOStreams: streams, } err := opts.Complete(tf, cmd, []string{"env=prod"}) if err == nil { @@ -507,9 +506,8 @@ func TestSetEnvRemote(t *testing.T) { outputFormat := "yaml" - out := new(bytes.Buffer) - cmd := NewCmdEnv(tf, out, out, out) - cmd.SetOutput(out) + streams := genericclioptions.NewTestIOStreamsDiscard() + cmd := NewCmdEnv(tf, streams) cmd.Flags().Set("output", outputFormat) opts := EnvOptions{ PrintFlags: &printers.PrintFlags{ @@ -518,8 +516,9 @@ func TestSetEnvRemote(t *testing.T) { OutputFormat: &outputFormat, }, - Out: out, - Local: false} + Local: false, + IOStreams: streams, + } err := opts.Complete(tf, cmd, input.args) assert.NoError(t, err) err = opts.RunEnv(tf) diff --git a/pkg/kubectl/cmd/set/set_image.go b/pkg/kubectl/cmd/set/set_image.go index 70e578e331c..8387584bdef 100644 --- a/pkg/kubectl/cmd/set/set_image.go +++ b/pkg/kubectl/cmd/set/set_image.go @@ -18,7 +18,6 @@ package set import ( "fmt" - "io" "k8s.io/kubernetes/pkg/printers" @@ -45,8 +44,6 @@ type SetImageOptions struct { Infos []*resource.Info Selector string - Out io.Writer - Err io.Writer DryRun bool All bool Output string @@ -59,6 +56,8 @@ type SetImageOptions struct { UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) Resources []string ContainerImages map[string]string + + genericclioptions.IOStreams } var ( @@ -85,20 +84,19 @@ var ( kubectl set image -f path/to/file.yaml nginx=nginx:1.9.1 --local -o yaml`) ) -func NewImageOptions(out, errOut io.Writer) *SetImageOptions { +func NewImageOptions(streams genericclioptions.IOStreams) *SetImageOptions { return &SetImageOptions{ PrintFlags: printers.NewPrintFlags("image updated"), RecordFlags: genericclioptions.NewRecordFlags(), Recorder: genericclioptions.NoopRecorder{}, - Out: out, - Err: errOut, + IOStreams: streams, } } -func NewCmdImage(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - o := NewImageOptions(out, errOut) +func NewCmdImage(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewImageOptions(streams) cmd := &cobra.Command{ Use: "image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N", diff --git a/pkg/kubectl/cmd/set/set_image_test.go b/pkg/kubectl/cmd/set/set_image_test.go index c5967f72e98..44e10871b07 100644 --- a/pkg/kubectl/cmd/set/set_image_test.go +++ b/pkg/kubectl/cmd/set/set_image_test.go @@ -17,7 +17,6 @@ limitations under the License. package set import ( - "bytes" "fmt" "io/ioutil" "net/http" @@ -42,6 +41,7 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -65,8 +65,8 @@ func TestImageLocal(t *testing.T) { outputFormat := "name" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdImage(tf, buf, buf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdImage(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("output", outputFormat) cmd.Flags().Set("local", "true") @@ -80,8 +80,9 @@ func TestImageLocal(t *testing.T) { }, FilenameOptions: resource.FilenameOptions{ Filenames: []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}}, - Out: buf, - Local: true} + Local: true, + IOStreams: streams, + } err := opts.Complete(tf, cmd, []string{"cassandra=thingy"}) if err == nil { err = opts.Validate() @@ -187,8 +188,8 @@ func TestSetMultiResourcesImageLocal(t *testing.T) { outputFormat := "name" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdImage(tf, buf, buf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdImage(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("output", outputFormat) cmd.Flags().Set("local", "true") @@ -202,8 +203,9 @@ func TestSetMultiResourcesImageLocal(t *testing.T) { }, FilenameOptions: resource.FilenameOptions{ Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}}, - Out: buf, - Local: true} + Local: true, + IOStreams: streams, + } err := opts.Complete(tf, cmd, []string{"*=thingy"}) if err == nil { err = opts.Validate() @@ -583,9 +585,8 @@ func TestSetImageRemote(t *testing.T) { outputFormat := "yaml" - out := new(bytes.Buffer) - cmd := NewCmdImage(tf, out, out) - cmd.SetOutput(out) + streams := genericclioptions.NewTestIOStreamsDiscard() + cmd := NewCmdImage(tf, streams) cmd.Flags().Set("output", outputFormat) opts := SetImageOptions{ PrintFlags: &printers.PrintFlags{ @@ -595,8 +596,9 @@ func TestSetImageRemote(t *testing.T) { OutputFormat: &outputFormat, }, - Out: out, - Local: false} + Local: false, + IOStreams: streams, + } err := opts.Complete(tf, cmd, input.args) assert.NoError(t, err) err = opts.Run() diff --git a/pkg/kubectl/cmd/set/set_resources.go b/pkg/kubectl/cmd/set/set_resources.go index 3fbb18f00a7..d3b635c373b 100644 --- a/pkg/kubectl/cmd/set/set_resources.go +++ b/pkg/kubectl/cmd/set/set_resources.go @@ -18,7 +18,6 @@ package set import ( "fmt" - "io" "strings" "k8s.io/kubernetes/pkg/printers" @@ -69,8 +68,6 @@ type SetResourcesOptions struct { RecordFlags *genericclioptions.RecordFlags Infos []*resource.Info - Out io.Writer - Err io.Writer Selector string ContainerSelector string Output string @@ -88,25 +85,27 @@ type SetResourcesOptions struct { UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) Resources []string + + genericclioptions.IOStreams } // NewResourcesOptions returns a ResourcesOptions indicating all containers in the selected // pod templates are selected by default. -func NewResourcesOptions(out io.Writer, errOut io.Writer) *SetResourcesOptions { +func NewResourcesOptions(streams genericclioptions.IOStreams) *SetResourcesOptions { return &SetResourcesOptions{ PrintFlags: printers.NewPrintFlags("resource requirements updated"), RecordFlags: genericclioptions.NewRecordFlags(), Recorder: genericclioptions.NoopRecorder{}, - Out: out, - Err: errOut, ContainerSelector: "*", + + IOStreams: streams, } } -func NewCmdResources(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command { - o := NewResourcesOptions(out, errOut) +func NewCmdResources(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewResourcesOptions(streams) resourceTypesWithPodTemplate := []string{} for _, resource := range f.SuggestedPodTemplateResources() { diff --git a/pkg/kubectl/cmd/set/set_resources_test.go b/pkg/kubectl/cmd/set/set_resources_test.go index 0b9fde4cfa4..1e5ec98c273 100644 --- a/pkg/kubectl/cmd/set/set_resources_test.go +++ b/pkg/kubectl/cmd/set/set_resources_test.go @@ -17,7 +17,6 @@ limitations under the License. package set import ( - "bytes" "fmt" "io/ioutil" "net/http" @@ -42,6 +41,7 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -64,8 +64,8 @@ func TestResourcesLocal(t *testing.T) { outputFormat := "name" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdResources(tf, buf, buf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdResources(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("output", outputFormat) cmd.Flags().Set("local", "true") @@ -79,11 +79,12 @@ func TestResourcesLocal(t *testing.T) { }, FilenameOptions: resource.FilenameOptions{ Filenames: []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}}, - Out: buf, Local: true, Limits: "cpu=200m,memory=512Mi", Requests: "cpu=200m,memory=512Mi", - ContainerSelector: "*"} + ContainerSelector: "*", + IOStreams: streams, + } err := opts.Complete(tf, cmd, []string{}) if err == nil { @@ -118,8 +119,8 @@ func TestSetMultiResourcesLimitsLocal(t *testing.T) { outputFormat := "name" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdResources(tf, buf, buf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdResources(tf, streams) cmd.SetOutput(buf) cmd.Flags().Set("output", outputFormat) cmd.Flags().Set("local", "true") @@ -133,11 +134,12 @@ func TestSetMultiResourcesLimitsLocal(t *testing.T) { }, FilenameOptions: resource.FilenameOptions{ Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}}, - Out: buf, Local: true, Limits: "cpu=200m,memory=512Mi", Requests: "cpu=200m,memory=512Mi", - ContainerSelector: "*"} + ContainerSelector: "*", + IOStreams: streams, + } err := opts.Complete(tf, cmd, []string{}) if err == nil { @@ -501,9 +503,8 @@ func TestSetResourcesRemote(t *testing.T) { outputFormat := "yaml" - buf := new(bytes.Buffer) - cmd := NewCmdResources(tf, buf, buf) - cmd.SetOutput(buf) + streams := genericclioptions.NewTestIOStreamsDiscard() + cmd := NewCmdResources(tf, streams) cmd.Flags().Set("output", outputFormat) opts := SetResourcesOptions{ PrintFlags: &printers.PrintFlags{ @@ -513,9 +514,10 @@ func TestSetResourcesRemote(t *testing.T) { OutputFormat: &outputFormat, }, - Out: buf, Limits: "cpu=200m,memory=512Mi", - ContainerSelector: "*"} + ContainerSelector: "*", + IOStreams: streams, + } err := opts.Complete(tf, cmd, input.args) if err == nil { err = opts.Validate() diff --git a/pkg/kubectl/cmd/set/set_selector.go b/pkg/kubectl/cmd/set/set_selector.go index 1fb92ac3080..cc09ca728af 100644 --- a/pkg/kubectl/cmd/set/set_selector.go +++ b/pkg/kubectl/cmd/set/set_selector.go @@ -18,7 +18,6 @@ package set import ( "fmt" - "io" "k8s.io/kubernetes/pkg/printers" @@ -53,7 +52,6 @@ type SetSelectorOptions struct { resources []string selector *metav1.LabelSelector - out io.Writer ClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error) PrintObj printers.ResourcePrinterFunc @@ -61,6 +59,8 @@ type SetSelectorOptions struct { builder *resource.Builder mapper meta.RESTMapper + + genericclioptions.IOStreams } var ( @@ -77,20 +77,20 @@ var ( kubectl create deployment my-dep -o yaml --dry-run | kubectl label --local -f - environment=qa -o yaml | kubectl create -f -`) ) -func NewSelectorOptions(out io.Writer) *SetSelectorOptions { +func NewSelectorOptions(streams genericclioptions.IOStreams) *SetSelectorOptions { return &SetSelectorOptions{ PrintFlags: printers.NewPrintFlags("selector updated"), RecordFlags: genericclioptions.NewRecordFlags(), Recorder: genericclioptions.NoopRecorder{}, - out: out, + IOStreams: streams, } } // NewCmdSelector is the "set selector" command. -func NewCmdSelector(f cmdutil.Factory, out io.Writer) *cobra.Command { - o := NewSelectorOptions(out) +func NewCmdSelector(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewSelectorOptions(streams) cmd := &cobra.Command{ Use: "selector (-f FILENAME | TYPE NAME) EXPRESSIONS [--resource-version=version]", @@ -226,7 +226,7 @@ func (o *SetSelectorOptions) RunSelector() error { return patch.Err } if o.local || o.dryrun { - return o.PrintObj(info.Object, o.out) + return o.PrintObj(info.Object, o.Out) } patched, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) @@ -235,7 +235,7 @@ func (o *SetSelectorOptions) RunSelector() error { } info.Refresh(patched, true) - return o.PrintObj(patch.Info.AsVersioned(), o.out) + return o.PrintObj(patch.Info.AsVersioned(), o.Out) }) } diff --git a/pkg/kubectl/cmd/set/set_selector_test.go b/pkg/kubectl/cmd/set/set_selector_test.go index 15dba1a947c..dfcd28aae0f 100644 --- a/pkg/kubectl/cmd/set/set_selector_test.go +++ b/pkg/kubectl/cmd/set/set_selector_test.go @@ -17,7 +17,6 @@ limitations under the License. package set import ( - "bytes" "net/http" "reflect" "strings" @@ -34,6 +33,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 TestUpdateSelectorForObjectTypes(t *testing.T) { @@ -331,9 +331,8 @@ func TestSelectorTest(t *testing.T) { tf.Namespace = "test" tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdSelector(tf, buf) - cmd.SetOutput(buf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdSelector(tf, streams) cmd.Flags().Set("output", "name") cmd.Flags().Set("local", "true") cmd.Flags().Set("filename", "../../../../test/e2e/testing-manifests/statefulset/cassandra/service.yaml") diff --git a/pkg/kubectl/cmd/set/set_serviceaccount.go b/pkg/kubectl/cmd/set/set_serviceaccount.go index 5723c943a32..91599acca91 100644 --- a/pkg/kubectl/cmd/set/set_serviceaccount.go +++ b/pkg/kubectl/cmd/set/set_serviceaccount.go @@ -19,7 +19,6 @@ package set import ( "errors" "fmt" - "io" "k8s.io/kubernetes/pkg/printers" @@ -62,8 +61,6 @@ type SetServiceAccountOptions struct { RecordFlags *genericclioptions.RecordFlags fileNameOptions resource.FilenameOptions - out io.Writer - err io.Writer dryRun bool shortOutput bool all bool @@ -75,23 +72,24 @@ type SetServiceAccountOptions struct { PrintObj printers.ResourcePrinterFunc Recorder genericclioptions.Recorder + + genericclioptions.IOStreams } -func NewSetServiceAccountOptions(out, errOut io.Writer) *SetServiceAccountOptions { +func NewSetServiceAccountOptions(streams genericclioptions.IOStreams) *SetServiceAccountOptions { return &SetServiceAccountOptions{ PrintFlags: printers.NewPrintFlags("serviceaccount updated"), RecordFlags: genericclioptions.NewRecordFlags(), Recorder: genericclioptions.NoopRecorder{}, - out: out, - err: errOut, + IOStreams: streams, } } // NewCmdServiceAccount returns the "set serviceaccount" command. -func NewCmdServiceAccount(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - o := NewSetServiceAccountOptions(out, errOut) +func NewCmdServiceAccount(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewSetServiceAccountOptions(streams) cmd := &cobra.Command{ Use: "serviceaccount (-f FILENAME | TYPE NAME) SERVICE_ACCOUNT", @@ -199,7 +197,7 @@ func (o *SetServiceAccountOptions) Run() error { continue } if o.local || o.dryRun { - if err := o.PrintObj(patch.Info.AsVersioned(), o.out); err != nil { + if err := o.PrintObj(patch.Info.AsVersioned(), o.Out); err != nil { return err } continue @@ -211,7 +209,7 @@ func (o *SetServiceAccountOptions) Run() error { } info.Refresh(patched, true) - if err := o.PrintObj(info.AsVersioned(), o.out); err != nil { + if err := o.PrintObj(info.AsVersioned(), o.Out); err != nil { return err } } diff --git a/pkg/kubectl/cmd/set/set_serviceaccount_test.go b/pkg/kubectl/cmd/set/set_serviceaccount_test.go index 6b0ddb3a862..2fa9b7784e5 100644 --- a/pkg/kubectl/cmd/set/set_serviceaccount_test.go +++ b/pkg/kubectl/cmd/set/set_serviceaccount_test.go @@ -42,6 +42,7 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/scheme" ) @@ -83,9 +84,8 @@ func TestSetServiceAccountLocal(t *testing.T) { outputFormat := "yaml" tf.Namespace = "test" - out := new(bytes.Buffer) - cmd := NewCmdServiceAccount(tf, out, out) - cmd.SetOutput(out) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdServiceAccount(tf, streams) cmd.Flags().Set("output", outputFormat) cmd.Flags().Set("local", "true") testapi.Default = testapi.Groups[input.apiGroup] @@ -98,13 +98,14 @@ func TestSetServiceAccountLocal(t *testing.T) { }, fileNameOptions: resource.FilenameOptions{ Filenames: []string{input.yaml}}, - out: out, - local: true} + local: true, + IOStreams: streams, + } err := saConfig.Complete(tf, cmd, []string{serviceAccount}) assert.NoError(t, err) err = saConfig.Run() assert.NoError(t, err) - assert.Contains(t, out.String(), "serviceAccountName: "+serviceAccount, fmt.Sprintf("serviceaccount not updated for %s", input.yaml)) + assert.Contains(t, buf.String(), "serviceAccountName: "+serviceAccount, fmt.Sprintf("serviceaccount not updated for %s", input.yaml)) }) } } @@ -128,9 +129,8 @@ func TestSetServiceAccountMultiLocal(t *testing.T) { outputFormat := "name" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdServiceAccount(tf, buf, buf) - cmd.SetOutput(buf) + streams, _, buf, _ := genericclioptions.NewTestIOStreams() + cmd := NewCmdServiceAccount(tf, streams) cmd.Flags().Set("output", outputFormat) cmd.Flags().Set("local", "true") opts := SetServiceAccountOptions{ @@ -142,8 +142,9 @@ func TestSetServiceAccountMultiLocal(t *testing.T) { }, fileNameOptions: resource.FilenameOptions{ Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}}, - out: buf, - local: true} + local: true, + IOStreams: streams, + } err := opts.Complete(tf, cmd, []string{serviceAccount}) if err == nil { @@ -373,9 +374,8 @@ func TestSetServiceAccountRemote(t *testing.T) { outputFormat := "yaml" - out := new(bytes.Buffer) - cmd := NewCmdServiceAccount(tf, out, out) - cmd.SetOutput(out) + streams := genericclioptions.NewTestIOStreamsDiscard() + cmd := NewCmdServiceAccount(tf, streams) cmd.Flags().Set("output", outputFormat) saConfig := SetServiceAccountOptions{ PrintFlags: &printers.PrintFlags{ @@ -385,8 +385,9 @@ func TestSetServiceAccountRemote(t *testing.T) { OutputFormat: &outputFormat, }, - out: out, - local: false} + local: false, + IOStreams: streams, + } err := saConfig.Complete(tf, cmd, input.args) assert.NoError(t, err) err = saConfig.Run() @@ -420,9 +421,8 @@ func TestServiceAccountValidation(t *testing.T) { outputFormat := "" tf.Namespace = "test" - out := bytes.NewBuffer([]byte{}) - cmd := NewCmdServiceAccount(tf, out, out) - cmd.SetOutput(out) + streams := genericclioptions.NewTestIOStreamsDiscard() + cmd := NewCmdServiceAccount(tf, streams) saConfig := &SetServiceAccountOptions{ PrintFlags: &printers.PrintFlags{ @@ -431,6 +431,7 @@ func TestServiceAccountValidation(t *testing.T) { OutputFormat: &outputFormat, }, + IOStreams: streams, } err := saConfig.Complete(tf, cmd, input.args) assert.EqualError(t, err, input.errorString) diff --git a/pkg/kubectl/cmd/set/set_subject.go b/pkg/kubectl/cmd/set/set_subject.go index 6e996b49306..5a976b7cc44 100644 --- a/pkg/kubectl/cmd/set/set_subject.go +++ b/pkg/kubectl/cmd/set/set_subject.go @@ -18,7 +18,6 @@ package set import ( "fmt" - "io" "strings" "k8s.io/kubernetes/pkg/printers" @@ -32,6 +31,7 @@ import ( "k8s.io/kubernetes/pkg/apis/rbac" "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" ) @@ -61,8 +61,6 @@ type SubjectOptions struct { resource.FilenameOptions Infos []*resource.Info - Out io.Writer - Err io.Writer Selector string ContainerSelector string Output string @@ -75,15 +73,20 @@ type SubjectOptions struct { ServiceAccounts []string PrintObj printers.ResourcePrinterFunc + + genericclioptions.IOStreams } -func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command { - options := &SubjectOptions{ +func NewSubjectOptions(streams genericclioptions.IOStreams) *SubjectOptions { + return &SubjectOptions{ PrintFlags: printers.NewPrintFlags("subjects updated"), - Out: out, - Err: errOut, + IOStreams: streams, } +} + +func NewCmdSubject(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + options := NewSubjectOptions(streams) cmd := &cobra.Command{ Use: "subject (-f FILENAME | TYPE NAME) [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]", diff --git a/pkg/kubectl/cmd/set/set_test.go b/pkg/kubectl/cmd/set/set_test.go index 1c7b42db060..7432a49bf76 100644 --- a/pkg/kubectl/cmd/set/set_test.go +++ b/pkg/kubectl/cmd/set/set_test.go @@ -17,20 +17,17 @@ limitations under the License. package set import ( - "bytes" "testing" "github.com/spf13/cobra" clientcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "os" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func TestLocalAndDryRunFlags(t *testing.T) { - out := &bytes.Buffer{} - errout := &bytes.Buffer{} f := clientcmdutil.NewFactory(nil) - setCmd := NewCmdSet(f, os.Stdin, out, errout) + setCmd := NewCmdSet(f, genericclioptions.NewTestIOStreamsDiscard()) ensureLocalAndDryRunFlagsOnChildren(t, setCmd, "") }