From beb0f33bed2e53d7d53d4e5efdcbf95d05312ddc Mon Sep 17 00:00:00 2001 From: juanvallejo Date: Wed, 27 Jun 2018 16:24:46 -0400 Subject: [PATCH] update importimage, projects, rsh, req_project --- pkg/oc/cli/cmd/importimage.go | 115 +++++++++--------- pkg/oc/cli/cmd/importimage_test.go | 7 +- pkg/oc/cli/cmd/project.go | 43 ++++--- pkg/oc/cli/cmd/projects.go | 46 +++---- pkg/oc/cli/cmd/request_project.go | 39 +++--- pkg/oc/cli/cmd/request_project_test.go | 13 +- pkg/oc/cli/cmd/rsh.go | 10 +- pkg/oc/clusterup/docker/openshift/project.go | 10 +- .../unprivileged_newproject_test.go | 14 +-- 9 files changed, 158 insertions(+), 139 deletions(-) diff --git a/pkg/oc/cli/cmd/importimage.go b/pkg/oc/cli/cmd/importimage.go index ee446d831087..454a6c271fc3 100644 --- a/pkg/oc/cli/cmd/importimage.go +++ b/pkg/oc/cli/cmd/importimage.go @@ -2,7 +2,6 @@ package cmd import ( "fmt" - "io" "strings" "github.com/spf13/cobra" @@ -41,39 +40,15 @@ var ( `) ) -// NewCmdImportImage implements the OpenShift cli import-image command. -func NewCmdImportImage(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { - opts := &ImportImageOptions{} - cmd := &cobra.Command{ - Use: "import-image IMAGESTREAM[:TAG]", - Short: "Imports images from a Docker registry", - Long: importImageLong, - Example: fmt.Sprintf(importImageExample, fullName), - Run: func(cmd *cobra.Command, args []string) { - kcmdutil.CheckErr(opts.Complete(f, cmd, args, fullName, streams.Out, streams.ErrOut)) - kcmdutil.CheckErr(opts.Validate(cmd)) - kcmdutil.CheckErr(opts.Run()) - }, - } - cmd.Flags().StringVar(&opts.From, "from", "", "A Docker image repository to import images from") - cmd.Flags().BoolVar(&opts.Confirm, "confirm", false, "If true, allow the image stream import location to be set or changed") - cmd.Flags().BoolVar(&opts.All, "all", false, "If true, import all tags from the provided source on creation or if --from is specified") - cmd.Flags().StringVar(&opts.ReferencePolicy, "reference-policy", sourceReferencePolicy, "Allow to request pullthrough for external image when set to 'local'. Defaults to 'source'.") - cmd.Flags().BoolVar(&opts.DryRun, "dry-run", false, "Fetch information about images without creating or updating an image stream.") - cmd.Flags().BoolVar(&opts.Scheduled, "scheduled", false, "Set each imported Docker image to be periodically imported from a remote repository. Defaults to false.") - opts.Insecure = cmd.Flags().Bool("insecure", false, "If true, allow importing from registries that have invalid HTTPS certificates or are hosted via HTTP. This flag will take precedence over the insecure annotation.") - - return cmd -} - // ImageImportOptions contains all the necessary information to perform an import. type ImportImageOptions struct { // user set values - From string - Confirm bool - All bool - Scheduled bool - Insecure *bool + From string + Confirm bool + All bool + Scheduled bool + Insecure bool + InsecureFlagProvided bool DryRun bool @@ -84,27 +59,54 @@ type ImportImageOptions struct { Target string ReferencePolicy string - CommandName string - // helpers - out io.Writer - errout io.Writer imageClient imageclient.ImageInterface isClient imageclient.ImageStreamInterface + + genericclioptions.IOStreams +} + +func NewImportImageOptions(name string, streams genericclioptions.IOStreams) *ImportImageOptions { + return &ImportImageOptions{ + IOStreams: streams, + ReferencePolicy: sourceReferencePolicy, + } +} + +// NewCmdImportImage implements the OpenShift cli import-image command. +func NewCmdImportImage(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewImportImageOptions(fullName, streams) + + cmd := &cobra.Command{ + Use: "import-image IMAGESTREAM[:TAG]", + Short: "Imports images from a Docker registry", + Long: importImageLong, + Example: fmt.Sprintf(importImageExample, fullName), + Run: func(cmd *cobra.Command, args []string) { + kcmdutil.CheckErr(o.Complete(f, cmd, args)) + kcmdutil.CheckErr(o.Validate(cmd)) + kcmdutil.CheckErr(o.Run()) + }, + } + cmd.Flags().StringVar(&o.From, "from", o.From, "A Docker image repository to import images from") + cmd.Flags().BoolVar(&o.Confirm, "confirm", o.Confirm, "If true, allow the image stream import location to be set or changed") + cmd.Flags().BoolVar(&o.All, "all", o.All, "If true, import all tags from the provided source on creation or if --from is specified") + cmd.Flags().StringVar(&o.ReferencePolicy, "reference-policy", o.ReferencePolicy, "Allow to request pullthrough for external image when set to 'local'. Defaults to 'source'.") + cmd.Flags().BoolVar(&o.DryRun, "dry-run", o.DryRun, "Fetch information about images without creating or updating an image stream.") + cmd.Flags().BoolVar(&o.Scheduled, "scheduled", o.Scheduled, "Set each imported Docker image to be periodically imported from a remote repository. Defaults to false.") + cmd.Flags().BoolVar(&o.Insecure, "insecure", o.Insecure, "If true, allow importing from registries that have invalid HTTPS certificates or are hosted via HTTP. This flag will take precedence over the insecure annotation.") + + return cmd } // Complete turns a partially defined ImportImageOptions into a solvent structure // which can be validated and used for aa import. -func (o *ImportImageOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string, commandName string, out, errout io.Writer) error { - o.CommandName = commandName - +func (o *ImportImageOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error { if len(args) > 0 { o.Target = args[0] } - if !cmd.Flags().Lookup("insecure").Changed { - o.Insecure = nil - } + o.InsecureFlagProvided = cmd.Flags().Lookup("insecure").Changed if !cmd.Flags().Lookup("reference-policy").Changed { o.ReferencePolicy = "" } @@ -127,9 +129,6 @@ func (o *ImportImageOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, ar o.imageClient = client.Image() o.isClient = client.Image().ImageStreams(namespace) - o.out = out - o.errout = errout - return nil } @@ -173,15 +172,15 @@ func (o *ImportImageOptions) Run() error { if o.DryRun { if wasError(result) { - fmt.Fprintf(o.errout, "The dry-run import completed with errors.\n\n") + fmt.Fprintf(o.ErrOut, "The dry-run import completed with errors.\n\n") } else { - fmt.Fprint(o.out, "The dry-run import completed successfully.\n\n") + fmt.Fprint(o.Out, "The dry-run import completed successfully.\n\n") } } else { if wasError(result) { - fmt.Fprintf(o.errout, "The import completed with errors.\n\n") + fmt.Fprintf(o.ErrOut, "The import completed with errors.\n\n") } else { - fmt.Fprint(o.out, "The import completed successfully.\n\n") + fmt.Fprint(o.Out, "The import completed successfully.\n\n") } } @@ -191,7 +190,7 @@ func (o *ImportImageOptions) Run() error { if err != nil { return err } - fmt.Fprintln(o.out, info) + fmt.Fprintln(o.Out, info) } if repo := result.Status.Repository; repo != nil { @@ -199,12 +198,12 @@ func (o *ImportImageOptions) Run() error { if image.Image != nil { info, err := describe.DescribeImage(image.Image, imageapi.JoinImageStreamTag(stream.Name, image.Tag)) if err != nil { - fmt.Fprintf(o.errout, "error: tag %s failed: %v\n", image.Tag, err) + fmt.Fprintf(o.ErrOut, "error: tag %s failed: %v\n", image.Tag, err) } else { - fmt.Fprintln(o.out, info) + fmt.Fprintln(o.Out, info) } } else { - fmt.Fprintf(o.errout, "error: repository tag %s failed: %v\n", image.Tag, image.Status.Message) + fmt.Fprintf(o.ErrOut, "error: repository tag %s failed: %v\n", image.Tag, image.Status.Message) } } } @@ -213,17 +212,17 @@ func (o *ImportImageOptions) Run() error { if image.Image != nil { info, err := describe.DescribeImage(image.Image, imageapi.JoinImageStreamTag(stream.Name, image.Tag)) if err != nil { - fmt.Fprintf(o.errout, "error: tag %s failed: %v\n", image.Tag, err) + fmt.Fprintf(o.ErrOut, "error: tag %s failed: %v\n", image.Tag, err) } else { - fmt.Fprintln(o.out, info) + fmt.Fprintln(o.Out, info) } } else { - fmt.Fprintf(o.errout, "error: tag %s failed: %v\n", image.Tag, image.Status.Message) + fmt.Fprintf(o.ErrOut, "error: tag %s failed: %v\n", image.Tag, image.Status.Message) } } if r := result.Status.Repository; r != nil && len(r.AdditionalTags) > 0 { - fmt.Fprintf(o.out, "\ninfo: The remote repository contained %d additional tags which were not imported: %s\n", len(r.AdditionalTags), strings.Join(r.AdditionalTags, ", ")) + fmt.Fprintf(o.Out, "\ninfo: The remote repository contained %d additional tags which were not imported: %s\n", len(r.AdditionalTags), strings.Join(r.AdditionalTags, ", ")) } return nil } @@ -457,8 +456,8 @@ func (o *ImportImageOptions) newImageStreamImport(stream *imageapi.ImageStream) insecureAnnotation := stream.Annotations[imageapi.InsecureRepositoryAnnotation] insecure := insecureAnnotation == "true" // --insecure flag (if provided) takes precedence over insecure annotation - if o.Insecure != nil { - insecure = *o.Insecure + if o.InsecureFlagProvided { + insecure = o.Insecure } return isi, insecure diff --git a/pkg/oc/cli/cmd/importimage_test.go b/pkg/oc/cli/cmd/importimage_test.go index 9206e5ad065c..0fb0531deb55 100644 --- a/pkg/oc/cli/cmd/importimage_test.go +++ b/pkg/oc/cli/cmd/importimage_test.go @@ -580,11 +580,16 @@ func TestCreateImageImport(t *testing.T) { From: test.from, All: test.all, Scheduled: test.scheduled, - Insecure: test.insecure, ReferencePolicy: test.referencePolicy, Confirm: test.confirm, isClient: fake.Image().ImageStreams("other"), } + + if test.insecure != nil { + o.Insecure = *test.insecure + o.InsecureFlagProvided = true + } + // we need to run Validate, because it sets appropriate Name and Tag if err := o.Validate(&cobra.Command{}); err != nil { t.Errorf("%s: unexpected error: %v", name, err) diff --git a/pkg/oc/cli/cmd/project.go b/pkg/oc/cli/cmd/project.go index da683c4429a4..de1fb3860a7e 100644 --- a/pkg/oc/cli/cmd/project.go +++ b/pkg/oc/cli/cmd/project.go @@ -4,7 +4,6 @@ import ( "bytes" "errors" "fmt" - "io" "net/url" kapierrors "k8s.io/apimachinery/pkg/api/errors" @@ -32,7 +31,6 @@ type ProjectOptions struct { Config clientcmdapi.Config ClientConfig *restclient.Config ClientFn func() (projectclient.ProjectInterface, kclientset.Interface, error) - Out io.Writer PathOptions *kclientcmd.PathOptions ProjectName string @@ -41,6 +39,8 @@ type ProjectOptions struct { // SkipAccessValidation means that if a specific name is requested, don't bother checking for access to the project SkipAccessValidation bool + + genericclioptions.IOStreams } var ( @@ -65,9 +65,15 @@ var ( %[1]s`) ) +func NewProjectOptions(streams genericclioptions.IOStreams) *ProjectOptions { + return &ProjectOptions{ + IOStreams: streams, + } +} + // NewCmdProject implements the OpenShift cli rollback command func NewCmdProject(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { - options := &ProjectOptions{} + o := NewProjectOptions(streams) cmd := &cobra.Command{ Use: "project [NAME]", @@ -75,22 +81,22 @@ func NewCmdProject(fullName string, f kcmdutil.Factory, streams genericclioption Long: projectLong, Example: fmt.Sprintf(projectExample, fullName), Run: func(cmd *cobra.Command, args []string) { - options.PathOptions = cliconfig.NewPathOptions(cmd) + o.PathOptions = cliconfig.NewPathOptions(cmd) - if err := options.Complete(f, args, streams.Out); err != nil { + if err := o.Complete(f, args); err != nil { kcmdutil.CheckErr(kcmdutil.UsageErrorf(cmd, err.Error())) } - if err := options.RunProject(); err != nil { + if err := o.RunProject(); err != nil { kcmdutil.CheckErr(err) } }, } - cmd.Flags().BoolVarP(&options.DisplayShort, "short", "q", false, "If true, display only the project name") + cmd.Flags().BoolVarP(&o.DisplayShort, "short", "q", false, "If true, display only the project name") return cmd } -func (o *ProjectOptions) Complete(f genericclioptions.RESTClientGetter, args []string, out io.Writer) error { +func (o *ProjectOptions) Complete(f genericclioptions.RESTClientGetter, args []string) error { var err error argsLength := len(args) @@ -146,8 +152,6 @@ func (o *ProjectOptions) Complete(f genericclioptions.RESTClientGetter, args []s return projectClient.Project(), kc, nil } - o.Out = out - return nil } func (o ProjectOptions) Validate() error { @@ -158,7 +162,6 @@ func (o ProjectOptions) Validate() error { func (o ProjectOptions) RunProject() error { config := o.Config clientCfg := o.ClientConfig - out := o.Out var currentProject string currentContext := config.Contexts[config.CurrentContext] @@ -170,7 +173,7 @@ func (o ProjectOptions) RunProject() error { if len(o.ProjectName) == 0 { if len(currentProject) > 0 { if o.DisplayShort { - fmt.Fprintln(out, currentProject) + fmt.Fprintln(o.Out, currentProject) return nil } @@ -193,17 +196,17 @@ func (o ProjectOptions) RunProject() error { // if they specified a project name and got a generated context, then only show the information they care about. They won't recognize // a context name they didn't choose if config.CurrentContext == defaultContextName { - fmt.Fprintf(out, "Using project %q on server %q.\n", currentProject, clientCfg.Host) + fmt.Fprintf(o.Out, "Using project %q on server %q.\n", currentProject, clientCfg.Host) } else { - fmt.Fprintf(out, "Using project %q from context named %q on server %q.\n", currentProject, config.CurrentContext, clientCfg.Host) + fmt.Fprintf(o.Out, "Using project %q from context named %q on server %q.\n", currentProject, config.CurrentContext, clientCfg.Host) } } else { if o.DisplayShort { return fmt.Errorf("no project has been set") } - fmt.Fprintf(out, "No project has been set. Pass a project name to make that the default.\n") + fmt.Fprintf(o.Out, "No project has been set. Pass a project name to make that the default.\n") } return nil } @@ -282,7 +285,7 @@ func (o ProjectOptions) RunProject() error { } if o.DisplayShort { - fmt.Fprintln(out, namespaceInUse) + fmt.Fprintln(o.Out, namespaceInUse) return nil } @@ -293,20 +296,20 @@ func (o ProjectOptions) RunProject() error { switch { // if there is no namespace, then the only information we can provide is the context and server case (len(namespaceInUse) == 0): - fmt.Fprintf(out, "Now using context named %q on server %q.\n", contextInUse, clientCfg.Host) + fmt.Fprintf(o.Out, "Now using context named %q on server %q.\n", contextInUse, clientCfg.Host) // inform them that they are already in the project they are trying to switch to case currentProject == namespaceInUse: - fmt.Fprintf(out, "Already on project %q on server %q.\n", currentProject, clientCfg.Host) + fmt.Fprintf(o.Out, "Already on project %q on server %q.\n", currentProject, clientCfg.Host) // if they specified a project name and got a generated context, then only show the information they care about. They won't recognize // a context name they didn't choose case (argument == namespaceInUse) && (contextInUse == defaultContextName): - fmt.Fprintf(out, "Now using project %q on server %q.\n", namespaceInUse, clientCfg.Host) + fmt.Fprintf(o.Out, "Now using project %q on server %q.\n", namespaceInUse, clientCfg.Host) // in all other cases, display all information default: - fmt.Fprintf(out, "Now using project %q from context named %q on server %q.\n", namespaceInUse, contextInUse, clientCfg.Host) + fmt.Fprintf(o.Out, "Now using project %q from context named %q on server %q.\n", namespaceInUse, contextInUse, clientCfg.Host) } diff --git a/pkg/oc/cli/cmd/projects.go b/pkg/oc/cli/cmd/projects.go index b6fe1919a6a2..ca7b17b9ff56 100644 --- a/pkg/oc/cli/cmd/projects.go +++ b/pkg/oc/cli/cmd/projects.go @@ -2,7 +2,6 @@ package cmd import ( "fmt" - "io" "sort" kapierrors "k8s.io/apimachinery/pkg/api/errors" @@ -30,13 +29,21 @@ type ProjectsOptions struct { ClientConfig *restclient.Config Client projectclient.ProjectInterface KubeClient kclientset.Interface - Out io.Writer PathOptions *kclientcmd.PathOptions // internal strings CommandName string DisplayShort bool + + genericclioptions.IOStreams +} + +func NewProjectsOptions(name string, streams genericclioptions.IOStreams) *ProjectsOptions { + return &ProjectsOptions{ + IOStreams: streams, + CommandName: name, + } } // SortByProjectName is sort @@ -62,35 +69,27 @@ var ( // NewCmdProjects implements the OpenShift cli rollback command func NewCmdProjects(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { - options := &ProjectsOptions{} + o := NewProjectsOptions(fullName, streams) cmd := &cobra.Command{ Use: "projects", Short: "Display existing projects", Long: projectsLong, Run: func(cmd *cobra.Command, args []string) { - options.PathOptions = cliconfig.NewPathOptions(cmd) - - if err := options.Complete(f, args, fullName, streams.Out); err != nil { + if err := o.Complete(f, cmd, args); err != nil { kcmdutil.CheckErr(kcmdutil.UsageErrorf(cmd, err.Error())) } - - if err := options.RunProjects(); err != nil { - kcmdutil.CheckErr(err) - } + kcmdutil.CheckErr(o.Validate(args)) + kcmdutil.CheckErr(o.RunProjects()) }, } - cmd.Flags().BoolVarP(&options.DisplayShort, "short", "q", false, "If true, display only the project names") + cmd.Flags().BoolVarP(&o.DisplayShort, "short", "q", false, "If true, display only the project names") return cmd } -func (o *ProjectsOptions) Complete(f kcmdutil.Factory, args []string, commandName string, out io.Writer) error { - if len(args) > 0 { - return fmt.Errorf("no arguments should be passed") - } - - o.CommandName = commandName +func (o *ProjectsOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error { + o.PathOptions = cliconfig.NewPathOptions(cmd) var err error o.Config, err = f.ToRawKubeConfigLoader().RawConfig() @@ -113,16 +112,19 @@ func (o *ProjectsOptions) Complete(f kcmdutil.Factory, args []string, commandNam } o.Client = projectClient.Project() - o.Out = out + return nil +} +func (o *ProjectsOptions) Validate(args []string) error { + if len(args) > 0 { + return fmt.Errorf("no arguments should be passed") + } return nil } // RunProjects lists all projects a user belongs to func (o ProjectsOptions) RunProjects() error { config := o.Config - clientCfg := o.ClientConfig - out := o.Out var currentProject string currentContext := config.Contexts[config.CurrentContext] @@ -205,9 +207,9 @@ func (o ProjectsOptions) RunProjects() error { // if they specified a project name and got a generated context, then only show the information they care about. They won't recognize // a context name they didn't choose if config.CurrentContext == defaultContextName { - fmt.Fprintf(out, "\nUsing project %q on server %q.\n", currentProject, clientCfg.Host) + fmt.Fprintf(o.Out, "\nUsing project %q on server %q.\n", currentProject, o.ClientConfig.Host) } else { - fmt.Fprintf(out, "\nUsing project %q from context named %q on server %q.\n", currentProject, config.CurrentContext, clientCfg.Host) + fmt.Fprintf(o.Out, "\nUsing project %q from context named %q on server %q.\n", currentProject, config.CurrentContext, o.ClientConfig.Host) } } return nil diff --git a/pkg/oc/cli/cmd/request_project.go b/pkg/oc/cli/cmd/request_project.go index faa92566ea8b..d199fd882c10 100644 --- a/pkg/oc/cli/cmd/request_project.go +++ b/pkg/oc/cli/cmd/request_project.go @@ -3,7 +3,6 @@ package cmd import ( "errors" "fmt" - "io" "github.com/spf13/cobra" @@ -21,8 +20,8 @@ import ( // RequestProjectRecommendedCommandName is the recommended command name. const RequestProjectRecommendedCommandName = "new-project" -// NewProjectOptions contains all the options for running the RequestProject cli command. -type NewProjectOptions struct { +// RequestProjectOptions contains all the options for running the RequestProject cli command. +type RequestProjectOptions struct { ProjectName string DisplayName string Description string @@ -35,7 +34,7 @@ type NewProjectOptions struct { Client projectclient.ProjectInterface ProjectOptions *ProjectOptions - Out io.Writer + genericclioptions.IOStreams } // RequestProject command description. @@ -73,11 +72,16 @@ To switch to this project and start adding applications, use: ` ) +func NewRequestProjectOptions(baseName string, streams genericclioptions.IOStreams) *RequestProjectOptions { + return &RequestProjectOptions{ + IOStreams: streams, + Name: baseName, + } +} + // NewCmdRequestProject implement the OpenShift cli RequestProject command. func NewCmdRequestProject(name, baseName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { - o := &NewProjectOptions{} - o.Out = streams.Out - o.Name = baseName + o := NewRequestProjectOptions(baseName, streams) cmd := &cobra.Command{ Use: fmt.Sprintf("%s NAME [--display-name=DISPLAYNAME] [--description=DESCRIPTION]", name), @@ -86,11 +90,6 @@ func NewCmdRequestProject(name, baseName string, f kcmdutil.Factory, streams gen Example: fmt.Sprintf(requestProjectExample, baseName, name), Run: func(cmd *cobra.Command, args []string) { kcmdutil.CheckErr(o.Complete(f, cmd, args)) - clientConfig, err := f.ToRESTConfig() - kcmdutil.CheckErr(err) - projectClient, err := projectclientinternal.NewForConfig(clientConfig) - kcmdutil.CheckErr(err) - o.Client = projectClient.Project() kcmdutil.CheckErr(o.Run()) }, } @@ -103,7 +102,7 @@ func NewCmdRequestProject(name, baseName string, f kcmdutil.Factory, streams gen } // Complete completes all the required options. -func (o *NewProjectOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error { +func (o *RequestProjectOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error { if len(args) != 1 { cmd.Help() return errors.New("must have exactly one argument") @@ -112,9 +111,9 @@ func (o *NewProjectOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, arg o.ProjectName = args[0] if !o.SkipConfigWrite { - o.ProjectOptions = &ProjectOptions{} + o.ProjectOptions = NewProjectOptions(o.IOStreams) o.ProjectOptions.PathOptions = cliconfig.NewPathOptions(cmd) - if err := o.ProjectOptions.Complete(f, []string{""}, o.Out); err != nil { + if err := o.ProjectOptions.Complete(f, []string{""}); err != nil { return err } } else { @@ -125,11 +124,18 @@ func (o *NewProjectOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, arg o.Server = clientConfig.Host } + clientConfig, err := f.ToRESTConfig() + if err != nil { + return err + } + projectClient, err := projectclientinternal.NewForConfig(clientConfig) + o.Client = projectClient.Project() + return nil } // Run implements all the necessary functionality for RequestProject. -func (o *NewProjectOptions) Run() error { +func (o *RequestProjectOptions) Run() error { if err := o.Client.RESTClient().Get().Resource("projectrequests").Do().Into(&metav1.Status{}); err != nil { return err } @@ -149,6 +155,7 @@ func (o *NewProjectOptions) Run() error { o.ProjectOptions.ProjectName = project.Name o.ProjectOptions.ProjectOnly = true o.ProjectOptions.SkipAccessValidation = true + o.ProjectOptions.IOStreams = o.IOStreams if err := o.ProjectOptions.RunProject(); err != nil { return err diff --git a/pkg/oc/cli/cmd/request_project_test.go b/pkg/oc/cli/cmd/request_project_test.go index d447159bebc2..e05b404dbf7c 100644 --- a/pkg/oc/cli/cmd/request_project_test.go +++ b/pkg/oc/cli/cmd/request_project_test.go @@ -1,7 +1,6 @@ package cmd import ( - "bytes" "fmt" "strconv" "testing" @@ -48,15 +47,15 @@ func TestRequestProjectDefaultFlags(t *testing.T) { // DISABLE_TestRequestProjectRun ensures that Run command calls the right actions. func DISABLE_TestRequestProjectRun(t *testing.T) { client := projectfake.NewSimpleClientset() - buf := &bytes.Buffer{} + ioStreams, _, out, _ := genericclioptions.NewTestIOStreams() test := struct { - opts *NewProjectOptions + opts *RequestProjectOptions expectedActions []testAction expectedErr error }{ - opts: &NewProjectOptions{ - Out: buf, + opts: &RequestProjectOptions{ + IOStreams: ioStreams, Server: "127.0.0.1", Client: client.Project(), Name: "oc", @@ -75,8 +74,8 @@ func DISABLE_TestRequestProjectRun(t *testing.T) { t.Fatalf("error mismatch: expected %v, got %v", test.expectedErr, err) } - if buf.String() != expectedOutput { - t.Fatalf("error mismatch output: expected %v, got %v", expectedOutput, buf) + if out.String() != expectedOutput { + t.Fatalf("error mismatch output: expected %v, got %v", expectedOutput, out) } got := client.Actions() diff --git a/pkg/oc/cli/cmd/rsh.go b/pkg/oc/cli/cmd/rsh.go index 72f92b17f8ec..c51309e6ff65 100644 --- a/pkg/oc/cli/cmd/rsh.go +++ b/pkg/oc/cli/cmd/rsh.go @@ -75,9 +75,8 @@ type RshOptions struct { *kubecmd.ExecOptions } -// NewCmdRsh returns a command that attempts to open a shell session to the server. -func NewCmdRsh(name string, parent string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { - options := &RshOptions{ +func NewRshOptions(parent string, streams genericclioptions.IOStreams) *RshOptions { + return &RshOptions{ ForceTTY: false, DisableTTY: false, Timeout: 10, @@ -92,6 +91,11 @@ func NewCmdRsh(name string, parent string, f kcmdutil.Factory, streams genericcl Executor: &kubecmd.DefaultRemoteExecutor{}, }, } +} + +// NewCmdRsh returns a command that attempts to open a shell session to the server. +func NewCmdRsh(name string, parent string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + options := NewRshOptions(parent, streams) cmd := &cobra.Command{ Use: fmt.Sprintf("%s [flags] POD [COMMAND]", name), diff --git a/pkg/oc/clusterup/docker/openshift/project.go b/pkg/oc/clusterup/docker/openshift/project.go index 85a88859a49d..83092b221da7 100644 --- a/pkg/oc/clusterup/docker/openshift/project.go +++ b/pkg/oc/clusterup/docker/openshift/project.go @@ -24,7 +24,7 @@ func CreateProject(f genericclioptions.RESTClientGetter, name, display, desc, ba return err } pathOptions := config.NewPathOptionsWithConfig("") - opt := &cmd.NewProjectOptions{ + opt := &cmd.RequestProjectOptions{ ProjectName: name, DisplayName: display, Description: desc, @@ -34,9 +34,9 @@ func CreateProject(f genericclioptions.RESTClientGetter, name, display, desc, ba Client: projectClient.Project(), ProjectOptions: &cmd.ProjectOptions{PathOptions: pathOptions}, - Out: ioutil.Discard, + IOStreams: genericclioptions.NewTestIOStreamsDiscard(), } - err = opt.ProjectOptions.Complete(f, []string{}, ioutil.Discard) + err = opt.ProjectOptions.Complete(f, []string{}) if err != nil { return err } @@ -52,8 +52,8 @@ func CreateProject(f genericclioptions.RESTClientGetter, name, display, desc, ba func setCurrentProject(f genericclioptions.RESTClientGetter, name string, out io.Writer) error { pathOptions := config.NewPathOptionsWithConfig("") - opt := &cmd.ProjectOptions{PathOptions: pathOptions} - opt.Complete(f, []string{name}, out) + opt := &cmd.ProjectOptions{PathOptions: pathOptions, IOStreams: genericclioptions.IOStreams{Out: out, ErrOut: ioutil.Discard}} + opt.Complete(f, []string{name}) return opt.RunProject() } diff --git a/test/integration/unprivileged_newproject_test.go b/test/integration/unprivileged_newproject_test.go index 168fdcd81228..be77b4be4d41 100644 --- a/test/integration/unprivileged_newproject_test.go +++ b/test/integration/unprivileged_newproject_test.go @@ -1,13 +1,13 @@ package integration import ( - "io/ioutil" "testing" "time" kapierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization" authorizationclient "github.com/openshift/origin/pkg/authorization/generated/internalclientset" @@ -86,13 +86,13 @@ func TestUnprivilegedNewProject(t *testing.T) { t.Fatalf("expected %v, got %v", metav1.StatusSuccess, allowed.Status) } - requestProject := oc.NewProjectOptions{ + requestProject := oc.RequestProjectOptions{ ProjectName: "new-project", DisplayName: "display name here", Description: "the special description", - Client: valerieProjectClient.Project(), - Out: ioutil.Discard, + Client: valerieProjectClient.Project(), + IOStreams: genericclioptions.NewTestIOStreamsDiscard(), } if err := requestProject.Run(); err != nil { @@ -170,13 +170,13 @@ func TestUnprivilegedNewProjectFromTemplate(t *testing.T) { t.Fatalf("unexpected error: %v", err) } - requestProject := oc.NewProjectOptions{ + requestProject := oc.RequestProjectOptions{ ProjectName: "new-project", DisplayName: "display name here", Description: "the special description", - Client: valerieProjectClient.Project(), - Out: ioutil.Discard, + Client: valerieProjectClient.Project(), + IOStreams: genericclioptions.NewTestIOStreamsDiscard(), } if err := requestProject.Run(); err != nil {